Skip to content

Commit

Permalink
feat: importMetaHook on instantiation if import.meta uttered by module
Browse files Browse the repository at this point in the history
  • Loading branch information
naugtur committed May 18, 2022
1 parent 0ddcd45 commit dfedd96
Show file tree
Hide file tree
Showing 11 changed files with 125 additions and 30 deletions.
2 changes: 1 addition & 1 deletion packages/compartment-mapper/src/bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ ${importsCellSetter(__liveExportMap__, index)}\
onceVar: {
${importsCellSetter(__fixedExportMap__, index)}\
},
metaVar: {
meta: {
url: '${packageLocation}'\
},
});
Expand Down
2 changes: 2 additions & 0 deletions packages/ses/src/compartment-shim.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ export const makeCompartmentConstructor = (
resolveHook,
importHook,
moduleMapHook,
importMetaHook,
} = options;
const globalTransforms = [...transforms, ...__shimTransforms__];

Expand Down Expand Up @@ -316,6 +317,7 @@ export const makeCompartmentConstructor = (
importHook,
moduleMap,
moduleMapHook,
importMetaHook,
moduleRecords,
__shimTransforms__,
deferredExports,
Expand Down
28 changes: 16 additions & 12 deletions packages/ses/src/module-instance.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
mapGet,
weakmapGet,
reflectHas,
assign,
} from './commons.js';
import { compartmentEvaluate } from './compartment-evaluate.js';

Expand Down Expand Up @@ -122,17 +123,23 @@ export const makeModuleInstance = (
moduleRecord,
importedInstances,
) => {
const { compartment, moduleSpecifier, staticModuleRecord } = moduleRecord;
const {
compartment,
moduleSpecifier,
staticModuleRecord,
meta: moduleRecordMeta,
} = moduleRecord;
const {
reexports: exportAlls = [],
__syncModuleProgram__: functorSource,
__fixedExportMap__: fixedExportMap = {},
__liveExportMap__: liveExportMap = {},
__usesImportMeta__: usesImportMeta = false,
} = staticModuleRecord;

const compartmentFields = weakmapGet(privateFields, compartment);

const { __shimTransforms__ } = compartmentFields;
const { __shimTransforms__, importMetaHook } = compartmentFields;

const { exportsProxy, proxiedExports, activate } = getDeferredExports(
compartment,
Expand All @@ -158,15 +165,12 @@ export const makeModuleInstance = (
// both initialize and update live bindings.
const liveVar = create(null);

const metaVar = create(null);
try {
metaVar.url = new URL(
moduleSpecifier,
compartmentFields.name || '.',
).toString();
} catch (e) {
metaVar.url = moduleSpecifier;
console.error('Wont URL:', moduleSpecifier, compartmentFields.name);
const meta = create(null);
if (moduleRecordMeta) {
assign(meta, moduleRecordMeta);
}
if (usesImportMeta && importMetaHook) {
importMetaHook(meta);
}

// {_localName_: [{get, set, notify}]} used to merge all the export updaters.
Expand Down Expand Up @@ -449,7 +453,7 @@ export const makeModuleInstance = (
imports: freeze(imports),
onceVar: freeze(onceVar),
liveVar: freeze(liveVar),
metaVar: freeze(metaVar),
meta,
}),
);
} catch (e) {
Expand Down
6 changes: 5 additions & 1 deletion packages/ses/src/module-load.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const loadRecord = async (
pendingJobs,
moduleLoads,
errors,
meta,
) => {
const { resolveHook, moduleRecords } = weakmapGet(
compartmentPrivateFields,
Expand All @@ -80,6 +81,7 @@ const loadRecord = async (
staticModuleRecord,
moduleSpecifier,
resolvedImports,
meta,
});

// Enqueue jobs to load this module's shallow dependencies.
Expand Down Expand Up @@ -181,6 +183,7 @@ const loadWithoutErrorAnnotation = async (
compartment: aliasCompartment = compartment,
specifier: aliasSpecifier = moduleSpecifier,
record: aliasModuleRecord,
meta,
} = staticModuleRecord;

const aliasRecord = await loadRecord(
Expand All @@ -192,6 +195,7 @@ const loadWithoutErrorAnnotation = async (
pendingJobs,
moduleLoads,
errors,
meta,
);
mapSet(moduleRecords, moduleSpecifier, aliasRecord);
return aliasRecord;
Expand Down Expand Up @@ -317,7 +321,7 @@ export const load = async (
`Failed to load module ${q(moduleSpecifier)} in package ${q(
compartmentName,
)} (${errors.length} underlying failures: ${arrayJoin(
arrayMap(errors, error => error.message),
arrayMap(errors, error => error.stack),
', ',
)}`,
);
Expand Down
13 changes: 12 additions & 1 deletion packages/ses/test/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,21 @@ export const makeLocator = root => {
};
};

const wrapImporterWithMeta = (importer, meta) => async specifier => {
const moduleRecord = await importer(specifier);
return { record: moduleRecord, meta };
};

// makeNodeImporter conveniently curries makeImporter with a Node.js style
// locator and static file retriever.
export const makeNodeImporter = sources => compartmentLocation => {
export const makeNodeImporter = sources => (
compartmentLocation,
options = {},
) => {
const locate = makeLocator(compartmentLocation);
const retrieve = makeStaticRetriever(sources);
if (options.meta) {
return wrapImporterWithMeta(makeImporter(locate, retrieve), options.meta);
}
return makeImporter(locate, retrieve);
};
68 changes: 64 additions & 4 deletions packages/ses/test/test-import.js
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,35 @@ test('child compartments are modular', async t => {
t.is(meaning, 42, 'child compartments have module support');
});

test.only('import.meta.url points to the module', async t => {
test('import.meta populated from module record', async t => {
t.plan(1);

const makeImportHook = makeNodeImporter({
'https://example.com/index.js': `
const myloc = import.meta.url;
export default myloc;
`,
});

const compartment = new Compartment(
{ t },
{},
{
name: 'https://example.com',
resolveHook: resolveNode,
importHook: makeImportHook('https://example.com', {
meta: { url: 'https://example.com/index.js' },
}),
},
);

const {
namespace: { default: metaurl },
} = await compartment.import('./index.js');
t.is(metaurl, 'https://example.com/index.js');
});

test('importMetaHook', async t => {
t.plan(1);

const makeImportHook = makeNodeImporter({
Expand All @@ -574,13 +602,45 @@ test.only('import.meta.url points to the module', async t => {
name: 'https://example.com',
resolveHook: resolveNode,
importHook: makeImportHook('https://example.com'),
importMetaHook: meta => {
meta.url = 'https://example.com/index.js';
},
},
);

const {
namespace:{
default: metaurl
}
namespace: { default: metaurl },
} = await compartment.import('./index.js');
t.is(metaurl, 'https://example.com/index.js');
});
test('importMetaHook and meta from record', async t => {
t.plan(1);

const makeImportHook = makeNodeImporter({
'https://example.com/index.js': `
const myloc = import.meta.url;
export default myloc;
`,
});

const compartment = new Compartment(
{ t },
{},
{
name: 'https://example.com',
resolveHook: resolveNode,
importHook: makeImportHook('https://example.com', {
meta: { url: 'https://example.com/index.js' },
}),
importMetaHook: meta => {
meta.url += '?foo';
meta.isStillMutableHopefully = 1;
},
},
);

const {
namespace: { default: metaurl },
} = await compartment.import('./index.js');
t.is(metaurl, 'https://example.com/index.js?foo');
});
18 changes: 13 additions & 5 deletions packages/static-module-record/src/babelPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ function makeModulePlugins(options) {
importDecls,
importSources,
liveExportMap,
importMetaProperties,
} = options;

if (sourceType !== 'module') {
Expand Down Expand Up @@ -308,13 +309,20 @@ function makeModulePlugins(options) {
},
};

const moduleVisitor = (doAnalyze, doTransform) => ({
MetaProperty(path){
if(path.node.meta.name==='import' && doTransform){
path.replaceWithMultiple([replace(path.node, t.identifier(h.HIDDEN_META))]);
const moduleVisitor = (doAnalyze, doTransform) => ({
MetaProperty(path) {
if (path.node.meta.name === 'import') {
if (doAnalyze && path.parentPath.isMemberExpression()) {
importMetaProperties.add(path.parentPath.node.property.name);
}
if (doTransform) {
path.replaceWithMultiple([
replace(path.node, hiddenIdentifier(h.HIDDEN_META)),
]);
}
}
},
// We handle all the import and export productions.
// We handle all the import and export productions.
ImportDeclaration(path) {
if (doAnalyze) {
const specs = path.node.specifiers;
Expand Down
2 changes: 1 addition & 1 deletion packages/static-module-record/src/hidden.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const HIDDEN_IMPORT = `${HIDDEN_PREFIX}import`;
export const HIDDEN_IMPORT_SELF = `${HIDDEN_PREFIX}importSelf`;
export const HIDDEN_IMPORTS = `${HIDDEN_PREFIX}imports`;
export const HIDDEN_ONCE = `${HIDDEN_PREFIX}once`;
export const HIDDEN_META = `${HIDDEN_PREFIX}meta`;
export const HIDDEN_META = `${HIDDEN_PREFIX}import_meta`;
export const HIDDEN_LIVE = `${HIDDEN_PREFIX}live`;
export const HIDDEN_IDENTIFIERS = [
HIDDEN_A,
Expand Down
4 changes: 4 additions & 0 deletions packages/static-module-record/src/static-module-record.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export function StaticModuleRecord(source, url) {
liveExportMap,
fixedExportMap,
exportAlls,
importMetaProperties,
} = analyzeModule({ string: source, url });
this.imports = freeze([...keys(imports)].sort());
this.exports = freeze(
Expand All @@ -60,5 +61,8 @@ export function StaticModuleRecord(source, url) {
this.__syncModuleProgram__ = functorSource;
this.__liveExportMap__ = liveExportMap;
this.__fixedExportMap__ = fixedExportMap;
this.__usesImportMeta__ = importMetaProperties.length > 0;
// useful for knowing if resolve or any other expensive features are used
this.__usesImportMetaProperties__ = importMetaProperties;
freeze(this);
}
10 changes: 6 additions & 4 deletions packages/static-module-record/src/transform-analyze.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ const makeTransformSource = (babel = null) => {
compact: true,
verbatim: true,
});
// console.log(`transformed`, transformedCode);
return transformedCode;
};

Expand All @@ -65,6 +64,8 @@ const makeCreateStaticRecord = transformSource =>
hoistedDecls: [],
importSources: Object.create(null),
importDecls: [],
// enables passing import.meta usage hints up.
importMetaProperties: new Set(),
};
if (moduleSource.startsWith('#!')) {
// Comment out the shebang lines.
Expand Down Expand Up @@ -113,7 +114,7 @@ const makeCreateStaticRecord = transformSource =>
imports: ${h.HIDDEN_IMPORTS}, \
liveVar: ${h.HIDDEN_LIVE}, \
onceVar: ${h.HIDDEN_ONCE}, \
metaVar: ${h.HIDDEN_META}, \
meta: ${h.HIDDEN_META}, \
}) => { \
${preamble} \
${scriptSource}
Expand All @@ -123,12 +124,14 @@ const makeCreateStaticRecord = transformSource =>
if (url) {
functorSource += `//# sourceURL=${url}\n`;
}

const moduleAnalysis = freeze({
exportAlls: freeze(sourceOptions.exportAlls),
imports: freeze(sourceOptions.imports),
liveExportMap: freeze(sourceOptions.liveExportMap),
fixedExportMap: freeze(sourceOptions.fixedExportMap),
importMetaProperties: freeze(
Array.from(sourceOptions.importMetaProperties),
),
functorSource,
});
return moduleAnalysis;
Expand Down Expand Up @@ -198,7 +201,6 @@ export const makeModuleTransformer = (babel, importer) => {
? maybeSource.slice(0, -1)
: maybeSource;

// console.log(ss.isExpr, `generated`, src, `from`, ast);
return { ...ss, endowments, src: actualSource };
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ function initialize(t, source, options = {}) {
imports: updateImports,
liveVar: liveUpdaters,
onceVar: onceUpdaters,
metaVar: { url: 'file://meta.url' },
meta: { url: 'file://meta.url' },
});

return { record, namespace, log, updaters };
Expand Down

0 comments on commit dfedd96

Please sign in to comment.