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 promises.push(loadResourcePromise(sourceURL).thenOrCatch(scriptSourceLoa ded.bind(null, i))); | 141 var thenCallback = scriptSourceLoaded.bind(null, i); |
apavlov
2014/10/31 13:26:26
Why this change? It's a very sensitive snippet tha
dgozman
2014/10/31 13:56:06
Copied from Promise.js, as this file cannot does n
| |
142 promises.push(loadResourcePromise(sourceURL).then(thenCallback, function (e) { thenCallback(undefined); })); | |
142 } | 143 } |
143 return Promise.all(promises).then(undefined); | 144 return Promise.all(promises).then(undefined); |
144 | 145 |
145 /** | 146 /** |
146 * @param {number} scriptNumber | 147 * @param {number} scriptNumber |
147 * @param {string=} scriptSource | 148 * @param {string=} scriptSource |
148 */ | 149 */ |
149 function scriptSourceLoaded(scriptNumber, scriptSource) | 150 function scriptSourceLoaded(scriptNumber, scriptSource) |
150 { | 151 { |
151 sources[scriptNumber] = scriptSource || ""; | 152 sources[scriptNumber] = scriptSource || ""; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
203 this._cachedTypeClasses = {}; | 204 this._cachedTypeClasses = {}; |
204 | 205 |
205 /** | 206 /** |
206 * @type {!Object.<string, !Runtime.ModuleDescriptor>} | 207 * @type {!Object.<string, !Runtime.ModuleDescriptor>} |
207 */ | 208 */ |
208 this._descriptorsMap = {}; | 209 this._descriptorsMap = {}; |
209 | 210 |
210 for (var i = 0; i < descriptors.length; ++i) | 211 for (var i = 0; i < descriptors.length; ++i) |
211 this._registerModule(descriptors[i]); | 212 this._registerModule(descriptors[i]); |
212 if (coreModuleNames) | 213 if (coreModuleNames) |
213 this._loadAutoStartModules(coreModuleNames).done(); | 214 this._loadAutoStartModules(coreModuleNames); |
apavlov
2014/10/31 13:26:26
This is critical to the correct rejection handling
dgozman
2014/10/31 13:56:06
Restored with a local version.
| |
214 } | 215 } |
215 | 216 |
216 /** | 217 /** |
217 * @type {!Object.<string, string>} | 218 * @type {!Object.<string, string>} |
218 */ | 219 */ |
219 Runtime._queryParamsObject = { __proto__: null }; | 220 Runtime._queryParamsObject = { __proto__: null }; |
220 | 221 |
221 /** | 222 /** |
222 * @type {!Object.<string, string>} | 223 * @type {!Object.<string, string>} |
223 */ | 224 */ |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
334 var name = descriptor["name"]; | 335 var name = descriptor["name"]; |
335 var moduleJSON = allDescriptorsByName[name]; | 336 var moduleJSON = allDescriptorsByName[name]; |
336 if (moduleJSON) | 337 if (moduleJSON) |
337 moduleJSONPromises.push(Promise.resolve(moduleJSON)); | 338 moduleJSONPromises.push(Promise.resolve(moduleJSON)); |
338 else | 339 else |
339 moduleJSONPromises.push(loadResourcePromise(name + "/module.json ").then(JSON.parse.bind(JSON))); | 340 moduleJSONPromises.push(loadResourcePromise(name + "/module.json ").then(JSON.parse.bind(JSON))); |
340 if (descriptor["type"] === "autostart") | 341 if (descriptor["type"] === "autostart") |
341 coreModuleNames.push(name); | 342 coreModuleNames.push(name); |
342 } | 343 } |
343 | 344 |
344 Promise.all(moduleJSONPromises).then(instantiateRuntime).done(); | 345 Promise.all(moduleJSONPromises).then(instantiateRuntime); |
apavlov
2014/10/31 13:26:26
Ditto
| |
345 /** | 346 /** |
346 * @param {!Array.<!Object>} moduleDescriptors | 347 * @param {!Array.<!Object>} moduleDescriptors |
347 */ | 348 */ |
348 function instantiateRuntime(moduleDescriptors) | 349 function instantiateRuntime(moduleDescriptors) |
349 { | 350 { |
350 for (var i = 0; !Runtime.isReleaseMode() && i < moduleDescriptors.le ngth; ++i) | 351 for (var i = 0; !Runtime.isReleaseMode() && i < moduleDescriptors.le ngth; ++i) |
351 moduleDescriptors[i]["name"] = configuration[i]["name"]; | 352 moduleDescriptors[i]["name"] = configuration[i]["name"]; |
352 self.runtime = new Runtime(moduleDescriptors, coreModuleNames); | 353 self.runtime = new Runtime(moduleDescriptors, coreModuleNames); |
353 } | 354 } |
354 } | 355 } |
(...skipping 14 matching lines...) Expand all Loading... | |
369 Runtime._experimentsSetting = function() | 370 Runtime._experimentsSetting = function() |
370 { | 371 { |
371 try { | 372 try { |
372 return /** @type {!Object} */ (JSON.parse(self.localStorage && self.loca lStorage["experiments"] ? self.localStorage["experiments"] : "{}")); | 373 return /** @type {!Object} */ (JSON.parse(self.localStorage && self.loca lStorage["experiments"] ? self.localStorage["experiments"] : "{}")); |
373 } catch (e) { | 374 } catch (e) { |
374 console.error("Failed to parse localStorage['experiments']"); | 375 console.error("Failed to parse localStorage['experiments']"); |
375 return {}; | 376 return {}; |
376 } | 377 } |
377 } | 378 } |
378 | 379 |
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; | |
apavlov
2014/10/31 13:26:26
I'd rather vsevik@ take a look at this, as I'm not
dgozman
2014/10/31 13:56:06
We can't do this without duplication.
| |
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 | |
379 Runtime.prototype = { | 433 Runtime.prototype = { |
380 | 434 |
381 /** | 435 /** |
382 * @param {!Runtime.ModuleDescriptor} descriptor | 436 * @param {!Runtime.ModuleDescriptor} descriptor |
383 */ | 437 */ |
384 _registerModule: function(descriptor) | 438 _registerModule: function(descriptor) |
385 { | 439 { |
386 var module = new Runtime.Module(this, descriptor); | 440 var module = new Runtime.Module(this, descriptor); |
387 this._modules.push(module); | 441 this._modules.push(module); |
388 this._modulesMap[descriptor["name"]] = module; | 442 this._modulesMap[descriptor["name"]] = module; |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
530 * @param {*} type | 584 * @param {*} type |
531 * @param {?Object=} context | 585 * @param {?Object=} context |
532 * @return {!Promise.<!Array.<!Object>>} | 586 * @return {!Promise.<!Array.<!Object>>} |
533 */ | 587 */ |
534 instancesPromise: function(type, context) | 588 instancesPromise: function(type, context) |
535 { | 589 { |
536 var extensions = this.extensions(type, context); | 590 var extensions = this.extensions(type, context); |
537 var promises = []; | 591 var promises = []; |
538 for (var i = 0; i < extensions.length; ++i) | 592 for (var i = 0; i < extensions.length; ++i) |
539 promises.push(extensions[i].instancePromise()); | 593 promises.push(extensions[i].instancePromise()); |
540 return Promise.some(promises); | 594 return Runtime._some(promises); |
541 }, | 595 }, |
542 | 596 |
543 /** | 597 /** |
544 * @param {*} type | 598 * @param {*} type |
545 * @param {?Object=} context | 599 * @param {?Object=} context |
546 * @return {!Promise.<!Object>} | 600 * @return {!Promise.<!Object>} |
547 */ | 601 */ |
548 instancePromise: function(type, context) | 602 instancePromise: function(type, context) |
549 { | 603 { |
550 var extension = this.extension(type, context); | 604 var extension = this.extension(type, context); |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
680 * @return {!Promise.<undefined>} | 734 * @return {!Promise.<undefined>} |
681 */ | 735 */ |
682 _loadScripts: function() | 736 _loadScripts: function() |
683 { | 737 { |
684 if (!this._descriptor.scripts) | 738 if (!this._descriptor.scripts) |
685 return Promise.resolve(undefined); | 739 return Promise.resolve(undefined); |
686 | 740 |
687 if (Runtime.isReleaseMode()) | 741 if (Runtime.isReleaseMode()) |
688 return loadScriptsPromise([this._name + "_module.js"]); | 742 return loadScriptsPromise([this._name + "_module.js"]); |
689 | 743 |
690 return loadScriptsPromise(this._descriptor.scripts.map(modularizeURL, th is)).catchAndReport(); | 744 return loadScriptsPromise(this._descriptor.scripts.map(modularizeURL, th is)).catch(reportError); |
691 | 745 |
692 /** | 746 /** |
693 * @param {string} scriptName | 747 * @param {string} scriptName |
694 * @this {Runtime.Module} | 748 * @this {Runtime.Module} |
695 */ | 749 */ |
696 function modularizeURL(scriptName) | 750 function modularizeURL(scriptName) |
697 { | 751 { |
698 return this._name + "/" + scriptName; | 752 return this._name + "/" + scriptName; |
699 } | 753 } |
754 | |
755 /** | |
756 * @param {*} e | |
757 */ | |
758 function reportError(e) | |
759 { | |
760 if (e instanceof Error) | |
761 console.error(e.stack); | |
762 else | |
763 console.error(e); | |
764 } | |
700 }, | 765 }, |
701 | 766 |
702 /** | 767 /** |
703 * @param {string} className | 768 * @param {string} className |
704 * @return {?Object} | 769 * @return {?Object} |
705 */ | 770 */ |
706 _instance: function(className) | 771 _instance: function(className) |
707 { | 772 { |
708 if (className in this._instanceMap) | 773 if (className in this._instanceMap) |
709 return this._instanceMap[className]; | 774 return this._instanceMap[className]; |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
846 self.localStorage["experiments"] = JSON.stringify(value); | 911 self.localStorage["experiments"] = JSON.stringify(value); |
847 }, | 912 }, |
848 | 913 |
849 /** | 914 /** |
850 * @param {string} experimentName | 915 * @param {string} experimentName |
851 * @param {string} experimentTitle | 916 * @param {string} experimentTitle |
852 * @param {boolean=} hidden | 917 * @param {boolean=} hidden |
853 */ | 918 */ |
854 register: function(experimentName, experimentTitle, hidden) | 919 register: function(experimentName, experimentTitle, hidden) |
855 { | 920 { |
856 console.assert(!this._experimentNames[experimentName], "Duplicate regist ration of experiment " + experimentName); | 921 Runtime._assert(!this._experimentNames[experimentName], "Duplicate regis tration of experiment " + experimentName); |
857 this._experimentNames[experimentName] = true; | 922 this._experimentNames[experimentName] = true; |
858 this._experiments.push(new Runtime.Experiment(this, experimentName, expe rimentTitle, !!hidden)); | 923 this._experiments.push(new Runtime.Experiment(this, experimentName, expe rimentTitle, !!hidden)); |
859 }, | 924 }, |
860 | 925 |
861 /** | 926 /** |
862 * @param {string} experimentName | 927 * @param {string} experimentName |
863 * @return {boolean} | 928 * @return {boolean} |
864 */ | 929 */ |
865 isEnabled: function(experimentName) | 930 isEnabled: function(experimentName) |
866 { | 931 { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
916 cleanedUpExperimentSetting[experimentName] = true; | 981 cleanedUpExperimentSetting[experimentName] = true; |
917 } | 982 } |
918 this._setExperimentsSetting(cleanedUpExperimentSetting); | 983 this._setExperimentsSetting(cleanedUpExperimentSetting); |
919 }, | 984 }, |
920 | 985 |
921 /** | 986 /** |
922 * @param {string} experimentName | 987 * @param {string} experimentName |
923 */ | 988 */ |
924 _checkExperiment: function(experimentName) | 989 _checkExperiment: function(experimentName) |
925 { | 990 { |
926 console.assert(this._experimentNames[experimentName], "Unknown experimen t " + experimentName); | 991 Runtime._assert(this._experimentNames[experimentName], "Unknown experime nt " + experimentName); |
927 } | 992 } |
928 } | 993 } |
929 | 994 |
930 /** | 995 /** |
931 * @constructor | 996 * @constructor |
932 * @param {!Runtime.ExperimentsSupport} experiments | 997 * @param {!Runtime.ExperimentsSupport} experiments |
933 * @param {string} name | 998 * @param {string} name |
934 * @param {string} title | 999 * @param {string} title |
935 * @param {boolean} hidden | 1000 * @param {boolean} hidden |
936 */ | 1001 */ |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
977 try { | 1042 try { |
978 var settings = JSON.parse(window.decodeURI(settingsParam)); | 1043 var settings = JSON.parse(window.decodeURI(settingsParam)); |
979 for (var key in settings) | 1044 for (var key in settings) |
980 window.localStorage[key] = settings[key]; | 1045 window.localStorage[key] = settings[key]; |
981 } catch(e) { | 1046 } catch(e) { |
982 // Ignore malformed settings. | 1047 // Ignore malformed settings. |
983 } | 1048 } |
984 } | 1049 } |
985 })();} | 1050 })();} |
986 | 1051 |
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 } | |
1091 | 1052 |
1092 // This must be constructed after the query parameters have been parsed. | 1053 // This must be constructed after the query parameters have been parsed. |
1093 Runtime.experiments = new Runtime.ExperimentsSupport(); | 1054 Runtime.experiments = new Runtime.ExperimentsSupport(); |
1094 | 1055 |
1095 /** @type {!Runtime} */ | 1056 /** @type {!Runtime} */ |
1096 var runtime; | 1057 var runtime; |
OLD | NEW |