fix: rename to originalValue
MODIFY
packages/ses/NEWS.md
packages/ses/NEWS.md
@@ -2,6 +2,12 @@ User-visible changes in SES:
## Next release
+* When converting each of [these data properties](src/enablements.js) to
+ accessor properties, to suppress the
+ [override mistake](https://github.com/tc39/ecma262/pull/1320), we now
+ add to that accessor's getter an `originalValue` property to mark it
+ as alleging that it is emulating a data property whose original value
+ was that value.
* Fixes an exception thrown when calling `lockdown` after just importing
`ses/lockdown` in all environments.

MODIFY
packages/ses/README.md
packages/ses/README.md
@@ -272,6 +272,21 @@ The compartment will call `execute` with:
method of third-party static module records to return promises, to support
top-level await.
+### Imperfect emulation
+
+JavaScript suffers from the so-called
+[override mistake](https://web.archive.org/web/20141230041441/http://wiki.ecmascript.org/doku.php?id=strawman:fixing_override_mistake),
+which prevents lockdown from *simply* hardening all the primordials. Rather,
+for each of
+[these data properties](src/enablements.js), we convert it to an accessor
+property whose getter and setter emulate [a data property without the override
+mistake](https://github.com/tc39/ecma262/pull/1320). For non-reflective code
+the illusion is perfect. But reflective code sees that it is an accessor
+rather than a data property. We add a `originalValue` property to the getter
+of that accessor, letting reflective code know that a getter alleges that it
+results from this transform, and what the original data value was. This enables
+a form of cooperative emulation, where that code can decide whether to uphold
+the illusion by pretending it sees the data property that would have been there.
## Bug Disclosure

MODIFY
packages/ses/src/enable-property-overrides.js
packages/ses/src/enable-property-overrides.js
@@ -27,9 +27,10 @@ function isObject(obj) {
*
* Because of lack of sufficient foresight at the time, ES5 unfortunately
* specified that a simple assignment to a non-existent property must fail if
- * it would override a non-writable data property of the same name. In
- * retrospect, this was a mistake, the so-called "override mistake". But it is
- * now too late and we must live with the consequences.
+ * it would override an non-writable data property of the same name in the
+ * shadow of the prototype chain. In retrospect, this was a mistake, the
+ * so-called "override mistake". But it is now too late and we must live with
+ * the consequences.
*
* As a result, simply freezing an object to make it tamper proof has the
* unfortunate side effect of breaking previously correct code that is
@@ -47,7 +48,7 @@ function isObject(obj) {
* writing, this is the best we know how to do.
*
* To the getter of the accessor we add a property named
- * `'originalDataPropertyValue'` whose value is, as it says, the value that the
+ * `'originalValue'` whose value is, as it says, the value that the
* data property had before being converted to an accessor property. We add
* this extra property to the getter for two reason:
*
@@ -63,7 +64,7 @@ function isObject(obj) {
* We enable a form of cooperative emulation, giving reflective code an
* opportunity to cooperate in upholding the illusion. When such cooperative
* reflective code sees an accessor property, where the accessor's getter
- * has an `originalDataPropertyValue` property, it knows that the getter is
+ * has an `originalValue` property, it knows that the getter is
* alleging that it is the result of the `enablePropertyOverrides` conversion
* pattern, so it can decide to cooperatively "pretend" that it sees a data
* property with that value.
@@ -78,7 +79,12 @@ export default function enablePropertyOverrides(intrinsics) {
function getter() {
return value;
}
- getter.originalDataPropertyValue = value;
+ defineProperty(getter, 'originalValue', {
+ value,
+ writable: false,
+ enumerable: false,
+ configurable: false,
+ });
function setter(newValue) {
if (obj === this) {

MODIFY
packages/ses/test/frozen-primordials.test.js
packages/ses/test/frozen-primordials.test.js
@@ -6,11 +6,11 @@ test('check if override-protected primordials are frozen', t => {
lockdown();
// After removing the detachedProperties mechanism and without
- // the originalDataPropertyValue mechanism, this test failed.
+ // the originalValue mechanism, this test failed.
t.ok(Object.isFrozen(Object.prototype.toString));
const desc = getOwnPropertyDescriptor(Object.prototype, 'toString');
- t.equals(desc.get.originalDataPropertyValue, Object.prototype.toString);
+ t.equals(desc.get.originalValue, Object.prototype.toString);
t.end();
});

fix: rename to originalValue (#476)