From bec9c661f9bf08ae676ba3ae3707c0e23599a58d Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Fri, 28 Feb 2020 02:34:03 -0800 Subject: [PATCH 1/7] feat(bundle-source): make getExport evaluate separate modules This still uses Rollup for bundling, but at least now the individual files are marked in stack traces. --- packages/bundle-source/demo/dir1/encourage.js | 1 + packages/bundle-source/demo/dir1/index.js | 5 +- packages/bundle-source/demo/dir1/sub/more.js | 3 + .../bundle-source/demo/dir1/sub/things.js | 1 + packages/bundle-source/package.json | 5 +- packages/bundle-source/src/index.js | 156 +++++++++++++++--- packages/bundle-source/test/sanity.js | 35 +++- yarn.lock | 45 ++++- 8 files changed, 220 insertions(+), 31 deletions(-) create mode 100644 packages/bundle-source/demo/dir1/sub/more.js create mode 100644 packages/bundle-source/demo/dir1/sub/things.js diff --git a/packages/bundle-source/demo/dir1/encourage.js b/packages/bundle-source/demo/dir1/encourage.js index 0c0bbddb713..7d08a850ca3 100644 --- a/packages/bundle-source/demo/dir1/encourage.js +++ b/packages/bundle-source/demo/dir1/encourage.js @@ -1,2 +1,3 @@ export const message = `You're great!`; export const encourage = nick => `Hey ${nick}! ${message}`; +export const makeError = msg => Error(msg); diff --git a/packages/bundle-source/demo/dir1/index.js b/packages/bundle-source/demo/dir1/index.js index ca8fac40fc7..deec7419fe7 100644 --- a/packages/bundle-source/demo/dir1/index.js +++ b/packages/bundle-source/demo/dir1/index.js @@ -1,8 +1,11 @@ import harden from '@agoric/harden'; -import { encourage } from './encourage'; +import { encourage, makeError } from './encourage'; +import more from './sub/more'; export default function makeEncourager() { return harden({ encourage, + makeError, + more, }); } diff --git a/packages/bundle-source/demo/dir1/sub/more.js b/packages/bundle-source/demo/dir1/sub/more.js new file mode 100644 index 00000000000..8ae41d56169 --- /dev/null +++ b/packages/bundle-source/demo/dir1/sub/more.js @@ -0,0 +1,3 @@ +const things = require('./things.js'); + +exports.more = `have more ${things.description}`; diff --git a/packages/bundle-source/demo/dir1/sub/things.js b/packages/bundle-source/demo/dir1/sub/things.js new file mode 100644 index 00000000000..b6d1d836d65 --- /dev/null +++ b/packages/bundle-source/demo/dir1/sub/things.js @@ -0,0 +1 @@ +exports.description = 'many different things'; diff --git a/packages/bundle-source/package.json b/packages/bundle-source/package.json index b3fe2fbd596..fd0f5e666ec 100644 --- a/packages/bundle-source/package.json +++ b/packages/bundle-source/package.json @@ -19,10 +19,11 @@ "dependencies": { "@agoric/acorn-eventual-send": "^2.0.0", "@agoric/harden": "^0.0.4", + "@rollup/plugin-commonjs": "^11.0.2", + "@rollup/plugin-node-resolve": "^7.1.1", "acorn": "^7.1.0", "esm": "^3.2.5", - "rollup": "^1.25.1", - "rollup-plugin-node-resolve": "^5.2.0" + "rollup": "^1.32.0" }, "keywords": [], "files": [ diff --git a/packages/bundle-source/src/index.js b/packages/bundle-source/src/index.js index 64e35180e6a..6d1984f45b4 100644 --- a/packages/bundle-source/src/index.js +++ b/packages/bundle-source/src/index.js @@ -1,6 +1,7 @@ import { rollup as rollup0 } from 'rollup'; import path from 'path'; -import resolve0 from 'rollup-plugin-node-resolve'; +import resolve0 from '@rollup/plugin-node-resolve'; +import commonjs0 from '@rollup/plugin-commonjs'; import eventualSend from '@agoric/acorn-eventual-send'; import * as acorn from 'acorn'; @@ -11,52 +12,165 @@ export default async function bundleSource( moduleFormat = DEFAULT_MODULE_FORMAT, access, ) { - const { rollup, resolvePlugin, pathResolve } = access || { + if (moduleFormat !== 'getExport') { + throw Error(`moduleFormat ${moduleFormat} is not implemented`); + } + const { commonjsPlugin, rollup, resolvePlugin, pathResolve } = access || { rollup: rollup0, resolvePlugin: resolve0, + commonjsPlugin: commonjs0, pathResolve: path.resolve, }; const resolvedPath = pathResolve(startFilename); const bundle = await rollup({ input: resolvedPath, treeshake: false, + preserveModules: true, external: ['@agoric/evaluate', '@agoric/nat', '@agoric/harden'], - plugins: [resolvePlugin({ preferBuiltins: true })], + plugins: [resolvePlugin({ preferBuiltins: true }), commonjsPlugin()], acornInjectPlugins: [eventualSend(acorn)], }); const { output } = await bundle.generate({ exports: 'named', - format: moduleFormat === 'getExport' ? 'cjs' : moduleFormat, + format: 'cjs', + sourcemap: true, }); - if (output.length !== 1) { - throw Error('unprepared for more than one chunk/asset'); + // console.log(output); + + // Create a source bundle. + const sourceBundle = {}; + let entrypoint; + for (const chunk of output) { + if (chunk.isAsset) { + throw Error(`unprepared for assets: ${chunk.fileName}`); + } + const { code, fileName, isEntry } = chunk; + if (isEntry) { + entrypoint = fileName; + } + sourceBundle[fileName] = code; } - if (output[0].isAsset) { - throw Error(`unprepared for assets: ${output[0].fileName}`); + + if (!entrypoint) { + throw Error('No entrypoint found in output bundle'); } - let { code: source } = output[0]; - // 'source' is now a string that contains a program, which references + // 'sourceBundle' is now an object that contains multiple programs, which references // require() and sets module.exports . This is close, but we need a single // stringifiable function, so we must wrap it in an outer function that - // returns the exports. + // returns the entrypoint exports. // // build-kernel.js will prefix this with 'export default' so it becomes an // ES6 module. The Vat controller will wrap it with parenthesis so it can // be evaluated and invoked to get at the exports. - const sourceMap = `//# sourceURL=${resolvedPath}\n`; - if (moduleFormat === 'getExport') - source = `\ -function getExport() { 'use strict'; \ -let exports = {}; \ -const module = { exports }; \ -\ -${source} + // const sourceMap = `//# sourceMappingURL=${output[0].map.toUrl()}\n`; + const sourceMap = `//# sourceURL:file:///bundle-source/${moduleFormat}-preamble.js`; -return module.exports; -} + // console.log(sourceMap); + let source; + if (moduleFormat === 'getExport') { + // This function's source code is inlined in the output bundle. + // It creates an evaluable string for a given module filename. + function createEvalString(filename) { + const code = sourceBundle[filename]; + if (!code) { + return undefined; + } + return `\ +(function getOneExport(require) { \ + 'use strict'; \ + let exports = {}; \ + const module = { exports }; \ + \ + ${code} + return module.exports; +}) +//# sourceURL=file:///bundle-source/${moduleFormat}/${filename} `; + } + + // This function's source code is inlined in the output bundle. + // It figures out the exports from a given module filename. + const nsBundle = {}; + function computeExports(filename, powers) { + const { eval: myEval, require: myRequire, _log } = powers; + // This captures the endowed require. + const match = filename.match(/^(.*)\/[^\/]+$/); + const thisdir = match ? match[1] : '.'; + const contextRequire = mod => { + // Do path algebra to find the actual source. + const els = mod.split('/'); + let prefix; + if (els[0][0] === '@') { + // Scoped name. + prefix = els.splice(0, 2).join('/'); + } else if (els[0][0] === '.') { + // Relative. + els.unshift(...thisdir.split('/')); + } else { + // Bare or absolute. + prefix = els.splice(0, 1); + } + + const suffix = []; + for (const el of els) { + if (el === '.' || el === '') { + // Do nothing. + } else if (el === '..') { + // Traverse upwards. + suffix.pop(); + } else { + suffix.push(el); + } + } + + // log(mod, prefix, suffix); + if (prefix !== undefined) { + suffix.unshift(prefix); + } + let modPath = suffix.join('/'); + if (modPath.startsWith('./')) { + modPath = modPath.slice(2); + } + // log('requiring', modPath); + if (!(modPath in nsBundle)) { + // log('evaluating', modPath); + nsBundle[modPath] = computeExports(modPath, powers); + } + + // log('returning', nsBundle[modPath]); + return nsBundle[modPath]; + }; + + const code = createEvalString(filename); + if (!code) { + // log('missing code for', filename, sourceBundle); + return myRequire(filename); + } + + // log('evaluating', code); + return (1, myEval)(code)(contextRequire); + } + + source = `\ +function getExport() { + 'use strict'; + // Serialised sources. + const moduleFormat = ${JSON.stringify(moduleFormat)}; + const sourceBundle = ${JSON.stringify(sourceBundle, undefined, 2)}; + const nsBundle = {}; + + ${createEvalString} + + ${computeExports} + + // Evaluate the entrypoint recursively. + const entrypoint = ${JSON.stringify(entrypoint)} + return computeExports(entrypoint, { eval, require, log(...args) { return console.log(...args); } }); +}`; + } + // console.log(sourceMap); return { source, sourceMap, moduleFormat }; } diff --git a/packages/bundle-source/test/sanity.js b/packages/bundle-source/test/sanity.js index 5a7b10e937c..d5b51c6f380 100644 --- a/packages/bundle-source/test/sanity.js +++ b/packages/bundle-source/test/sanity.js @@ -3,17 +3,40 @@ import bundleSource from '..'; test('sanity', async t => { try { - const { moduleFormat: mf1, source: src1 } = await bundleSource( - `${__dirname}/../demo/dir1`, - ); + const { + moduleFormat: mf1, + source: src1, + sourceMap: map1, + } = await bundleSource(`${__dirname}/../demo/dir1`); + + const srcMap1 = `(${src1}\n)()\n${map1}`; + + // console.log(srcMap1); + t.equal(mf1, 'getExport', 'module format is getExport'); t.assert(src1.match(/require\('@agoric\/harden'\)/), 'harden is required'); - const { moduleFormat: mf2, source: src2 } = await bundleSource( - `${__dirname}/../demo/dir1/encourage.js`, + + // eslint-disable-next-line no-eval + const ex1 = (1, eval)(`function require() { return o => o };${srcMap1}`); + + const bundle = ex1.default(); + const err = bundle.makeError('foo'); + t.assert( + err.stack.indexOf('(file:///bundle-source/getExport/encourage.js:') >= 0, + 'bundled source is in stack trace', ); + + const { + moduleFormat: mf2, + source: src2, + sourceMap: map2, + } = await bundleSource(`${__dirname}/../demo/dir1/encourage.js`); t.equal(mf2, 'getExport', 'module format 2 is getExport'); + + const srcMap2 = `(${src2}\n)()\n${map2}`; + // eslint-disable-next-line no-eval - const ex2 = eval(`(${src2}\n)()`); + const ex2 = (1, eval)(srcMap2); t.equal(ex2.message, `You're great!`, 'exported message matches'); t.equal( ex2.encourage('Nick'), diff --git a/yarn.lock b/yarn.lock index ae9863ce944..e1a8f177edd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1671,6 +1671,35 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== +"@rollup/plugin-commonjs@^11.0.2": + version "11.0.2" + resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-11.0.2.tgz#837cc6950752327cb90177b608f0928a4e60b582" + integrity sha512-MPYGZr0qdbV5zZj8/2AuomVpnRVXRU5XKXb3HVniwRoRCreGlf5kOE081isNWeiLIi6IYkwTX9zE0/c7V8g81g== + dependencies: + "@rollup/pluginutils" "^3.0.0" + estree-walker "^1.0.1" + is-reference "^1.1.2" + magic-string "^0.25.2" + resolve "^1.11.0" + +"@rollup/plugin-node-resolve@^7.1.1": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.1.tgz#8c6e59c4b28baf9d223028d0e450e06a485bb2b7" + integrity sha512-14ddhD7TnemeHE97a4rLOhobfYvUVcaYuqTnL8Ti7Jxi9V9Jr5LY7Gko4HZ5k4h4vqQM0gBQt6tsp9xXW94WPA== + dependencies: + "@rollup/pluginutils" "^3.0.6" + "@types/resolve" "0.0.8" + builtin-modules "^3.1.0" + is-module "^1.0.0" + resolve "^1.14.2" + +"@rollup/pluginutils@^3.0.0", "@rollup/pluginutils@^3.0.6": + version "3.0.8" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.0.8.tgz#4e94d128d94b90699e517ef045422960d18c8fde" + integrity sha512-rYGeAc4sxcZ+kPG/Tw4/fwJODC3IXHYDH4qusdN/b6aLw5LPUbzpecYbEJh4sVQGPFJxd2dBU4kc1H3oy9/bnw== + dependencies: + estree-walker "^1.0.1" + "@svgr/babel-plugin-add-jsx-attribute@^4.2.0": version "4.2.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.2.0.tgz#dadcb6218503532d6884b210e7f3c502caaa44b1" @@ -4969,6 +4998,11 @@ estree-walker@^0.6.1: resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362" integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w== +estree-walker@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" + integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== + esutils@^2.0.0, esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -10778,7 +10812,7 @@ rollup-pluginutils@^2.8.1: dependencies: estree-walker "^0.6.1" -rollup@^1.16.6, rollup@^1.16.7, rollup@^1.2.2, rollup@^1.23.1, rollup@^1.24.0, rollup@^1.25.1, rollup@^1.26.2: +rollup@^1.16.6, rollup@^1.16.7, rollup@^1.2.2, rollup@^1.23.1, rollup@^1.24.0, rollup@^1.26.2: version "1.27.5" resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.27.5.tgz#d100fb0ffd8353575cb2057152547b9abfddfe59" integrity sha512-8rfVdzuTg2kt8ObD9LNJpEwUN7B6lsl3sHc5fddtgICpLjpYeSf4m2+RftBzcCaBTMi1iYX3Ez8zFT4Gj2nJjg== @@ -10787,6 +10821,15 @@ rollup@^1.16.6, rollup@^1.16.7, rollup@^1.2.2, rollup@^1.23.1, rollup@^1.24.0, r "@types/node" "*" acorn "^7.1.0" +rollup@^1.32.0: + version "1.32.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.32.0.tgz#c65ce134850aca1ce595fcac07d1dc5d53bf227c" + integrity sha512-ab2tF5pdDqm2zuI8j02ceyrJSScl9V2C24FgWQ1v1kTFTu1UrG5H0hpP++mDZlEFyZX4k0chtGEHU2i+pAzBgA== + dependencies: + "@types/estree" "*" + "@types/node" "*" + acorn "^7.1.0" + rsvp@^4.8.4: version "4.8.5" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" From f234d49be14d50d13249d79f7302aa8e594e23d2 Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Fri, 28 Feb 2020 13:09:53 -0800 Subject: [PATCH 2/7] fix(bundle-source): regain default 'getExport' --- packages/bundle-source/src/index.js | 52 ++++++++++++++----- packages/bundle-source/test/sanity.js | 74 ++++++++++++++++++++++++--- 2 files changed, 106 insertions(+), 20 deletions(-) diff --git a/packages/bundle-source/src/index.js b/packages/bundle-source/src/index.js index 6d1984f45b4..67c8e4f692f 100644 --- a/packages/bundle-source/src/index.js +++ b/packages/bundle-source/src/index.js @@ -6,13 +6,15 @@ import eventualSend from '@agoric/acorn-eventual-send'; import * as acorn from 'acorn'; const DEFAULT_MODULE_FORMAT = 'getExport'; +const DEFAULT_FILE_PREFIX = '/bundled-source'; +const SUPPORTED_FORMATS = ['getExport', 'nestedEvaluate']; export default async function bundleSource( startFilename, moduleFormat = DEFAULT_MODULE_FORMAT, - access, + access = undefined, ) { - if (moduleFormat !== 'getExport') { + if (!SUPPORTED_FORMATS.includes(moduleFormat)) { throw Error(`moduleFormat ${moduleFormat} is not implemented`); } const { commonjsPlugin, rollup, resolvePlugin, pathResolve } = access || { @@ -25,7 +27,7 @@ export default async function bundleSource( const bundle = await rollup({ input: resolvedPath, treeshake: false, - preserveModules: true, + preserveModules: moduleFormat === 'nestedEvaluate', external: ['@agoric/evaluate', '@agoric/nat', '@agoric/harden'], plugins: [resolvePlugin({ preferBuiltins: true }), commonjsPlugin()], acornInjectPlugins: [eventualSend(acorn)], @@ -65,20 +67,40 @@ export default async function bundleSource( // be evaluated and invoked to get at the exports. // const sourceMap = `//# sourceMappingURL=${output[0].map.toUrl()}\n`; - const sourceMap = `//# sourceURL:file:///bundle-source/${moduleFormat}-preamble.js`; // console.log(sourceMap); + let sourceMap; let source; if (moduleFormat === 'getExport') { + sourceMap = `//# sourceURL=${resolvedPath}\n`; + + if (Object.keys(sourceBundle).length !== 1) { + throw Error('unprepared for more than one chunk'); + } + + source = `\ +function getExport() { 'use strict'; \ +let exports = {}; \ +const module = { exports }; \ +\ +${sourceBundle[entrypoint]} + +return module.exports; +} +`; + } else if (moduleFormat === 'nestedEvaluate') { + sourceMap = `//# sourceURL=${DEFAULT_FILE_PREFIX}-preamble.js\n`; + // This function's source code is inlined in the output bundle. // It creates an evaluable string for a given module filename. + const filePrefix = DEFAULT_FILE_PREFIX; function createEvalString(filename) { const code = sourceBundle[filename]; if (!code) { return undefined; } return `\ -(function getOneExport(require) { \ +(function getExport(require) { \ 'use strict'; \ let exports = {}; \ const module = { exports }; \ @@ -86,15 +108,18 @@ export default async function bundleSource( ${code} return module.exports; }) -//# sourceURL=file:///bundle-source/${moduleFormat}/${filename} +//# sourceURL=${filePrefix}/${filename} `; } // This function's source code is inlined in the output bundle. // It figures out the exports from a given module filename. const nsBundle = {}; + const nestedEvaluate = _src => { + throw Error('need to override nestedEvaluate'); + }; function computeExports(filename, powers) { - const { eval: myEval, require: myRequire, _log } = powers; + const { require: myRequire, _log } = powers; // This captures the endowed require. const match = filename.match(/^(.*)\/[^\/]+$/); const thisdir = match ? match[1] : '.'; @@ -149,15 +174,19 @@ export default async function bundleSource( return myRequire(filename); } - // log('evaluating', code); - return (1, myEval)(code)(contextRequire); + // log('evaluating', typeof nestedEvaluate, code); + return nestedEvaluate(code)(contextRequire); } source = `\ -function getExport() { +function getExportWithNestedEvaluate(filePrefix) { 'use strict'; // Serialised sources. + if (filePrefix === undefined) { + filePrefix = ${JSON.stringify(DEFAULT_FILE_PREFIX)}; + } const moduleFormat = ${JSON.stringify(moduleFormat)}; + const entrypoint = ${JSON.stringify(entrypoint)}; const sourceBundle = ${JSON.stringify(sourceBundle, undefined, 2)}; const nsBundle = {}; @@ -166,8 +195,7 @@ function getExport() { ${computeExports} // Evaluate the entrypoint recursively. - const entrypoint = ${JSON.stringify(entrypoint)} - return computeExports(entrypoint, { eval, require, log(...args) { return console.log(...args); } }); + return computeExports(entrypoint, { require, log(...args) { return console.log(...args); } }); }`; } diff --git a/packages/bundle-source/test/sanity.js b/packages/bundle-source/test/sanity.js index d5b51c6f380..95f9ef33ad0 100644 --- a/packages/bundle-source/test/sanity.js +++ b/packages/bundle-source/test/sanity.js @@ -1,29 +1,87 @@ import { test } from 'tape-promise/tape'; +import { evaluateProgram as evaluate } from '@agoric/evaluate'; import bundleSource from '..'; -test('sanity', async t => { +test('nestedEvaluate', async t => { try { const { moduleFormat: mf1, source: src1, sourceMap: map1, - } = await bundleSource(`${__dirname}/../demo/dir1`); + } = await bundleSource(`${__dirname}/../demo/dir1`, 'nestedEvaluate'); - const srcMap1 = `(${src1}\n)()\n${map1}`; + const srcMap1 = `(${src1})\n${map1}`; + + // console.log(srcMap1); + + t.equal(mf1, 'nestedEvaluate', 'module format is nestedEvaluate'); + t.assert(src1.match(/require\('@agoric\/harden'\)/), 'harden is required'); + + // Fake out `require('@agoric/harden')`. + const require = _ => o => o; + const nestedEvaluate = src => { + // console.log('========== evaluating', src); + return evaluate(src, { require, nestedEvaluate }); + }; + const ex1 = nestedEvaluate(srcMap1)(); + + const bundle = ex1.default(); + const err = bundle.makeError('foo'); + t.assert( + err.stack.indexOf('(/bundled-source/encourage.js:') >= 0, + 'bundled source is in stack trace', + ); + + const { + moduleFormat: mf2, + source: src2, + sourceMap: map2, + } = await bundleSource( + `${__dirname}/../demo/dir1/encourage.js`, + 'nestedEvaluate', + ); + t.equal(mf2, 'nestedEvaluate', 'module format 2 is nestedEvaluate'); + + const srcMap2 = `(${src2})\n${map2}`; + + const ex2 = nestedEvaluate(srcMap2)(); + t.equal(ex2.message, `You're great!`, 'exported message matches'); + t.equal( + ex2.encourage('Nick'), + `Hey Nick! You're great!`, + 'exported encourage matches', + ); + } catch (e) { + t.isNot(e, e, 'unexpected exception'); + } finally { + t.end(); + } +}); + +test('getExport', async t => { + try { + const { + moduleFormat: mf1, + source: src1, + sourceMap: map1, + } = await bundleSource(`${__dirname}/../demo/dir1`, 'getExport'); + + const srcMap1 = `(${src1})\n${map1}`; // console.log(srcMap1); t.equal(mf1, 'getExport', 'module format is getExport'); t.assert(src1.match(/require\('@agoric\/harden'\)/), 'harden is required'); + // Fake out `require('@agoric/harden')`. // eslint-disable-next-line no-eval - const ex1 = (1, eval)(`function require() { return o => o };${srcMap1}`); + const ex1 = eval(`const require = _ => o => o;${srcMap1}`)(); const bundle = ex1.default(); const err = bundle.makeError('foo'); t.assert( - err.stack.indexOf('(file:///bundle-source/getExport/encourage.js:') >= 0, - 'bundled source is in stack trace', + err.stack.indexOf('(/bundled-source/encourage.js:') < 0, + 'bundled source is not in stack trace', ); const { @@ -33,10 +91,10 @@ test('sanity', async t => { } = await bundleSource(`${__dirname}/../demo/dir1/encourage.js`); t.equal(mf2, 'getExport', 'module format 2 is getExport'); - const srcMap2 = `(${src2}\n)()\n${map2}`; + const srcMap2 = `(${src2})\n${map2}`; // eslint-disable-next-line no-eval - const ex2 = (1, eval)(srcMap2); + const ex2 = eval(srcMap2)(); t.equal(ex2.message, `You're great!`, 'exported message matches'); t.equal( ex2.encourage('Nick'), From deb8ee73437cb86ef98c160239c931305fb370ad Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Fri, 28 Feb 2020 13:10:45 -0800 Subject: [PATCH 3/7] feat(nestedEvaluate): support new moduleFormat --- packages/SwingSet/scripts/build-kernel.js | 1 + packages/SwingSet/src/controller.js | 23 +++++++++++---- packages/spawner/src/contractHost.js | 29 ++++++++++++++----- packages/tame-metering/src/ses1.js | 1 + packages/zoe/src/evalContractCode.js | 6 ++-- packages/zoe/src/zoe.js | 3 +- packages/zoe/test/bundle-source.js | 4 +++ .../zoe-metering/test-zoe-metering.js | 2 +- .../zoe/test/swingsetTests/zoe/test-zoe.js | 2 +- .../contracts/test-automaticRefund.js | 2 +- .../test/unitTests/contracts/test-autoswap.js | 2 +- .../unitTests/contracts/test-coveredCall.js | 2 +- .../unitTests/contracts/test-myFirstDapp.js | 2 +- .../unitTests/contracts/test-publicAuction.js | 2 +- .../unitTests/contracts/test-publicSwap.js | 2 +- .../contracts/test-simpleExchange.js | 2 +- 16 files changed, 60 insertions(+), 25 deletions(-) create mode 100644 packages/zoe/test/bundle-source.js diff --git a/packages/SwingSet/scripts/build-kernel.js b/packages/SwingSet/scripts/build-kernel.js index d5442454a17..62b1a16cef8 100644 --- a/packages/SwingSet/scripts/build-kernel.js +++ b/packages/SwingSet/scripts/build-kernel.js @@ -5,6 +5,7 @@ import bundleSource from '@agoric/bundle-source'; async function main() { const { source, sourceMap } = await bundleSource( `${__dirname}/../src/kernel/index.js`, + 'nestedEvaluate', ); const actualSource = `export default ${source}\n${sourceMap}`; const f = await fs.promises.open('src/bundles/kernel', 'w', 0o644); diff --git a/packages/SwingSet/src/controller.js b/packages/SwingSet/src/controller.js index 3f8782bb73b..40f705272cb 100644 --- a/packages/SwingSet/src/controller.js +++ b/packages/SwingSet/src/controller.js @@ -204,11 +204,19 @@ function realmRegisterEndOfCrank(fn) { // static vats once we add metering support to the dynamic vat // implementation. // FIXME: Same for registerEndOfCrank. - return s.evaluate(src, { - require: r, - registerEndOfCrank: realmRegisterEndOfCrank, - replaceGlobalMeter, - })().default; + + // Cope with ESM problems. + src = src.replace(/(_[a-zA-Z0-9]{3}\u200d\.e)/g, 'eval'); + + // Support both getExport and nestedEvaluate module format. + const nestedEvaluate = source => + s.evaluate(source, { + require: r, + registerEndOfCrank: realmRegisterEndOfCrank, + replaceGlobalMeter, + nestedEvaluate, + }); + return nestedEvaluate(src)().default; }; } @@ -271,7 +279,10 @@ export async function buildVatController(config, withSES = true, argv = []) { // (which is expected to initialize some state and export some facetIDs) let setup; if (withSES) { - const { source, sourceMap } = await bundleSource(`${sourceIndex}`); + const { source, sourceMap } = await bundleSource( + `${sourceIndex}`, + 'nestedEvaluate', + ); const actualSource = `(${source})\n${sourceMap}`; setup = sesEvaluator(actualSource); } else { diff --git a/packages/spawner/src/contractHost.js b/packages/spawner/src/contractHost.js index 97abccd53a1..fbfa1b2012d 100644 --- a/packages/spawner/src/contractHost.js +++ b/packages/spawner/src/contractHost.js @@ -98,10 +98,18 @@ function makeContractHost(E, evaluate, additionalEndowments = {}) { return meter; }; - const fn = evaluate(functionSrcString, { - ...fullEndowments, - getMeter, - }); + // Inject the evaluator. + const nestedEvaluate = src => { + const allEndowments = { + ...fullEndowments, + getMeter, + nestedEvaluate, + }; + // console.log(allEndowments, src); + return evaluate(src, allEndowments); + }; + + const fn = nestedEvaluate(functionSrcString); assert( typeof fn === 'function', `"${functionSrcString}" must be a string for a function, but produced ${typeof fn}`, @@ -140,7 +148,10 @@ function makeContractHost(E, evaluate, additionalEndowments = {}) { let installation; if (moduleFormat === 'object') { installation = extractCheckFunctions(contractSrcs); - } else if (moduleFormat === 'getExport') { + } else if ( + moduleFormat === 'getExport' || + moduleFormat === 'nestedEvaluate' + ) { // We don't support 'check' functions in getExport format, // because we only do a single evaluate, and the whole // contract must be metered per-spawn, not per-installation. @@ -161,8 +172,12 @@ function makeContractHost(E, evaluate, additionalEndowments = {}) { function spawn(termsP) { let startFn; if (moduleFormat === 'object') { - startFn = evaluateStringToFn(contractSrcs.start); - } else if (moduleFormat === 'getExport') { + startFn = evaluateStringToFn(contractSrcs.start, ); + } else if ( + moduleFormat === 'getExport' || + moduleFormat === 'nestedEvaluate' + ) { + // We support getExport because it is forward-compatible with nestedEvaluate. const getExports = evaluateStringToFn(contractSrcs); const ns = getExports(); startFn = ns.default; diff --git a/packages/tame-metering/src/ses1.js b/packages/tame-metering/src/ses1.js index 181a0763c94..99555d68a76 100644 --- a/packages/tame-metering/src/ses1.js +++ b/packages/tame-metering/src/ses1.js @@ -23,6 +23,7 @@ const shim = `\ }; })()`; +// Adapt to ESM. export const SES1TameMeteringShim = shim.replace( /_[a-z0-9]{3}\u200d\.g\./gs, '', diff --git a/packages/zoe/src/evalContractCode.js b/packages/zoe/src/evalContractCode.js index 00397f422ef..a157024e643 100644 --- a/packages/zoe/src/evalContractCode.js +++ b/packages/zoe/src/evalContractCode.js @@ -1,5 +1,5 @@ /* global replaceGlobalMeter, registerEndOfCrank */ -import evaluate from '@agoric/evaluate'; +import { evaluateProgram } from '@agoric/evaluate'; import Nat from '@agoric/nat'; import harden from '@agoric/harden'; @@ -12,7 +12,9 @@ import { sameStructure } from '@agoric/same-structure'; const evaluateStringToFn = (functionSrcString, endowments) => { assert.typeof(functionSrcString, 'string'); - const fn = evaluate(functionSrcString, endowments); + const nestedEvaluate = src => + evaluateProgram(src, { ...endowments, nestedEvaluate }); + const fn = nestedEvaluate(`(${functionSrcString})`); assert.typeof( fn, 'function', diff --git a/packages/zoe/src/zoe.js b/packages/zoe/src/zoe.js index f44e3b642cf..42568a6b04d 100644 --- a/packages/zoe/src/zoe.js +++ b/packages/zoe/src/zoe.js @@ -249,9 +249,10 @@ const makeZoe = (additionalEndowments = {}) => { * registering it with Zoe. We have a moduleFormat to allow for * different future formats without silent failures. */ - install: (code, moduleFormat = 'getExport') => { + install: (code, moduleFormat = 'nestedEvaluate') => { let installation; switch (moduleFormat) { + case 'nestedEvaluate': case 'getExport': { installation = evalContractCode(code, additionalEndowments); break; diff --git a/packages/zoe/test/bundle-source.js b/packages/zoe/test/bundle-source.js new file mode 100644 index 00000000000..d5da8b8cd95 --- /dev/null +++ b/packages/zoe/test/bundle-source.js @@ -0,0 +1,4 @@ +import bundleSource from '@agoric/bundle-source'; + +// Use the new format. +export default src => bundleSource(src, 'nestedEvaluate'); diff --git a/packages/zoe/test/swingsetTests/zoe-metering/test-zoe-metering.js b/packages/zoe/test/swingsetTests/zoe-metering/test-zoe-metering.js index d6c78dd0501..bf379cd2ac3 100644 --- a/packages/zoe/test/swingsetTests/zoe-metering/test-zoe-metering.js +++ b/packages/zoe/test/swingsetTests/zoe-metering/test-zoe-metering.js @@ -2,7 +2,7 @@ import { test } from 'tape-promise/tape'; import { loadBasedir, buildVatController } from '@agoric/swingset-vat'; import path from 'path'; import fs from 'fs'; -import bundleSource from '@agoric/bundle-source'; +import bundleSource from '../../bundle-source'; // Don't let unhandled promises crash our process. process.on('unhandledRejection', e => console.log('unhandled rejection', e)); diff --git a/packages/zoe/test/swingsetTests/zoe/test-zoe.js b/packages/zoe/test/swingsetTests/zoe/test-zoe.js index c06a8de04b8..d112e8a9a90 100644 --- a/packages/zoe/test/swingsetTests/zoe/test-zoe.js +++ b/packages/zoe/test/swingsetTests/zoe/test-zoe.js @@ -2,7 +2,7 @@ import { test } from 'tape-promise/tape'; import { loadBasedir, buildVatController } from '@agoric/swingset-vat'; import path from 'path'; import fs from 'fs'; -import bundleSource from '@agoric/bundle-source'; +import bundleSource from '../../bundle-source'; const CONTRACT_FILES = [ 'automaticRefund', diff --git a/packages/zoe/test/unitTests/contracts/test-automaticRefund.js b/packages/zoe/test/unitTests/contracts/test-automaticRefund.js index 392bb33813f..3b543a9b95a 100644 --- a/packages/zoe/test/unitTests/contracts/test-automaticRefund.js +++ b/packages/zoe/test/unitTests/contracts/test-automaticRefund.js @@ -1,6 +1,6 @@ import { test } from 'tape-promise/tape'; import harden from '@agoric/harden'; -import bundleSource from '@agoric/bundle-source'; +import bundleSource from '../../bundle-source'; import { makeZoe } from '../../../src/zoe'; import { setup } from '../setupBasicMints'; diff --git a/packages/zoe/test/unitTests/contracts/test-autoswap.js b/packages/zoe/test/unitTests/contracts/test-autoswap.js index 5d80335f1fe..5e6bfe958f1 100644 --- a/packages/zoe/test/unitTests/contracts/test-autoswap.js +++ b/packages/zoe/test/unitTests/contracts/test-autoswap.js @@ -1,6 +1,6 @@ import { test } from 'tape-promise/tape'; import harden from '@agoric/harden'; -import bundleSource from '@agoric/bundle-source'; +import bundleSource from '../../bundle-source'; import { makeZoe } from '../../../src/zoe'; import { setup } from '../setupBasicMints'; diff --git a/packages/zoe/test/unitTests/contracts/test-coveredCall.js b/packages/zoe/test/unitTests/contracts/test-coveredCall.js index 258b2235efa..90d3e650560 100644 --- a/packages/zoe/test/unitTests/contracts/test-coveredCall.js +++ b/packages/zoe/test/unitTests/contracts/test-coveredCall.js @@ -1,6 +1,6 @@ import { test } from 'tape-promise/tape'; import harden from '@agoric/harden'; -import bundleSource from '@agoric/bundle-source'; +import bundleSource from '../../bundle-source'; import { sameStructure } from '@agoric/same-structure'; import buildManualTimer from '../../../tools/manualTimer'; diff --git a/packages/zoe/test/unitTests/contracts/test-myFirstDapp.js b/packages/zoe/test/unitTests/contracts/test-myFirstDapp.js index c3a5cf7e6f5..2a16f9d40d5 100644 --- a/packages/zoe/test/unitTests/contracts/test-myFirstDapp.js +++ b/packages/zoe/test/unitTests/contracts/test-myFirstDapp.js @@ -1,6 +1,6 @@ import { test } from 'tape-promise/tape'; import harden from '@agoric/harden'; -import bundleSource from '@agoric/bundle-source'; +import bundleSource from '../../bundle-source'; import { makeZoe } from '../../../src/zoe'; import { setup } from '../setupBasicMints'; diff --git a/packages/zoe/test/unitTests/contracts/test-publicAuction.js b/packages/zoe/test/unitTests/contracts/test-publicAuction.js index 6c655abbba7..79f8adb82c0 100644 --- a/packages/zoe/test/unitTests/contracts/test-publicAuction.js +++ b/packages/zoe/test/unitTests/contracts/test-publicAuction.js @@ -1,6 +1,6 @@ import { test } from 'tape-promise/tape'; import harden from '@agoric/harden'; -import bundleSource from '@agoric/bundle-source'; +import bundleSource from '../../bundle-source'; import { makeZoe } from '../../../src/zoe'; import { setup } from '../setupBasicMints'; diff --git a/packages/zoe/test/unitTests/contracts/test-publicSwap.js b/packages/zoe/test/unitTests/contracts/test-publicSwap.js index 48f3604884b..ba722622b7c 100644 --- a/packages/zoe/test/unitTests/contracts/test-publicSwap.js +++ b/packages/zoe/test/unitTests/contracts/test-publicSwap.js @@ -1,6 +1,6 @@ import { test } from 'tape-promise/tape'; import harden from '@agoric/harden'; -import bundleSource from '@agoric/bundle-source'; +import bundleSource from '../../bundle-source'; import { makeZoe } from '../../../src/zoe'; import { setup } from '../setupBasicMints'; diff --git a/packages/zoe/test/unitTests/contracts/test-simpleExchange.js b/packages/zoe/test/unitTests/contracts/test-simpleExchange.js index a1f032a3d7a..f26aa0808cb 100644 --- a/packages/zoe/test/unitTests/contracts/test-simpleExchange.js +++ b/packages/zoe/test/unitTests/contracts/test-simpleExchange.js @@ -1,6 +1,6 @@ import { test } from 'tape-promise/tape'; import harden from '@agoric/harden'; -import bundleSource from '@agoric/bundle-source'; +import bundleSource from '../../bundle-source'; import { makeZoe } from '../../../src/zoe'; import { setup } from '../setupBasicMints'; From a41d67d21714e1398649fe7375b6ad89a16951d0 Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Fri, 28 Feb 2020 14:03:52 -0800 Subject: [PATCH 4/7] doc(bundle-source): describe moduleFormats --- packages/bundle-source/README.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/packages/bundle-source/README.md b/packages/bundle-source/README.md index 2028b828608..949fb2ba5c6 100644 --- a/packages/bundle-source/README.md +++ b/packages/bundle-source/README.md @@ -25,3 +25,34 @@ or inside an async function (and therefore outside of Jessie), do: const { moduleFormat, source, sourceMap } = await sourceBundleP; ... ``` + +## getExport moduleFormat + +The first main `moduleFormat` is the `"getExport"` format. It generates +source like: + +```js +function getExport() { + let exports = {}; + const module = { exports }; + // CommonJS source translated from the inputs. + ... + return module.exports; +} +``` + +To evaluate it and obtain the resulting module namespace, you need to endow +a `require` function to resolve external imports. + +## nestedEvaluate moduleFormat + +This is logically similar to the `getExport` format, except that the code +may additionally depend upon a `nestedEvaluate(src)` function to be used +to evaluate submodules in the same context as the parent function. + +The advantage of this format is that it helps preserve the filenames within +the bundle in the event of any stack traces. + +Also, the toplevel `getExport(filePrefix = "/bundled-source")` accepts an +optional `filePrefix` argument in order to help sanitize stack +traces (which is prepended to relative paths for the bundled files). From efc6b4a369cc23813788f5626c61ec412e4e3f6a Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Fri, 28 Feb 2020 15:20:08 -0800 Subject: [PATCH 5/7] fix: make code clearer --- packages/SwingSet/src/controller.js | 42 ++++++++++++++--------------- packages/bundle-source/README.md | 4 +-- packages/bundle-source/src/index.js | 11 ++++++-- 3 files changed, 32 insertions(+), 25 deletions(-) diff --git a/packages/SwingSet/src/controller.js b/packages/SwingSet/src/controller.js index 40f705272cb..5be5f7c9625 100644 --- a/packages/SwingSet/src/controller.js +++ b/packages/SwingSet/src/controller.js @@ -26,6 +26,9 @@ import { insistStorageAPI } from './storageAPI'; import { insistCapData } from './capdata'; import { parseVatSlot } from './parseVatSlots'; +// FIXME: Put this somewhere better. +process.on('unhandledRejection', e => console.log('unhandledRejection', e)); + const ADMIN_DEVICE_PATH = require.resolve('./kernel/vatAdmin/vatAdmin-src'); const ADMIN_VAT_PATH = require.resolve('./kernel/vatAdmin/vatAdminWrapper'); @@ -197,32 +200,29 @@ function realmRegisterEndOfCrank(fn) { { registerEndOfCrank }, ); - return src => { - // FIXME: Note that this replaceGlobalMeter endowment is not any - // worse than before metering existed. However, it probably is - // only necessary to be added to the kernel, rather than all - // static vats once we add metering support to the dynamic vat - // implementation. - // FIXME: Same for registerEndOfCrank. - - // Cope with ESM problems. - src = src.replace(/(_[a-zA-Z0-9]{3}\u200d\.e)/g, 'eval'); - - // Support both getExport and nestedEvaluate module format. + return (src, filePrefix = '/SwingSet-bundled-source') => { const nestedEvaluate = source => s.evaluate(source, { + // Support both getExport and nestedEvaluate module format. require: r, + nestedEvaluate, + + // FIXME: Note that this replaceGlobalMeter endowment is not any + // worse than before metering existed. However, it probably is + // only necessary to be added to the kernel, rather than all + // static vats once we add metering support to the dynamic vat + // implementation. + // FIXME: Same for registerEndOfCrank. registerEndOfCrank: realmRegisterEndOfCrank, replaceGlobalMeter, - nestedEvaluate, }); - return nestedEvaluate(src)().default; + return nestedEvaluate(src)(filePrefix).default; }; } function buildSESKernel(sesEvaluator, endowments) { const kernelSource = getKernelSource(); - const buildKernel = sesEvaluator(kernelSource); + const buildKernel = sesEvaluator(kernelSource, '/SwingSet-kernel'); return buildKernel(endowments); } @@ -266,7 +266,7 @@ export async function buildVatController(config, withSES = true, argv = []) { // Evaluate source to produce a setup function. This binds withSES from the // enclosing context and evaluates it either in a SES context, or without SES // by directly calling require(). - async function evaluateToSetup(sourceIndex) { + async function evaluateToSetup(sourceIndex, filePrefix = undefined) { if (!(sourceIndex[0] === '.' || path.isAbsolute(sourceIndex))) { throw Error( 'sourceIndex must be relative (./foo) or absolute (/foo) not bare (foo)', @@ -284,7 +284,7 @@ export async function buildVatController(config, withSES = true, argv = []) { 'nestedEvaluate', ); const actualSource = `(${source})\n${sourceMap}`; - setup = sesEvaluator(actualSource); + setup = sesEvaluator(actualSource, filePrefix); } else { // eslint-disable-next-line global-require,import/no-dynamic-require setup = require(`${sourceIndex}`).default; @@ -298,8 +298,8 @@ export async function buildVatController(config, withSES = true, argv = []) { setImmediate, hostStorage, runEndOfCrank, - vatAdminDevSetup: await evaluateToSetup(ADMIN_DEVICE_PATH), - vatAdminVatSetup: await evaluateToSetup(ADMIN_VAT_PATH), + vatAdminDevSetup: await evaluateToSetup(ADMIN_DEVICE_PATH, '/SwingSet/src'), + vatAdminVatSetup: await evaluateToSetup(ADMIN_VAT_PATH, '/SwingSet/src'), }; const kernel = withSES @@ -308,12 +308,12 @@ export async function buildVatController(config, withSES = true, argv = []) { async function addGenesisVat(name, sourceIndex, options = {}) { console.log(`= adding vat '${name}' from ${sourceIndex}`); - const setup = await evaluateToSetup(sourceIndex); + const setup = await evaluateToSetup(sourceIndex, `/SwingSet-vat-${name}`); kernel.addGenesisVat(name, setup, options); } async function addGenesisDevice(name, sourceIndex, endowments) { - const setup = await evaluateToSetup(sourceIndex); + const setup = await evaluateToSetup(sourceIndex, `/SwingSet-dev-${name}`); kernel.addGenesisDevice(name, setup, endowments); } diff --git a/packages/bundle-source/README.md b/packages/bundle-source/README.md index 949fb2ba5c6..c567268ee64 100644 --- a/packages/bundle-source/README.md +++ b/packages/bundle-source/README.md @@ -54,5 +54,5 @@ The advantage of this format is that it helps preserve the filenames within the bundle in the event of any stack traces. Also, the toplevel `getExport(filePrefix = "/bundled-source")` accepts an -optional `filePrefix` argument in order to help sanitize stack -traces (which is prepended to relative paths for the bundled files). +optional `filePrefix` argument (which is prepended to relative paths for the +bundled files) in order to help give context to stack traces. diff --git a/packages/bundle-source/src/index.js b/packages/bundle-source/src/index.js index 67c8e4f692f..56ac37b9d2c 100644 --- a/packages/bundle-source/src/index.js +++ b/packages/bundle-source/src/index.js @@ -119,7 +119,7 @@ return module.exports; throw Error('need to override nestedEvaluate'); }; function computeExports(filename, powers) { - const { require: myRequire, _log } = powers; + const { require: systemRequire, _log } = powers; // This captures the endowed require. const match = filename.match(/^(.*)\/[^\/]+$/); const thisdir = match ? match[1] : '.'; @@ -171,7 +171,14 @@ return module.exports; const code = createEvalString(filename); if (!code) { // log('missing code for', filename, sourceBundle); - return myRequire(filename); + if (systemRequire) { + return systemRequire(filename); + } + throw Error( + `require(${JSON.stringify( + filename, + )}) failed; no toplevel require endowment`, + ); } // log('evaluating', typeof nestedEvaluate, code); From 6993c1b9dc06d63d24c7a30656368131cff631a1 Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Fri, 28 Feb 2020 15:54:04 -0800 Subject: [PATCH 6/7] fix(spawner): get tests to pass by fighting the esm package This ugly hack will go away once we excise the esm package. --- packages/spawner/src/contractHost.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/spawner/src/contractHost.js b/packages/spawner/src/contractHost.js index fbfa1b2012d..cee4d2d1ec0 100644 --- a/packages/spawner/src/contractHost.js +++ b/packages/spawner/src/contractHost.js @@ -59,6 +59,7 @@ function makeContractHost(E, evaluate, additionalEndowments = {}) { sameStructure, mustBeSameStructure, }; + const fullEndowments = Object.create(null, { ...Object.getOwnPropertyDescriptors(defaultEndowments), ...Object.getOwnPropertyDescriptors(additionalEndowments), @@ -71,6 +72,12 @@ function makeContractHost(E, evaluate, additionalEndowments = {}) { `"${functionSrcString}" must be a string, but was ${typeof functionSrcString}`, ); + // FIXME: Defeat ESM! + functionSrcString = functionSrcString.replace( + /sameStructure\.((mustBeS|s)ameStructure)/g, + '$1', + ); + // Refill a meter each crank. const { meter, refillFacet } = makeMeter(); const doRefill = () => { @@ -172,7 +179,7 @@ function makeContractHost(E, evaluate, additionalEndowments = {}) { function spawn(termsP) { let startFn; if (moduleFormat === 'object') { - startFn = evaluateStringToFn(contractSrcs.start, ); + startFn = evaluateStringToFn(contractSrcs.start); } else if ( moduleFormat === 'getExport' || moduleFormat === 'nestedEvaluate' From 069aa6491bbf2b4109d1ddceddff550eee036cbb Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Fri, 28 Feb 2020 15:54:46 -0800 Subject: [PATCH 7/7] chore(lint-fix): fix the lint --- packages/bundle-source/package.json | 1 + packages/bundle-source/src/index.js | 2 +- packages/cosmic-swingset/.eslintignore | 3 +++ packages/cosmic-swingset/lib/ag-solo/bundle.js | 2 +- packages/cosmic-swingset/lib/ag-solo/reset-state.js | 5 ++++- packages/cosmic-swingset/lib/ag-solo/start.js | 9 +++++++-- packages/cosmic-swingset/lib/ag-solo/vats/bootstrap.js | 1 - packages/cosmic-swingset/lib/ag-solo/vats/repl.js | 4 ++-- packages/cosmic-swingset/lib/ag-solo/vats/vat-http.js | 9 ++++++--- .../zoe/test/unitTests/contracts/test-coveredCall.js | 2 +- 10 files changed, 26 insertions(+), 12 deletions(-) diff --git a/packages/bundle-source/package.json b/packages/bundle-source/package.json index fd0f5e666ec..9d92720b213 100644 --- a/packages/bundle-source/package.json +++ b/packages/bundle-source/package.json @@ -18,6 +18,7 @@ }, "dependencies": { "@agoric/acorn-eventual-send": "^2.0.0", + "@agoric/evaluate": "^2.2.0", "@agoric/harden": "^0.0.4", "@rollup/plugin-commonjs": "^11.0.2", "@rollup/plugin-node-resolve": "^7.1.1", diff --git a/packages/bundle-source/src/index.js b/packages/bundle-source/src/index.js index 56ac37b9d2c..eb1579b2034 100644 --- a/packages/bundle-source/src/index.js +++ b/packages/bundle-source/src/index.js @@ -121,7 +121,7 @@ return module.exports; function computeExports(filename, powers) { const { require: systemRequire, _log } = powers; // This captures the endowed require. - const match = filename.match(/^(.*)\/[^\/]+$/); + const match = filename.match(/^(.*)\/[^/]+$/); const thisdir = match ? match[1] : '.'; const contextRequire = mod => { // Do path algebra to find the actual source. diff --git a/packages/cosmic-swingset/.eslintignore b/packages/cosmic-swingset/.eslintignore index e47b3326b1e..5af2ad09f5f 100644 --- a/packages/cosmic-swingset/.eslintignore +++ b/packages/cosmic-swingset/.eslintignore @@ -1,2 +1,5 @@ /dist /src/bundles/ +t[0-9]/ +node_modules/ +build/ diff --git a/packages/cosmic-swingset/lib/ag-solo/bundle.js b/packages/cosmic-swingset/lib/ag-solo/bundle.js index 82afeaac49f..4772130b3de 100644 --- a/packages/cosmic-swingset/lib/ag-solo/bundle.js +++ b/packages/cosmic-swingset/lib/ag-solo/bundle.js @@ -22,7 +22,7 @@ const sendJSON = (ws, obj) => { if (ws.readyState !== ws.OPEN) { return; } - //console.log('sending', obj); + // console.log('sending', obj); ws.send(JSON.stringify(obj)); }; diff --git a/packages/cosmic-swingset/lib/ag-solo/reset-state.js b/packages/cosmic-swingset/lib/ag-solo/reset-state.js index 6ac6577e5ef..d35b04dccc4 100644 --- a/packages/cosmic-swingset/lib/ag-solo/reset-state.js +++ b/packages/cosmic-swingset/lib/ag-solo/reset-state.js @@ -4,7 +4,10 @@ import fs from 'fs'; import { initSwingStore } from '@agoric/swing-store-simple'; export default async function resetState(basedir) { - const mailboxStateFile = path.resolve(basedir, 'swingset-kernel-mailbox.json'); + const mailboxStateFile = path.resolve( + basedir, + 'swingset-kernel-mailbox.json', + ); fs.writeFileSync(mailboxStateFile, `{}\n`); const kernelStateDBDir = path.join(basedir, 'swingset-kernel-state'); const { commit, close } = initSwingStore(kernelStateDBDir); diff --git a/packages/cosmic-swingset/lib/ag-solo/start.js b/packages/cosmic-swingset/lib/ag-solo/start.js index e2edd0515f0..1ccf96282cc 100644 --- a/packages/cosmic-swingset/lib/ag-solo/start.js +++ b/packages/cosmic-swingset/lib/ag-solo/start.js @@ -164,7 +164,10 @@ async function buildSwingset( } export default async function start(basedir, withSES, argv) { - const mailboxStateFile = path.resolve(basedir, 'swingset-kernel-mailbox.json'); + const mailboxStateFile = path.resolve( + basedir, + 'swingset-kernel-mailbox.json', + ); const connections = JSON.parse( fs.readFileSync(path.join(basedir, 'connections.json')), ); @@ -213,7 +216,9 @@ export default async function start(basedir, withSES, argv) { } break; case 'fake-chain': { - console.log(`adding follower/sender for fake chain ${c.role} ${c.GCI}`); + console.log( + `adding follower/sender for fake chain ${c.role} ${c.GCI}`, + ); const deliverator = await connectToFakeChain( basedir, c.GCI, diff --git a/packages/cosmic-swingset/lib/ag-solo/vats/bootstrap.js b/packages/cosmic-swingset/lib/ag-solo/vats/bootstrap.js index 11ada298d0b..ece3450a2aa 100644 --- a/packages/cosmic-swingset/lib/ag-solo/vats/bootstrap.js +++ b/packages/cosmic-swingset/lib/ag-solo/vats/bootstrap.js @@ -67,7 +67,6 @@ export default function setup(syscall, state, helpers) { const zoe = await E(vats.zoe).getZoe(); const contractHost = await E(vats.host).makeHost(); - // Make the other demo mints const assetNames = ['moola', 'simolean']; const assays = await Promise.all( diff --git a/packages/cosmic-swingset/lib/ag-solo/vats/repl.js b/packages/cosmic-swingset/lib/ag-solo/vats/repl.js index 50cd170a361..b792261560c 100644 --- a/packages/cosmic-swingset/lib/ag-solo/vats/repl.js +++ b/packages/cosmic-swingset/lib/ag-solo/vats/repl.js @@ -58,7 +58,7 @@ export function getReplHandler(E, homeObjects, sendBroadcast) { let highestHistory = -1; function updateHistorySlot(histnum, s) { - //console.log(`sendBroadcast ${histnum}`); + // console.log(`sendBroadcast ${histnum}`); sendBroadcast({ type: 'updateHistory', histnum, @@ -82,7 +82,7 @@ export function getReplHandler(E, homeObjects, sendBroadcast) { }, rebroadcastHistory() { - //console.log(`rebroadcastHistory`, highestHistory); + // console.log(`rebroadcastHistory`, highestHistory); for (let histnum = 0; histnum <= highestHistory; histnum++) { updateHistorySlot(histnum); } diff --git a/packages/cosmic-swingset/lib/ag-solo/vats/vat-http.js b/packages/cosmic-swingset/lib/ag-solo/vats/vat-http.js index c0edc7d578b..6e49a7e06d1 100644 --- a/packages/cosmic-swingset/lib/ag-solo/vats/vat-http.js +++ b/packages/cosmic-swingset/lib/ag-solo/vats/vat-http.js @@ -91,9 +91,12 @@ function build(E, D) { o.connectionID = obj.connectionID; D(commandDevice).sendBroadcast(o); }; - const { dispatch, abort } = makeCapTP(obj.connectionID, sendObj, () => - // Harden only our exported objects. - harden(exportedToCapTP), + const { dispatch, abort } = makeCapTP( + obj.connectionID, + sendObj, + () => + // Harden only our exported objects. + harden(exportedToCapTP), ); conns.set(obj.connectionID, [dispatch, abort]); }, diff --git a/packages/zoe/test/unitTests/contracts/test-coveredCall.js b/packages/zoe/test/unitTests/contracts/test-coveredCall.js index 90d3e650560..d3f47ce98f0 100644 --- a/packages/zoe/test/unitTests/contracts/test-coveredCall.js +++ b/packages/zoe/test/unitTests/contracts/test-coveredCall.js @@ -1,7 +1,7 @@ import { test } from 'tape-promise/tape'; import harden from '@agoric/harden'; -import bundleSource from '../../bundle-source'; import { sameStructure } from '@agoric/same-structure'; +import bundleSource from '../../bundle-source'; import buildManualTimer from '../../../tools/manualTimer'; import { makeZoe } from '../../../src/zoe';