Open JasonRammoray opened 6 years ago
@ maxnordlund, please, keep in mind, that not only a context object might be frozen, but also each and every prototype in the object's prototype chain.
True, but I don't think any JS engine old enough to need this implements Object.freeze
. I don't have the tweet at hand, but I did ask someone doing research on these old engines, and try
/catch
is not a thing. So this needs to be fixed as well, but I didn't get a VM running old Netscape and IE.
Edit: Here's the tweet https://twitter.com/nevonnen/status/916565339370131456
True. Object.freeze has been shipped to Firefox 4 / IE 9 / Chrome 6 / Opera 12 / Safari 5.1, which are not so old enough browsers compared to Netscape. Yet I think it is a good idea to test if object is immutable (for example, by adding a property to it and checking if it is there afterwards). There should be another strategy in case of immutable context. What do you think?
After looking around a bit, and reading the first version of ECMAScript-262 it seems like you can use the typeof
operator to figure out if Object.freeze
is available.
But according to MDN it was first implemented in JavaScript 1.1, which translates to Netscape 3.0.
Since this project tries to work in those ancient browsers that doesn't work. Both instanceof
and try
/catch
is even younger, introduced in ECMAScript 3.
After reading some more, and finding the changelog for 1.1 I've realized I need 1.1 in order to support Function.prototype
at all. So the typeof
solution will work.
Now the real question is how to implement this for frozen objects. I don't think it's possible, AFAIK there's no other way to set the this
context without modifying the object itself. You could inherit from the object, mutate the resulting instance and call it like so. But then any modifications will end up on the temporary object. Which is really confusing as it should explode, being frozen.
That would look something like:
function TempClass() {};
TempClass.prototype = thisArg;
object = new TempClass;
object[symbol];
eval(...);
Not sure though how inheritance helps to resolve a following case:
var obj = {
prop: 'value'
};
// Freeze the object by some way
function some (param) {
return this === obj && param === 42;
}
/*
* In that case this will point to an object inheriting from obj, but
* that is not something we need
*/
some.call(obj, 42);
Example:
As a result we get a runtime error (
Uncaught TypeError: object[symbol] is not a function
), because function hasn't been added to a context object, because the latter was frozen.