OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
| 5 /// Bootstrap to initialize polymer applications. This library is will be |
| 6 /// replaced by boot.dart in the near future (see dartbug.com/18007). |
| 7 /// |
| 8 /// This script contains logic to bootstrap polymer apps during development. It |
| 9 /// internally discovers special Dart script tags through HTML imports, and |
| 10 /// constructs a new entrypoint for the application that is then launched in an |
| 11 /// isolate. |
| 12 /// |
| 13 /// For each script tag found, we will load the corresponding Dart library and |
| 14 /// execute all methods annotated with `@initMethod` and register all classes |
| 15 /// labeled with `@CustomTag`. We keep track of the order of imports and execute |
| 16 /// initializers in the same order. |
| 17 /// |
| 18 /// All polymer applications use this bootstrap logic. It is included |
| 19 /// automatically when you include the polymer.html import: |
| 20 /// |
| 21 /// <link rel="import" href="packages/polymer/polymer.html"> |
| 22 /// |
| 23 /// There are two important changes compared to previous versions of polymer |
| 24 /// (0.10.0-pre.6 and older): |
| 25 /// |
| 26 /// * Use 'application/dart;component=1' instead of 'application/dart': |
| 27 /// Dartium already limits to have a single script tag per document, but it |
| 28 /// will be changing semantics soon and make them even stricter. Multiple |
| 29 /// script tags are not going to be running on the same isolate after this |
| 30 /// change. For polymer applications we'll use a parameter on the script tags |
| 31 /// mime-type to prevent Dartium from loading them separately. Instead this |
| 32 /// bootstrap script combines those special script tags and creates the |
| 33 /// application Dartium needs to run. |
| 34 /// |
| 35 // If you had: |
| 36 /// |
| 37 /// <polymer-element name="x-foo"> ... |
| 38 /// <script type="application/dart" src="x_foo.dart'></script> |
| 39 /// |
| 40 /// Now you need to write: |
| 41 /// |
| 42 /// <polymer-element name="x-foo"> ... |
| 43 /// <script type="application/dart;component=1" src="x_foo.dart'></script> |
| 44 /// |
| 45 /// * `initPolymer` is gone: we used to initialize applications in two |
| 46 /// possible ways: using `init.dart` or invoking initPolymer in your main. Any |
| 47 /// of these initialization patterns can be replaced to use an `@initMethod` |
| 48 /// instead. For example, If you need to run some initialization code before |
| 49 /// any other code is executed, include a "application/dart;component=1" |
| 50 /// script tag that contains an initializer method with the body of your old |
| 51 /// main, and make sure this tag is placed above other html-imports that load |
| 52 /// the rest of the application. Initialization methods are executed in the |
| 53 /// order in which they are discovered in the HTML document. |
5 (function() { | 54 (function() { |
6 console.error('"boot.js" is now deprecated. Instead, you can initialize ' | 55 // Only run in Dartium. |
7 + 'your polymer application by adding the following tags: \'' + | 56 if (navigator.userAgent.indexOf('(Dart)') === -1) return; |
8 + '<script type="application/dart">export "package:polymer/init.dart";' | 57 |
9 + '</script><script src="packages/browser/dart.js"></script>\'. ' | 58 // Extract a Dart import URL from a script tag, which is the 'src' attribute |
10 + 'Make sure these script tags come after all HTML imports.'); | 59 // of the script tag, or a data-url with the script contents for inlined code. |
| 60 function getScriptUrl(script) { |
| 61 var url = script.src; |
| 62 if (url) { |
| 63 // Normalize package: urls |
| 64 var index = url.indexOf('packages/'); |
| 65 if (index == 0 || (index > 0 && url[index - 1] == '/')) { |
| 66 url = "package:" + url.slice(index + 9); |
| 67 } |
| 68 return url; |
| 69 } |
| 70 |
| 71 // TODO(sigmund): change back to application/dart: using application/json is |
| 72 // wrong but it hides a warning in Dartium (dartbug.com/18000). |
| 73 return "data:application/json;base64," + window.btoa(script.textContent); |
| 74 } |
| 75 |
| 76 // Creates a Dart program that imports [urls] and passes them to |
| 77 // startPolymerInDevelopment, which in turn will invoke methods marked with |
| 78 // @initMethod, and register any custom tag labeled with @CustomTag in those |
| 79 // libraries. |
| 80 function createMain(urls, mainUrl) { |
| 81 var imports = Array(urls.length + 1); |
| 82 for (var i = 0; i < urls.length; ++i) { |
| 83 imports[i] = 'import "' + urls[i] + '" as i' + i + ';'; |
| 84 } |
| 85 imports[urls.length] = 'import "package:polymer/src/mirror_loader.dart";'; |
| 86 var arg = urls.length == 0 ? '[]' : |
| 87 ('[\n "' + urls.join('",\n "') + '"\n ]'); |
| 88 return (imports.join('\n') + |
| 89 '\n\nmain() {\n' + |
| 90 ' startPolymerInDevelopment(' + arg + ');\n' + |
| 91 '}\n'); |
| 92 } |
| 93 |
| 94 function discoverScripts(content, state) { |
| 95 if (!state) { |
| 96 // internal state tracking documents we've visited, the resulting list of |
| 97 // scripts, and any tags with the incorrect mime-type. |
| 98 state = {seen: {}, scripts: [], badTags: []}; |
| 99 } |
| 100 if (!content) return state; |
| 101 |
| 102 // Note: we visit both script and link-imports together to ensure we |
| 103 // preserve the order of the script tags as they are discovered. |
| 104 var nodes = content.querySelectorAll('script,link[rel="import"]'); |
| 105 for (var i = 0; i < nodes.length; i++) { |
| 106 var node = nodes[i]; |
| 107 if (node instanceof HTMLLinkElement) { |
| 108 // TODO(jmesserly): figure out why ".import" fails in content_shell but |
| 109 // works in Dartium. |
| 110 if (node.import && node.import.href) node = node.import; |
| 111 |
| 112 if (state.seen[node.href]) continue; |
| 113 state.seen[node.href] = node; |
| 114 discoverScripts(node.import, state); |
| 115 } else if (node instanceof HTMLScriptElement) { |
| 116 if (node.type == 'application/dart;component=1') { |
| 117 state.scripts.push(getScriptUrl(node)); |
| 118 } |
| 119 if (node.type == 'application/dart') { |
| 120 state.badTags.push(node); |
| 121 } |
| 122 } |
| 123 } |
| 124 return state; |
| 125 } |
| 126 |
| 127 // Waits for all imports to be loaded, then calls [callback]. |
| 128 function onImportsReady(callback) { |
| 129 // Note: we only need to check the main document because an import is loaded |
| 130 // only when all it's transitive imports are loaded too. |
| 131 var nodes = document.querySelectorAll('link[rel="import"]'); |
| 132 var total = nodes.length; |
| 133 var loaded = 0; |
| 134 function incrementLoaded() { |
| 135 loaded++; |
| 136 if (loaded == total) callback(); |
| 137 } |
| 138 |
| 139 for (var i = 0; i < total; i++) { |
| 140 if (nodes[i].import) { |
| 141 incrementLoaded(); |
| 142 } else { |
| 143 nodes[i].addEventListener('load', incrementLoaded); |
| 144 } |
| 145 } |
| 146 } |
| 147 |
| 148 onImportsReady(function () { |
| 149 // Append a new script tag that initializes everything. |
| 150 var newScript = document.createElement('script'); |
| 151 newScript.type = "application/dart"; |
| 152 |
| 153 var results = discoverScripts(document); |
| 154 if (results.badTags.length > 0) { |
| 155 console.warn('Dartium currently only allows a single Dart script tag ' |
| 156 + 'per application, and in the future it will run them in ' |
| 157 + 'separtate isolates. To prepare for this all the following ' |
| 158 + 'script tags need to be updated to use the mime-type ' |
| 159 + '"application/dart;component=1" instead of "application/dart":'); |
| 160 for (var i = 0; i < results.badTags.length; i++) { |
| 161 console.warn(results.badTags[i]); |
| 162 } |
| 163 |
| 164 } |
| 165 newScript.textContent = createMain(results.scripts); |
| 166 document.body.appendChild(newScript); |
| 167 }); |
11 })(); | 168 })(); |
OLD | NEW |