refactor(ses): remove makeEvaluateFactory remnants
Rewrite tests to verify functionality of evaluate instead asserting the
string output of the factory.
MODIFY
packages/ses/src/make-evaluate.js
packages/ses/src/make-evaluate.js
+// @ts-check
+
import { FERAL_FUNCTION, arrayJoin, apply } from './commons.js';
import { getScopeConstants } from './scope-constants.js';
@@ -17,17 +19,20 @@ function buildOptimizer(constants) {
}
/**
- * makeEvaluateFactory()
- * The factory create 'evaluate' functions with the correct optimizer
- * inserted.
+ * makeEvaluate()
+ * Create an 'evaluate' function with the correct optimizer inserted.
*
- * @param {Array<string>} [globalObjectConstants]
- * @param {Array<string>} [globalLexicalConstants]
+ * @param {object} context
+ * @param {object} context.evalScope
+ * @param {object} context.globalLexicals
+ * @param {object} context.globalObject
+ * @param {object} context.scopeTerminator
*/
-export const makeEvaluateFactory = (
- globalObjectConstants = [],
- globalLexicalConstants = [],
-) => {
+export const makeEvaluate = context => {
+ const { globalObjectConstants, globalLexicalConstants } = getScopeConstants(
+ context.globalObject,
+ context.globalLexicals,
+ );
const globalObjectOptimizer = buildOptimizer(
globalObjectConstants,
'globalObject',
@@ -71,7 +76,7 @@ export const makeEvaluateFactory = (
// reused for multiple evaluations, but in practice we have no such calls.
// We could probably both move the optimizer into the inner function
// and we could also simplify makeEvaluateFactory to simply evaluate.
- return FERAL_FUNCTION(`
+ const evaluateFactory = FERAL_FUNCTION(`
with (this.scopeTerminator) {
with (this.globalObject) {
with (this.globalLexicals) {
@@ -87,23 +92,6 @@ export const makeEvaluateFactory = (
}
}
`);
-};
-/**
- * @param {object} context
- * @param {object} context.evalScope
- * @param {object} context.globalLexicals
- * @param {object} context.globalObject
- * @param {object} context.scopeTerminator
- */
-export const makeEvaluate = context => {
- const { globalObjectConstants, globalLexicalConstants } = getScopeConstants(
- context.globalObject,
- context.globalLexicals,
- );
- const evaluateFactory = makeEvaluateFactory(
- globalObjectConstants,
- globalLexicalConstants,
- );
return apply(evaluateFactory, context, []);
};

DELETE
packages/ses/test/test-make-evaluate-factory.js
-import test from 'ava';
-import { makeEvaluateFactory } from '../src/make-evaluate.js';
-
-test('Intrinsics - values', t => {
- t.plan(4);
-
- t.is(
- makeEvaluateFactory()
- .toString()
- .replace(/\s/g, ' ')
- .replace(/ +/g, ' '),
- "function anonymous( ) { with (this.scopeTerminator) { with (this.globalObject) { with (this.globalLexicals) { with (this.evalScope) { return function() { 'use strict'; return eval(arguments[0]); }; } } } } }",
- );
-
- t.is(
- makeEvaluateFactory(['foot'])
- .toString()
- .replace(/\s/g, ' ')
- .replace(/ +/g, ' '),
- "function anonymous( ) { with (this.scopeTerminator) { with (this.globalObject) { with (this.globalLexicals) { with (this.evalScope) { const {foot} = this.globalObject; return function() { 'use strict'; return eval(arguments[0]); }; } } } } }",
- );
-
- t.is(
- makeEvaluateFactory([], ['bart'])
- .toString()
- .replace(/\s/g, ' ')
- .replace(/ +/g, ' '),
- "function anonymous( ) { with (this.scopeTerminator) { with (this.globalObject) { with (this.globalLexicals) { with (this.evalScope) { const {bart} = this.globalLexicals; return function() { 'use strict'; return eval(arguments[0]); }; } } } } }",
- );
-
- t.is(
- makeEvaluateFactory(['foot'], ['bart'])
- .toString()
- .replace(/\s/g, ' ')
- .replace(/ +/g, ' '),
- "function anonymous( ) { with (this.scopeTerminator) { with (this.globalObject) { with (this.globalLexicals) { with (this.evalScope) { const {foot} = this.globalObject; const {bart} = this.globalLexicals; return function() { 'use strict'; return eval(arguments[0]); }; } } } } }",
- );
-});

ADD
packages/ses/test/test-make-evaluate.js
+import test from 'ava';
+import { apply, freeze } from '../src/commons.js';
+import { makeEvaluate } from '../src/make-evaluate.js';
+import { strictScopeTerminator } from '../src/strict-scope-terminator.js';
+import { createEvalScope } from '../src/eval-scope.js';
+
+const makeObservingProxy = target => {
+ const ops = [];
+ const proxy = new Proxy(target, {
+ get(_target, prop, _receiver) {
+ if (prop !== Symbol.unscopables) {
+ ops.push(['get', prop]);
+ }
+ return Reflect.get(target, prop);
+ },
+ });
+
+ return [proxy, ops];
+};
+
+test('makeEvaluate - optimizer', t => {
+ t.plan(5);
+
+ const globalObjectTarget = Object.create(null, {
+ foo: { value: true },
+ bar: { value: true },
+ baz: { value: true, writable: true },
+ });
+ const globalLexicalsTarget = Object.create(null, { foo: { value: false } });
+
+ const [globalObject, globalObjectOps] = makeObservingProxy(
+ globalObjectTarget,
+ );
+ const [globalLexicals, globalLexicalsOps] = makeObservingProxy(
+ globalLexicalsTarget,
+ );
+
+ const scopeTerminator = strictScopeTerminator;
+ const { evalScope, allowNextEvalToBeUnsafe } = createEvalScope();
+
+ const evaluate = makeEvaluate(
+ freeze({ scopeTerminator, globalObject, globalLexicals, evalScope }),
+ );
+
+ t.deepEqual(globalObjectOps, [['get', 'bar']]);
+ t.deepEqual(globalLexicalsOps, [['get', 'foo']]);
+
+ globalObjectOps.length = 0;
+ globalLexicalsOps.length = 0;
+
+ allowNextEvalToBeUnsafe();
+
+ const result = apply(evaluate, globalObject, [`!foo && bar && baz`]);
+
+ t.is(result, true);
+ t.deepEqual(globalObjectOps, [['get', 'baz']]);
+ t.deepEqual(globalLexicalsOps, []);
+});
+
+test('makeEvaluate - strict-mode', t => {
+ t.plan(2);
+
+ const globalObject = Object.create(null);
+ const globalLexicals = Object.create(null);
+
+ const scopeTerminator = strictScopeTerminator;
+ const { evalScope, allowNextEvalToBeUnsafe } = createEvalScope();
+
+ const evaluate = makeEvaluate(
+ freeze({ scopeTerminator, globalObject, globalLexicals, evalScope }),
+ );
+
+ allowNextEvalToBeUnsafe();
+ t.throws(() => apply(evaluate, globalObject, [`foo = 42`]));
+
+ allowNextEvalToBeUnsafe();
+ t.throws(() => apply(evaluate, globalObject, [`with({}) {}`]));
+});

refactor(ses): remove makeEvaluateFactory remnants

Rewrite tests to verify functionality of evaluate instead asserting the
string output of the factory.