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 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 var sources = new Array(scriptNames.length); | 131 var sources = new Array(scriptNames.length); |
132 var scriptToEval = 0; | 132 var scriptToEval = 0; |
133 for (var i = 0; i < scriptNames.length; ++i) { | 133 for (var i = 0; i < scriptNames.length; ++i) { |
134 var scriptName = scriptNames[i]; | 134 var scriptName = scriptNames[i]; |
135 var sourceURL = self._importScriptPathPrefix + scriptName; | 135 var sourceURL = self._importScriptPathPrefix + scriptName; |
136 var schemaIndex = sourceURL.indexOf("://") + 3; | 136 var schemaIndex = sourceURL.indexOf("://") + 3; |
137 sourceURL = sourceURL.substring(0, schemaIndex) + normalizePath(sourceUR
L.substring(schemaIndex)); | 137 sourceURL = sourceURL.substring(0, schemaIndex) + normalizePath(sourceUR
L.substring(schemaIndex)); |
138 if (_loadedScripts[sourceURL]) | 138 if (_loadedScripts[sourceURL]) |
139 continue; | 139 continue; |
140 urls.push(sourceURL); | 140 urls.push(sourceURL); |
141 var thenCallback = scriptSourceLoaded.bind(null, i); | 141 promises.push(loadResourcePromise(sourceURL).thenOrCatch(scriptSourceLoa
ded.bind(null, i))); |
142 promises.push(loadResourcePromise(sourceURL).then(thenCallback, function
(e) { thenCallback(undefined); })); | |
143 } | 142 } |
144 return Promise.all(promises).then(undefined); | 143 return Promise.all(promises).then(undefined); |
145 | 144 |
146 /** | 145 /** |
147 * @param {number} scriptNumber | 146 * @param {number} scriptNumber |
148 * @param {string=} scriptSource | 147 * @param {string=} scriptSource |
149 */ | 148 */ |
150 function scriptSourceLoaded(scriptNumber, scriptSource) | 149 function scriptSourceLoaded(scriptNumber, scriptSource) |
151 { | 150 { |
152 sources[scriptNumber] = scriptSource || ""; | 151 sources[scriptNumber] = scriptSource || ""; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 this._cachedTypeClasses = {}; | 203 this._cachedTypeClasses = {}; |
205 | 204 |
206 /** | 205 /** |
207 * @type {!Object.<string, !Runtime.ModuleDescriptor>} | 206 * @type {!Object.<string, !Runtime.ModuleDescriptor>} |
208 */ | 207 */ |
209 this._descriptorsMap = {}; | 208 this._descriptorsMap = {}; |
210 | 209 |
211 for (var i = 0; i < descriptors.length; ++i) | 210 for (var i = 0; i < descriptors.length; ++i) |
212 this._registerModule(descriptors[i]); | 211 this._registerModule(descriptors[i]); |
213 if (coreModuleNames) | 212 if (coreModuleNames) |
214 this._loadAutoStartModules(coreModuleNames).catch(Runtime._reportError); | 213 this._loadAutoStartModules(coreModuleNames).done(); |
215 } | 214 } |
216 | 215 |
217 /** | 216 /** |
218 * @type {!Object.<string, string>} | 217 * @type {!Object.<string, string>} |
219 */ | 218 */ |
220 Runtime._queryParamsObject = { __proto__: null }; | 219 Runtime._queryParamsObject = { __proto__: null }; |
221 | 220 |
222 /** | 221 /** |
223 * @type {!Object.<string, string>} | 222 * @type {!Object.<string, string>} |
224 */ | 223 */ |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 var name = descriptor["name"]; | 334 var name = descriptor["name"]; |
336 var moduleJSON = allDescriptorsByName[name]; | 335 var moduleJSON = allDescriptorsByName[name]; |
337 if (moduleJSON) | 336 if (moduleJSON) |
338 moduleJSONPromises.push(Promise.resolve(moduleJSON)); | 337 moduleJSONPromises.push(Promise.resolve(moduleJSON)); |
339 else | 338 else |
340 moduleJSONPromises.push(loadResourcePromise(name + "/module.json
").then(JSON.parse.bind(JSON))); | 339 moduleJSONPromises.push(loadResourcePromise(name + "/module.json
").then(JSON.parse.bind(JSON))); |
341 if (descriptor["type"] === "autostart") | 340 if (descriptor["type"] === "autostart") |
342 coreModuleNames.push(name); | 341 coreModuleNames.push(name); |
343 } | 342 } |
344 | 343 |
345 Promise.all(moduleJSONPromises).then(instantiateRuntime).catch(Runtime._
reportError); | 344 Promise.all(moduleJSONPromises).then(instantiateRuntime).done(); |
346 /** | 345 /** |
347 * @param {!Array.<!Object>} moduleDescriptors | 346 * @param {!Array.<!Object>} moduleDescriptors |
348 */ | 347 */ |
349 function instantiateRuntime(moduleDescriptors) | 348 function instantiateRuntime(moduleDescriptors) |
350 { | 349 { |
351 for (var i = 0; !Runtime.isReleaseMode() && i < moduleDescriptors.le
ngth; ++i) | 350 for (var i = 0; !Runtime.isReleaseMode() && i < moduleDescriptors.le
ngth; ++i) |
352 moduleDescriptors[i]["name"] = configuration[i]["name"]; | 351 moduleDescriptors[i]["name"] = configuration[i]["name"]; |
353 self.runtime = new Runtime(moduleDescriptors, coreModuleNames); | 352 self.runtime = new Runtime(moduleDescriptors, coreModuleNames); |
354 } | 353 } |
355 } | 354 } |
(...skipping 14 matching lines...) Expand all Loading... |
370 Runtime._experimentsSetting = function() | 369 Runtime._experimentsSetting = function() |
371 { | 370 { |
372 try { | 371 try { |
373 return /** @type {!Object} */ (JSON.parse(self.localStorage && self.loca
lStorage["experiments"] ? self.localStorage["experiments"] : "{}")); | 372 return /** @type {!Object} */ (JSON.parse(self.localStorage && self.loca
lStorage["experiments"] ? self.localStorage["experiments"] : "{}")); |
374 } catch (e) { | 373 } catch (e) { |
375 console.error("Failed to parse localStorage['experiments']"); | 374 console.error("Failed to parse localStorage['experiments']"); |
376 return {}; | 375 return {}; |
377 } | 376 } |
378 } | 377 } |
379 | 378 |
380 /** | |
381 * @param {!Array.<!Promise.<T, !Error>>} promises | |
382 * @return {!Promise.<!Array.<T>>} | |
383 * @template T | |
384 */ | |
385 Runtime._some = function(promises) | |
386 { | |
387 var all = []; | |
388 var wasRejected = []; | |
389 for (var i = 0; i < promises.length; ++i) { | |
390 // Workaround closure compiler bug. | |
391 var handlerFunction = /** @type {function()} */ (handler.bind(promises[i
], i)); | |
392 all.push(promises[i].catch(handlerFunction)); | |
393 } | |
394 | |
395 return Promise.all(all).then(filterOutFailuresResults); | |
396 | |
397 /** | |
398 * @param {!Array.<T>} results | |
399 * @return {!Array.<T>} | |
400 * @template T | |
401 */ | |
402 function filterOutFailuresResults(results) | |
403 { | |
404 var filtered = []; | |
405 for (var i = 0; i < results.length; ++i) { | |
406 if (!wasRejected[i]) | |
407 filtered.push(results[i]); | |
408 } | |
409 return filtered; | |
410 } | |
411 | |
412 /** | |
413 * @this {!Promise} | |
414 * @param {number} index | |
415 * @param {!Error} e | |
416 */ | |
417 function handler(index, e) | |
418 { | |
419 wasRejected[index] = true; | |
420 console.error(e.stack); | |
421 } | |
422 } | |
423 | |
424 Runtime._console = console; | |
425 Runtime._originalAssert = console.assert; | |
426 Runtime._assert = function(value, message) | |
427 { | |
428 if (value) | |
429 return; | |
430 Runtime._originalAssert.call(Runtime._console, value, message); | |
431 } | |
432 | |
433 /** | |
434 * @param {*} e | |
435 */ | |
436 Runtime._reportError = function(e) | |
437 { | |
438 if (e instanceof Error) | |
439 console.error(e.stack); | |
440 else | |
441 console.error(e); | |
442 } | |
443 | |
444 Runtime.prototype = { | 379 Runtime.prototype = { |
445 | 380 |
446 /** | 381 /** |
447 * @param {!Runtime.ModuleDescriptor} descriptor | 382 * @param {!Runtime.ModuleDescriptor} descriptor |
448 */ | 383 */ |
449 _registerModule: function(descriptor) | 384 _registerModule: function(descriptor) |
450 { | 385 { |
451 var module = new Runtime.Module(this, descriptor); | 386 var module = new Runtime.Module(this, descriptor); |
452 this._modules.push(module); | 387 this._modules.push(module); |
453 this._modulesMap[descriptor["name"]] = module; | 388 this._modulesMap[descriptor["name"]] = module; |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
595 * @param {*} type | 530 * @param {*} type |
596 * @param {?Object=} context | 531 * @param {?Object=} context |
597 * @return {!Promise.<!Array.<!Object>>} | 532 * @return {!Promise.<!Array.<!Object>>} |
598 */ | 533 */ |
599 instancesPromise: function(type, context) | 534 instancesPromise: function(type, context) |
600 { | 535 { |
601 var extensions = this.extensions(type, context); | 536 var extensions = this.extensions(type, context); |
602 var promises = []; | 537 var promises = []; |
603 for (var i = 0; i < extensions.length; ++i) | 538 for (var i = 0; i < extensions.length; ++i) |
604 promises.push(extensions[i].instancePromise()); | 539 promises.push(extensions[i].instancePromise()); |
605 return Runtime._some(promises); | 540 return Promise.some(promises); |
606 }, | 541 }, |
607 | 542 |
608 /** | 543 /** |
609 * @param {*} type | 544 * @param {*} type |
610 * @param {?Object=} context | 545 * @param {?Object=} context |
611 * @return {!Promise.<!Object>} | 546 * @return {!Promise.<!Object>} |
612 */ | 547 */ |
613 instancePromise: function(type, context) | 548 instancePromise: function(type, context) |
614 { | 549 { |
615 var extension = this.extension(type, context); | 550 var extension = this.extension(type, context); |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
745 * @return {!Promise.<undefined>} | 680 * @return {!Promise.<undefined>} |
746 */ | 681 */ |
747 _loadScripts: function() | 682 _loadScripts: function() |
748 { | 683 { |
749 if (!this._descriptor.scripts) | 684 if (!this._descriptor.scripts) |
750 return Promise.resolve(undefined); | 685 return Promise.resolve(undefined); |
751 | 686 |
752 if (Runtime.isReleaseMode()) | 687 if (Runtime.isReleaseMode()) |
753 return loadScriptsPromise([this._name + "_module.js"]); | 688 return loadScriptsPromise([this._name + "_module.js"]); |
754 | 689 |
755 return loadScriptsPromise(this._descriptor.scripts.map(modularizeURL, th
is)).catch(Runtime._reportError); | 690 return loadScriptsPromise(this._descriptor.scripts.map(modularizeURL, th
is)).catchAndReport(); |
756 | 691 |
757 /** | 692 /** |
758 * @param {string} scriptName | 693 * @param {string} scriptName |
759 * @this {Runtime.Module} | 694 * @this {Runtime.Module} |
760 */ | 695 */ |
761 function modularizeURL(scriptName) | 696 function modularizeURL(scriptName) |
762 { | 697 { |
763 return this._name + "/" + scriptName; | 698 return this._name + "/" + scriptName; |
764 } | 699 } |
765 }, | 700 }, |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
911 self.localStorage["experiments"] = JSON.stringify(value); | 846 self.localStorage["experiments"] = JSON.stringify(value); |
912 }, | 847 }, |
913 | 848 |
914 /** | 849 /** |
915 * @param {string} experimentName | 850 * @param {string} experimentName |
916 * @param {string} experimentTitle | 851 * @param {string} experimentTitle |
917 * @param {boolean=} hidden | 852 * @param {boolean=} hidden |
918 */ | 853 */ |
919 register: function(experimentName, experimentTitle, hidden) | 854 register: function(experimentName, experimentTitle, hidden) |
920 { | 855 { |
921 Runtime._assert(!this._experimentNames[experimentName], "Duplicate regis
tration of experiment " + experimentName); | 856 console.assert(!this._experimentNames[experimentName], "Duplicate regist
ration of experiment " + experimentName); |
922 this._experimentNames[experimentName] = true; | 857 this._experimentNames[experimentName] = true; |
923 this._experiments.push(new Runtime.Experiment(this, experimentName, expe
rimentTitle, !!hidden)); | 858 this._experiments.push(new Runtime.Experiment(this, experimentName, expe
rimentTitle, !!hidden)); |
924 }, | 859 }, |
925 | 860 |
926 /** | 861 /** |
927 * @param {string} experimentName | 862 * @param {string} experimentName |
928 * @return {boolean} | 863 * @return {boolean} |
929 */ | 864 */ |
930 isEnabled: function(experimentName) | 865 isEnabled: function(experimentName) |
931 { | 866 { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
981 cleanedUpExperimentSetting[experimentName] = true; | 916 cleanedUpExperimentSetting[experimentName] = true; |
982 } | 917 } |
983 this._setExperimentsSetting(cleanedUpExperimentSetting); | 918 this._setExperimentsSetting(cleanedUpExperimentSetting); |
984 }, | 919 }, |
985 | 920 |
986 /** | 921 /** |
987 * @param {string} experimentName | 922 * @param {string} experimentName |
988 */ | 923 */ |
989 _checkExperiment: function(experimentName) | 924 _checkExperiment: function(experimentName) |
990 { | 925 { |
991 Runtime._assert(this._experimentNames[experimentName], "Unknown experime
nt " + experimentName); | 926 console.assert(this._experimentNames[experimentName], "Unknown experimen
t " + experimentName); |
992 } | 927 } |
993 } | 928 } |
994 | 929 |
995 /** | 930 /** |
996 * @constructor | 931 * @constructor |
997 * @param {!Runtime.ExperimentsSupport} experiments | 932 * @param {!Runtime.ExperimentsSupport} experiments |
998 * @param {string} name | 933 * @param {string} name |
999 * @param {string} title | 934 * @param {string} title |
1000 * @param {boolean} hidden | 935 * @param {boolean} hidden |
1001 */ | 936 */ |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1042 try { | 977 try { |
1043 var settings = JSON.parse(window.decodeURI(settingsParam)); | 978 var settings = JSON.parse(window.decodeURI(settingsParam)); |
1044 for (var key in settings) | 979 for (var key in settings) |
1045 window.localStorage[key] = settings[key]; | 980 window.localStorage[key] = settings[key]; |
1046 } catch(e) { | 981 } catch(e) { |
1047 // Ignore malformed settings. | 982 // Ignore malformed settings. |
1048 } | 983 } |
1049 } | 984 } |
1050 })();} | 985 })();} |
1051 | 986 |
| 987 /** |
| 988 * @param {string} error |
| 989 * @return {!Promise.<T>} |
| 990 * @template T |
| 991 */ |
| 992 Promise.rejectWithError = function(error) |
| 993 { |
| 994 return Promise.reject(new Error(error)); |
| 995 } |
| 996 |
| 997 /** |
| 998 * @param {function((T|undefined))} callback |
| 999 * @return {!Promise.<T>} |
| 1000 * @template T |
| 1001 */ |
| 1002 Promise.prototype.thenOrCatch = function(callback) |
| 1003 { |
| 1004 return this.then(callback, reject.bind(this)); |
| 1005 |
| 1006 /** |
| 1007 * @param {*} e |
| 1008 */ |
| 1009 function reject(e) |
| 1010 { |
| 1011 this._reportError(e); |
| 1012 callback(undefined); |
| 1013 } |
| 1014 } |
| 1015 |
| 1016 Promise.prototype.done = function() |
| 1017 { |
| 1018 this.catchAndReport(); |
| 1019 } |
| 1020 |
| 1021 Promise.prototype.catchAndReport = function() |
| 1022 { |
| 1023 return this.catch(this._reportError.bind(this)); |
| 1024 } |
| 1025 |
| 1026 /** |
| 1027 * @param {*} e |
| 1028 */ |
| 1029 Promise.prototype._reportError = function(e) |
| 1030 { |
| 1031 if (e instanceof Error) |
| 1032 console.error(e.stack); |
| 1033 else |
| 1034 console.error(e); |
| 1035 } |
| 1036 |
| 1037 /** |
| 1038 * @param {!Array.<!Promise.<T, !Error>>} promises |
| 1039 * @return {!Promise.<!Array.<T>>} |
| 1040 * @template T |
| 1041 */ |
| 1042 Promise.some = function(promises) |
| 1043 { |
| 1044 var all = []; |
| 1045 var wasRejected = []; |
| 1046 for (var i = 0; i < promises.length; ++i) { |
| 1047 // Workaround closure compiler bug. |
| 1048 var handlerFunction = /** @type {function()} */ (handler.bind(promises[i
], i)); |
| 1049 all.push(promises[i].catch(handlerFunction)); |
| 1050 } |
| 1051 |
| 1052 return Promise.all(all).then(filterOutFailuresResults); |
| 1053 |
| 1054 /** |
| 1055 * @param {!Array.<T>} results |
| 1056 * @return {!Array.<T>} |
| 1057 * @template T |
| 1058 */ |
| 1059 function filterOutFailuresResults(results) |
| 1060 { |
| 1061 var filtered = []; |
| 1062 for (var i = 0; i < results.length; ++i) { |
| 1063 if (!wasRejected[i]) |
| 1064 filtered.push(results[i]); |
| 1065 } |
| 1066 return filtered; |
| 1067 } |
| 1068 |
| 1069 /** |
| 1070 * @this {!Promise} |
| 1071 * @param {number} index |
| 1072 * @param {!Error} e |
| 1073 */ |
| 1074 function handler(index, e) |
| 1075 { |
| 1076 wasRejected[index] = true; |
| 1077 this._reportError(e); |
| 1078 } |
| 1079 } |
| 1080 |
| 1081 // FIXME: This performance optimization should be moved to blink so that all dev
elopers could enjoy it. |
| 1082 // console is retrieved with V8Window.getAttribute method which is slow. Here we
copy it to a js variable for faster access. |
| 1083 console = console; |
| 1084 console.__originalAssert = console.assert; |
| 1085 console.assert = function(value, message) |
| 1086 { |
| 1087 if (value) |
| 1088 return; |
| 1089 console.__originalAssert(value, message); |
| 1090 } |
1052 | 1091 |
1053 // This must be constructed after the query parameters have been parsed. | 1092 // This must be constructed after the query parameters have been parsed. |
1054 Runtime.experiments = new Runtime.ExperimentsSupport(); | 1093 Runtime.experiments = new Runtime.ExperimentsSupport(); |
1055 | 1094 |
1056 /** @type {!Runtime} */ | 1095 /** @type {!Runtime} */ |
1057 var runtime; | 1096 var runtime; |
OLD | NEW |