mirror of https://github.com/svaarala/duktape.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
213 lines
5.7 KiB
213 lines
5.7 KiB
/*
|
|
* Proxy (ES6 draft) 'has'.
|
|
*/
|
|
|
|
function propDump(obj, prop) {
|
|
try {
|
|
print(prop + ': ' + (prop in obj));
|
|
} catch (e) {
|
|
print(prop + ': ' + e.name);
|
|
}
|
|
}
|
|
|
|
/*===
|
|
basic test
|
|
foo: true
|
|
1: true
|
|
4: false
|
|
foo: true
|
|
baz: false
|
|
handler.has: true true string 0
|
|
0: true
|
|
handler.has: true true string 1
|
|
1: true
|
|
handler.has: true true string 2
|
|
2: true
|
|
handler.has: true true string 3
|
|
3: false
|
|
handler.has: true true string 0
|
|
0: true
|
|
handler.has: true true string 1
|
|
1: true
|
|
handler.has: true true string 2
|
|
2: true
|
|
handler.has: true true string 3
|
|
3: false
|
|
handler.has: true true string key1
|
|
key1: false
|
|
handler.has: true true string key2
|
|
key2: true
|
|
handler.has: true true string key3
|
|
key3: false
|
|
handler.has: true true string key4
|
|
key4: true
|
|
handler.has: true true string key5
|
|
key5: false
|
|
handler.has: true true string key6
|
|
key6: true
|
|
handler.has: true true string foo
|
|
foo: false
|
|
handler.has: true true string baz
|
|
baz: true
|
|
handler.has: true true string foo
|
|
foo: true
|
|
handler.has: true true string bar
|
|
bar: true
|
|
handler.has: true true string quux
|
|
quux: true
|
|
handler.has: true true string foo
|
|
foo: true
|
|
handler.has: true true string bar
|
|
bar: true
|
|
handler.has: true true string quux
|
|
quux: true
|
|
handler.has: true true string foo
|
|
foo: false
|
|
handler.has: true true string bar
|
|
bar: TypeError
|
|
handler.has: true true string quux
|
|
quux: false
|
|
handler.has: true true string foo
|
|
foo: TypeError
|
|
handler.has: true true string bar
|
|
bar: TypeError
|
|
handler.has: true true string quux
|
|
quux: false
|
|
===*/
|
|
|
|
function basicExistenceTest() {
|
|
var target;
|
|
var proxy;
|
|
var handler;
|
|
|
|
// Simple target object, no proxies.
|
|
|
|
target = { foo: 1, bar: 2, quux: [ 1, 2, 3 ] };
|
|
propDump(target, 'foo');
|
|
target = [ 'foo', 'bar', 'quux' ];
|
|
target.prop = 'propval';
|
|
propDump(target, '1');
|
|
propDump(target, '4');
|
|
|
|
// Simple target object, proxy without 'has'. Existence check
|
|
// goes through to the proxy target.
|
|
|
|
target = { foo: 1, bar: 2, quux: [ 1, 2, 3 ] };
|
|
handler = {};
|
|
proxy = new Proxy(target, handler);
|
|
propDump(proxy, 'foo');
|
|
propDump(proxy, 'baz');
|
|
|
|
// Proxy target, check key coercion.
|
|
// For 'x in y', 'x' is string coerced before HasProperty() internal
|
|
// algorithm is invoked so in ES6 the key is always a string (!).
|
|
|
|
target = [ 'foo', 'bar', 'quux' ];
|
|
handler = {
|
|
has: function (targ, key) {
|
|
print('handler.has:', this === handler, targ === target, typeof key, key);
|
|
return key in targ;
|
|
}
|
|
};
|
|
proxy = new Proxy(target, handler);
|
|
propDump(proxy, '0');
|
|
propDump(proxy, '1');
|
|
propDump(proxy, '2');
|
|
propDump(proxy, '3');
|
|
propDump(proxy, 0);
|
|
propDump(proxy, 1);
|
|
propDump(proxy, 2);
|
|
propDump(proxy, 3);
|
|
|
|
// Proxy return value is boolean coerced.
|
|
|
|
target = {};
|
|
handler = {
|
|
has: function (targ, key) {
|
|
print('handler.has:', this === handler, targ === target, typeof key, key);
|
|
if (key === 'key1') { return 0; }
|
|
if (key === 'key2') { return 1; }
|
|
if (key === 'key3') { return false; }
|
|
if (key === 'key4') { return true; }
|
|
if (key === 'key5') { return ''; }
|
|
if (key === 'key6') { return 'foo'; }
|
|
return false;
|
|
}
|
|
};
|
|
proxy = new Proxy(target, handler);
|
|
propDump(proxy, 'key1');
|
|
propDump(proxy, 'key2');
|
|
propDump(proxy, 'key3');
|
|
propDump(proxy, 'key4');
|
|
propDump(proxy, 'key5');
|
|
propDump(proxy, 'key6');
|
|
|
|
// Proxies which return true/false regardless of what is in the target.
|
|
// The target is extensible so this doesn't matter.
|
|
|
|
target = { foo: 1, bar: 2, quux: [ 1, 2, 3 ] };
|
|
handler = {
|
|
has: function (targ, key) {
|
|
print('handler.has:', this === handler, targ === target, typeof key, key);
|
|
if (key === 'foo') { return false; } // false when key exists
|
|
if (key === 'baz') { return true; } // true when key does not exist
|
|
return true;
|
|
}
|
|
};
|
|
proxy = new Proxy(target, handler);
|
|
propDump(proxy, 'foo');
|
|
propDump(proxy, 'baz');
|
|
|
|
// Proxy indicates property exists. This is never rejected, even if
|
|
// the target object is non-extensible.
|
|
|
|
target = { foo: 1 };
|
|
Object.defineProperty(target, 'bar', {
|
|
value: 2, writable: true, enumerable: true, configurable: false
|
|
});
|
|
handler = {
|
|
has: function (targ, key) {
|
|
print('handler.has:', this === handler, targ === target, typeof key, key);
|
|
return true;
|
|
}
|
|
};
|
|
proxy = new Proxy(target, handler);
|
|
propDump(proxy, 'foo');
|
|
propDump(proxy, 'bar');
|
|
propDump(proxy, 'quux');
|
|
|
|
Object.preventExtensions(target);
|
|
propDump(proxy, 'foo');
|
|
propDump(proxy, 'bar');
|
|
propDump(proxy, 'quux');
|
|
|
|
// Proxy indicates property does not exist. This is rejected in some cases.
|
|
|
|
target = { foo: 1 };
|
|
Object.defineProperty(target, 'bar', {
|
|
value: 2, writable: true, enumerable: true, configurable: false
|
|
});
|
|
handler = {
|
|
has: function (targ, key) {
|
|
print('handler.has:', this === handler, targ === target, typeof key, key);
|
|
return false;
|
|
}
|
|
};
|
|
proxy = new Proxy(target, handler);
|
|
propDump(proxy, 'foo');
|
|
propDump(proxy, 'bar'); // rejected: exists in target, non-configurable
|
|
propDump(proxy, 'quux');
|
|
|
|
Object.preventExtensions(target);
|
|
propDump(proxy, 'foo'); // rejected: exists in target, target not extensible
|
|
propDump(proxy, 'bar'); // rejected: exists in target, non-configurable
|
|
propDump(proxy, 'quux'); // accepted: does not exist in target, target not extensible; es6 rev23/24 still allows this
|
|
}
|
|
|
|
print('basic test');
|
|
|
|
try {
|
|
basicExistenceTest();
|
|
} catch (e) {
|
|
print(e);
|
|
}
|
|
|