deepFreeze: update for new environment
Use 'git diff --ignore-space-change' to make the actual changes more
apparent: the main logic remains the same, but the internals were rearranged
slightly, comments were added, and the outer function wrapper was updated.
MODIFY
src/deepFreeze.js
src/deepFreeze.js
// https://github.com/google/caja/blob/master/src/com/google/caja/ses/startSES.js
// https://github.com/google/caja/blob/master/src/com/google/caja/ses/repairES5.js
-// Mitigate proxy-related security issues
-// https://github.com/tc39/ecma262/issues/272
+// then copied from proposal-frozen-realms deep-freeze.js
-import { freeze, getOwnPropertyDescriptors, getPrototypeOf, ownKeys } from './commons';
+function deepFreeze(primordialRoots) {
+
+ const { freeze, getOwnPropertyDescriptors, getPrototypeOf } = Object;
+ const { ownKeys } = Reflect;
// Objects that are deeply frozen.
const frozenSet = new WeakSet();
@@ -17,7 +19,7 @@ const frozenSet = new WeakSet();
* reachable from it via transitive reflective property and prototype
* traversal.
*/
-export function deepFreeze(node) {
+ function deepFreeze(node) {
// Objects that we have frozen in this round.
const freezingSet = new Set();
@@ -34,10 +36,11 @@ export function deepFreeze(node) {
throw new TypeError(`Unexpected typeof: ${type}`);
}
if (frozenSet.has(val) || freezingSet.has(val)) {
+ // todo use uncurried form
// Ignore if already frozen or freezing
return;
}
- freezingSet.add(val);
+ freezingSet.add(val); // todo use uncurried form
}
function doFreeze(obj) {
@@ -50,11 +53,25 @@ export function deepFreeze(node) {
// Throws if this fails (strict mode).
freeze(obj);
- enqueue(getPrototypeOf(obj));
+ // we rely upon certain commitments of Object.freeze and proxies here
+
+ // get stable/immutable outbound links before a Proxy has a chance to do
+ // something sneaky.
+ const proto = getPrototypeOf(obj);
const descs = getOwnPropertyDescriptors(obj);
+ enqueue(proto);
ownKeys(descs).forEach(name => {
+ // todo uncurried form
+ // todo: getOwnPropertyDescriptors is guaranteed to return well-formed
+ // descriptors, but they still inherit from Object.prototype. If
+ // someone has poisoned Object.prototype to add 'value' or 'get'
+ // properties, then a simple 'if ("value" in desc)' or 'desc.value'
+ // test could be confused. We use hasOwnProperty to be sure about
+ // whether 'value' is present or not, which tells us for sure that this
+ // is a data property.
const desc = descs[name];
if ('value' in desc) {
+ // todo uncurried form
enqueue(desc.value);
} else {
enqueue(desc.get);
@@ -65,10 +82,14 @@ export function deepFreeze(node) {
function dequeue() {
// New values added before forEach() has finished will be visited.
- freezingSet.forEach(doFreeze);
+ freezingSet.forEach(doFreeze); // todo curried forEach
}
function commit() {
+ // todo curried forEach
+ // we capture the real WeakSet.prototype.add above, in case someone
+ // changes it. The two-argument form of forEach passes the second
+ // argument as the 'this' binding, so we add to the correct set.
freezingSet.forEach(frozenSet.add, frozenSet);
}
@@ -76,3 +97,6 @@ export function deepFreeze(node) {
dequeue();
commit();
}
+
+ deepFreeze(primordialRoots);
+}

deepFreeze: update for new environment

Use 'git diff --ignore-space-change' to make the actual changes more
apparent: the main logic remains the same, but the internals were rearranged
slightly, comments were added, and the outer function wrapper was updated.