pass some live binding tests
MODIFY
src/helpers.js
src/helpers.js
@@ -133,7 +133,7 @@ function makeModuleInstance(
}
};
- // Always register the update function.
+ // Always register the updater function.
// If not in tdz, also update now.
const notify = updater => {
updaters.push(updater);
@@ -198,7 +198,8 @@ function makeModuleInstance(
...getProps(trappers),
});
- let optFunctor = evaluator(moduleStaticRecord.functorSource, endowments);
+ const { functorSource } = moduleStaticRecord;
+ let optFunctor = evaluator(functorSource, endowments);
function initialize() {
if (optFunctor) {
// uninitialized

MODIFY
src/index.js
src/index.js
@@ -14,9 +14,7 @@ const HIDDEN_SYMBOLS = [
const makeModulePlugin = options =>
function rewriteModules({ types: t }) {
- const {
- fixedExports,
- } = options;
+ const { fixedExports, liveExportMap } = options;
const hiddenIdentifier = h => {
const ident = t.identifier(h);
ident.agoricInternal = true;
@@ -58,6 +56,44 @@ const makeModulePlugin = options =>
);
path.replaceWith(t.callExpression(callee, [path.node.declaration]));
},
+ ExportNamedDeclaration(path) {
+ const decl = path.node.declaration;
+ const specs = path.node.specifiers;
+ const replace = [];
+ if (decl) {
+ replace.push(
+ ...decl.declarations.map(dec => {
+ // TODO: Detect if a non-const declaration is actually fixed.
+ const isLive = decl.kind !== 'const';
+ const { name } = dec.id;
+ if (isLive) {
+ liveExportMap[name] = [name];
+ } else {
+ fixedExports.push(name);
+ }
+ const callee = t.memberExpression(
+ hiddenIdentifier(isLive ? HIDDEN_LIVE : HIDDEN_ONCE),
+ dec.id,
+ );
+ return t.expressionStatement(
+ t.callExpression(callee, dec.init ? [dec.init] : []),
+ );
+ }),
+ );
+ }
+ replace.push(
+ ...specs.map(spec => {
+ const { local, exported } = spec;
+ liveExportMap[exported.name] = [local.name];
+ const callee = t.memberExpression(
+ hiddenIdentifier(HIDDEN_LIVE),
+ exported,
+ );
+ return t.expressionStatement(t.callExpression(callee, []));
+ }),
+ );
+ path.replaceWithMultiple(replace);
+ },
ImportNamespaceSpecifier(path) {
throw path.buildCodeFrameError(`"import *" is not yet implemented`);
},
@@ -123,6 +159,9 @@ const makeModuleTransformer = babelCore => {
parserOpts: {
plugins: parserPlugins,
},
+ generatorOpts: {
+ retainLines: true,
+ },
plugins: [modulePlugin],
});
@@ -144,12 +183,30 @@ const makeModuleTransformer = babelCore => {
fixedExports: [],
imports: {},
liveExportMap: {},
+ importSources: {},
+ importDecls: [],
};
const scriptSource = transformSource(moduleSource, sourceOptions);
+ let preamble = sourceOptions.importDecls.join(',');
+ if (preamble !== '') {
+ preamble = `let ${preamble};`;
+ }
+ const js = JSON.stringify;
+ const isrc = sourceOptions.importSources;
+ preamble += `${HIDDEN_IMPORTS}({${Object.keys(isrc)
+ .map(
+ src =>
+ `${js(src)}: ${Object.entries(isrc[src])
+ .map(([exp, upds]) => `${js(exp)}: [${upds.join(',')}]`)
+ .join(',')}`,
+ )
+ .join(',')}});`;
+
const functorSource = `\
(function moduleFunctor(${HIDDEN_IMPORTS}, ${HIDDEN_ONCE}, ${HIDDEN_LIVE}) { \
'use strict'; \
+ ${preamble} \
${scriptSource}
})`;
@@ -193,14 +250,7 @@ const makeModuleTransformer = babelCore => {
};
}
- return {
- endow(es) {
- // Add the $h_import hidden endowment.
- return {
- ...es,
- endowments: {
- ...es.endowments,
- [HIDDEN_IMPORT](importHandle) {
+ const hiddenImport = es => importHandle => {
const {
evaluatorAllowHidden,
url: baseUrl,
@@ -267,9 +317,13 @@ const makeModuleTransformer = babelCore => {
importExpr.meta = Object.create(null);
importExpr.meta.url = baseUrl;
return importExpr;
- },
- },
};
+
+ return {
+ endow(es) {
+ // Add the $h_import hidden endowment.
+ Object.assign(es.endowments, { [HIDDEN_IMPORT]: hiddenImport(es) });
+ return es;
},
rewrite(ss) {
// Transform the source into evaluable form.

RENAME
test/test.js
test/test-sanity.js
@@ -42,43 +42,3 @@ test('sanity', async t => {
t.end();
}
});
-
-test('import expressions', async t => {
- try {
- const transforms = [makeModuleTransformer(babelCore)];
- const { evaluateExpr, evaluateProgram, evaluateModule } = makeEvaluators({
- transforms,
- });
- for (const [name, myEval] of Object.entries({
- evaluateExpr,
- evaluateProgram,
- })) {
- t.deepEqual(
- // eslint-disable-next-line no-await-in-loop
- await myEval(
- `import('foo')`,
- {},
- {
- loader(spec) {
- return Promise.resolve([
- '.',
- `export default ${JSON.stringify(spec)};`,
- ]);
- },
- },
- ),
- { default: 'foo' },
- `${name} import expression works`,
- );
- }
- t.deepEqual(
- await evaluateModule(`export default bb;`, { bb: 'bingbang' }),
- { default: 'bingbang' },
- );
- } catch (e) {
- console.log('unexpected exception', e);
- t.assert(false, e);
- } finally {
- t.end();
- }
-});

pass some live binding tests