See this comment for a revised version.
The override mistake is a problem introduced with ES5's ability to mark properties as non-writable. When a property on the prototype of an object is marked non-writable, it makes the property unaddable on the object.
A notable example of this is if we freeze (which marks all properties as non-writable) on Object.prototype
.
Object.freeze(Object.prototype);
When we do this, it becomes impossible to set toString()
on any objects that don't already have a .toString()
.
e.g. the following fails:
"use strict";
Object.freeze(Object.prototype);
const newObject = {};
newObject.toString = () => "Some string"; // TypeError
This is of particular concern to the SES proposal, which needs to freeze all builtins in order to guarantee security properties.
In this proposal we propose a new descriptor member called overridable
,
this member may only be present when writable
is set to false
.
When overridable
is present, non-writable properties on the prototype will be ignored when attempting to set them.
For example the following will print 10
:
"use strict";
const proto = {};
Object.defineProperty(proto, 'example', { value: 5, writable: false, overridable: true });
const object = { __proto__: proto };
object.example = 10;
console.log(object.example);
For SES, we need to be able to able to freeze entire objects, but without creating the problems of the override mistake.
As such a new function will be provided called Object.harden
, this method acts just like Object.freeze
,
except it sets overridable: true
on all descriptors (that are configurable).
For example, the following will just work now:
"use strict";
Object.harden(Object.prototype);
const object = {};
object.toString = () => "Hello world!";
console.log(object.toString()); // Hello world!
QUESTION: Should this simply be an option to freeze
rather than a new method?
If we expose overridable: boolean
as a new property on descriptors returned from Object.getOwnPropertyDescriptor(s)
,
will existing code break?
If so, should we add a new method to get overridable
to Object
(e.g. Object.getIsOverridable(object, name)
), or should we expose overridable
only when it is set to true
.
Do you mean, only when set to false? Either way, I'd expect it to be allowed to be
false
explicitly, otherwise conditionally setting it to a boolean value gets a bit awkward.How would/could this proposal be polyfilled?