Chromium Code Reviews| 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 |