blob: 446055a84fab60e3a40f827e3a8ec048456d29d3 [file] [log] [blame]
function shouldBe(actual, expected) {
if (actual !== expected)
throw new Error("bad value: " + actual);
}
function makeDictionary(dict) {
for (let i = 0; i < 1000; ++i)
dict["k" + i] = i;
return dict;
}
function makePolyProtoObject() {
function foo() {
class C {
constructor() {
this._field = 42;
}
}
return new C();
}
for (let i = 0; i < 15; ++i)
foo();
return foo();
}
function test(proto, key1, key2) {
proto[key1] = 1;
proto[key2] = 2;
Object.defineProperty(proto, key2, {writable: false});
const child = Object.create(proto);
let nextValue = 10;
function isKey1WritableStrict(obj) {
"use strict";
try {
obj[key1] = ++nextValue;
} catch {
return false;
}
return true;
}
function isKey1Writable(obj) {
obj[key1] = ++nextValue;
return obj[key1] === nextValue;
}
function isKey2WritableStrict(obj) {
"use strict";
try {
obj[key2] = ++nextValue;
} catch {
return false;
}
return true;
}
function isKey2Writable(obj) {
obj[key2] = ++nextValue;
return obj[key2] === nextValue;
}
noInline(isKey1WritableStrict);
noInline(isKey1Writable);
noInline(isKey2WritableStrict);
noInline(isKey2Writable);
for (let i = 0; i < 1e4; ++i) {
shouldBe(isKey1WritableStrict(child), true);
shouldBe(isKey1Writable(proto), true);
shouldBe(isKey2WritableStrict(child), false);
shouldBe(isKey2Writable(proto), false);
delete child[key1];
delete child[key2];
}
Object.defineProperty(proto, key1, {writable: false});
shouldBe(isKey1WritableStrict(child), false);
shouldBe(isKey1Writable(proto), false);
Object.defineProperty(proto, key2, {writable: true});
shouldBe(isKey2WritableStrict(child), true);
shouldBe(isKey2Writable(proto), true);
}
test({}, 0, "bar");
test(Object.create(null), "__proto__", 1);
test(makeDictionary({}), "foo", 2);
test(makeDictionary(Object.create(null)), 3, "__proto__");
test(makePolyProtoObject(), "foo", "bar");
test(makePolyProtoObject(), 4, 5);