Skip to content
This repository was archived by the owner on Jul 13, 2020. It is now read-only.

Commit 30d9a72

Browse files
committed
support error caching (#533)
1 parent d3a2e33 commit 30d9a72

File tree

1 file changed

+29
-63
lines changed

1 file changed

+29
-63
lines changed

core/register-loader.js

+29-63
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export default RegisterLoader;
1111
* - loader.register support
1212
* - hookable higher-level resolve
1313
* - instantiate hook returning a ModuleNamespace or undefined for es module loading
14-
* - loader error behaviour as in HTML and loader specs, clearing failed modules from registration cache synchronously
14+
* - loader error behaviour as in HTML and loader specs, caching load and eval errors separately
1515
* - build tracing support by providing a .trace=true and .loads object format
1616
*/
1717

@@ -25,8 +25,10 @@ function RegisterLoader () {
2525
var deleted = registryDelete.call(this, key);
2626

2727
// also delete from register registry if linked
28-
if (records.hasOwnProperty(key) && !records[key].linkRecord)
28+
if (records.hasOwnProperty(key) && !records[key].linkRecord) {
2929
delete records[key];
30+
deleted = true;
31+
}
3032

3133
return deleted;
3234
};
@@ -74,6 +76,9 @@ function createLoadRecord (state, key, registration) {
7476
// for already-loaded modules by adding themselves to their importerSetters
7577
importerSetters: undefined,
7678

79+
loadError: undefined,
80+
evalError: undefined,
81+
7782
// in-flight linking record
7883
linkRecord: {
7984
// promise for instantiated
@@ -96,9 +101,8 @@ function createLoadRecord (state, key, registration) {
96101
// indicates if the load and all its dependencies are instantiated and linked
97102
// but not yet executed
98103
// mostly just a performance shortpath to avoid rechecking the promises above
99-
linked: false,
104+
linked: false
100105

101-
error: undefined
102106
// NB optimization and way of ensuring module objects in setters
103107
// indicates setters which should run pre-execution of that dependency
104108
// setters is then just for completely executed module objects
@@ -130,10 +134,6 @@ RegisterLoader.prototype[Loader.resolveInstantiate] = function (key, parentKey)
130134
return instantiateDeps(loader, instantiated, instantiated.linkRecord, registry, state, [instantiated])
131135
.then(function () {
132136
return ensureEvaluate(loader, instantiated, instantiated.linkRecord, registry, state, undefined);
133-
})
134-
.catch(function (err) {
135-
clearLoadErrors(loader, instantiated);
136-
throw err;
137137
});
138138
});
139139
};
@@ -243,7 +243,8 @@ function instantiate (loader, load, link, registry, state) {
243243
return load;
244244
})
245245
.catch(function (err) {
246-
throw link.error = addToError(err, 'Instantiating ' + load.key);
246+
load.linkRecord = undefined;
247+
throw load.loadError = load.loadError || addToError(err, 'Instantiating ' + load.key);
247248
}));
248249
}
249250

@@ -402,6 +403,9 @@ function instantiateDeps (loader, load, link, registry, state, seen) {
402403
var depLoad = link.dependencyInstantiations[i];
403404
var depLink = depLoad.linkRecord;
404405

406+
if (depLoad.loadError)
407+
throw depLoad.loadError;
408+
405409
if (!depLink || depLink.linked)
406410
continue;
407411

@@ -426,51 +430,12 @@ function instantiateDeps (loader, load, link, registry, state, seen) {
426430
return load;
427431
})
428432
.catch(function (err) {
429-
err = addToError(err, 'Loading ' + load.key);
430-
431433
// throw up the instantiateDeps stack
432-
// loads are then synchonously cleared at the top-level through the clearLoadErrors helper below
433-
// this then ensures avoiding partially unloaded tree states
434-
link.error = link.error || err;
435-
436-
throw err;
434+
load.linkRecord = undefined;
435+
throw load.loadError = load.loadError || addToError(err, 'Loading ' + load.key);
437436
});
438437
}
439438

440-
// clears an errored load and all its errored dependencies from the loads registry
441-
function clearLoadErrors (loader, load) {
442-
var state = loader[REGISTER_INTERNAL];
443-
444-
// clear from loads
445-
if (state.records[load.key] === load)
446-
delete state.records[load.key];
447-
448-
var link = load.linkRecord;
449-
450-
if (!link)
451-
return;
452-
453-
if (link.dependencyInstantiations)
454-
link.dependencyInstantiations.forEach(function (depLoad, index) {
455-
if (!depLoad || depLoad instanceof ModuleNamespace)
456-
return;
457-
458-
if (depLoad.linkRecord) {
459-
if (depLoad.linkRecord.error) {
460-
// provides a circular reference check
461-
if (state.records[depLoad.key] === depLoad)
462-
clearLoadErrors(loader, depLoad);
463-
}
464-
465-
// unregister setters for es dependency load records that will remain
466-
if (link.setters && depLoad.importerSetters) {
467-
var setterIndex = depLoad.importerSetters.indexOf(link.setters[index]);
468-
depLoad.importerSetters.splice(setterIndex, 1);
469-
}
470-
}
471-
});
472-
}
473-
474439
/*
475440
* System.register
476441
*/
@@ -530,19 +495,17 @@ function ensureEvaluate (loader, load, link, registry, state, seen) {
530495
if (load.module)
531496
return load.module;
532497

533-
if (link.error)
534-
throw link.error;
498+
if (load.evalError)
499+
throw load.evalError;
535500

536501
if (seen && seen.indexOf(load) !== -1)
537502
return load.linkRecord.moduleObj;
538503

539504
// for ES loads we always run ensureEvaluate on top-level, so empty seen is passed regardless
540505
// for dynamic loads, we pass seen if also dynamic
541506
var err = doEvaluate(loader, load, link, registry, state, link.setters ? [] : seen || []);
542-
if (err) {
543-
clearLoadErrors(loader, load);
507+
if (err)
544508
throw err;
545-
}
546509

547510
return load.module;
548511
}
@@ -587,16 +550,19 @@ function doEvaluate (loader, load, link, registry, state, seen) {
587550
// custom Module returned from instantiate
588551
depLink = depLoad.linkRecord;
589552
if (depLink && seen.indexOf(depLoad) === -1) {
590-
if (depLink.error)
591-
err = depLink.error;
553+
if (depLoad.evalError)
554+
err = depLoad.evalError;
592555
else
593556
// dynamic / declarative boundaries clear the "seen" list
594557
// we just let cross format circular throw as would happen in real implementations
595558
err = doEvaluate(loader, depLoad, depLink, registry, state, depLink.setters ? seen : []);
596559
}
597560

598-
if (err)
599-
return link.error = addToError(err, 'Evaluating ' + load.key);
561+
if (err) {
562+
load.linkRecord = undefined;
563+
load.evalError = addToError(err, 'Evaluating ' + load.key);
564+
return load.evalError;
565+
}
600566
}
601567
}
602568

@@ -647,8 +613,11 @@ function doEvaluate (loader, load, link, registry, state, seen) {
647613
}
648614
}
649615

616+
// dispose link record
617+
load.linkRecord = undefined;
618+
650619
if (err)
651-
return link.error = addToError(err, 'Evaluating ' + load.key);
620+
return load.evalError = addToError(err, 'Evaluating ' + load.key);
652621

653622
registry[load.key] = load.module = new ModuleNamespace(link.moduleObj);
654623

@@ -661,9 +630,6 @@ function doEvaluate (loader, load, link, registry, state, seen) {
661630
load.importerSetters[i](load.module);
662631
load.importerSetters = undefined;
663632
}
664-
665-
// dispose link record
666-
load.linkRecord = undefined;
667633
}
668634

669635
// {} is the closest we can get to call(undefined)

0 commit comments

Comments
 (0)