OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2014 Google Inc. All rights reserved. | 2 * Copyright (C) 2014 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 10 matching lines...) Expand all Loading... | |
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 */ | 29 */ |
30 | 30 |
31 var _importedScripts = {}; | 31 // This gets all concatenated module descriptors in the release mode. |
32 var allDescriptors = []; | |
33 var _loadedScripts = {}; | |
32 | 34 |
33 /** | 35 /** |
34 * @param {string} url | 36 * @param {string} url |
35 * @return {string} | 37 * @return {string} |
36 */ | 38 */ |
37 function loadResource(url) | 39 function loadResource(url) |
38 { | 40 { |
39 var xhr = new XMLHttpRequest(); | 41 var xhr = new XMLHttpRequest(); |
40 xhr.open("GET", url, false); | 42 xhr.open("GET", url, false); |
41 try { | 43 try { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
74 return normalizedPath; | 76 return normalizedPath; |
75 if (path[0] === "/" && normalizedPath) | 77 if (path[0] === "/" && normalizedPath) |
76 normalizedPath = "/" + normalizedPath; | 78 normalizedPath = "/" + normalizedPath; |
77 if ((path[path.length - 1] === "/") || (segments[segments.length - 1] === ". ") || (segments[segments.length - 1] === "..")) | 79 if ((path[path.length - 1] === "/") || (segments[segments.length - 1] === ". ") || (segments[segments.length - 1] === "..")) |
78 normalizedPath = normalizedPath + "/"; | 80 normalizedPath = normalizedPath + "/"; |
79 | 81 |
80 return normalizedPath; | 82 return normalizedPath; |
81 } | 83 } |
82 | 84 |
83 /** | 85 /** |
84 * This function behavior depends on the "debug_devtools" flag value. | |
85 * - In debug mode it loads scripts synchronously via xhr request. | |
86 * - In release mode every occurrence of "importScript" in the js files | |
87 * that have been whitelisted in the build system gets replaced with | |
88 * the script source code on the compilation phase. | |
89 * The build system will throw an exception if it finds an importScript() call | |
90 * in other files. | |
91 * | |
92 * To load scripts lazily in release mode call "loadScript" function. | |
93 * @param {string} scriptName | 86 * @param {string} scriptName |
94 */ | 87 */ |
95 function importScript(scriptName) | 88 function loadScript(scriptName) |
96 { | 89 { |
97 var sourceURL = self._importScriptPathPrefix + scriptName; | 90 var sourceURL = self._importScriptPathPrefix + scriptName; |
98 var schemaIndex = sourceURL.indexOf("://") + 3; | 91 var schemaIndex = sourceURL.indexOf("://") + 3; |
99 sourceURL = sourceURL.substring(0, schemaIndex) + normalizePath(sourceURL.su bstring(schemaIndex)); | 92 sourceURL = sourceURL.substring(0, schemaIndex) + normalizePath(sourceURL.su bstring(schemaIndex)); |
100 if (_importedScripts[sourceURL]) | 93 if (_loadedScripts[sourceURL]) |
101 return; | 94 return; |
102 _importedScripts[sourceURL] = true; | 95 _loadedScripts[sourceURL] = true; |
103 var scriptSource = loadResource(sourceURL); | 96 var scriptSource = loadResource(sourceURL); |
104 if (!scriptSource) | 97 if (!scriptSource) |
105 throw "empty response arrived for script '" + sourceURL + "'"; | 98 throw "empty response arrived for script '" + sourceURL + "'"; |
106 var oldPrefix = self._importScriptPathPrefix; | 99 var oldPrefix = self._importScriptPathPrefix; |
107 self._importScriptPathPrefix += scriptName.substring(0, scriptName.lastIndex Of("/") + 1); | 100 self._importScriptPathPrefix += scriptName.substring(0, scriptName.lastIndex Of("/") + 1); |
108 try { | 101 try { |
109 self.eval(scriptSource + "\n//# sourceURL=" + sourceURL); | 102 self.eval(scriptSource + "\n//# sourceURL=" + sourceURL); |
110 } finally { | 103 } finally { |
111 self._importScriptPathPrefix = oldPrefix; | 104 self._importScriptPathPrefix = oldPrefix; |
112 } | 105 } |
113 } | 106 } |
114 | 107 |
115 (function() { | 108 (function() { |
116 var baseUrl = location.origin + location.pathname; | 109 var baseUrl = location.origin + location.pathname; |
117 self._importScriptPathPrefix = baseUrl.substring(0, baseUrl.lastIndexOf("/") + 1); | 110 self._importScriptPathPrefix = baseUrl.substring(0, baseUrl.lastIndexOf("/") + 1); |
118 })(); | 111 })(); |
119 | 112 |
120 var loadScript = importScript; | |
121 | |
122 /** | 113 /** |
123 * @constructor | 114 * @constructor |
124 * @param {!Array.<!Runtime.ModuleDescriptor>} descriptors | |
125 */ | 115 */ |
126 var Runtime = function(descriptors) | 116 var Runtime = function() |
127 { | 117 { |
128 /** | 118 /** |
129 * @type {!Array.<!Runtime.Module>} | 119 * @type {!Array.<!Runtime.Module>} |
130 */ | 120 */ |
131 this._modules = []; | 121 this._modules = []; |
132 /** | 122 /** |
133 * @type {!Object.<string, !Runtime.Module>} | 123 * @type {!Object.<string, !Runtime.Module>} |
134 */ | 124 */ |
135 this._modulesMap = {}; | 125 this._modulesMap = {}; |
136 /** | 126 /** |
137 * @type {!Array.<!Runtime.Extension>} | 127 * @type {!Array.<!Runtime.Extension>} |
138 */ | 128 */ |
139 this._extensions = []; | 129 this._extensions = []; |
140 | 130 |
141 /** | 131 /** |
142 * @type {!Object.<string, !function(new:Object)>} | 132 * @type {!Object.<string, !function(new:Object)>} |
143 */ | 133 */ |
144 this._cachedTypeClasses = {}; | 134 this._cachedTypeClasses = {}; |
145 | 135 |
146 /** | 136 /** |
147 * @type {!Object.<string, !Runtime.ModuleDescriptor>} | 137 * @type {!Object.<string, !Runtime.ModuleDescriptor>} |
148 */ | 138 */ |
149 this._descriptorsMap = {}; | 139 this._descriptorsMap = {}; |
150 for (var i = 0; i < descriptors.length; ++i) | 140 for (var i = 0; i < allDescriptors.length; ++i) |
151 this._descriptorsMap[descriptors[i]["name"]] = descriptors[i]; | 141 this._descriptorsMap[allDescriptors[i]["name"]] = allDescriptors[i]; |
152 } | 142 } |
153 | 143 |
154 /** | 144 /** |
145 * @return {boolean} | |
146 */ | |
147 Runtime.isReleaseMode = function() | |
148 { | |
149 return !!allDescriptors.length; | |
150 } | |
151 | |
152 /** | |
155 * @param {string} moduleName | 153 * @param {string} moduleName |
156 * @return {!Worker} | 154 * @return {!Worker} |
157 */ | 155 */ |
158 Runtime.startWorker = function(moduleName) | 156 Runtime.startWorker = function(moduleName) |
159 { | 157 { |
160 return new Worker(moduleName + "/_module.js"); | 158 if (Runtime.isReleaseMode()) |
159 return new Worker(moduleName + ".js"); | |
160 | |
161 var content = loadResource(moduleName + "/module.json"); | |
162 if (!content) | |
vsevik
2014/08/18 12:04:31
We'd better do console.error and silently return i
apavlov
2014/08/18 12:21:43
Since we return a Worker instance, we'll have to c
| |
163 throw new Error("Worker is not defined: " + moduleName + " " + new Error ().stack); | |
164 var message = []; | |
165 var scripts = JSON.parse(content)["scripts"]; | |
166 for (var i = 0; i < scripts.length; ++i) { | |
167 var url = self._importScriptPathPrefix + moduleName + "/" + scripts[i]; | |
168 var parts = url.split("://"); | |
169 url = parts.length === 1 ? url : parts[0] + "://" + normalizePath(parts[ 1]); | |
170 message.push({ | |
171 source: loadResource(moduleName + "/" + scripts[i]), | |
172 url: url | |
173 }); | |
174 } | |
175 | |
176 /** | |
177 * @suppress {checkTypes} | |
178 */ | |
179 var loader = function() { | |
180 self.onmessage = function(event) { | |
181 self.onmessage = null; | |
182 var scripts = event.data; | |
183 for (var i = 0; i < scripts.length; ++i) { | |
184 var source = scripts[i]["source"]; | |
185 self.eval(source + "\n//# sourceURL=" + scripts[i]["url"]); | |
186 } | |
187 }; | |
188 }; | |
189 | |
190 var blob = new Blob(["(" + loader.toString() + ")()\n//# sourceURL=" + modul eName], { type: "text/javascript" }); | |
191 var workerURL = window.URL.createObjectURL(blob); | |
192 try { | |
193 var worker = new Worker(workerURL); | |
194 worker.postMessage(message); | |
195 return worker; | |
196 } finally { | |
vsevik
2014/08/18 12:04:31
I don't think we actually care about revoking obje
apavlov
2014/08/18 12:21:43
lushnikov@ asked for this. Anyway, this seems like
| |
197 window.URL.revokeObjectURL(workerURL); | |
198 } | |
161 } | 199 } |
162 | 200 |
163 Runtime.prototype = { | 201 Runtime.prototype = { |
164 /** | 202 /** |
165 * @param {!Array.<string>} configuration | 203 * @param {!Array.<string>} configuration |
166 */ | 204 */ |
167 registerModules: function(configuration) | 205 registerModules: function(configuration) |
168 { | 206 { |
169 for (var i = 0; i < configuration.length; ++i) | 207 for (var i = 0; i < configuration.length; ++i) |
170 this._registerModule(configuration[i]); | 208 this._registerModule(configuration[i]); |
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
471 Error.stackTraceLimit = 50; | 509 Error.stackTraceLimit = 50; |
472 console.assert(false, "Module " + this._name + " is loaded from itse lf: " + new Error().stack); | 510 console.assert(false, "Module " + this._name + " is loaded from itse lf: " + new Error().stack); |
473 Error.stackTraceLimit = oldStackTraceLimit; | 511 Error.stackTraceLimit = oldStackTraceLimit; |
474 return; | 512 return; |
475 } | 513 } |
476 | 514 |
477 this._isLoading = true; | 515 this._isLoading = true; |
478 var dependencies = this._descriptor.dependencies; | 516 var dependencies = this._descriptor.dependencies; |
479 for (var i = 0; dependencies && i < dependencies.length; ++i) | 517 for (var i = 0; dependencies && i < dependencies.length; ++i) |
480 this._manager.loadModule(dependencies[i]); | 518 this._manager.loadModule(dependencies[i]); |
481 if (this._descriptor.scripts) | 519 if (this._descriptor.scripts) { |
482 loadScript(this._name + "/_module.js"); | 520 if (Runtime.isReleaseMode()) { |
521 loadScript(this._name + ".js"); | |
522 } else { | |
523 var scripts = this._descriptor.scripts; | |
524 for (var i = 0; i < scripts.length; ++i) | |
525 loadScript(this._name + "/" + scripts[i]); | |
526 } | |
527 } | |
483 this._isLoading = false; | 528 this._isLoading = false; |
484 this._loaded = true; | 529 this._loaded = true; |
485 } | 530 } |
486 } | 531 } |
487 | 532 |
488 /** | 533 /** |
489 * @constructor | 534 * @constructor |
490 * @param {!Runtime.Module} module | 535 * @param {!Runtime.Module} module |
491 * @param {!Runtime.ExtensionDescriptor} descriptor | 536 * @param {!Runtime.ExtensionDescriptor} descriptor |
492 */ | 537 */ |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
558 this._instance = new constructorFunction(); | 603 this._instance = new constructorFunction(); |
559 } | 604 } |
560 return this._instance; | 605 return this._instance; |
561 } | 606 } |
562 } | 607 } |
563 | 608 |
564 /** | 609 /** |
565 * @type {!Runtime} | 610 * @type {!Runtime} |
566 */ | 611 */ |
567 var runtime; | 612 var runtime; |
OLD | NEW |