Skip to content

Commit

Permalink
feat(ses): Add ModuleStaticRecord (#279)
Browse files Browse the repository at this point in the history
  • Loading branch information
kriskowal committed Apr 30, 2020
1 parent deb0578 commit 98c3a8f
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ export default [
],
plugins: [
resolve({
only: ["ses", "@agoric/make-hardener"]
only: [
"ses",
"@agoric/make-hardener",
"@agoric/transform-module",
"@agoric/babel-standalone"
]
})
]
}
Expand Down
4 changes: 3 additions & 1 deletion packages/ses/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@
"demo": "http-server -o /demos"
},
"dependencies": {
"@agoric/make-hardener": "0.0.8"
"@agoric/babel-standalone": "^7.9.5",
"@agoric/make-hardener": "0.0.8",
"@agoric/transform-module": "^0.3.0"
},
"devDependencies": {
"@agoric/test262-runner": "~0.1.0",
Expand Down
49 changes: 49 additions & 0 deletions packages/ses/src/compartment-shim.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,57 @@
// This module exports both Compartment and ModuleStaticRecord because they
// communicate through the moduleAnalyses private side-table.
/* eslint max-classes-per-file: ["error", 2] */

import * as babel from '@agoric/babel-standalone';
// We are using the above import form, and referring to its default export
// explicitly below like babel.default, because the proper construct causes a
// Rollup error.
// This form:
// import babel from '@agoric/babel-standalone';
// And this variant:
// import { default as babel } from '@agoric/babel-standalone';
// Both produce:
// Error: 'default' is not exported by .../@agoric/babel-standalone/babel.js
import { makeModuleAnalyzer } from '@agoric/transform-module';
import { assign } from './commons.js';
import { createGlobalObject } from './global-object.js';
import { performEval } from './evaluate.js';
import { getCurrentRealmRec } from './realm-rec.js';

const analyzeModule = makeModuleAnalyzer(babel.default);

// moduleAnalyses are the private data of a ModuleStaticRecord.
// We use moduleAnalyses in the loader/linker to look up
// the analysis corresponding to any ModuleStaticRecord constructed by an
// importHook.
const moduleAnalyses = new WeakMap();

/**
* ModuleStaticRecord captures the effort of parsing and analyzing module text
* so a cache of ModuleStaticRecords may be shared by multiple Compartments.
*/
export class ModuleStaticRecord {
constructor(text) {
const analysis = analyzeModule({ string: text });

this.imports = Object.keys(analysis.imports).sort();

Object.freeze(this);
Object.freeze(this.imports);

moduleAnalyses.set(this, analysis);
}

// eslint-disable-next-line class-methods-use-this
toString() {
return '[object ModuleStaticRecord]';
}

static toString() {
return 'function ModuleStaticRecord() { [shim code] }';
}
}

/**
* Compartment()
* The Compartment constructor is a global. A host that wants to execute
Expand Down
1 change: 1 addition & 0 deletions packages/ses/src/intrinsics-global.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ const globalIntrinsicNames = [

'globalThis',
'Compartment',
'ModuleStaticRecord',
'harden',
];

Expand Down
2 changes: 1 addition & 1 deletion packages/ses/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
// limitations under the License.

export { lockdown } from './lockdown-shim.js';
export { Compartment } from './compartment-shim.js';
export { Compartment, ModuleStaticRecord } from './compartment-shim.js';
9 changes: 9 additions & 0 deletions packages/ses/src/whitelist.js
Original file line number Diff line number Diff line change
Expand Up @@ -1535,5 +1535,14 @@ export default {
global: getter,
},

ModuleStaticRecord: {
'**proto**': 'FunctionPrototype',
prototype: 'ModuleStaticRecordPrototype',
},

ModuleStaticRecordPrototype: {
constructor: 'ModuleStaticRecord',
},

harden: fn,
};
56 changes: 56 additions & 0 deletions packages/ses/test/module-static-record.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import tap from 'tap';
import { ModuleStaticRecord } from '../src/main.js';

const { test } = tap;

test('module static record constructor', t => {
const msr = new ModuleStaticRecord(`
import foo from 'import-default-export-from-me.js';
import oof from 'import-default-export-from-me.js';
import * as bar from 'import-all-from-me.js';
import { fizz, buzz } from 'import-named-exports-from-me.js';
import { color as colour } from 'import-named-export-and-rename.js';
export let quuux = null;
export { qux } from 'import-and-reexport-name-from-me.js';
export * from 'import-and-export-all.js';
export default 42;
export const quux = 'Hello, World!';
// Late binding of an exported variable.
quuux = 'Hello, World!';
`);

t.equal(
'[object ModuleStaticRecord]',
msr.toString(),
'instance string representation should be fixed',
);
t.equal(
'function ModuleStaticRecord() { [shim code] }',
ModuleStaticRecord.toString(),
'constructor string representation should be fixed',
);

t.deepEquals(
msr.imports,
[
'import-all-from-me.js',
'import-and-export-all.js',
'import-and-reexport-name-from-me.js',
'import-default-export-from-me.js',
'import-named-export-and-rename.js',
'import-named-exports-from-me.js',
],
'should capture sorted unique imports',
);

t.ok(Object.isFrozen(msr), 'ModuleStaticRecords should be frozen');
t.ok(
Object.isFrozen(msr.imports),
'ModuleStaticRecord imports should be frozen',
);

t.end();
});
9 changes: 8 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
resolved "https://registry.yarnpkg.com/@agoric/babel-parser/-/babel-parser-7.6.4.tgz#8dd5d36554cc758c29042713b5aa57dc58ee5273"
integrity sha512-3FQC3eP2hekhz1zn+2LcSL7tAG2dGgSqbmCeRfIFqhVS8bbE1hR7EvrC6jYlvqdU6yzlly43VykyRy9MHBvUAw==

"@agoric/babel-standalone@^7.9.5":
version "7.9.5"
resolved "https://registry.yarnpkg.com/@agoric/babel-standalone/-/babel-standalone-7.9.5.tgz#1ca0c17844924199d31e49d6b67e8b2a629b8599"
integrity sha512-1Aa23oPuRi4kywUyZODo8zey9Gq2NpD2xUnNvgJLoT8orMQRlVOtvbG3JeHq5sjJERlF/q6csg4/P8t8/5IABA==

"@agoric/default-evaluate-options@^0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@agoric/default-evaluate-options/-/default-evaluate-options-0.3.0.tgz#c65f4342c286d8c7f912e1fc33c7b855bc615e3e"
Expand Down Expand Up @@ -9376,9 +9381,11 @@ serve-static@^1.12.4:
send "0.17.1"

"ses@file:packages/ses":
version "0.7.6"
version "0.7.7"
dependencies:
"@agoric/babel-standalone" "^7.9.5"
"@agoric/make-hardener" "0.0.8"
"@agoric/transform-module" "^0.3.0"

set-blocking@^2.0.0, set-blocking@~2.0.0:
version "2.0.0"
Expand Down

0 comments on commit 98c3a8f

Please sign in to comment.