Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1210)

Unified Diff: pkg/polymer/lib/src/loader.dart

Issue 182193002: [polymer] interop with polymer-element and polymer.js (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/polymer/lib/src/loader.dart
diff --git a/pkg/polymer/lib/src/loader.dart b/pkg/polymer/lib/src/loader.dart
index e6f17f5fbb3c1983a10e60a8bcd5fd9b5a44f7e1..d7c29b2a87b4da3f564f07b7b062aa559010d74e 100644
--- a/pkg/polymer/lib/src/loader.dart
+++ b/pkg/polymer/lib/src/loader.dart
@@ -46,20 +46,12 @@ Zone initPolymer() {
Zone initPolymerOptimized() {
// TODO(sigmund): refactor this so we can replace it by codegen.
smoke.useMirrors();
- // TODO(jmesserly): there is some code in src/declaration/polymer-element.js,
- // git version 37eea00e13b9f86ab21c85a955585e8e4237e3d2, right before
- // it registers polymer-element, which uses Platform.deliverDeclarations to
- // coordinate with HTML Imports. I don't think we need it so skipping.
- document.register(PolymerDeclaration._TAG, PolymerDeclaration);
+ _hookJsPolymer();
for (var initializer in _initializers) {
initializer();
}
- // Run this after user code so they can add to Polymer.veiledElements
- _preventFlashOfUnstyledContent();
-
- customElementsReady.then((_) => Polymer._ready.complete());
return Zone.current;
}
@@ -188,15 +180,14 @@ void _loadLibrary(String uriString, List<Function> initializers) {
_addInitMethod(lib, f, initializers);
}
- for (var c in lib.declarations.values.where((d) => d is ClassMirror)) {
- // Search for @CustomTag on classes
- for (var m in c.metadata) {
- var meta = m.reflectee;
- if (meta is CustomTag) {
- initializers.add(() => Polymer.register(meta.tagName, c.reflectedType));
- }
- }
+ // Dart note: we don't get back @CustomTags in a reliable order from mirrors,
+ // at least on Dart VM. So we need to sort them so base classes are registered
+ // first, which ensures that document.register will work correctly for a
+ // set of types within in the same library.
+ var customTags = new LinkedHashMap<Type, Function>();
+ for (var c in lib.declarations.values.where((d) => d is ClassMirror)) {
+ _loadCustomTags(lib, c, customTags);
// TODO(sigmund): check also static methods marked with @initMethod.
// This is blocked on two bugs:
// - dartbug.com/12133 (static methods are incorrectly listed as top-level
@@ -204,6 +195,38 @@ void _loadLibrary(String uriString, List<Function> initializers) {
// - dartbug.com/12134 (sometimes "method.metadata" throws an exception,
// we could wrap and hide those exceptions, but it's not ideal).
}
+
+ initializers.addAll(customTags.values);
+}
+
+void _loadCustomTags(LibraryMirror lib, ClassMirror cls,
+ LinkedHashMap registerFns) {
+ if (cls == null || cls.reflectedType == HtmlElement) return;
+
+ // Register superclass first.
+ _loadCustomTags(lib, cls.superclass, registerFns);
+
+ if (cls.owner != lib) {
+ // Don't register classes from different libraries.
+ // TODO(jmesserly): @CustomTag does not currently respect re-export, because
+ // LibraryMirror.declarations doesn't include these.
+ return;
+ }
+
+ var meta = _getCustomTagMetadata(cls);
+ if (meta == null) return;
+
+ registerFns.putIfAbsent(cls.reflectedType, () =>
+ () => Polymer.register(meta.tagName, cls.reflectedType));
+}
+
+/// Search for @CustomTag on a classemirror
+CustomTag _getCustomTagMetadata(ClassMirror c) {
+ for (var m in c.metadata) {
+ var meta = m.reflectee;
+ if (meta is CustomTag) return meta;
+ }
+ return null;
}
void _addInitMethod(ObjectMirror obj, MethodMirror method,
@@ -232,3 +255,63 @@ void _addInitMethod(ObjectMirror obj, MethodMirror method,
class _InitMethodAnnotation {
const _InitMethodAnnotation();
}
+
+/// To ensure Dart can interoperate with polymer-element registered by
+/// polymer.js, we need to be able to execute Dart code if we are registering
+/// a Dart class for that element. We trigger Dart logic by patching
+/// polymer-element's register function and:
+///
+/// * if it has a Dart class, run PolymerDeclaration's register.
+/// * otherwise it is a JS prototype, run polymer-element's normal register.
+void _hookJsPolymer() {
+ var polymerJs = js.context['Polymer'];
+ if (polymerJs == null) {
+ throw new StateError('polymer.js must be loaded before polymer.dart, please'
+ ' add <link rel="import" href="packages/polymer/polymer.html"> to your'
+ ' <head> before any Dart scripts. Alternatively you can get a different'
+ ' version of polymer.js by following the instructions at'
+ ' http://www.polymer-project.org; if you do that be sure to include'
+ ' the platform polyfills.');
+ }
+
+ // TODO(jmesserly): dart:js appears to not callback in the correct zone:
+ // https://code.google.com/p/dart/issues/detail?id=17301
+ var zone = Zone.current;
+
+ polymerJs.callMethod('whenPolymerReady',
+ [zone.bindCallback(() => Polymer._ready.complete())]);
+
+ // Note: we need to call createElement through JavaScript to get the right
+ // JavaScript prototype.
+ // TODO(jmesserly): what's going on here? Are we getting a strange mix of
Siggi Cherem (dart-lang) 2014/03/06 18:18:08 not sure I understand the TODO, what does this app
Jennifer Messerly 2014/03/06 21:05:08 Well, at the time I didn't understand the problem
+ // polyfilled things in JS and native in Dart?
+ var jsPolymer = new JsObject.fromBrowserObject(document)
+ .callMethod('createElement', ['polymer-element']);
+
+ var proto = js.context['Object'].callMethod('getPrototypeOf', [jsPolymer]);
+ if (proto is Node) {
+ proto = new JsObject.fromBrowserObject(proto);
+ }
+
+ JsFunction originalRegister = proto['register'];
+ if (originalRegister == null) {
+ throw new StateError('polymer.js must expose "register" function on '
+ 'polymer-element to enable polymer.dart to interoperate.');
+ }
+
+ registerDart(jsElem, String name, String extendee) {
+ // By the time we get here, we'll know for sure if it is a Dart object
+ // or not, because polymer-element will wait for us to notify that
+ // the @CustomTag was found.
+ final type = _getRegisteredType(name);
+ if (type != null) {
+ final extendsDecl = _getDeclaration(extendee);
+ return zone.run(() =>
+ new PolymerDeclaration(jsElem, name, type, extendsDecl).register());
+ }
+ // It's a JavaScript polymer element, fall back to the original register.
+ return originalRegister.apply([name, extendee], thisArg: jsElem);
+ }
+
+ proto['register'] = new JsFunction.withThis(registerDart);
Siggi Cherem (dart-lang) 2014/03/06 18:18:08 wow -- I knew you were going to do this, was just
Jennifer Messerly 2014/03/06 21:05:08 Yeah, it's kinda neat we can do it. It's a lot cle
+}

Powered by Google App Engine
This is Rietveld 408576698