-
Notifications
You must be signed in to change notification settings - Fork 67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[shim] add example of a frozen realm #35
Comments
I have not tested it, but here's an attempt at fixing the deepFreeze from your This is probably not minimal but it should at least make the issues clear. Not really blocked by #24 (comment) but it would help. const getProto = Object.getPrototypeOf;
const freeze = Object.freeze;
const gopds = Object.getOwnPropertyDescriptors;
const ownKeys = Reflect.ownKeys;
// Objects that are deeply frozen
const frozenSet = new WeakSet();
/**
* To deepFreeze an object is to freeze it and all objects
* transitively reachable from it via transitive reflective
* property and prototype traversal.
*/
function deepFreeze(node) {
// Objects that we're attempting to freeze
const freezingSet = new Set();
// If val is something we should be freezing but aren't yet,
// add it to freezingSet and return true.
function addFreezing(val) {
if (Object(val) !== val) {
// ignore primitives
return false;
}
const t = typeof val;
if (t !== 'object' && t !== 'function') {
// future proof: break until someone figures out what it should do
throw new TypeError(`unexpected typeof: ${t}`);
}
if (frozenSet.has(val) || freezingSet.has(val)) {
// Ignore if already frozen or freezing
return false;
}
freezingSet.add(val);
return true;
}
function recur(node) {
if (!addFreezing(node)) { return; }
if (!freeze(node)) {
// Yuck. We allowed freeze to indicate failure by returning
// false rather than throwing, so we need to check for that.
throw new TypeError(`not frozen ${node}`);
}
recur(getProto(node));
const descs = gopds(node);
ownKeys(descs).forEach(key => {
const desc = descs[key];
if ('value' in desc) {
recur(desc.value);
} else {
// On an accessor property, deepFreeze does not do a [[Get]]
// or invoke the getter. Rather, it only recursively freezes
// the getter and setter themselves.
recur(desc.get);
recur(desc.set);
}
});
}
recur(node);
// This initial call to recur must be in a state where freezingSet
// is empty, so a non-erroneous return from recur implies that node
// and everything in freezingSet is successfully deeply frozen.
for (let n of freezingSet) { frozenSet.add(n); }
return node;
} |
@erights I have added this code, it works :), I have also created an interactive console to play around with the frozen realm, here is the link: https://rawgit.com/caridy/proposal-realms/master/shim/examples/frozen.html We can discuss the details tomorrow during our weekly meeting. |
Nice. @caridy Curious why you're passing frozenSet in as an argument rather than letting deepFreeze encapsulate it? |
@erights You pinged me, you get a code review. I haven't looked at caridy's version.
Does the specification guarantee that implementation extensions and future versions of the specification will not break the property this code assumes?
It occurs to me that since you have freezingSet, you could write this using freezingSet as a work queue rather than the stack. This would have the advantage of not possibly overflowing the stack (which, as we know, is hazardous) due to a large (finite) structure.
You have defined
This clarification should be promoted to the documentation (comment). |
@kpreid yes, |
I'm creating a new |
@erights LGTM. As Kevin indicated, |
As Kevin indicated,
Object.freeze can never return false. If node is a proxy, it can indeed
make the freeze process fail, but Object.freeze will convert into
TypeError.
Unless the object refusing to be frozen is the browser's bizarre global
object, i.e., the one called WindowProxy (which is btw not a Proxy). For
this case explicitly, we allow it to report its refusal to be frozen by
returning false rather than throwing. This was the least damaging
adjustment we could make that would not break the web. Everything else that
was proposed would have compromised the invariants themselves.
|
No, not a confusion. This code takes advantage of that fact that returning an object means returning something truthy. In that one bizarre case I mentioned (browser's WindowProxy), we allow Object.freeze to report failure by returning false rather than throwing, which its only possible falsey result when applied to an object. |
I thought that was for |
@raulsebastianmihaila Yes! |
@kpreid, applying your idea of a work queue, we get:
If that code is correct, there is a small performance gain as seen on JSPerf |
Is |
Yes, that's the specified behavior for
It's an incontinent behavior in loops, and that's why I have added the comment. For example, it's not the case with loops on Array:
Other loops don't specify the behavior, for example |
@jfparadis |
Thanks. We are |
If |
We have decided that the concept of a frozen realm should not be part of this proposal. Additionally, this issue is related to the Shim implementation, closing since it was moved into https://github.com/Agoric/realms-shim. |
patch
that will be called during the initialization phasepatch
method can mutate some intrinsics (e.g.: polyfillArray.prototype.includes
)patch
during theinit
phasepatch
The text was updated successfully, but these errors were encountered: