Monday, April 7, 2014

Kicking the Tires on Polymer.dart 0.10 (and js-interop)

Curiosity got the better of me yesterday as I wondered if I might use a Vulcanized JavaScript Polymer element inside a Polymer.dart. It couldn't—but maybe it will be able to...

The CHANGELOG for the 0.10-pre release of Polymer.dart includes this nifty little tidbit:
* Interop with polymer-js elements now works.
That makes it seem like the next release of Polymer.dart will support it. So, letting my curiosity drive me yet again, I will give it a go tonight. First up, I need to replace the 0.9 dependency in my application's pubspec.yaml package configuration. It is currently being locked to 0.9 in the resulting pubspec.lock:
# ...
    description: polymer
    source: hosted
    version: "0.9.5"
# ...
So, back in the application's pubspec.yaml, I try to limit the dependency to 0.10.0-pre.7 or higher:
name: deployment_experiment
# ...
  polymer: ">=0.10.0-pre.7"
# ...
That is, of course a non-started with the current 1.2 version of Dart:
➜  dart git:(master) ✗ pub update    
Resolving dependencies........
Package polymer requires SDK version >=1.3.0-dev.5.0 <2.0.0 but the current SDK is 1.2.0
No worries, I should have been using the prerelease all along and especially should be using it now that it is nearing the release.

So I grab the latest dev channel release of Dart:
➜  Downloads  wget
➜  Downloads  cd ~/local
➜  local  unzip ~/Downloads/
That expands into the dart directory. I have various locations under $HOME/local/dart in my $PATH:
Some of those come directly from the ZIP file, others I need to massage or outright download. I complete the installation by downloading and installing (per my $PATH) the content_shell executable for running headless tests:
➜  local  cd dart/
➜  dart  ./chromium/
Downloading to
Download finished.
➜  dart  mv drt-lucid64-full-dev-34756.0 content_shell
Then I replace the regular Dartium with the debug version:
➜  dart  ./chromium/
Downloading to
Download finished.
➜  dart  unzip 
➜  dart  mv chromium chromium.orig                             
➜  dart  mv dartium-lucid64-debug-dev-34756.0 chromium
Now I am ready to roll. Back in my application, I again pub update to get the latest Polymer.dart:
➜  dart git:(master) ✗ pub update
These packages are no longer being depended on:
- custom_element 0.9.2
- html_import 0.9.0
- mutation_observer 0.9.0
- shadow_dom 0.9.2
- unmodifiable_collection 0.9.2+1
Downloading polymer 0.10.0-pre.8...
Changed 17 dependencies!
I have to make a few minor changes to the overall application to work with 0.10. First, there is no more initPolymer() (yay!). Instead, I now need to import a Polymer HTML file similar to how it is done in JavaScript-land:
    <link rel="import" href="packages/polymer/polymer.html">
    <link rel="import" href="packages/deployment_experiment/elements/x-pizza.html">
In each of the Polymer template files, I also have to modify the mime-type of the backing script:
<link rel="import" href="x-pizza-toppings.html">
<polymer-element name="x-pizza">
  <template><!-- ... --></template>
  <script type="application/dart;component=1" src="x_pizza.dart"></script>
The component=1 parameter is an uglyish way to signal to the Dart VM in the browser that it should not run this script in a separate isolate—that it should be run as part of the same isolate used by other Polymer elements. After making those changes to the Polymer.dart code, my Polymer is working perfectly again. Now to the task at hand. Instead of using the Dart version of the <x-pizza-toppings> Polymer element, I want to use last night's Vulcanized JavaScript version.

So I swap the import from the template definition file of the containing <x-pizza> element:
<!-- <link rel="import" href="x-pizza-toppings.html"> -->
<link rel="import" href="vulcanized.html">
<polymer-element name="x-pizza">
  <template><!-- ... --></template>
  <script type="application/dart;component=1" src="x_pizza.dart"></script>
Unfortunately, when I fire this up in Dartium, I get errors:
Uncaught Possible attempt to load Polymer
Exception: NoSuchMethodError: method not found: 'whenPolymerReady'
Receiver: Instance of 'JsFunction'
Arguments: [Closure: () => dynamic]
When I vulcanized this polymer, I did so by inlining all of the backing JavaScript, including the platform and polymer libraries. After removing the inlined Polymer library code from vulcanized.html, I am a little closer. The Dart <x-pizza> element now displays as does the template from the 3 JavaScript <x-pizza-toppings> elements:

Some of the bindings between the elements are even working—the button names in the JavaScript <x-pizza-toppings> elements are bound variables from the Dart <x-pizza>. Unfortunately, the ingredient list is not bound properly, nor are the events that transfer information.

Looking through some of the js-interop tests in the Polymer.dart project, it seems that some js-interop method calling from Dart may be in order. I will investigate that further tomorrow and give it a try in code tomorrow night. For now, just getting this far will be enough progress for one day.

Day #27


  1. Thanks for looking into this. It would be nice to be able to use some of those JavaScript Polymer elements, inside a Dart one, made available, at some site, I've been to but can't remember where it is.

  2. I found the site of pre-made polymer elements, but they're all JS.