Wednesday, June 4, 2014

What the Heck is an @initMethod (in Polymer.dart)?


While mucking around in 0.9 Polymer.dart, I was surprised that the @initMethod annotation seemed to have some effect on the code. I had thought it was a 0.10 pre-release annotation that helped Polymer.dart determine code isolates in which to run Polymer-related code—in particular which methods were main entry points.

I never did figure out what @initMethod did in 0.9 and I am unsure what it does now that 0.10 is here and has dropped some of the isolate-related features. So tonight I set out to figure out what @initMethod does and if I need to be aware of it in Patterns in Polymer.

Digging through the source code in the book repository, I find that I did use the @initPolymer annotation on some Polymer code that needed a main() entry point in addition to Polymer initialization. This was 0.10 pre-release code, so it loaded the Polymer library differently and initialized Polymer differently. I had to place the @initMethod annotation on the main() entry point to get Polymer to invoke it during the initialization process:
import 'package:polymer/polymer.dart';
@initMethod
main() {
  // Code here...
}
In this pre-release, I did not have to invoke initPolymer() but that is back now that official Polymer.dart 0.10 is here. So what does the @initMethod annotation do in official 0.10? Throw an exception apparently.

If I add initPolymer() to the main() entry point:
import 'package:polymer/polymer.dart';
@initMethod
main() {
  initPolymer();
  // ...
}
Then reload in Dartium, I get an exception:
Exception: Initialization was already done.
I am not certain where that exception is actually thrown (the debug version of Dartium has gone missing), but removing the @initMethod annotation eliminates the exception and, if I have setup my page correctly:
<!DOCTYPE html>
<html lang="en">
  <head>
    <link rel="import" href="packages/polymer/polymer.html">
    <link rel="import" href="packages/changes_from_outside/elements/hello-you.html">
    <script type="application/dart" src="main.dart"></script>
  </head>
  <body>
    <div class="container">
      <hello-you><!-- ... --></hello-you>
    </div>
  </body>
</html>
Then everything works including the code in the main() entry point and in the Polymer element.

That is obviously not the right way to use @initPolymer, so what is? Well, I finally read the documentation, which states that initPolymer() will:
...for each library included transitively from HTML and HTML imports, register custom elements declared there (labeled with @CustomTag) and invoke the initialization method on it (top-level functions annotated with @initMethod).
That makes it seem like @initMethod will invoke a method defined in the actual Polymer code. So I give that a try:
import 'package:polymer/polymer.dart';

@initMethod
bob() {
  print('Go talk to bob.');
}

@CustomTag('hello-you')
class HelloYou extends PolymerElement {
  // Normal Polymer code here...
}
And indeed that actually works. When I load my application, the code in the main() entry point continues to work as does the Polymer code. And if I check the console, I see:



So it seems that @initMethod can be used for some register-time code evaluation. I am unsure if this is meant for external custom element authors or just something for internal Polymer.dart authors. I am also unsure if the meaning will end up changing in the future. Still, it seems like something that might come in pretty handy.


Day #84

No comments:

Post a Comment