blob: 4e8abdd0d651e903ee74accb2314d8140e2ee885 [file] [log] [blame]
function shouldBe(actual, expected) {
if (actual !== expected)
throw new Error('bad value: ' + actual);
}
function unreachable()
{
throw new Error('unreachable');
}
function assert(b) {
if (!b)
throw new Error("bad assertion");
}
{
let target = {
x: 30
};
let called = false;
let handler = {
set: 45
};
let proxy = new Proxy(target, handler);
for (let i = 0; i < 1000; i++) {
let threw = false;
try {
Reflect.set(proxy, 'x', 40);
unreachable();
} catch(e) {
assert(e.toString() === "TypeError: 'set' property of a Proxy's handler should be callable");
threw = true;
}
assert(threw);
}
}
{
let target = {
x: 30
};
let error = null;
let handler = {
get set() {
error = new Error;
throw error;
}
};
let proxy = new Proxy(target, handler);
for (let i = 0; i < 1000; i++) {
let threw = false;
try {
Reflect.set(proxy, 'x', 40);
unreachable();
} catch(e) {
assert(e === error);
threw = true;
}
assert(threw);
error = null;
}
}
{
let target = {
x: 30
};
let error = null;
let handler = {
set: function() {
error = new Error;
throw error;
}
};
let proxy = new Proxy(target, handler);
for (let i = 0; i < 1000; i++) {
let threw = false;
try {
Reflect.set(proxy, 'x', 40);
unreachable();
} catch(e) {
assert(e === error);
threw = true;
}
assert(threw);
error = null;
}
}
{
let target = { };
Object.defineProperty(target, "x", {
configurable: false,
writable: false,
value: 500
});
let called = false;
let handler = {
set: function(theTarget, propName, value, receiver) {
assert(theTarget === target);
called = true;
theTarget[propName] = value;
return false;
}
};
let proxy = new Proxy(target, handler);
for (let i = 0; i < 1000; i++) {
shouldBe(Reflect.set(proxy, 'x', 40), false);
assert(called);
assert(proxy.x === 500);
assert(target.x === 500);
called = false;
}
}
{
let target = { };
Object.defineProperty(target, "x", {
configurable: false,
writable: false,
value: 500
});
let handler = {
set: function(theTarget, propName, value, receiver) {
assert(theTarget === target);
theTarget[propName] = value;
return true;
}
};
let proxy = new Proxy(target, handler);
for (let i = 0; i < 1000; i++) {
let threw = false;
try {
Reflect.set(proxy, 'x', 40);
unreachable();
} catch(e) {
threw = true;
assert(e.toString() === "TypeError: Proxy handler's 'set' on a non-configurable and non-writable property on 'target' should either return false or be the same value already on the 'target'");
}
assert(threw);
}
}
{
let target = { };
Object.defineProperty(target, "x", {
configurable: false,
get: function() {
return 25;
}
});
let called = false;
let handler = {
set: function(theTarget, propName, value, receiver) {
assert(theTarget === target);
called = true;
theTarget[propName] = value;
return false;
}
};
let proxy = new Proxy(target, handler);
for (let i = 0; i < 1000; i++) {
shouldBe(Reflect.set(proxy, 'x', 40), false);
assert(proxy.x === 25);
assert(called);
called = false;
}
}
{
let target = { };
Object.defineProperty(target, "x", {
configurable: false,
get: function() {
return 25;
}
});
let called = false;
let handler = {
set: function(theTarget, propName, value, receiver) {
assert(theTarget === target);
called = true;
theTarget[propName] = value;
return true;
}
};
let proxy = new Proxy(target, handler);
for (let i = 0; i < 1000; i++) {
let threw = false;
try {
Reflect.set(proxy, 'x', 40);
unreachable();
} catch(e) {
threw = true;
assert(e.toString() === "TypeError: Proxy handler's 'set' method on a non-configurable accessor property without a setter should return false");
}
assert(threw);
}
}
{
let target = { };
Object.defineProperty(target, "x", {
configurable: false,
writable: true,
value: 50
});
let called = false;
let handler = {
set: function(theTarget, propName, value, receiver) {
assert(theTarget === target);
called = true;
theTarget[propName] = value;
return true;
}
};
let proxy = new Proxy(target, handler);
for (let i = 0; i < 1000; i++) {
shouldBe(Reflect.set(proxy, 'x', i), true);
assert(called);
assert(proxy.x === i);
assert(target.x === i);
called = false;
}
}
{
let target = {
x: 30
};
let called = false;
let handler = {
set: function(theTarget, propName, value, receiver) {
assert(target === theTarget);
assert(receiver === proxy);
called = true;
theTarget[propName] = value;
}
};
let proxy = new Proxy(target, handler);
for (let i = 0; i < 1000; i++) {
shouldBe(Reflect.set(proxy, 'x', i), false);
assert(called);
assert(proxy.x === i);
assert(target.x === i);
called = false;
shouldBe(Reflect.set(proxy, 'y', i), false);
assert(called);
assert(proxy.y === i);
assert(target.y === i);
called = false;
}
}
{
let target = {
x: 30
};
let called = false;
let handler = {
set: function(theTarget, propName, value, receiver) {
assert(target === theTarget);
assert(receiver === proxy);
called = true;
theTarget[propName] = value;
}
};
let proxy = new Proxy(target, handler);
for (let i = 0; i < 1000; i++) {
shouldBe(Reflect.set(proxy, 'x', i), false);
assert(called);
assert(proxy.x === i);
assert(target.x === i);
called = false;
shouldBe(Reflect.set(proxy, 'y', i), false);
assert(called);
assert(proxy.y === i);
assert(target.y === i);
called = false;
}
}
{
let target = [];
let called = false;
let handler = { };
let proxy = new Proxy(target, handler);
for (let i = 0; i < 1000; i++) {
shouldBe(Reflect.set(proxy, i, i), true);
assert(proxy[i] === i);
assert(target[i] === i);
}
}
{
let target = [];
let called = false;
let handler = {
set: function(theTarget, propName, value, receiver) {
assert(target === theTarget);
assert(receiver === proxy);
called = true;
theTarget[propName] = value;
}
};
let proxy = new Proxy(target, handler);
for (let i = 0; i < 1000; i++) {
shouldBe(Reflect.set(proxy, i, i), false);
assert(proxy[i] === i);
assert(target[i] === i);
assert(called);
called = false;
}
}
{
let target = [];
let called = false;
let handler = {
set: function(theTarget, propName, value, receiver) {
assert(target === theTarget);
assert(receiver === proxy);
called = true;
theTarget[propName] = value;
}
};
let proxy = new Proxy(target, handler);
for (let i = 0; i < 1000; i++) {
shouldBe(Reflect.set(proxy, i, i), false);
assert(proxy[i] === i);
assert(target[i] === i);
assert(called);
called = false;
}
}
{
let called = false;
let throughProxy = false;
let target = {
set x(v) {
assert(this === target);
this._x = v;
called = true;
},
get x() {
if (throughProxy)
assert(this === proxy);
else
assert(this === target);
return this._x;
}
};
let handler = {
set: function(theTarget, propName, value, receiver) {
assert(target === theTarget);
assert(receiver === proxy);
theTarget[propName] = value;
return true;
}
};
let proxy = new Proxy(target, handler);
for (let i = 0; i < 1000; i++) {
shouldBe(Reflect.set(proxy, 'x', i), true);
assert(called);
throughProxy = true;
assert(proxy.x === i);
throughProxy = false;
assert(target.x === i);
assert(proxy._x === i);
assert(target._x === i);
called = false;
}
}
{
let called = false;
let target = {};
let handler = {
set: function(theTarget, propName, value, receiver) {
assert(target === theTarget);
assert(receiver === obj);
theTarget[propName] = value;
called = true;
return true;
}
};
let proxy = new Proxy(target, handler);
let obj = Object.create(proxy, {
own: {
writable: true,
configurable: true,
value: null
}
});
for (let i = 0; i < 1000; i++) {
shouldBe(Reflect.set(obj, 'own', i), true);
assert(!called);
assert(obj.own === i);
shouldBe(Reflect.set(obj, 'notOwn', i), true);
assert(target.notOwn === i);
assert(proxy.notOwn === i);
assert(obj.notOwn === i);
assert(called);
called = false;
}
}
{
let target = {};
let handler = { };
let proxy = new Proxy(target, handler);
let obj = Object.create(proxy, {
own: {
writable: true,
configurable: true,
value: null
}
});
for (let i = 0; i < 1000; i++) {
shouldBe(Reflect.set(obj, 'own', i), true);
assert(obj.own === i);
assert(proxy.own === undefined);
shouldBe(Reflect.set(obj, 'notOwn', i), true);
// The receiver is always |obj|.
// obj.[[Set]](P, V, obj) -> Proxy.[[Set]](P, V, obj) -> target.[[Set]](P, V, obj)
assert(target.notOwn === undefined);
assert(proxy.notOwn === undefined);
assert(obj.notOwn === i);
}
}
{
let called = false;
let target = {};
let handler = {
set: function(theTarget, propName, value, receiver) {
assert(target === theTarget);
assert(receiver === obj);
theTarget[propName] = value;
called = true;
return true;
}
};
let proxy = new Proxy(target, handler);
let obj = Object.create(proxy, {
[0]: {
writable: true,
configurable: true,
value: null
}
});
for (let i = 0; i < 1000; i++) {
shouldBe(Reflect.set(obj, 0, i), true);
assert(!called);
assert(obj[0] === i);
assert(proxy[0] === undefined);
shouldBe(Reflect.set(obj, 1, i), true);
assert(target[1] === i);
assert(proxy[1] === i);
assert(obj[1] === i);
assert(called);
called = false;
}
}
{
let target = {};
let handler = { };
let proxy = new Proxy(target, handler);
let obj = Object.create(proxy, {
[0]: {
writable: true,
configurable: true,
value: null
}
});
for (let i = 0; i < 1000; i++) {
shouldBe(Reflect.set(obj, 0, i), true);
assert(obj[0] === i);
assert(proxy[0] === undefined);
shouldBe(Reflect.set(obj, 1, i), true);
// The receiver is always |obj|.
// obj.[[Set]](P, V, obj) -> Proxy.[[Set]](P, V, obj) -> target.[[Set]](P, V, obj)
assert(target[1] === undefined);
assert(proxy[1] === undefined);
assert(obj[1] === i);
}
}
{
let called = false;
let target = {};
let handler = {
set: function(theTarget, propName, value, receiver) {
assert(target === theTarget);
assert(receiver === obj);
theTarget[propName] = value;
called = true;
return true;
}
};
let proxy = new Proxy(target, handler);
let obj = Object.create(proxy, {
[0]: {
writable: true,
configurable: true,
value: null
}
});
for (let i = 0; i < 1000; i++) {
shouldBe(Reflect.set(obj, 0, i), true);
assert(!called);
assert(obj[0] === i);
assert(proxy[0] === undefined);
shouldBe(Reflect.set(obj, 1, i), true);
assert(target[1] === i);
assert(proxy[1] === i);
assert(obj[1] === i);
assert(called);
called = false;
}
}
{
let called = false;
let target = [25];
let handler = {
set: function(theTarget, propName, value, receiver) {
assert(target === theTarget);
assert(receiver === obj);
theTarget[propName] = value;
called = true;
return true;
}
};
let proxy = new Proxy(target, handler);
let obj = Object.create(proxy, {
[0]: {
writable: true,
configurable: true,
value: null
}
});
for (let i = 0; i < 1000; i++) {
shouldBe(Reflect.set(obj, 0, i), true);
assert(!called);
assert(obj[0] === i);
assert(proxy[0] === 25);
shouldBe(Reflect.set(obj, 1, i), true);
assert(target[1] === i);
assert(proxy[1] === i);
assert(obj[1] === i);
assert(called);
called = false;
}
}
{
let called = false;
let ogTarget = {};
let target = new Proxy(ogTarget, {
set: function(theTarget, propName, value, receiver) {
assert(theTarget === ogTarget);
assert(receiver === obj);
called = true;
theTarget[propName] = value;
}
});
let handler = { };
let proxy = new Proxy(target, handler);
let obj = Object.create(proxy, {
own: {
writable: true,
configurable: true,
value: null
}
});
for (let i = 0; i < 1000; i++) {
shouldBe(Reflect.set(obj, 'own', i), true);
assert(!called);
assert(obj.own === i);
assert(proxy.own === undefined);
shouldBe(Reflect.set(obj, 'notOwn', i), false);
assert(target.notOwn === i);
assert(proxy.notOwn === i);
assert(obj.notOwn === i);
assert(called);
called = false;
}
}
{
let called = false;
let ogTarget = [25];
let target = new Proxy(ogTarget, {
set: function(theTarget, propName, value, receiver) {
assert(theTarget === ogTarget);
assert(receiver === obj);
called = true;
theTarget[propName] = value;
}
});
let handler = { };
let proxy = new Proxy(target, handler);
let obj = Object.create(proxy, {
[0]: {
writable: true,
configurable: true,
value: null
}
});
for (let i = 0; i < 1000; i++) {
shouldBe(Reflect.set(obj, 0, i), true);
assert(!called);
assert(obj[0] === i);
assert(proxy[0] === 25);
shouldBe(Reflect.set(obj, 1, i), false);
assert(target[1] === i);
assert(proxy[1] === i);
assert(obj[1] === i);
assert(called);
called = false;
}
}