OLD | NEW |
1 // Copyright (c) 2014, 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 | 5 /// Experimental bootstrap to initialize polymer applications. This library is |
6 /// replaced by boot.dart in the near future (see dartbug.com/18007). | 6 /// not used by default, and may be replaced by Dart code in the near future. |
7 /// | 7 /// |
8 /// This script contains logic to bootstrap polymer apps during development. It | 8 /// This script contains logic to bootstrap polymer apps during development. It |
9 /// internally discovers special Dart script tags through HTML imports, and | 9 /// internally discovers Dart script tags through HTML imports, and constructs |
10 /// constructs a new entrypoint for the application that is then launched in an | 10 /// a new entrypoint for the application that is then launched in an isolate. |
11 /// isolate. | |
12 /// | 11 /// |
13 /// For each script tag found, we will load the corresponding Dart library and | 12 /// For each script tag found, we will load the corresponding Dart library and |
14 /// execute all methods annotated with `@initMethod` and register all classes | 13 /// execute all methods annotated with `@initMethod` and register all classes |
15 /// labeled with `@CustomTag`. We keep track of the order of imports and execute | 14 /// labeled with `@CustomTag`. We keep track of the order of imports and execute |
16 /// initializers in the same order. | 15 /// initializers in the same order. |
17 /// | 16 /// |
18 /// All polymer applications use this bootstrap logic. It is included | 17 /// You can this experimental bootstrap logic by including the |
19 /// automatically when you include the polymer.html import: | 18 /// polymer_experimental.html import, instead of polymer.html: |
20 /// | 19 /// |
21 /// <link rel="import" href="packages/polymer/polymer.html"> | 20 /// <link rel="import" href="packages/polymer/polymer_experimental.html"> |
22 /// | 21 /// |
23 /// There are two important changes compared to previous versions of polymer | 22 /// This bootstrap replaces `initPolymer` so Dart code might need to be changed |
24 /// (0.10.0-pre.6 and older): | 23 /// too. If you loaded init.dart directly, you can remove it. But if you invoke |
25 /// | 24 /// initPolymer in your main, you should remove that call and change to use |
26 /// * Use 'application/dart;component=1' instead of 'application/dart': | 25 /// `@initMethod` instead. The current bootstrap doesn't support having Dart |
27 /// Dartium already limits to have a single script tag per document, but it | 26 /// script tags in the main page, so you may need to move some code into an HTML |
28 /// will be changing semantics soon and make them even stricter. Multiple | 27 /// import. For example, If you need to run some initialization code before any |
29 /// script tags are not going to be running on the same isolate after this | 28 /// other code is executed, include an HTML import to an html file with a |
30 /// change. For polymer applications we'll use a parameter on the script tags | 29 /// "application/dart" script tag that contains an initializer |
31 /// mime-type to prevent Dartium from loading them separately. Instead this | 30 /// method with the body of your old main, and make sure this tag is placed |
32 /// bootstrap script combines those special script tags and creates the | 31 /// above other html-imports that load the rest of the application. |
33 /// application Dartium needs to run. | 32 /// Initialization methods are executed in the order in which they are |
34 /// | 33 /// discovered in the HTML document. |
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. | |
54 (function() { | 34 (function() { |
55 // Only run in Dartium. | 35 // Only run in Dartium. |
56 if (navigator.userAgent.indexOf('(Dart)') === -1) return; | 36 if (navigator.userAgent.indexOf('(Dart)') === -1) return; |
57 | 37 |
58 // Extract a Dart import URL from a script tag, which is the 'src' attribute | 38 // Extract a Dart import URL from a script tag, which is the 'src' attribute |
59 // of the script tag, or a data-url with the script contents for inlined code. | 39 // of the script tag, or a data-url with the script contents for inlined code. |
60 function getScriptUrl(script) { | 40 function getScriptUrl(script) { |
61 var url = script.src; | 41 var url = script.src; |
62 if (url) { | 42 if (url) { |
63 // Normalize package: urls | 43 // Normalize package: urls |
(...skipping 20 matching lines...) Expand all Loading... |
84 } | 64 } |
85 imports[urls.length] = 'import "package:polymer/src/mirror_loader.dart";'; | 65 imports[urls.length] = 'import "package:polymer/src/mirror_loader.dart";'; |
86 var arg = urls.length == 0 ? '[]' : | 66 var arg = urls.length == 0 ? '[]' : |
87 ('[\n "' + urls.join('",\n "') + '"\n ]'); | 67 ('[\n "' + urls.join('",\n "') + '"\n ]'); |
88 return (imports.join('\n') + | 68 return (imports.join('\n') + |
89 '\n\nmain() {\n' + | 69 '\n\nmain() {\n' + |
90 ' startPolymerInDevelopment(' + arg + ');\n' + | 70 ' startPolymerInDevelopment(' + arg + ');\n' + |
91 '}\n'); | 71 '}\n'); |
92 } | 72 } |
93 | 73 |
94 function discoverScripts(content, state) { | 74 function discoverScripts(content, state, importedDoc) { |
95 if (!state) { | 75 if (!state) { |
96 // internal state tracking documents we've visited, the resulting list of | 76 // internal state tracking documents we've visited, the resulting list of |
97 // scripts, and any tags with the incorrect mime-type. | 77 // scripts, and any tags with the incorrect mime-type. |
98 state = {seen: {}, scripts: [], badTags: []}; | 78 state = {seen: {}, scripts: [], badTags: []}; |
99 } | 79 } |
100 if (!content) return state; | 80 if (!content) return state; |
101 | 81 |
102 // Note: we visit both script and link-imports together to ensure we | 82 // Note: we visit both script and link-imports together to ensure we |
103 // preserve the order of the script tags as they are discovered. | 83 // preserve the order of the script tags as they are discovered. |
104 var nodes = content.querySelectorAll('script,link[rel="import"]'); | 84 var nodes = content.querySelectorAll('script,link[rel="import"]'); |
105 for (var i = 0; i < nodes.length; i++) { | 85 for (var i = 0; i < nodes.length; i++) { |
106 var node = nodes[i]; | 86 var node = nodes[i]; |
107 if (node instanceof HTMLLinkElement) { | 87 if (node instanceof HTMLLinkElement) { |
108 // TODO(jmesserly): figure out why ".import" fails in content_shell but | 88 // TODO(jmesserly): figure out why ".import" fails in content_shell but |
109 // works in Dartium. | 89 // works in Dartium. |
110 if (node.import && node.import.href) node = node.import; | 90 if (node.import && node.import.href) node = node.import; |
111 | 91 |
112 if (state.seen[node.href]) continue; | 92 if (state.seen[node.href]) continue; |
113 state.seen[node.href] = node; | 93 state.seen[node.href] = node; |
114 discoverScripts(node.import, state); | 94 discoverScripts(node.import, state, true); |
115 } else if (node instanceof HTMLScriptElement) { | 95 } else if (node instanceof HTMLScriptElement) { |
116 if (node.type == 'application/dart;component=1') { | 96 if (node.type != 'application/dart') continue; |
| 97 if (importedDoc) { |
117 state.scripts.push(getScriptUrl(node)); | 98 state.scripts.push(getScriptUrl(node)); |
118 } | 99 } else { |
119 if (node.type == 'application/dart') { | |
120 state.badTags.push(node); | 100 state.badTags.push(node); |
121 } | 101 } |
122 } | 102 } |
123 } | 103 } |
124 return state; | 104 return state; |
125 } | 105 } |
126 | 106 |
127 // TODO(jmesserly): we're using this function because DOMContentLoaded can | 107 // TODO(jmesserly): we're using this function because DOMContentLoaded can |
128 // be fired too soon: https://www.w3.org/Bugs/Public/show_bug.cgi?id=23526 | 108 // be fired too soon: https://www.w3.org/Bugs/Public/show_bug.cgi?id=23526 |
129 HTMLImports.whenImportsReady(function() { | 109 HTMLImports.whenImportsReady(function() { |
130 // Append a new script tag that initializes everything. | 110 // Append a new script tag that initializes everything. |
131 var newScript = document.createElement('script'); | 111 var newScript = document.createElement('script'); |
132 newScript.type = "application/dart"; | 112 newScript.type = "application/dart"; |
133 | 113 |
134 var results = discoverScripts(document); | 114 var results = discoverScripts(document); |
135 if (results.badTags.length > 0) { | 115 if (results.badTags.length > 0) { |
136 console.warn('Dartium currently only allows a single Dart script tag ' | 116 console.warn('The experimental polymer boostrap does not support ' |
137 + 'per application, and in the future it will run them in ' | 117 + 'having script tags in the main document. You can move the script ' |
138 + 'separtate isolates. To prepare for this all the following ' | 118 + 'tag to an HTML import instead. Also make sure your script tag ' |
139 + 'script tags need to be updated to use the mime-type ' | 119 + 'doesn\'t have a main, but a top-level method marked with ' |
140 + '"application/dart;component=1" instead of "application/dart":'); | 120 + '@initMethod instead'); |
141 for (var i = 0; i < results.badTags.length; i++) { | 121 for (var i = 0; i < results.badTags.length; i++) { |
142 console.warn(results.badTags[i]); | 122 console.warn(results.badTags[i]); |
143 } | 123 } |
144 } | 124 } |
145 newScript.textContent = createMain(results.scripts); | 125 newScript.textContent = createMain(results.scripts); |
146 document.body.appendChild(newScript); | 126 document.body.appendChild(newScript); |
147 }); | 127 }); |
148 })(); | 128 })(); |
OLD | NEW |