Chromium Code Reviews| Index: pkg/polymer/lib/src/loader.dart |
| diff --git a/pkg/polymer/lib/src/loader.dart b/pkg/polymer/lib/src/loader.dart |
| index cdc223bb4c08cd2bd65d23491e7672fe704489e3..aa548ac6f2b2f1579fad92e8c2be63e6623aa6a6 100644 |
| --- a/pkg/polymer/lib/src/loader.dart |
| +++ b/pkg/polymer/lib/src/loader.dart |
| @@ -19,45 +19,125 @@ const initMethod = const _InitMethodAnnotation(); |
| /** |
| * Initializes a polymer application as follows: |
| * * set up up polling for observable changes |
| - * * initialize MDV |
| - * * for each library in [libraries], register custom elements labeled with |
| - * [CustomTag] and invoke the initialization method on it. |
| + * * initialize MDV |
|
Jennifer Messerly
2013/10/17 02:04:35
initialize Model-Driven Views (MDV)
Siggi Cherem (dart-lang)
2013/10/17 02:37:40
Done.
|
| + * * Include some style to prevent FUOC |
|
Jennifer Messerly
2013/10/17 02:04:35
Include some style to prevent flash of unstyled co
Siggi Cherem (dart-lang)
2013/10/17 02:37:40
Done.
|
| + * * 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 either a method named `main` or |
| - * a top-level function and annotated with [initMethod]. |
| + * The initialization on each library is a top-level function and annotated with |
| + * [initMethod]. |
| * |
| - * The urls in [libraries] can be absolute or relative to [srcUrl]. |
| + * The urls in [libraries] can be absolute or relative to |
| + * `currentMirrorSystem().isolate.rootLibrary.uri`. |
| */ |
| -void initPolymer(List<String> libraries, [String srcUrl]) { |
| +void initPolymer([List<String> libraries]) { |
| runMicrotask(() { |
| // DOM events don't yet go through microtasks, so we catch those here. |
| new Timer.periodic(new Duration(milliseconds: 125), |
| (_) => performMicrotaskCheckpoint()); |
| + preventFuoc(); |
|
Jennifer Messerly
2013/10/17 02:04:35
Rename this "preventFlashOfUnstyledContent"?
alte
Siggi Cherem (dart-lang)
2013/10/17 02:37:40
Done.
|
| + |
| // TODO(jmesserly): mdv should use initMdv instead of mdv.initialize. |
| mdv.initialize(); |
| document.register(PolymerDeclaration._TAG, PolymerDeclaration); |
| - for (var lib in libraries) { |
| - _loadLibrary(lib, srcUrl); |
| + if (libraries != null) { |
| + _loadLibraries(libraries); |
| + return; |
| } |
| - Polymer._ready.complete(); |
| - |
| - // TODO(sigmund): move to boot.dart once it's ready. |
| - document.body.style.transition = 'opacity 0.3s'; |
| - document.body.style.opacity = '1'; |
| + window.onLoad.listen((_) { |
|
Jennifer Messerly
2013/10/17 02:04:35
do we need to worry about initPolymer being called
Siggi Cherem (dart-lang)
2013/10/17 02:37:40
fixed - I got rid of the onLoad event. This was ne
|
| + _loadLibraries(_discoverScripts(document, window.location.href)); |
| + }); |
| }); |
| } |
| +void _loadLibraries(libraries) { |
| + for (var lib in libraries) { |
| + _loadLibrary(lib); |
| + } |
| + Polymer._ready.complete(); |
| +} |
| + |
| +/** |
| + * Walks the HTML import structure to discover all script tags that are |
| + * implicitly loaded. |
| + */ |
| +List<String> _discoverScripts(Document doc, String baseUri, |
| + [Set<Document> seen, List<String> scripts]) { |
| + if (seen == null) seen = new Set<Document>(); |
| + if (scripts == null) scripts = <String>[]; |
| + if (seen.contains(doc)) return scripts; |
| + seen.add(doc); |
| + |
| + var inlinedScriptCount = 0; |
| + for (var node in doc.queryAll('script,link[rel="import"]')) { |
| + if (node is LinkElement) { |
| + _discoverScripts(node.import, node.href, seen, scripts); |
| + } else if (node is ScriptElement && node.type == 'application/dart') { |
| + var url = node.src; |
| + if (url != '') { |
| + // TODO(sigmund): consider either normalizing package: urls or add a |
| + // warning to let users know about cannonicalization issues. |
| + scripts.add(url); |
| + } else { |
| + // We generate a unique identifier for inlined scripts which we later |
| + // translate to the unique identifiers used by Dartium. Dartium uses |
| + // line/column number information which we can't compute here. |
| + scripts.add('$baseUri:$inlinedScriptCount'); |
| + inlinedScriptCount++; |
| + } |
| + } |
| + } |
| + return scripts; |
| +} |
| + |
| /** All libraries in the current isolate. */ |
| final _libs = currentMirrorSystem().libraries; |
| +final _rootUri = currentMirrorSystem().isolate.rootLibrary.uri; |
|
Jennifer Messerly
2013/10/17 02:04:35
do we have a bug # about this?
Siggi Cherem (dart-lang)
2013/10/17 02:37:40
oops, yes, I removed the TODO when moving the code
|
| + |
| +/** Regex that matches urls used to represent inlined scripts. */ |
| +final RegExp _inlineScriptRegExp = new RegExp('\(.*\.html.*\):\([0-9]\+\)'); |
| + |
| +/** |
| + * Map URLs fabricated by polymer to URLs fabricated by Dartium to represent |
| + * inlined scripts. Polymer uses baseUri:script#, Dartium uses baseUri:line# |
| + */ |
| +// TODO(sigmund): figure out if we can generate the same URL and expose it. |
| +final Map<Uri, List<Uri>> _inlinedScriptMapping = () { |
| + var map = {}; |
| + for (var uri in _libs.keys) { |
| + var uriString = uri.toString(); |
| + var match = _inlineScriptRegExp.firstMatch(uriString); |
| + if (match == null) continue; |
| + var baseUri = Uri.parse(match.group(1)); |
| + if (map[baseUri] == null) map[baseUri] = []; |
| + map[baseUri].add(uri); |
| + } |
| + return map; |
| +}(); |
| + |
| +/** Returns a new Uri that replaces [path] in [uri]. */ |
| +Uri _replacePath(Uri uri, String path) { |
| + return new Uri(scheme: uri.scheme, host: uri.host, port: uri.port, |
| + path: path, query: uri.query, fragment: uri.fragment); |
| +} |
| + |
| +/** Returns the Uri in [href] without query parameters or fragments. */ |
| +String _baseUri(String href) { |
| + var uri = Uri.parse(window.location.href); |
| + var trimUri = new Uri(scheme: uri.scheme, host: uri.host, |
| + port: uri.port, path: uri.path); |
| + return trimUri.toString(); |
| +} |
| + |
| /** |
| * Reads the library at [uriString] (which can be an absolute URI or a relative |
| - * URI from [srcUrl]), and: |
| - * |
| - * * If present, invokes `main`. |
| + * URI from the root library), and: |
| * |
| * * If present, invokes any top-level and static functions marked |
| * with the [initMethod] annotation (in the order they appear). |
| @@ -65,22 +145,25 @@ final _libs = currentMirrorSystem().libraries; |
| * * Registers any [PolymerElement] that is marked with the [CustomTag] |
| * annotation. |
| */ |
| -void _loadLibrary(String uriString, [String srcUrl]) { |
| - var uri = Uri.parse(uriString); |
| - if (uri.scheme == '' && srcUrl != null) { |
| - uri = Uri.parse(path.normalize(path.join(path.dirname(srcUrl), uriString))); |
| +void _loadLibrary(String uriString) { |
| + var uri = _rootUri.resolve(uriString); |
| + var lib; |
| + var match = _inlineScriptRegExp.firstMatch(uriString); |
| + if (match != null) { |
| + var baseUri = Uri.parse(match.group(1)); |
| + var list = _inlinedScriptMapping[baseUri]; |
| + var pos = int.parse(match.group(2), onError: (_) => -1); |
| + if (list != null && pos >= 0 && pos < list.length && list[pos] != null) { |
| + lib = _libs[list[pos]]; |
| + } |
| + } else { |
| + lib = _libs[uri]; |
| } |
| - var lib = _libs[uri]; |
| if (lib == null) { |
| print('warning: $uri library not found'); |
| return; |
| } |
| - // Invoke `main`, if present. |
| - if (lib.functions[#main] != null) { |
| - lib.invoke(#main, const []); |
| - } |
| - |
| // Search top-level functions marked with @initMethod |
| for (var f in lib.functions.values) { |
| _maybeInvoke(lib, f); |