Monday, March 31, 2014

Forking Dart2JS in a Pub Transform (ICK)


My quest to generate a single JS file from a Polymer.dart source continues tonight with an attempt to get dart2js generated code into that single JS file.

After the previous two nights, I have the <polymer-element> template in said JS file (Polymer.dart puts it directly in the HTML by default) and various supporting libraries in that same JS file. But I lack the most important piece of this puzzle—the compiled backing class itself. The problem is that the dart2js transformer is run at the very end of the Dart Pub transform process.

The first thing that I try tonight is to place the $dart2js options before my custom, single JS transformer in my project's pubspec.yaml:
name: deployment_experiment
dependencies:
  polymer: any
dev_dependencies:
  scheduled_test: any
transformers:
- polymer:
    entry_points: web/index.html
- $dart2js:
    verbose: true
- deployment_experiment:
    entry_points: web/index.html
I have not looked into the $dart2js transformer code and the documentation never states this explicitly, but my sense is that the dart2js transformer is run last no matter what and that the $dart2js options are just that—options for that last transformer.

Still, best not to assume, so:
$ pub build
Building deployment_experiment.................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................^C
I let that run for a good ten minutes with no discernable results. There is nothing happening to the filesystem:
➜  polymer-book git:(master) ✗ find play/deployment -mmin -60 -ls | grep -v node_modules | grep -v dart/packages
1188688    4 drwxr-xr-x  10 chris    chris        4096 Mar 31 22:17 play/deployment/dart
1196105    4 drwxr-xr-x   2 chris    chris        4096 Mar 31 21:58 play/deployment/dart/test
1186073    0 lrwxrwxrwx   1 chris    chris          11 Mar 31 21:58 play/deployment/dart/test/packages -> ../packages
1196106    4 drwxr-xr-x   2 chris    chris        4096 Mar 31 21:58 play/deployment/dart/web
1186074    0 lrwxrwxrwx   1 chris    chris          11 Mar 31 21:58 play/deployment/dart/web/packages -> ../packages
1188969    4 -rw-r--r--   1 chris    chris         349 Mar 31 22:10 play/deployment/dart/pubspec.yaml
1188960    4 -rw-r--r--   1 chris    chris        2203 Mar 31 21:58 play/deployment/dart/pubspec.lock
1188690    4 drwxr-xr-x   3 chris    chris        4096 Mar 31 22:00 play/deployment/dart/lib
1186103    4 -rw-r--r--   1 chris    chris        2240 Mar 31 22:00 play/deployment/dart/lib/transformer.dart
1196109    4 drwxr-xr-x   2 chris    chris        4096 Mar 31 22:10 play/deployment/dart/build
So I Ctrl-C the process.

If I move the $dart2js configuration to the end of pubspec.yaml, then the pub build works normally, albeit without the ability to transform dart2js output.

So ugh. It seems that I have do this the ugly way. The ugly way involves identifying the Polymer transform assets that get compiled into JavaScript by the default dart2js process at the end of pub build. Using that list, I then need to manually compiled these assets as part of my transform.

I identify the parts as part of the Transformer's determination of which elements are “primary” elements. These dart2js elements are not primary, but I squirrel them away in a list to be processed:
library single_file.transformer;

import 'dart:io';
import 'dart:async';
import 'package:barback/barback.dart';

class SingleJsPolymerTransformer extends Transformer {
  String entry_points;
  List<AssetId> bootstrappedPolymerElements = [];
  // ...
  Future<bool> isPrimary(Asset input) {
    if (input.id.path.contains('html_bootstrap.dart')) {
      bootstrappedPolymerElements.add(input.id);
    }

    if (entry_points == input.id.path) return new Future.value(true);
    return new Future.value(false);
  }
  // ...
}
With that, I can then run dart2js on the assets, but...

But I have to first write them out to the disk. The built-in dart2js transformer must have some kind of compile-from-asset capability. I will look into that at some point, but for tonight I content myself with ugly hacks like:
  buildSingleJavaScript(templateHtml, transform) {
    return transform.
      readInputAsString(bootstrappedPolymerElements.first).
      then((code) {
        new File('index.html_bootstrap.dart').
          openSync(mode: FileMode.WRITE).
          writeStringSync(code);

        var result = Process.runSync(
         'dart2js',
         ['-o', 'index.html_bootstrap.dart.js', 'index.html_bootstrap.dart']
        );
        // ...
      });
  }
Even that does not quite do the trick. It seems that there are secondary Polymer.dart elements that are required because I wind up with compilation errors along the lines of:
index.html_bootstrap.dart:7:8: Error: Can't read 'file:///home/chris/repos/polymer-book/play/deployment/dart/index.html.0.dart' (Error reading
 'index.html.0.dart' (OS Error: No such file or directory, errno = 2)).
import 'index.html.0.dart' as i2;
       ^^^^^^^^^^^^^^^^^^^
index.html_bootstrap.dart:15:3: Warning: Cannot resolve 'i2'.
  i2.main();
  ^^
Error: Compilation failed.
Bother.

I do think I am on the right track, but I call it a night at this point. I will pick back up fresh tomorrow either investigating how dart2js compiles assets or working through the remaining secondary Polymer.dart elements that are needed to compile this darn file.



Day #20

No comments:

Post a Comment