Skip to content

Commit

Permalink
Test global lexical accessor behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
kriskowal committed Jul 2, 2020
1 parent 90dfecd commit 788b190
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 35 deletions.
11 changes: 6 additions & 5 deletions packages/ses/src/compartment-shim.js
Expand Up @@ -16,10 +16,11 @@ import { makeModuleAnalyzer } from '@agoric/transform-module';
import {
assign,
create,
getOwnPropertyDescriptors,
getOwnPropertyNames,
defineProperties,
entries,
getOwnPropertyNames,
getOwnPropertyDescriptors,
freeze,
} from './commons.js';
import { createGlobalObject } from './global-object.js';
import { performEval } from './evaluate.js';
Expand Down Expand Up @@ -50,8 +51,8 @@ export class StaticModuleRecord {

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

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

moduleAnalyses.set(this, analysis);
}
Expand Down Expand Up @@ -169,7 +170,7 @@ export class Compartment {
// the compartment constructor, but the compartment only respects the
// original values and they are constants in the scope of evaluated
// programs and executed modules.
globalLexicals: Object.freeze({ ...globalLexicals }),
globalLexicals: freeze({ ...globalLexicals }),
});
}

Expand Down
84 changes: 54 additions & 30 deletions packages/ses/test/global-lexicals-evaluate.test.js
Expand Up @@ -157,33 +157,57 @@ test('global lexicals are captured on construction', t => {
t.equal(whom, 'World!');
});

// TODO uncomment this test after removing support for per-evaluate endowments.
//
// test('global lexical accessors are sampled once up front', t => {
// t.plan(4);
//
// let counter = 0;
// let receiver;
// const globalLexicals = {
// get next() {
// // Capture this for future reference.
// // Testing it here may lead to logging, which may lead to unbounded
// // recursion.
// receiver = this;
// const result = counter;
// counter += 1;
// return result;
// },
// };
//
// const endowments = {};
// const modules = {};
// const compartment = new Compartment(endowments, modules, { globalLexicals });
//
// const zero = compartment.evaluate('next');
// t.equal(zero, 0);
// t.equal(receiver, compartment.globalThis);
// const stillZero = compartment.evaluate('next');
// t.equal(stillZero, 0);
// t.equal(receiver, compartment.globalThis);
// });
test('global lexical accessors are sampled once up front', t => {
t.plan(2);

let counter = 0;
const globalLexicals = {
get next() {
const result = counter;
counter += 1;
return result;
},
};

const endowments = {};
const modules = {};
const compartment = new Compartment(endowments, modules, { globalLexicals });

const zero = compartment.evaluate('next');
t.equal(zero, 0);
const stillZero = compartment.evaluate('next');
t.equal(stillZero, 0);
});

test('global lexical accessors receive globalThis', t => {
t.plan(1);

let receiver;
const globalLexicals = Object.create(null, {
hello: {
get() {
receiver = this;
},
enumerable: true,
configurable: true,
},
goodbye: {
get() {
throw new Error('Non-enumerable properties should not be captured');
},
enumerable: false,
configurable: true,
},
});

const endowments = {};
const modules = {};
// eslint-disable-next-line no-unused-vars
const compartment = new Compartment(endowments, modules, { globalLexicals });

// Capturing globalLexicals.hello is a side-effect of Compartment
// construction.
// Code run in the compartment does not need to access the global lexical for
// it to be captured.
t.equal(receiver, globalLexicals);
});

0 comments on commit 788b190

Please sign in to comment.