]>
Commit | Line | Data |
---|---|---|
399fa2ee SR |
1 | (function (global, factory) { |
2 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : | |
3 | typeof define === 'function' && define.amd ? define(factory) : | |
4 | (global.BrowserESModuleLoader = factory()); | |
5 | }(this, (function () { 'use strict'; | |
6 | ||
7 | /* | |
8 | * Environment | |
9 | */ | |
10 | var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined'; | |
11 | var isNode = typeof process !== 'undefined' && process.versions && process.versions.node; | |
12 | var isWindows = typeof process !== 'undefined' && typeof process.platform === 'string' && process.platform.match(/^win/); | |
13 | ||
14 | var envGlobal = typeof self !== 'undefined' ? self : global; | |
15 | /* | |
16 | * Simple Symbol() shim | |
17 | */ | |
18 | var hasSymbol = typeof Symbol !== 'undefined'; | |
19 | function createSymbol (name) { | |
20 | return hasSymbol ? Symbol() : '@@' + name; | |
21 | } | |
22 | ||
23 | ||
24 | ||
25 | ||
26 | ||
27 | /* | |
28 | * Environment baseURI | |
29 | */ | |
30 | var baseURI; | |
31 | ||
32 | // environent baseURI detection | |
33 | if (typeof document != 'undefined' && document.getElementsByTagName) { | |
34 | baseURI = document.baseURI; | |
35 | ||
36 | if (!baseURI) { | |
37 | var bases = document.getElementsByTagName('base'); | |
38 | baseURI = bases[0] && bases[0].href || window.location.href; | |
39 | } | |
40 | } | |
41 | else if (typeof location != 'undefined') { | |
42 | baseURI = location.href; | |
43 | } | |
44 | ||
45 | // sanitize out the hash and querystring | |
46 | if (baseURI) { | |
47 | baseURI = baseURI.split('#')[0].split('?')[0]; | |
48 | var slashIndex = baseURI.lastIndexOf('/'); | |
49 | if (slashIndex !== -1) | |
50 | baseURI = baseURI.substr(0, slashIndex + 1); | |
51 | } | |
52 | else if (typeof process !== 'undefined' && process.cwd) { | |
53 | baseURI = 'file://' + (isWindows ? '/' : '') + process.cwd(); | |
54 | if (isWindows) | |
55 | baseURI = baseURI.replace(/\\/g, '/'); | |
56 | } | |
57 | else { | |
58 | throw new TypeError('No environment baseURI'); | |
59 | } | |
60 | ||
61 | // ensure baseURI has trailing "/" | |
62 | if (baseURI[baseURI.length - 1] !== '/') | |
63 | baseURI += '/'; | |
64 | ||
65 | /* | |
66 | * LoaderError with chaining for loader stacks | |
67 | */ | |
68 | var errArgs = new Error(0, '_').fileName == '_'; | |
69 | function LoaderError__Check_error_message_for_loader_stack (childErr, newMessage) { | |
70 | // Convert file:/// URLs to paths in Node | |
71 | if (!isBrowser) | |
72 | newMessage = newMessage.replace(isWindows ? /file:\/\/\//g : /file:\/\//g, ''); | |
73 | ||
74 | var message = (childErr.message || childErr) + '\n ' + newMessage; | |
75 | ||
76 | var err; | |
77 | if (errArgs && childErr.fileName) | |
78 | err = new Error(message, childErr.fileName, childErr.lineNumber); | |
79 | else | |
80 | err = new Error(message); | |
81 | ||
82 | ||
83 | var stack = childErr.originalErr ? childErr.originalErr.stack : childErr.stack; | |
84 | ||
85 | if (isNode) | |
86 | // node doesn't show the message otherwise | |
87 | err.stack = message + '\n ' + stack; | |
88 | else | |
89 | err.stack = stack; | |
90 | ||
91 | err.originalErr = childErr.originalErr || childErr; | |
92 | ||
93 | return err; | |
94 | } | |
95 | ||
96 | var resolvedPromise = Promise.resolve(); | |
97 | ||
98 | /* | |
99 | * Simple Array values shim | |
100 | */ | |
101 | function arrayValues (arr) { | |
102 | if (arr.values) | |
103 | return arr.values(); | |
104 | ||
105 | if (typeof Symbol === 'undefined' || !Symbol.iterator) | |
106 | throw new Error('Symbol.iterator not supported in this browser'); | |
107 | ||
108 | var iterable = {}; | |
109 | iterable[Symbol.iterator] = function () { | |
110 | var keys = Object.keys(arr); | |
111 | var keyIndex = 0; | |
112 | return { | |
113 | next: function () { | |
114 | if (keyIndex < keys.length) | |
115 | return { | |
116 | value: arr[keys[keyIndex++]], | |
117 | done: false | |
118 | }; | |
119 | else | |
120 | return { | |
121 | value: undefined, | |
122 | done: true | |
123 | }; | |
124 | } | |
125 | }; | |
126 | }; | |
127 | return iterable; | |
128 | } | |
129 | ||
130 | /* | |
131 | * 3. Reflect.Loader | |
132 | * | |
133 | * We skip the entire native internal pipeline, just providing the bare API | |
134 | */ | |
135 | // 3.1.1 | |
136 | function Loader () { | |
137 | this.registry = new Registry(); | |
138 | } | |
139 | // 3.3.1 | |
140 | Loader.prototype.constructor = Loader; | |
141 | ||
142 | function ensureInstantiated (module) { | |
143 | if (!(module instanceof ModuleNamespace)) | |
144 | throw new TypeError('Module instantiation did not return a valid namespace object.'); | |
145 | return module; | |
146 | } | |
147 | ||
148 | // 3.3.2 | |
149 | Loader.prototype.import = function (key, parent) { | |
150 | if (typeof key !== 'string') | |
151 | throw new TypeError('Loader import method must be passed a module key string'); | |
152 | // custom resolveInstantiate combined hook for better perf | |
153 | var loader = this; | |
154 | return resolvedPromise | |
155 | .then(function () { | |
156 | return loader[RESOLVE_INSTANTIATE](key, parent); | |
157 | }) | |
158 | .then(ensureInstantiated) | |
159 | //.then(Module.evaluate) | |
160 | .catch(function (err) { | |
161 | throw LoaderError__Check_error_message_for_loader_stack(err, 'Loading ' + key + (parent ? ' from ' + parent : '')); | |
162 | }); | |
163 | }; | |
164 | // 3.3.3 | |
165 | var RESOLVE = Loader.resolve = createSymbol('resolve'); | |
166 | ||
167 | /* | |
168 | * Combined resolve / instantiate hook | |
169 | * | |
170 | * Not in current reduced spec, but necessary to separate RESOLVE from RESOLVE + INSTANTIATE as described | |
171 | * in the spec notes of this repo to ensure that loader.resolve doesn't instantiate when not wanted. | |
172 | * | |
173 | * We implement RESOLVE_INSTANTIATE as a single hook instead of a separate INSTANTIATE in order to avoid | |
174 | * the need for double registry lookups as a performance optimization. | |
175 | */ | |
176 | var RESOLVE_INSTANTIATE = Loader.resolveInstantiate = createSymbol('resolveInstantiate'); | |
177 | ||
178 | // default resolveInstantiate is just to call resolve and then get from the registry | |
179 | // this provides compatibility for the resolveInstantiate optimization | |
180 | Loader.prototype[RESOLVE_INSTANTIATE] = function (key, parent) { | |
181 | var loader = this; | |
182 | return loader.resolve(key, parent) | |
183 | .then(function (resolved) { | |
184 | return loader.registry.get(resolved); | |
185 | }); | |
186 | }; | |
187 | ||
188 | function ensureResolution (resolvedKey) { | |
189 | if (resolvedKey === undefined) | |
190 | throw new RangeError('No resolution found.'); | |
191 | return resolvedKey; | |
192 | } | |
193 | ||
194 | Loader.prototype.resolve = function (key, parent) { | |
195 | var loader = this; | |
196 | return resolvedPromise | |
197 | .then(function() { | |
198 | return loader[RESOLVE](key, parent); | |
199 | }) | |
200 | .then(ensureResolution) | |
201 | .catch(function (err) { | |
202 | throw LoaderError__Check_error_message_for_loader_stack(err, 'Resolving ' + key + (parent ? ' to ' + parent : '')); | |
203 | }); | |
204 | }; | |
205 | ||
206 | // 3.3.4 (import without evaluate) | |
207 | // this is not documented because the use of deferred evaluation as in Module.evaluate is not | |
208 | // documented, as it is not considered a stable feature to be encouraged | |
209 | // Loader.prototype.load may well be deprecated if this stays disabled | |
210 | /* Loader.prototype.load = function (key, parent) { | |
211 | return Promise.resolve(this[RESOLVE_INSTANTIATE](key, parent || this.key)) | |
212 | .catch(function (err) { | |
213 | throw addToError(err, 'Loading ' + key + (parent ? ' from ' + parent : '')); | |
214 | }); | |
215 | }; */ | |
216 | ||
217 | /* | |
218 | * 4. Registry | |
219 | * | |
220 | * Instead of structuring through a Map, just use a dictionary object | |
221 | * We throw for construction attempts so this doesn't affect the public API | |
222 | * | |
223 | * Registry has been adjusted to use Namespace objects over ModuleStatus objects | |
224 | * as part of simplifying loader API implementation | |
225 | */ | |
226 | var iteratorSupport = typeof Symbol !== 'undefined' && Symbol.iterator; | |
227 | var REGISTRY = createSymbol('registry'); | |
228 | function Registry() { | |
229 | this[REGISTRY] = {}; | |
230 | this._registry = REGISTRY; | |
231 | } | |
232 | // 4.4.1 | |
233 | if (iteratorSupport) { | |
234 | // 4.4.2 | |
235 | Registry.prototype[Symbol.iterator] = function () { | |
236 | return this.entries()[Symbol.iterator](); | |
237 | }; | |
238 | ||
239 | // 4.4.3 | |
240 | Registry.prototype.entries = function () { | |
241 | var registry = this[REGISTRY]; | |
242 | return arrayValues(Object.keys(registry).map(function (key) { | |
243 | return [key, registry[key]]; | |
244 | })); | |
245 | }; | |
246 | } | |
247 | ||
248 | // 4.4.4 | |
249 | Registry.prototype.keys = function () { | |
250 | return arrayValues(Object.keys(this[REGISTRY])); | |
251 | }; | |
252 | // 4.4.5 | |
253 | Registry.prototype.values = function () { | |
254 | var registry = this[REGISTRY]; | |
255 | return arrayValues(Object.keys(registry).map(function (key) { | |
256 | return registry[key]; | |
257 | })); | |
258 | }; | |
259 | // 4.4.6 | |
260 | Registry.prototype.get = function (key) { | |
261 | return this[REGISTRY][key]; | |
262 | }; | |
263 | // 4.4.7 | |
264 | Registry.prototype.set = function (key, namespace) { | |
265 | if (!(namespace instanceof ModuleNamespace)) | |
266 | throw new Error('Registry must be set with an instance of Module Namespace'); | |
267 | this[REGISTRY][key] = namespace; | |
268 | return this; | |
269 | }; | |
270 | // 4.4.8 | |
271 | Registry.prototype.has = function (key) { | |
272 | return Object.hasOwnProperty.call(this[REGISTRY], key); | |
273 | }; | |
274 | // 4.4.9 | |
275 | Registry.prototype.delete = function (key) { | |
276 | if (Object.hasOwnProperty.call(this[REGISTRY], key)) { | |
277 | delete this[REGISTRY][key]; | |
278 | return true; | |
279 | } | |
280 | return false; | |
281 | }; | |
282 | ||
283 | /* | |
284 | * Simple ModuleNamespace Exotic object based on a baseObject | |
285 | * We export this for allowing a fast-path for module namespace creation over Module descriptors | |
286 | */ | |
287 | // var EVALUATE = createSymbol('evaluate'); | |
288 | var BASE_OBJECT = createSymbol('baseObject'); | |
289 | ||
290 | // 8.3.1 Reflect.Module | |
291 | /* | |
292 | * Best-effort simplified non-spec implementation based on | |
293 | * a baseObject referenced via getters. | |
294 | * | |
295 | * Allows: | |
296 | * | |
297 | * loader.registry.set('x', new Module({ default: 'x' })); | |
298 | * | |
299 | * Optional evaluation function provides experimental Module.evaluate | |
300 | * support for non-executed modules in registry. | |
301 | */ | |
302 | function ModuleNamespace (baseObject/*, evaluate*/) { | |
303 | Object.defineProperty(this, BASE_OBJECT, { | |
304 | value: baseObject | |
305 | }); | |
306 | ||
307 | // evaluate defers namespace population | |
308 | /* if (evaluate) { | |
309 | Object.defineProperty(this, EVALUATE, { | |
310 | value: evaluate, | |
311 | configurable: true, | |
312 | writable: true | |
313 | }); | |
314 | } | |
315 | else { */ | |
316 | Object.keys(baseObject).forEach(extendNamespace, this); | |
317 | //} | |
318 | } | |
319 | // 8.4.2 | |
320 | ModuleNamespace.prototype = Object.create(null); | |
321 | ||
322 | if (typeof Symbol !== 'undefined' && Symbol.toStringTag) | |
323 | Object.defineProperty(ModuleNamespace.prototype, Symbol.toStringTag, { | |
324 | value: 'Module' | |
325 | }); | |
326 | ||
327 | function extendNamespace (key) { | |
328 | Object.defineProperty(this, key, { | |
329 | enumerable: true, | |
330 | get: function () { | |
331 | return this[BASE_OBJECT][key]; | |
332 | } | |
333 | }); | |
334 | } | |
335 | ||
336 | /* function doEvaluate (evaluate, context) { | |
337 | try { | |
338 | evaluate.call(context); | |
339 | } | |
340 | catch (e) { | |
341 | return e; | |
342 | } | |
343 | } | |
344 | ||
345 | // 8.4.1 Module.evaluate... not documented or used because this is potentially unstable | |
346 | Module.evaluate = function (ns) { | |
347 | var evaluate = ns[EVALUATE]; | |
348 | if (evaluate) { | |
349 | ns[EVALUATE] = undefined; | |
350 | var err = doEvaluate(evaluate); | |
351 | if (err) { | |
352 | // cache the error | |
353 | ns[EVALUATE] = function () { | |
354 | throw err; | |
355 | }; | |
356 | throw err; | |
357 | } | |
358 | Object.keys(ns[BASE_OBJECT]).forEach(extendNamespace, ns); | |
359 | } | |
360 | // make chainable | |
361 | return ns; | |
362 | }; */ | |
363 | ||
364 | /* | |
365 | * Optimized URL normalization assuming a syntax-valid URL parent | |
366 | */ | |
367 | function throwResolveError (relUrl, parentUrl) { | |
368 | throw new RangeError('Unable to resolve "' + relUrl + '" to ' + parentUrl); | |
369 | } | |
370 | function resolveIfNotPlain (relUrl, parentUrl) { | |
371 | relUrl = relUrl.trim(); | |
372 | var parentProtocol = parentUrl && parentUrl.substr(0, parentUrl.indexOf(':') + 1); | |
373 | ||
374 | var firstChar = relUrl[0]; | |
375 | var secondChar = relUrl[1]; | |
376 | ||
377 | // protocol-relative | |
378 | if (firstChar === '/' && secondChar === '/') { | |
379 | if (!parentProtocol) | |
380 | throwResolveError(relUrl, parentUrl); | |
381 | return parentProtocol + relUrl; | |
382 | } | |
383 | // relative-url | |
384 | else if (firstChar === '.' && (secondChar === '/' || secondChar === '.' && (relUrl[2] === '/' || relUrl.length === 2) || relUrl.length === 1) | |
385 | || firstChar === '/') { | |
386 | var parentIsPlain = !parentProtocol || parentUrl[parentProtocol.length] !== '/'; | |
387 | ||
388 | // read pathname from parent if a URL | |
389 | // pathname taken to be part after leading "/" | |
390 | var pathname; | |
391 | if (parentIsPlain) { | |
392 | // resolving to a plain parent -> skip standard URL prefix, and treat entire parent as pathname | |
393 | if (parentUrl === undefined) | |
394 | throwResolveError(relUrl, parentUrl); | |
395 | pathname = parentUrl; | |
396 | } | |
397 | else if (parentUrl[parentProtocol.length + 1] === '/') { | |
398 | // resolving to a :// so we need to read out the auth and host | |
399 | if (parentProtocol !== 'file:') { | |
400 | pathname = parentUrl.substr(parentProtocol.length + 2); | |
401 | pathname = pathname.substr(pathname.indexOf('/') + 1); | |
402 | } | |
403 | else { | |
404 | pathname = parentUrl.substr(8); | |
405 | } | |
406 | } | |
407 | else { | |
408 | // resolving to :/ so pathname is the /... part | |
409 | pathname = parentUrl.substr(parentProtocol.length + 1); | |
410 | } | |
411 | ||
412 | if (firstChar === '/') { | |
413 | if (parentIsPlain) | |
414 | throwResolveError(relUrl, parentUrl); | |
415 | else | |
416 | return parentUrl.substr(0, parentUrl.length - pathname.length - 1) + relUrl; | |
417 | } | |
418 | ||
419 | // join together and split for removal of .. and . segments | |
420 | // looping the string instead of anything fancy for perf reasons | |
421 | // '../../../../../z' resolved to 'x/y' is just 'z' regardless of parentIsPlain | |
422 | var segmented = pathname.substr(0, pathname.lastIndexOf('/') + 1) + relUrl; | |
423 | ||
424 | var output = []; | |
425 | var segmentIndex = undefined; | |
426 | ||
427 | for (var i = 0; i < segmented.length; i++) { | |
428 | // busy reading a segment - only terminate on '/' | |
429 | if (segmentIndex !== undefined) { | |
430 | if (segmented[i] === '/') { | |
431 | output.push(segmented.substr(segmentIndex, i - segmentIndex + 1)); | |
432 | segmentIndex = undefined; | |
433 | } | |
434 | continue; | |
435 | } | |
436 | ||
437 | // new segment - check if it is relative | |
438 | if (segmented[i] === '.') { | |
439 | // ../ segment | |
440 | if (segmented[i + 1] === '.' && (segmented[i + 2] === '/' || i === segmented.length - 2)) { | |
441 | output.pop(); | |
442 | i += 2; | |
443 | } | |
444 | // ./ segment | |
445 | else if (segmented[i + 1] === '/' || i === segmented.length - 1) { | |
446 | i += 1; | |
447 | } | |
448 | else { | |
449 | // the start of a new segment as below | |
450 | segmentIndex = i; | |
451 | continue; | |
452 | } | |
453 | ||
454 | // this is the plain URI backtracking error (../, package:x -> error) | |
455 | if (parentIsPlain && output.length === 0) | |
456 | throwResolveError(relUrl, parentUrl); | |
457 | ||
458 | // trailing . or .. segment | |
459 | if (i === segmented.length) | |
460 | output.push(''); | |
461 | continue; | |
462 | } | |
463 | ||
464 | // it is the start of a new segment | |
465 | segmentIndex = i; | |
466 | } | |
467 | // finish reading out the last segment | |
468 | if (segmentIndex !== undefined) | |
469 | output.push(segmented.substr(segmentIndex, segmented.length - segmentIndex)); | |
470 | ||
471 | return parentUrl.substr(0, parentUrl.length - pathname.length) + output.join(''); | |
472 | } | |
473 | ||
474 | // sanitizes and verifies (by returning undefined if not a valid URL-like form) | |
475 | // Windows filepath compatibility is an added convenience here | |
476 | var protocolIndex = relUrl.indexOf(':'); | |
477 | if (protocolIndex !== -1) { | |
478 | if (isNode) { | |
479 | // C:\x becomes file:///c:/x (we don't support C|\x) | |
480 | if (relUrl[1] === ':' && relUrl[2] === '\\' && relUrl[0].match(/[a-z]/i)) | |
481 | return 'file:///' + relUrl.replace(/\\/g, '/'); | |
482 | } | |
483 | return relUrl; | |
484 | } | |
485 | } | |
486 | ||
487 | /* | |
488 | * Register Loader | |
489 | * | |
490 | * Builds directly on top of loader polyfill to provide: | |
491 | * - loader.register support | |
492 | * - hookable higher-level resolve | |
493 | * - instantiate hook returning a ModuleNamespace or undefined for es module loading | |
494 | * - loader error behaviour as in HTML and loader specs, clearing failed modules from registration cache synchronously | |
495 | * - build tracing support by providing a .trace=true and .loads object format | |
496 | */ | |
497 | ||
498 | var REGISTER_INTERNAL = createSymbol('register-internal'); | |
499 | ||
500 | function RegisterLoader$1 () { | |
501 | Loader.call(this); | |
502 | ||
503 | var registryDelete = this.registry.delete; | |
504 | this.registry.delete = function (key) { | |
505 | var deleted = registryDelete.call(this, key); | |
506 | ||
507 | // also delete from register registry if linked | |
508 | if (records.hasOwnProperty(key) && !records[key].linkRecord) | |
509 | delete records[key]; | |
510 | ||
511 | return deleted; | |
512 | }; | |
513 | ||
514 | var records = {}; | |
515 | ||
516 | this[REGISTER_INTERNAL] = { | |
517 | // last anonymous System.register call | |
518 | lastRegister: undefined, | |
519 | // in-flight es module load records | |
520 | records: records | |
521 | }; | |
522 | ||
523 | // tracing | |
524 | this.trace = false; | |
525 | } | |
526 | ||
527 | RegisterLoader$1.prototype = Object.create(Loader.prototype); | |
528 | RegisterLoader$1.prototype.constructor = RegisterLoader$1; | |
529 | ||
530 | var INSTANTIATE = RegisterLoader$1.instantiate = createSymbol('instantiate'); | |
531 | ||
532 | // default normalize is the WhatWG style normalizer | |
533 | RegisterLoader$1.prototype[RegisterLoader$1.resolve = Loader.resolve] = function (key, parentKey) { | |
534 | return resolveIfNotPlain(key, parentKey || baseURI); | |
535 | }; | |
536 | ||
537 | RegisterLoader$1.prototype[INSTANTIATE] = function (key, processAnonRegister) {}; | |
538 | ||
539 | // once evaluated, the linkRecord is set to undefined leaving just the other load record properties | |
540 | // this allows tracking new binding listeners for es modules through importerSetters | |
541 | // for dynamic modules, the load record is removed entirely. | |
542 | function createLoadRecord (state, key, registration) { | |
543 | return state.records[key] = { | |
544 | key: key, | |
545 | ||
546 | // defined System.register cache | |
547 | registration: registration, | |
548 | ||
549 | // module namespace object | |
550 | module: undefined, | |
551 | ||
552 | // es-only | |
553 | // this sticks around so new module loads can listen to binding changes | |
554 | // for already-loaded modules by adding themselves to their importerSetters | |
555 | importerSetters: undefined, | |
556 | ||
557 | // in-flight linking record | |
558 | linkRecord: { | |
559 | // promise for instantiated | |
560 | instantiatePromise: undefined, | |
561 | dependencies: undefined, | |
562 | execute: undefined, | |
563 | executingRequire: false, | |
564 | ||
565 | // underlying module object bindings | |
566 | moduleObj: undefined, | |
567 | ||
568 | // es only, also indicates if es or not | |
569 | setters: undefined, | |
570 | ||
571 | // promise for instantiated dependencies (dependencyInstantiations populated) | |
572 | depsInstantiatePromise: undefined, | |
573 | // will be the array of dependency load record or a module namespace | |
574 | dependencyInstantiations: undefined, | |
575 | ||
576 | // indicates if the load and all its dependencies are instantiated and linked | |
577 | // but not yet executed | |
578 | // mostly just a performance shortpath to avoid rechecking the promises above | |
579 | linked: false, | |
580 | ||
581 | error: undefined | |
582 | // NB optimization and way of ensuring module objects in setters | |
583 | // indicates setters which should run pre-execution of that dependency | |
584 | // setters is then just for completely executed module objects | |
585 | // alternatively we just pass the partially filled module objects as | |
586 | // arguments into the execute function | |
587 | // hoisted: undefined | |
588 | } | |
589 | }; | |
590 | } | |
591 | ||
592 | RegisterLoader$1.prototype[Loader.resolveInstantiate] = function (key, parentKey) { | |
593 | var loader = this; | |
594 | var state = this[REGISTER_INTERNAL]; | |
595 | var registry = loader.registry[loader.registry._registry]; | |
596 | ||
597 | return resolveInstantiate(loader, key, parentKey, registry, state) | |
598 | .then(function (instantiated) { | |
599 | if (instantiated instanceof ModuleNamespace) | |
600 | return instantiated; | |
601 | ||
602 | // if already beaten to linked, return | |
603 | if (instantiated.module) | |
604 | return instantiated.module; | |
605 | ||
606 | // resolveInstantiate always returns a load record with a link record and no module value | |
607 | if (instantiated.linkRecord.linked) | |
608 | return ensureEvaluate(loader, instantiated, instantiated.linkRecord, registry, state, undefined); | |
609 | ||
610 | return instantiateDeps(loader, instantiated, instantiated.linkRecord, registry, state, [instantiated]) | |
611 | .then(function () { | |
612 | return ensureEvaluate(loader, instantiated, instantiated.linkRecord, registry, state, undefined); | |
613 | }) | |
614 | .catch(function (err) { | |
615 | clearLoadErrors(loader, instantiated); | |
616 | throw err; | |
617 | }); | |
618 | }); | |
619 | }; | |
620 | ||
621 | function resolveInstantiate (loader, key, parentKey, registry, state) { | |
622 | // normalization shortpath for already-normalized key | |
623 | // could add a plain name filter, but doesn't yet seem necessary for perf | |
624 | var module = registry[key]; | |
625 | if (module) | |
626 | return Promise.resolve(module); | |
627 | ||
628 | var load = state.records[key]; | |
629 | ||
630 | // already linked but not in main registry is ignored | |
631 | if (load && !load.module) | |
632 | return instantiate(loader, load, load.linkRecord, registry, state); | |
633 | ||
634 | return loader.resolve(key, parentKey) | |
635 | .then(function (resolvedKey) { | |
636 | // main loader registry always takes preference | |
637 | module = registry[resolvedKey]; | |
638 | if (module) | |
639 | return module; | |
640 | ||
641 | load = state.records[resolvedKey]; | |
642 | ||
643 | // already has a module value but not already in the registry (load.module) | |
644 | // means it was removed by registry.delete, so we should | |
645 | // disgard the current load record creating a new one over it | |
646 | // but keep any existing registration | |
647 | if (!load || load.module) | |
648 | load = createLoadRecord(state, resolvedKey, load && load.registration); | |
649 | ||
650 | var link = load.linkRecord; | |
651 | if (!link) | |
652 | return load; | |
653 | ||
654 | return instantiate(loader, load, link, registry, state); | |
655 | }); | |
656 | } | |
657 | ||
658 | function createProcessAnonRegister (loader, load, state) { | |
659 | return function () { | |
660 | var lastRegister = state.lastRegister; | |
661 | ||
662 | if (!lastRegister) | |
663 | return !!load.registration; | |
664 | ||
665 | state.lastRegister = undefined; | |
666 | load.registration = lastRegister; | |
667 | ||
668 | return true; | |
669 | }; | |
670 | } | |
671 | ||
672 | function instantiate (loader, load, link, registry, state) { | |
673 | return link.instantiatePromise || (link.instantiatePromise = | |
674 | // if there is already an existing registration, skip running instantiate | |
675 | (load.registration ? Promise.resolve() : Promise.resolve().then(function () { | |
676 | state.lastRegister = undefined; | |
677 | return loader[INSTANTIATE](load.key, loader[INSTANTIATE].length > 1 && createProcessAnonRegister(loader, load, state)); | |
678 | })) | |
679 | .then(function (instantiation) { | |
680 | // direct module return from instantiate -> we're done | |
681 | if (instantiation !== undefined) { | |
682 | if (!(instantiation instanceof ModuleNamespace)) | |
683 | throw new TypeError('Instantiate did not return a valid Module object.'); | |
684 | ||
685 | delete state.records[load.key]; | |
686 | if (loader.trace) | |
687 | traceLoad(loader, load, link); | |
688 | return registry[load.key] = instantiation; | |
689 | } | |
690 | ||
691 | // run the cached loader.register declaration if there is one | |
692 | var registration = load.registration; | |
693 | // clear to allow new registrations for future loads (combined with registry delete) | |
694 | load.registration = undefined; | |
695 | if (!registration) | |
696 | throw new TypeError('Module instantiation did not call an anonymous or correctly named System.register.'); | |
697 | ||
698 | link.dependencies = registration[0]; | |
699 | ||
700 | load.importerSetters = []; | |
701 | ||
702 | link.moduleObj = {}; | |
703 | ||
704 | // process System.registerDynamic declaration | |
705 | if (registration[2]) { | |
706 | link.moduleObj.default = {}; | |
707 | link.moduleObj.__useDefault = true; | |
708 | link.executingRequire = registration[1]; | |
709 | link.execute = registration[2]; | |
710 | } | |
711 | ||
712 | // process System.register declaration | |
713 | else { | |
714 | registerDeclarative(loader, load, link, registration[1]); | |
715 | } | |
716 | ||
717 | // shortpath to instantiateDeps | |
718 | if (!link.dependencies.length) { | |
719 | link.linked = true; | |
720 | if (loader.trace) | |
721 | traceLoad(loader, load, link); | |
722 | } | |
723 | ||
724 | return load; | |
725 | }) | |
726 | .catch(function (err) { | |
727 | throw link.error = LoaderError__Check_error_message_for_loader_stack(err, 'Instantiating ' + load.key); | |
728 | })); | |
729 | } | |
730 | ||
731 | // like resolveInstantiate, but returning load records for linking | |
732 | function resolveInstantiateDep (loader, key, parentKey, registry, state, traceDepMap) { | |
733 | // normalization shortpaths for already-normalized key | |
734 | // DISABLED to prioritise consistent resolver calls | |
735 | // could add a plain name filter, but doesn't yet seem necessary for perf | |
736 | /* var load = state.records[key]; | |
737 | var module = registry[key]; | |
738 | ||
739 | if (module) { | |
740 | if (traceDepMap) | |
741 | traceDepMap[key] = key; | |
742 | ||
743 | // registry authority check in case module was deleted or replaced in main registry | |
744 | if (load && load.module && load.module === module) | |
745 | return load; | |
746 | else | |
747 | return module; | |
748 | } | |
749 | ||
750 | // already linked but not in main registry is ignored | |
751 | if (load && !load.module) { | |
752 | if (traceDepMap) | |
753 | traceDepMap[key] = key; | |
754 | return instantiate(loader, load, load.linkRecord, registry, state); | |
755 | } */ | |
756 | return loader.resolve(key, parentKey) | |
757 | .then(function (resolvedKey) { | |
758 | if (traceDepMap) | |
759 | traceDepMap[key] = resolvedKey; | |
760 | ||
761 | // normalization shortpaths for already-normalized key | |
762 | var load = state.records[resolvedKey]; | |
763 | var module = registry[resolvedKey]; | |
764 | ||
765 | // main loader registry always takes preference | |
766 | if (module && (!load || load.module && module !== load.module)) | |
767 | return module; | |
768 | ||
769 | // already has a module value but not already in the registry (load.module) | |
770 | // means it was removed by registry.delete, so we should | |
771 | // disgard the current load record creating a new one over it | |
772 | // but keep any existing registration | |
773 | if (!load || !module && load.module) | |
774 | load = createLoadRecord(state, resolvedKey, load && load.registration); | |
775 | ||
776 | var link = load.linkRecord; | |
777 | if (!link) | |
778 | return load; | |
779 | ||
780 | return instantiate(loader, load, link, registry, state); | |
781 | }); | |
782 | } | |
783 | ||
784 | function traceLoad (loader, load, link) { | |
785 | loader.loads = loader.loads || {}; | |
786 | loader.loads[load.key] = { | |
787 | key: load.key, | |
788 | deps: link.dependencies, | |
789 | depMap: link.depMap || {} | |
790 | }; | |
791 | } | |
792 | ||
793 | /* | |
794 | * Convert a CJS module.exports into a valid object for new Module: | |
795 | * | |
796 | * new Module(getEsModule(module.exports)) | |
797 | * | |
798 | * Sets the default value to the module, while also reading off named exports carefully. | |
799 | */ | |
800 | function registerDeclarative (loader, load, link, declare) { | |
801 | var moduleObj = link.moduleObj; | |
802 | var importerSetters = load.importerSetters; | |
803 | ||
804 | var locked = false; | |
805 | ||
806 | // closure especially not based on link to allow link record disposal | |
807 | var declared = declare.call(envGlobal, function (name, value) { | |
808 | // export setter propogation with locking to avoid cycles | |
809 | if (locked) | |
810 | return; | |
811 | ||
812 | if (typeof name === 'object') { | |
813 | for (var p in name) | |
814 | if (p !== '__useDefault') | |
815 | moduleObj[p] = name[p]; | |
816 | } | |
817 | else { | |
818 | moduleObj[name] = value; | |
819 | } | |
820 | ||
821 | locked = true; | |
822 | for (var i = 0; i < importerSetters.length; i++) | |
823 | importerSetters[i](moduleObj); | |
824 | locked = false; | |
825 | ||
826 | return value; | |
827 | }, new ContextualLoader(loader, load.key)); | |
828 | ||
829 | link.setters = declared.setters; | |
830 | link.execute = declared.execute; | |
831 | if (declared.exports) | |
832 | link.moduleObj = moduleObj = declared.exports; | |
833 | } | |
834 | ||
835 | function instantiateDeps (loader, load, link, registry, state, seen) { | |
836 | return (link.depsInstantiatePromise || (link.depsInstantiatePromise = Promise.resolve() | |
837 | .then(function () { | |
838 | var depsInstantiatePromises = Array(link.dependencies.length); | |
839 | ||
840 | for (var i = 0; i < link.dependencies.length; i++) | |
841 | depsInstantiatePromises[i] = resolveInstantiateDep(loader, link.dependencies[i], load.key, registry, state, loader.trace && link.depMap || (link.depMap = {})); | |
842 | ||
843 | return Promise.all(depsInstantiatePromises); | |
844 | }) | |
845 | .then(function (dependencyInstantiations) { | |
846 | link.dependencyInstantiations = dependencyInstantiations; | |
847 | ||
848 | // run setters to set up bindings to instantiated dependencies | |
849 | if (link.setters) { | |
850 | for (var i = 0; i < dependencyInstantiations.length; i++) { | |
851 | var setter = link.setters[i]; | |
852 | if (setter) { | |
853 | var instantiation = dependencyInstantiations[i]; | |
854 | ||
855 | if (instantiation instanceof ModuleNamespace) { | |
856 | setter(instantiation); | |
857 | } | |
858 | else { | |
859 | setter(instantiation.module || instantiation.linkRecord.moduleObj); | |
860 | // this applies to both es and dynamic registrations | |
861 | if (instantiation.importerSetters) | |
862 | instantiation.importerSetters.push(setter); | |
863 | } | |
864 | } | |
865 | } | |
866 | } | |
867 | }))) | |
868 | .then(function () { | |
869 | // now deeply instantiateDeps on each dependencyInstantiation that is a load record | |
870 | var deepDepsInstantiatePromises = []; | |
871 | ||
872 | for (var i = 0; i < link.dependencies.length; i++) { | |
873 | var depLoad = link.dependencyInstantiations[i]; | |
874 | var depLink = depLoad.linkRecord; | |
875 | ||
876 | if (!depLink || depLink.linked) | |
877 | continue; | |
878 | ||
879 | if (seen.indexOf(depLoad) !== -1) | |
880 | continue; | |
881 | seen.push(depLoad); | |
882 | ||
883 | deepDepsInstantiatePromises.push(instantiateDeps(loader, depLoad, depLoad.linkRecord, registry, state, seen)); | |
884 | } | |
885 | ||
886 | return Promise.all(deepDepsInstantiatePromises); | |
887 | }) | |
888 | .then(function () { | |
889 | // as soon as all dependencies instantiated, we are ready for evaluation so can add to the registry | |
890 | // this can run multiple times, but so what | |
891 | link.linked = true; | |
892 | if (loader.trace) | |
893 | traceLoad(loader, load, link); | |
894 | ||
895 | return load; | |
896 | }) | |
897 | .catch(function (err) { | |
898 | err = LoaderError__Check_error_message_for_loader_stack(err, 'Loading ' + load.key); | |
899 | ||
900 | // throw up the instantiateDeps stack | |
901 | // loads are then synchonously cleared at the top-level through the clearLoadErrors helper below | |
902 | // this then ensures avoiding partially unloaded tree states | |
903 | link.error = link.error || err; | |
904 | ||
905 | throw err; | |
906 | }); | |
907 | } | |
908 | ||
909 | // clears an errored load and all its errored dependencies from the loads registry | |
910 | function clearLoadErrors (loader, load) { | |
911 | var state = loader[REGISTER_INTERNAL]; | |
912 | ||
913 | // clear from loads | |
914 | if (state.records[load.key] === load) | |
915 | delete state.records[load.key]; | |
916 | ||
917 | var link = load.linkRecord; | |
918 | ||
919 | if (!link) | |
920 | return; | |
921 | ||
922 | if (link.dependencyInstantiations) | |
923 | link.dependencyInstantiations.forEach(function (depLoad, index) { | |
924 | if (!depLoad || depLoad instanceof ModuleNamespace) | |
925 | return; | |
926 | ||
927 | if (depLoad.linkRecord) { | |
928 | if (depLoad.linkRecord.error) { | |
929 | // provides a circular reference check | |
930 | if (state.records[depLoad.key] === depLoad) | |
931 | clearLoadErrors(loader, depLoad); | |
932 | } | |
933 | ||
934 | // unregister setters for es dependency load records that will remain | |
935 | if (link.setters && depLoad.importerSetters) { | |
936 | var setterIndex = depLoad.importerSetters.indexOf(link.setters[index]); | |
937 | depLoad.importerSetters.splice(setterIndex, 1); | |
938 | } | |
939 | } | |
940 | }); | |
941 | } | |
942 | ||
943 | /* | |
944 | * System.register | |
945 | */ | |
946 | RegisterLoader$1.prototype.register = function (key, deps, declare) { | |
947 | var state = this[REGISTER_INTERNAL]; | |
948 | ||
949 | // anonymous modules get stored as lastAnon | |
950 | if (declare === undefined) { | |
951 | state.lastRegister = [key, deps, undefined]; | |
952 | } | |
953 | ||
954 | // everything else registers into the register cache | |
955 | else { | |
956 | var load = state.records[key] || createLoadRecord(state, key, undefined); | |
957 | load.registration = [deps, declare, undefined]; | |
958 | } | |
959 | }; | |
960 | ||
961 | /* | |
962 | * System.registerDyanmic | |
963 | */ | |
964 | RegisterLoader$1.prototype.registerDynamic = function (key, deps, executingRequire, execute) { | |
965 | var state = this[REGISTER_INTERNAL]; | |
966 | ||
967 | // anonymous modules get stored as lastAnon | |
968 | if (typeof key !== 'string') { | |
969 | state.lastRegister = [key, deps, executingRequire]; | |
970 | } | |
971 | ||
972 | // everything else registers into the register cache | |
973 | else { | |
974 | var load = state.records[key] || createLoadRecord(state, key, undefined); | |
975 | load.registration = [deps, executingRequire, execute]; | |
976 | } | |
977 | }; | |
978 | ||
979 | // ContextualLoader class | |
980 | // backwards-compatible with previous System.register context argument by exposing .id | |
981 | function ContextualLoader (loader, key) { | |
982 | this.loader = loader; | |
983 | this.key = this.id = key; | |
984 | } | |
985 | ContextualLoader.prototype.constructor = function () { | |
986 | throw new TypeError('Cannot subclass the contextual loader only Reflect.Loader.'); | |
987 | }; | |
988 | ContextualLoader.prototype.import = function (key) { | |
989 | return this.loader.import(key, this.key); | |
990 | }; | |
991 | ContextualLoader.prototype.resolve = function (key) { | |
992 | return this.loader.resolve(key, this.key); | |
993 | }; | |
994 | ContextualLoader.prototype.load = function (key) { | |
995 | return this.loader.load(key, this.key); | |
996 | }; | |
997 | ||
998 | // this is the execution function bound to the Module namespace record | |
999 | function ensureEvaluate (loader, load, link, registry, state, seen) { | |
1000 | if (load.module) | |
1001 | return load.module; | |
1002 | ||
1003 | if (link.error) | |
1004 | throw link.error; | |
1005 | ||
1006 | if (seen && seen.indexOf(load) !== -1) | |
1007 | return load.linkRecord.moduleObj; | |
1008 | ||
1009 | // for ES loads we always run ensureEvaluate on top-level, so empty seen is passed regardless | |
1010 | // for dynamic loads, we pass seen if also dynamic | |
1011 | var err = doEvaluate(loader, load, link, registry, state, link.setters ? [] : seen || []); | |
1012 | if (err) { | |
1013 | clearLoadErrors(loader, load); | |
1014 | throw err; | |
1015 | } | |
1016 | ||
1017 | return load.module; | |
1018 | } | |
1019 | ||
1020 | function makeDynamicRequire (loader, key, dependencies, dependencyInstantiations, registry, state, seen) { | |
1021 | // we can only require from already-known dependencies | |
1022 | return function (name) { | |
1023 | for (var i = 0; i < dependencies.length; i++) { | |
1024 | if (dependencies[i] === name) { | |
1025 | var depLoad = dependencyInstantiations[i]; | |
1026 | var module; | |
1027 | ||
1028 | if (depLoad instanceof ModuleNamespace) | |
1029 | module = depLoad; | |
1030 | else | |
1031 | module = ensureEvaluate(loader, depLoad, depLoad.linkRecord, registry, state, seen); | |
1032 | ||
1033 | return module.__useDefault ? module.default : module; | |
1034 | } | |
1035 | } | |
1036 | throw new Error('Module ' + name + ' not declared as a System.registerDynamic dependency of ' + key); | |
1037 | }; | |
1038 | } | |
1039 | ||
1040 | // ensures the given es load is evaluated | |
1041 | // returns the error if any | |
1042 | function doEvaluate (loader, load, link, registry, state, seen) { | |
1043 | seen.push(load); | |
1044 | ||
1045 | var err; | |
1046 | ||
1047 | // es modules evaluate dependencies first | |
1048 | // non es modules explicitly call moduleEvaluate through require | |
1049 | if (link.setters) { | |
1050 | var depLoad, depLink; | |
1051 | for (var i = 0; i < link.dependencies.length; i++) { | |
1052 | depLoad = link.dependencyInstantiations[i]; | |
1053 | ||
1054 | if (depLoad instanceof ModuleNamespace) | |
1055 | continue; | |
1056 | ||
1057 | // custom Module returned from instantiate | |
1058 | depLink = depLoad.linkRecord; | |
1059 | if (depLink && seen.indexOf(depLoad) === -1) { | |
1060 | if (depLink.error) | |
1061 | err = depLink.error; | |
1062 | else | |
1063 | // dynamic / declarative boundaries clear the "seen" list | |
1064 | // we just let cross format circular throw as would happen in real implementations | |
1065 | err = doEvaluate(loader, depLoad, depLink, registry, state, depLink.setters ? seen : []); | |
1066 | } | |
1067 | ||
1068 | if (err) | |
1069 | return link.error = LoaderError__Check_error_message_for_loader_stack(err, 'Evaluating ' + load.key); | |
1070 | } | |
1071 | } | |
1072 | ||
1073 | // link.execute won't exist for Module returns from instantiate on top-level load | |
1074 | if (link.execute) { | |
1075 | // ES System.register execute | |
1076 | // "this" is null in ES | |
1077 | if (link.setters) { | |
1078 | err = declarativeExecute(link.execute); | |
1079 | } | |
1080 | // System.registerDynamic execute | |
1081 | // "this" is "exports" in CJS | |
1082 | else { | |
1083 | var module = { id: load.key }; | |
1084 | var moduleObj = link.moduleObj; | |
1085 | Object.defineProperty(module, 'exports', { | |
1086 | configurable: true, | |
1087 | set: function (exports) { | |
1088 | moduleObj.default = exports; | |
1089 | }, | |
1090 | get: function () { | |
1091 | return moduleObj.default; | |
1092 | } | |
1093 | }); | |
1094 | ||
1095 | var require = makeDynamicRequire(loader, load.key, link.dependencies, link.dependencyInstantiations, registry, state, seen); | |
1096 | ||
1097 | // evaluate deps first | |
1098 | if (!link.executingRequire) | |
1099 | for (var i = 0; i < link.dependencies.length; i++) | |
1100 | require(link.dependencies[i]); | |
1101 | ||
1102 | err = dynamicExecute(link.execute, require, moduleObj.default, module); | |
1103 | ||
1104 | // pick up defineProperty calls to module.exports when we can | |
1105 | if (module.exports !== moduleObj.default) | |
1106 | moduleObj.default = module.exports; | |
1107 | ||
1108 | var moduleDefault = moduleObj.default; | |
1109 | ||
1110 | // __esModule flag extension support via lifting | |
1111 | if (moduleDefault && moduleDefault.__esModule) { | |
1112 | if (moduleObj.__useDefault) | |
1113 | delete moduleObj.__useDefault; | |
1114 | for (var p in moduleDefault) { | |
1115 | if (Object.hasOwnProperty.call(moduleDefault, p)) | |
1116 | moduleObj[p] = moduleDefault[p]; | |
1117 | } | |
1118 | moduleObj.__esModule = true; | |
1119 | } | |
1120 | } | |
1121 | } | |
1122 | ||
1123 | if (err) | |
1124 | return link.error = LoaderError__Check_error_message_for_loader_stack(err, 'Evaluating ' + load.key); | |
1125 | ||
1126 | registry[load.key] = load.module = new ModuleNamespace(link.moduleObj); | |
1127 | ||
1128 | // if not an esm module, run importer setters and clear them | |
1129 | // this allows dynamic modules to update themselves into es modules | |
1130 | // as soon as execution has completed | |
1131 | if (!link.setters) { | |
1132 | if (load.importerSetters) | |
1133 | for (var i = 0; i < load.importerSetters.length; i++) | |
1134 | load.importerSetters[i](load.module); | |
1135 | load.importerSetters = undefined; | |
1136 | } | |
1137 | ||
1138 | // dispose link record | |
1139 | load.linkRecord = undefined; | |
1140 | } | |
1141 | ||
1142 | // {} is the closest we can get to call(undefined) | |
1143 | var nullContext = {}; | |
1144 | if (Object.freeze) | |
1145 | Object.freeze(nullContext); | |
1146 | ||
1147 | function declarativeExecute (execute) { | |
1148 | try { | |
1149 | execute.call(nullContext); | |
1150 | } | |
1151 | catch (e) { | |
1152 | return e; | |
1153 | } | |
1154 | } | |
1155 | ||
1156 | function dynamicExecute (execute, require, exports, module) { | |
1157 | try { | |
1158 | var output = execute.call(envGlobal, require, exports, module); | |
1159 | if (output !== undefined) | |
1160 | module.exports = output; | |
1161 | } | |
1162 | catch (e) { | |
1163 | return e; | |
1164 | } | |
1165 | } | |
1166 | ||
1167 | var loader; | |
1168 | ||
1169 | // <script type="module"> support | |
1170 | var anonSources = {}; | |
1171 | if (typeof document != 'undefined' && document.getElementsByTagName) { | |
36653517 PO |
1172 | function handleError(err) { |
1173 | // dispatch an error event so that we can display in errors in browsers | |
1174 | // that don't yet support unhandledrejection | |
999b5da7 PO |
1175 | if (window.onunhandledrejection === undefined) { |
1176 | try { | |
1177 | var evt = new Event('error'); | |
1178 | } catch (_eventError) { | |
1179 | var evt = document.createEvent('Event'); | |
1180 | evt.initEvent('error', true, true); | |
1181 | } | |
1182 | evt.message = err.message; | |
5d00fd9b PO |
1183 | if (err.fileName) { |
1184 | evt.filename = err.fileName; | |
1185 | evt.lineno = err.lineNumber; | |
1186 | evt.colno = err.columnNumber; | |
1187 | } else if (err.sourceURL) { | |
1188 | evt.filename = err.sourceURL; | |
1189 | evt.lineno = err.line; | |
1190 | evt.colno = err.column; | |
1191 | } | |
999b5da7 PO |
1192 | evt.error = err; |
1193 | window.dispatchEvent(evt); | |
36653517 | 1194 | } |
36653517 PO |
1195 | |
1196 | // throw so it still shows up in the console | |
1197 | throw err; | |
1198 | } | |
1199 | ||
399fa2ee SR |
1200 | function ready() { |
1201 | document.removeEventListener('DOMContentLoaded', ready, false ); | |
1202 | ||
1203 | var anonCnt = 0; | |
1204 | ||
1205 | var scripts = document.getElementsByTagName('script'); | |
1206 | for (var i = 0; i < scripts.length; i++) { | |
1207 | var script = scripts[i]; | |
1208 | if (script.type == 'module' && !script.loaded) { | |
1209 | script.loaded = true; | |
1210 | if (script.src) { | |
36653517 | 1211 | loader.import(script.src).catch(handleError); |
399fa2ee SR |
1212 | } |
1213 | // anonymous modules supported via a custom naming scheme and registry | |
1214 | else { | |
1215 | var uri = './<anon' + ++anonCnt + '>'; | |
1216 | if (script.id !== ""){ | |
1217 | uri = "./" + script.id; | |
1218 | } | |
1219 | ||
1220 | var anonName = resolveIfNotPlain(uri, baseURI); | |
1221 | anonSources[anonName] = script.innerHTML; | |
36653517 | 1222 | loader.import(anonName).catch(handleError); |
399fa2ee SR |
1223 | } |
1224 | } | |
1225 | } | |
1226 | } | |
1227 | ||
1228 | // simple DOM ready | |
1229 | if (document.readyState === 'complete') | |
1230 | setTimeout(ready); | |
1231 | else | |
1232 | document.addEventListener('DOMContentLoaded', ready, false); | |
1233 | } | |
1234 | ||
1235 | function BrowserESModuleLoader(baseKey) { | |
1236 | if (baseKey) | |
1237 | this.baseKey = resolveIfNotPlain(baseKey, baseURI) || resolveIfNotPlain('./' + baseKey, baseURI); | |
1238 | ||
1239 | RegisterLoader$1.call(this); | |
1240 | ||
1241 | var loader = this; | |
1242 | ||
1243 | // ensure System.register is available | |
1244 | envGlobal.System = envGlobal.System || {}; | |
1245 | if (typeof envGlobal.System.register == 'function') | |
1246 | var prevRegister = envGlobal.System.register; | |
1247 | envGlobal.System.register = function() { | |
1248 | loader.register.apply(loader, arguments); | |
1249 | if (prevRegister) | |
1250 | prevRegister.apply(this, arguments); | |
1251 | }; | |
1252 | } | |
1253 | BrowserESModuleLoader.prototype = Object.create(RegisterLoader$1.prototype); | |
1254 | ||
1255 | // normalize is never given a relative name like "./x", that part is already handled | |
1256 | BrowserESModuleLoader.prototype[RegisterLoader$1.resolve] = function(key, parent) { | |
1257 | var resolved = RegisterLoader$1.prototype[RegisterLoader$1.resolve].call(this, key, parent || this.baseKey) || key; | |
1258 | if (!resolved) | |
1259 | throw new RangeError('ES module loader does not resolve plain module names, resolving "' + key + '" to ' + parent); | |
1260 | ||
1261 | return resolved; | |
1262 | }; | |
1263 | ||
1264 | function xhrFetch(url, resolve, reject) { | |
1265 | var xhr = new XMLHttpRequest(); | |
1266 | function load(source) { | |
1267 | resolve(xhr.responseText); | |
1268 | } | |
1269 | function error() { | |
1270 | reject(new Error('XHR error' + (xhr.status ? ' (' + xhr.status + (xhr.statusText ? ' ' + xhr.statusText : '') + ')' : '') + ' loading ' + url)); | |
1271 | } | |
1272 | ||
1273 | xhr.onreadystatechange = function () { | |
1274 | if (xhr.readyState === 4) { | |
1275 | // in Chrome on file:/// URLs, status is 0 | |
1276 | if (xhr.status == 0) { | |
1277 | if (xhr.responseText) { | |
1278 | load(); | |
1279 | } | |
1280 | else { | |
1281 | // when responseText is empty, wait for load or error event | |
1282 | // to inform if it is a 404 or empty file | |
1283 | xhr.addEventListener('error', error); | |
1284 | xhr.addEventListener('load', load); | |
1285 | } | |
1286 | } | |
1287 | else if (xhr.status === 200) { | |
1288 | load(); | |
1289 | } | |
1290 | else { | |
1291 | error(); | |
1292 | } | |
1293 | } | |
1294 | }; | |
1295 | xhr.open("GET", url, true); | |
1296 | xhr.send(null); | |
1297 | } | |
1298 | ||
1299 | var WorkerPool = function (script, size) { | |
1300 | this._workers = new Array(size); | |
1301 | this._ind = 0; | |
1302 | this._size = size; | |
1303 | this._jobs = 0; | |
1304 | this.onmessage = undefined; | |
1305 | this._stopTimeout = undefined; | |
1306 | for (let i = 0; i < size; i++) { | |
1307 | let wrkr = new Worker(script); | |
1308 | wrkr._count = 0; | |
1309 | wrkr._ind = i; | |
1310 | wrkr.onmessage = this._onmessage.bind(this, wrkr); | |
1311 | this._workers[i] = wrkr; | |
1312 | } | |
1313 | ||
1314 | this._checkJobs(); | |
1315 | }; | |
1316 | WorkerPool.prototype = { | |
1317 | postMessage: function (msg) { | |
1318 | if (this._stopTimeout !== undefined) { | |
1319 | clearTimeout(this._stopTimeout); | |
1320 | this._stopTimeout = undefined; | |
1321 | } | |
1322 | let wrkr = this._workers[this._ind % this._size]; | |
1323 | wrkr._count++; | |
1324 | this._jobs++; | |
1325 | wrkr.postMessage(msg); | |
1326 | this._ind++; | |
1327 | }, | |
1328 | ||
1329 | _onmessage: function (wrkr, evt) { | |
1330 | wrkr._count--; | |
1331 | this._jobs--; | |
1332 | this.onmessage(evt, wrkr); | |
1333 | this._checkJobs(); | |
1334 | }, | |
1335 | ||
1336 | _checkJobs: function () { | |
1337 | if (this._jobs === 0 && this._stopTimeout === undefined) { | |
1338 | // wait for 2s of inactivity before stopping (that should be enough for local loading) | |
1339 | this._stopTimeout = setTimeout(this._stop.bind(this), 2000); | |
1340 | } | |
1341 | }, | |
1342 | ||
1343 | _stop: function () { | |
152c3995 | 1344 | this._workers.forEach(function(wrkr) { |
399fa2ee | 1345 | wrkr.terminate(); |
152c3995 | 1346 | }); |
399fa2ee SR |
1347 | } |
1348 | }; | |
1349 | ||
1350 | var promiseMap = new Map(); | |
d6c17390 | 1351 | var babelWorker = new WorkerPool('/vendor/browser-es-module-loader/dist/babel-worker.js', 3); |
399fa2ee SR |
1352 | babelWorker.onmessage = function (evt) { |
1353 | var promFuncs = promiseMap.get(evt.data.key); | |
1354 | promFuncs.resolve(evt.data); | |
1355 | promiseMap.delete(evt.data.key); | |
1356 | }; | |
1357 | ||
1358 | // instantiate just needs to run System.register | |
1359 | // so we fetch the source, convert into the Babel System module format, then evaluate it | |
1360 | BrowserESModuleLoader.prototype[RegisterLoader$1.instantiate] = function(key, processAnonRegister) { | |
1361 | var loader = this; | |
1362 | ||
1363 | // load as ES with Babel converting into System.register | |
1364 | return new Promise(function(resolve, reject) { | |
1365 | // anonymous module | |
1366 | if (anonSources[key]) { | |
1367 | resolve(anonSources[key]); | |
1368 | anonSources[key] = undefined; | |
1369 | } | |
1370 | // otherwise we fetch | |
1371 | else { | |
1372 | xhrFetch(key, resolve, reject); | |
1373 | } | |
1374 | }) | |
1375 | .then(function(source) { | |
1376 | // check our cache first | |
1377 | const cacheEntryTrans = localStorage.getItem(key+'!transpiled'); | |
1378 | if (cacheEntryTrans) { | |
1379 | const cacheEntryRaw = localStorage.getItem(key+'!raw'); | |
1380 | // TODO: store a hash instead | |
1381 | if (cacheEntryRaw === source) { | |
1382 | return Promise.resolve({key: key, code: cacheEntryTrans, source: source}); | |
1383 | } | |
1384 | } | |
1385 | return new Promise(function (resolve, reject) { | |
1386 | promiseMap.set(key, {resolve: resolve, reject: reject}); | |
1387 | babelWorker.postMessage({key: key, source: source}); | |
1388 | }); | |
1389 | }).then(function (data) { | |
1390 | // evaluate without require, exports and module variables | |
1391 | // we leave module in for now to allow module.require access | |
d6c17390 SR |
1392 | if (data.key.slice(-8) !== '#nocache') { |
1393 | localStorage.setItem(key+'!raw', data.source); | |
1394 | localStorage.setItem(data.key+'!transpiled', data.code); | |
1395 | } | |
399fa2ee SR |
1396 | (0, eval)(data.code + '\n//# sourceURL=' + data.key + '!transpiled'); |
1397 | processAnonRegister(); | |
1398 | }); | |
1399 | }; | |
1400 | ||
1401 | // create a default loader instance in the browser | |
1402 | if (isBrowser) | |
1403 | loader = new BrowserESModuleLoader(); | |
1404 | ||
1405 | return BrowserESModuleLoader; | |
1406 | ||
1407 | }))); |