fix: flatten tameFunctionToString
MODIFY
packages/ses/lockdown.js
packages/ses/lockdown.js
@@ -24,8 +24,6 @@ import {
CompartmentPrototype,
} from './src/compartment-shim.js';
-// TODO wasteful to do it twice, once before lockdown and again during
-// lockdown. The second is doubly indirect. We should at least flatten that.
const nativeBrander = tameFunctionToString();
const Compartment = makeCompartmentConstructor(

MODIFY
packages/ses/ses.js
packages/ses/ses.js
@@ -26,8 +26,6 @@ import {
assign(whitelist, modulesWhitelist);
-// TODO wasteful to do it twice, once before lockdown and again during
-// lockdown. The second is doubly indirect. We should at least flatten that.
const nativeBrander = tameFunctionToString();
const ModularCompartment = makeModularCompartmentConstructor(

MODIFY
packages/ses/src/tame-function-tostring.js
packages/ses/src/tame-function-tostring.js
-import { defineProperty, apply } from './commons.js';
+import { defineProperty, apply, freeze } from './commons.js';
const nativeSuffix = ') { [native code] }';
+// Note: Top level mutable state. Does not make anything worse, since the
+// patching of `Function.prototype.toString` is also globally stateful. We
+// use this top level state so that multiple calls to `tameFunctionToString` are
+// idempotent, rather than creating redundant indirections.
+let nativeBrander;
+
+/**
+ * Replace `Function.prototype.toString` with one that recognizes
+ * shimmed functions as honorary native functions.
+ */
export function tameFunctionToString() {
+ if (nativeBrander === undefined) {
const nativeBrand = new WeakSet();
const originalFunctionToString = Function.prototype.toString;
@@ -21,5 +32,7 @@ export function tameFunctionToString() {
value: tamingMethods.toString,
});
- return func => nativeBrand.add(func);
+ nativeBrander = freeze(func => nativeBrand.add(func));
+ }
+ return nativeBrander;
}

fix: flatten tameFunctionToString (#482)