129 lines
3.9 KiB
JavaScript
129 lines
3.9 KiB
JavaScript
"use strict";
|
|
|
|
function assert(x) {
|
|
if (!x)
|
|
throw new Error("Bad assert!");
|
|
}
|
|
|
|
function shouldThrow(func, expectedError) {
|
|
var errorThrown = false;
|
|
try {
|
|
func();
|
|
} catch (error) {
|
|
errorThrown = true;
|
|
if (String(error) !== expectedError)
|
|
throw new Error(`Bad error: ${error}`);
|
|
}
|
|
if (!errorThrown)
|
|
throw new Error("Didn't throw!");
|
|
}
|
|
|
|
const customTestGetterSetter = $vm.createCustomTestGetterSetter();
|
|
Object.setPrototypeOf(customTestGetterSetter, {
|
|
set customValue(_v) { throw new Error("Should be unreachable!"); },
|
|
set customValueGlobalObject(_v) { throw new Error("Should be unreachable!"); },
|
|
set customAccessor(_v) { throw new Error("Should be unreachable!"); },
|
|
set customAccessorGlobalObject(_v) { throw new Error("Should be unreachable!"); },
|
|
});
|
|
|
|
const primitives = [true, 1, "", Symbol(), 1n];
|
|
for (let primitive of primitives) {
|
|
let prototype = Object.getPrototypeOf(primitive);
|
|
Object.setPrototypeOf(prototype, customTestGetterSetter);
|
|
}
|
|
|
|
function getObjects() {
|
|
return [
|
|
...primitives.map(Object),
|
|
Object.create(customTestGetterSetter),
|
|
Object.create(Object.create(customTestGetterSetter)),
|
|
Object.create(new Proxy(customTestGetterSetter, {})),
|
|
Object.create($vm.createProxy(customTestGetterSetter)),
|
|
];
|
|
}
|
|
|
|
function getBases() {
|
|
return [
|
|
...primitives,
|
|
...getObjects(),
|
|
];
|
|
}
|
|
|
|
// CustomAccessor: exception check
|
|
(() => {
|
|
for (let base of getBases()) {
|
|
for (let i = 0; i < 100; ++i) {
|
|
let value = {};
|
|
base.customAccessor = value;
|
|
assert(value.hasOwnProperty("result"));
|
|
}
|
|
assert(Reflect.set(Object(base), "customAccessor", {}));
|
|
}
|
|
})();
|
|
|
|
// CustomValue: exception check
|
|
(() => {
|
|
for (let base of getBases()) {
|
|
for (let i = 0; i < 100; ++i) {
|
|
let value = {};
|
|
base.customValue = value;
|
|
assert(value.hasOwnProperty("result"));
|
|
}
|
|
assert(Reflect.set(Object(base), "customValue", {}));
|
|
}
|
|
})();
|
|
|
|
// CustomAccessor: setter returns |false|
|
|
(() => {
|
|
for (let base of getBases()) {
|
|
for (let i = 0; i < 100; ++i)
|
|
base.customAccessor = 1;
|
|
// This is intentional:
|
|
assert(!base.hasOwnProperty("customAccessor"));
|
|
assert(Reflect.set(Object(base), "customAccessor", 1));
|
|
}
|
|
})();
|
|
|
|
// CustomValue: setter returns |false|
|
|
// FIXME: Once legacy RegExp features are implemented, there would be no use case for calling CustomValue setter if receiver is altered.
|
|
(() => {
|
|
for (let base of getBases()) {
|
|
for (let i = 0; i < 100; ++i)
|
|
base.customValue = 1;
|
|
assert(!base.hasOwnProperty("customValue"));
|
|
assert(Reflect.set(Object(base), "customValue", 1));
|
|
}
|
|
})();
|
|
|
|
// CustomAccessor: no setter
|
|
(() => {
|
|
for (let base of getBases()) {
|
|
for (let i = 0; i < 100; ++i)
|
|
shouldThrow(() => { base.customAccessorReadOnly = {}; }, "TypeError: Attempted to assign to readonly property.");
|
|
assert(!Reflect.set(Object(base), "customAccessorReadOnly", {}));
|
|
}
|
|
})();
|
|
|
|
// CustomValue: no setter
|
|
(() => {
|
|
for (let primitive of primitives) {
|
|
for (let i = 0; i < 100; ++i)
|
|
shouldThrow(() => { primitive.customValueNoSetter = {}; }, "TypeError: Attempted to assign to readonly property.");
|
|
}
|
|
|
|
for (let object of getObjects()) {
|
|
for (let i = 0; i < 100; ++i)
|
|
object.customValueNoSetter = {};
|
|
assert(object.hasOwnProperty("customValueNoSetter"));
|
|
assert(Reflect.set(object, "customValueNoSetter", {}));
|
|
}
|
|
|
|
for (let object of getObjects()) {
|
|
Object.preventExtensions(object);
|
|
for (let i = 0; i < 100; ++i) {
|
|
shouldThrow(() => { object.customValueNoSetter = {}; }, "TypeError: Attempted to assign to readonly property.");
|
|
assert(!Reflect.set(object, "customValueNoSetter", {}));
|
|
}
|
|
}
|
|
})();
|