Index: pkg/polymer/lib/src/loader.dart |
diff --git a/pkg/polymer/lib/src/loader.dart b/pkg/polymer/lib/src/loader.dart |
index 28adf3dcf6832c511c0cb8c6125e50bf0b46e3f0..e43022c7fdc2573eb1f0b96da672fdde1c4786f2 100644 |
--- a/pkg/polymer/lib/src/loader.dart |
+++ b/pkg/polymer/lib/src/loader.dart |
@@ -21,78 +21,84 @@ const initMethod = const _InitMethodAnnotation(); |
* * set up up polling for observable changes |
* * initialize Model-Driven Views |
* * Include some style to prevent flash of unstyled content (FOUC) |
- * * for each library in [libraries], register custom elements labeled with |
- * [CustomTag] and invoke the initialization method on it. If [libraries] |
- * is null, first find all libraries that need to be loaded by scanning for |
- * HTML imports in the main document. |
- * |
- * The initialization on each library is a top-level function and annotated with |
- * [initMethod]. |
- * |
- * The urls in [libraries] can be absolute or relative to |
- * `currentMirrorSystem().isolate.rootLibrary.uri`. |
+ * * 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]). |
*/ |
Zone initPolymer() { |
+ // We use this pattern, and not the inline lazy initialization pattern, so we |
+ // can help dart2js detect that _discoverInitializers can be tree-shaken for |
+ // deployment (and hence all uses of dart:mirrors from this loading logic). |
+ // TODO(sigmund): fix polymer's transformers so they can replace initPolymer |
+ // by initPolymerOptimized. |
+ if (_initializers == null) _initializers = _discoverInitializers(); |
if (_useDirtyChecking) { |
- return dirtyCheckZone()..run(_initPolymerOptimized); |
+ return dirtyCheckZone()..run(initPolymerOptimized); |
} |
- _initPolymerOptimized(); |
- return Zone.current; |
+ return initPolymerOptimized(); |
} |
/** |
* Same as [initPolymer], but runs the version that is optimized for deployment |
* to the internet. The biggest difference is it omits the [Zone] that |
- * automatically invokes [Observable.dirtyCheck], and the list of libraries must |
- * be supplied instead of being dynamically searched for at runtime. |
+ * automatically invokes [Observable.dirtyCheck], and the list of initializers |
+ * must be supplied instead of being dynamically searched for at runtime using |
+ * mirrors. |
*/ |
-// TODO(jmesserly): change the Polymer build step to call this directly. |
-void _initPolymerOptimized() { |
+Zone initPolymerOptimized() { |
document.register(PolymerDeclaration._TAG, PolymerDeclaration); |
- _loadLibraries(); |
+ 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; |
} |
/** |
* Configures [initPolymer] making it optimized for deployment to the internet. |
- * With this setup the list of libraries to initialize is supplied instead of |
- * being dynamically searched for at runtime. Additionally, after this method is |
- * called, [initPolymer] omits the [Zone] that automatically invokes |
+ * With this setup the initializer list is supplied instead of being dynamically |
+ * searched for at runtime. Additionally, after this method is called, |
+ * [initPolymer] omits the [Zone] that automatically invokes |
* [Observable.dirtyCheck]. |
*/ |
-void configureForDeployment(List<String> libraries) { |
- _librariesToLoad = libraries; |
+void configureForDeployment(List<Function> initializers) { |
+ _initializers = initializers; |
_useDirtyChecking = false; |
} |
/** |
- * Libraries that will be initialized. For each library, the intialization |
- * registers any type tagged with a [CustomTag] annotation and calls any |
+ * List of initializers that by default will be executed when calling |
+ * initPolymer. If null, initPolymer will compute the list of initializers by |
+ * crawling HTML imports, searchfing for script tags, and including an |
+ * initializer for each type tagged with a [CustomTag] annotation and for each |
* top-level method annotated with [initMethod]. The value of this field is |
* assigned programatically by the code generated from the polymer deploy |
- * scripts. During development, the libraries are inferred by crawling HTML |
- * imports and searching for script tags. |
+ * scripts. |
*/ |
-List<String> _librariesToLoad = |
- _discoverScripts(document, window.location.href); |
+List<Function> _initializers; |
+ |
bool _useDirtyChecking = true; |
-void _loadLibraries() { |
- for (var lib in _librariesToLoad) { |
+List<Function> _discoverInitializers() { |
+ var initializers = []; |
+ var librariesToLoad = _discoverScripts(document, window.location.href); |
+ for (var lib in librariesToLoad) { |
try { |
- _loadLibrary(lib); |
+ _loadLibrary(lib, initializers); |
} catch (e, s) { |
// Deliver errors async, so if a single library fails it doesn't prevent |
// other things from loading. |
new Completer().completeError(e, s); |
} |
} |
+ return initializers; |
} |
/** |
@@ -159,7 +165,7 @@ bool _isHttpStylePackageUrl(Uri uri) { |
* * Registers any [PolymerElement] that is marked with the [CustomTag] |
* annotation. |
*/ |
-void _loadLibrary(String uriString) { |
+void _loadLibrary(String uriString, List<Function> initializers) { |
var uri = _rootUri.resolve(uriString); |
var lib = _libs[uri]; |
if (_isHttpStylePackageUrl(uri)) { |
@@ -185,7 +191,7 @@ void _loadLibrary(String uriString) { |
// Search top-level functions marked with @initMethod |
for (var f in lib.declarations.values.where((d) => d is MethodMirror)) { |
- _maybeInvoke(lib, f); |
+ _addInitMethod(lib, f, initializers); |
} |
for (var c in lib.declarations.values.where((d) => d is ClassMirror)) { |
@@ -193,7 +199,7 @@ void _loadLibrary(String uriString) { |
for (var m in c.metadata) { |
var meta = m.reflectee; |
if (meta is CustomTag) { |
- Polymer.register(meta.tagName, c.reflectedType); |
+ initializers.add(() => Polymer.register(meta.tagName, c.reflectedType)); |
} |
} |
@@ -206,7 +212,8 @@ void _loadLibrary(String uriString) { |
} |
} |
-void _maybeInvoke(ObjectMirror obj, MethodMirror method) { |
+void _addInitMethod(ObjectMirror obj, MethodMirror method, |
+ List<Function> initializers) { |
var annotationFound = false; |
for (var meta in method.metadata) { |
if (identical(meta.reflectee, initMethod)) { |
@@ -225,7 +232,7 @@ void _maybeInvoke(ObjectMirror obj, MethodMirror method) { |
"arguments, ${method.simpleName} expects some."); |
return; |
} |
- obj.invoke(method.simpleName, const []); |
+ initializers.add(() => obj.invoke(method.simpleName, const [])); |
} |
class _InitMethodAnnotation { |