Wednesday, February 5, 2014

Running Two Dart Scripts from the Same Page


Dart's double main limitation: sigh.

I am thinking about how (and even if) to present reuse of Polymer in Patterns in Polymer. I think I already know how both the Dart and JavaScript versions of Polymer want me to do reuse, but my mind rebels. I don't want to use Dart Pub and Bower packages. I don't want to build pages that link these packages and some of their dependencies.

I don't even want to initPolymer() inside the main() entry point of another Dart script. Due to Dart's double main limitation, which only allows one Dart script per page, I don't think I have a choice on that account (more on that in a second).

What I really want is to add a <script> tag—either Dart or dart2js compiled JavaScript—to a page and have it load everything about my Polymer. With that one <script>, the Polymer polyfills should be loaded, my individual Polymer (template and code) should be loaded, and the Polymer platform should be loaded. With that one <script> tag, I ought to be able to use an <x-pizza> Polymer anywhere and it just work™. I don't think that's even possible in JavaScript yet, but I would like to explore the idea in Dart tonight.

The main problem that I have is that if I want to run a Dart application and Polymer, things break. Consider a page with:
  <head>
    <title>Reusing Polymers</title>

    <!-- Load component(s) -->
    <link rel="import" href="packages/reuse/elements/hello-you.html">
    <!-- Load Polymer -->
    <script type="application/dart">
      export 'package:polymer/init.dart';
    </script>
    <script type="application/dart" src="main.dart"></script>
  </head>
  <body>
    <div class="container">
      <h1>Polymer Reuse</h1>
      <hello-you></hello-you>
    </div>
  </body>
The problem is that both the <script> around export of Polymer's init.dart and the <script> that references main.dart conflict:
Only one Dart script tag allowed per document
warning: more than one Dart script tag in http://localhost:8080/index.html. Dartium currently only allows a single Dart script tag per document.
In my mind, I would like the Polymer initialization and my application's main.dart to both run in separate isolates that share access to the page's DOM. That way Polymer could do its thing getting custom elements up and running while my application could do its thing setting up the application.

That's just nonsense talk though. Isolates are small workers whose entire point is to share nothing, communicating only via message passing. As such, an isolate should not even have access to the web page—it should just be able to work on whatever messages are passed to it. I double check that by removing Polymer, and spawning an isolate in main.dart:
import 'dart:isolate';

main() {
  ReceivePort receivePort = new ReceivePort();
  receivePort.listen((msg) {
    print('Received from isolate: $msg');
  });

  Isolate.spawnUri('main2.dart', [], receivePort.sendPort).
    then((ret)=> print('isolate spawned'));
}
Then, in the main2.dart isolate, I send back the content of document.body:
import 'dart:html';
import 'dart:isolate';
main(List<String> args, SendPort sendPort) {
  sendPort.send('hello');
  sendPort.send(document.body.text);
}
That, of course, fails. Only the first message comes back and the isolate is never heard from again.

So, am I out of luck here? Possibly, but I can get both the main.dart and the exported Polymer init.dart running at the same time. I just need to only use the dart2js compiled version on main.dart. That is, instead of relying on dart.js to fallback to the compiled version of main.dart, I use it from the outset:
    <!-- Load component(s) -->
    <link rel="import" href="packages/reuse/elements/hello-you.html">
    <!-- Load Polymer -->
    <script type="application/dart">
      export 'package:polymer/init.dart';
    </script>
    <script src="main.dart.js"></script>
With that, I get both my Polymer and my simple main.dart console output:



Sure, that's cheating. I am not really running two different Dart scripts at the same time. But it seems to work. I may explore this a bit more tomorrow. Then again, the isolate exercise help solidify my thinking more than I care to admit. I did not expect it to work, but seeing it fail gave me more of an appreciation for the current zone approach in Polymer.dart. Or I may even give this a go in JavaScript.

But first, I need to finish that Angular chapter in Patterns in Polymer...

Day #1,018

2 comments: