Alternative `harden` implementation approach
See original GitHub issueWhat is the Problem Being Solved?
The current implementation of harden uses membership in a WeakSet to determine whether various objects, functions, etc. have already been hardened. This prevents infinite recursion and improves performance by preventing walking already-frozen object graphs. The algorithm cannot just use isFrozen for the test because a user could manually freeze objects that reference still-mutable state.
That hardened WeakSet can get very large, whereas in both typical JavaScript programs and in Agoric’s model using harden, Object.freeze is rarely used. Can we eliminate the need for the large hardened set?
Description of the Design
This alternative implementation approach is inspired by the assumption that we harden many more objects than we just freeze. So we record the usages of freeze instead.
- change the
hardenedWeakSet to aonlyFrozenWeakSet. - shim
Object.freezeto both freeze the object and add it to theonlyFrozenset isFrozenis unchangedhardenjust recursively freezes. If it finds a frozen object, it checks whether it’s in theonlyFrozenset. If so, it removes it from the set and recurs on it- if
freezecannot be shimmed early enough, thenlockdownmay use ahardenedset to recur into frozen things it has not seen before.
As a result, isHardened(o) is isFrozen(o) && !onlyFrozen.has(o)
Security Considerations
3 potential concerns:
- objects frozen before
lockdownis called - freezing things without using
Object.freeze - things that get frozen by the execution semantics
Re #2, @erights had some insight:
Need to also patch
Object.preventExtensions,{Object,Reflect}.{defineProperty,defineProperties}since those can make an object frozen. Actually, once an object is non-extensible, it is too easy to make it accidentally frozen, such a property deletion. I think you should mark everything made non-extensible, since that’s a narrower funnel. IIUC, it does not hurt to take a non-extensible but non-frozen object and put it intoonlyFrozenjust in case. [I agree]
Issue Analytics
- State:
- Created 2 years ago
- Comments:12 (11 by maintainers)

Top Related StackOverflow Question
Also, Dean found a third case that I forgot: The ThrowTypeError object. But it is already included in our primordials and hardened on
lockdown, so not a problem.Unless they’re empty, in which case, like the templates array, they’re transitively immutable anyway, and so not a threat.