pipeline: rename just to makeImporter
MODIFY
src/index.js
src/index.js
@@ -2,4 +2,4 @@ export { makeRootedResolver } from './resolve';
export { makeSuffixLocator } from './locate';
export { makeProtocolRetriever } from './retrieve';
-export { makeImportPipeline as default } from './pipeline';
+export { makeImporter as default } from './pipeline';

MODIFY
src/pipeline.js
src/pipeline.js
-export const makeImportPipeline = (importHooks, moduleCache = new Map()) => {
+export const makeImporter = (importHooks, moduleCache = new Map()) => {
const {
// Functions for the pipeline.
resolve,
@@ -8,8 +8,8 @@ export const makeImportPipeline = (importHooks, moduleCache = new Map()) => {
rootContainer,
} = importHooks;
- let makeImporter;
- function recursiveLink(moduleId, container) {
+ let importer;
+ function recursiveLink(moduleId, container, preEndowments) {
const subContainer =
(container.containerFor && container.containerFor(moduleId)) || container;
@@ -20,28 +20,66 @@ export const makeImportPipeline = (importHooks, moduleCache = new Map()) => {
// Translate the linkage record into a module instance, and cache it.
const linkageRecord = moduleCache.get(moduleId);
- moduleInstance = subContainer.link(linkageRecord, makeImporter);
+ moduleInstance = subContainer.link(
+ linkageRecord,
+ makeImporter,
+ preEndowments,
+ );
subContainer.instanceCache.set(moduleId, moduleInstance);
return moduleInstance;
}
- makeImporter = referrer => {
- return async specifier => {
+ async function loadOne(specifier, referrer) {
const scopedRef = resolve(specifier, referrer);
const moduleId = await locate(scopedRef);
- if (!moduleCache.has(moduleId)) {
- // This is sequential because we are beginning an import cycle.
- const body = await retrieve(moduleId);
- const linkageRecord = await rewrite(moduleId, body);
+
+ let loadedP = moduleCache.get(moduleId);
+ if (!loadedP) {
+ // Begin the recursive load.
+ loadedP = retrieve(moduleId)
+ .then(body => rewrite({ sourceType: 'module', src: body }))
+ .then(({ linkageRecord }) => {
+ // Prevent circularity.
moduleCache.set(moduleId, linkageRecord);
+ return Promise.all(
+ Object.keys(linkageRecord.imports).map(spec =>
+ loadOne(spec, moduleId),
+ ),
+ );
+ });
+ moduleCache.set(moduleId, loadedP);
+ }
+
+ // Loading in progress, or already a moduleId with linkageRecord.
+ // Our caller really just wants to know the moduleId.
+ return Promise.resolve(loadedP).then(() => moduleId);
+ }
+
+ importer = async (srcSpec, preEndowments) => {
+ const { spec, linkageRecord, url } = srcSpec;
+ let moduleId;
+ if (linkageRecord !== undefined) {
+ // The linkage record is already prepared,
+ // so bypass the rewriter.
+ moduleId = {
+ toString() {
+ return `linkageRecord:${url}`;
+ },
+ };
+ moduleCache.set(moduleId, linkageRecord);
+ } else {
+ moduleId = await loadOne(spec, url);
}
// Begin initialization of the linked modules.
- const moduleInstance = recursiveLink(moduleId, rootContainer);
+ const moduleInstance = recursiveLink(
+ moduleId,
+ rootContainer,
+ preEndowments,
+ );
return moduleInstance.initialize();
};
- };
- return makeImporter;
+ return importer;
};

MODIFY
test/test-pipeline.js
test/test-pipeline.js
import { test } from 'tape-promise/tape';
-import makeImportPipeline from '../src';
+import makeImporter from '../src';
test('import cached specifier', async t => {
try {
@@ -12,7 +12,7 @@ test('import cached specifier', async t => {
},
],
]);
- const makeImporter = makeImportPipeline(
+ const importer = makeImporter(
{
resolve(specifier, _referrer) {
if (moduleCache.has(specifier)) {
@@ -28,6 +28,7 @@ test('import cached specifier', async t => {
},
rootContainer: {
link(mlr, _mimp) {
+ console.log(`linking`, mlr);
if (!mlr.source) {
throw TypeError(`Don't know how to link non-source mlr`);
}
@@ -44,19 +45,19 @@ test('import cached specifier', async t => {
moduleCache,
);
- const importer = makeImporter('file:///some/where/over');
+ const imp = spec => importer({ spec, url: 'file:///some/where/over' });
t.deepEquals(
- (await importer('@agoric/hello'))('you'),
+ (await imp('@agoric/hello'))('you'),
'Hello, you!',
`cached module passes pipeline`,
);
await t.rejects(
- importer('@agoric/goodbye'),
+ imp('@agoric/goodbye'),
TypeError,
'no cached specifier fails pipeline',
);
await t.rejects(
- importer('./foo.js'),
+ imp('./foo.js'),
TypeError,
'relative specifier fails pipeline',
);

pipeline: rename just to makeImporter