diff --git a/tests/ecmascript/test-bi-array-proto-reverse.js b/tests/ecmascript/test-bi-array-proto-reverse.js index cb94a0b06c..30470bed66 100644 --- a/tests/ecmascript/test-bi-array-proto-reverse.js +++ b/tests/ecmascript/test-bi-array-proto-reverse.js @@ -1,27 +1,6 @@ // XXX: shared test utils -function formatValue(v) { - if (typeof v === 'function') { - return 'function'; - } - return typeof(v) + ':' + String(v); -} - -function printDescriptor(obj, key) { - var pd = Object.getOwnPropertyDescriptor(obj, key); - if (!pd) { - print('key=' + key, 'nonexistent'); - return; - } - - print('key=' + key, - 'value=' + formatValue(pd.value), - 'writable=' + formatValue(pd.writable), - 'enumerable=' + formatValue(pd.enumerable), - 'configurable=' + formatValue(pd.configurable), - 'get=' + formatValue(pd.get), - 'set=' + formatValue(pd.set)); -} +/*@include util-object.js@*/ function dumpValue(x) { var i, n, clipped; @@ -157,14 +136,14 @@ try { /*=== attributes true true false false false true false true -key=0 value=undefined:undefined writable=undefined:undefined enumerable=boolean:false configurable=boolean:true get=function set=function -key=1 value=undefined:undefined writable=undefined:undefined enumerable=boolean:false configurable=boolean:true get=function set=function -key=2 nonexistent -key=3 nonexistent -key=4 nonexistent -key=5 value=undefined:undefined writable=undefined:undefined enumerable=boolean:true configurable=boolean:true get=function set=function -key=6 nonexistent -key=7 value=undefined:undefined writable=undefined:undefined enumerable=boolean:true configurable=boolean:true get=function set=function +key: 0, desc: get=function,set=function,enumerable=false,configurable=true +key: 1, desc: get=function,set=function,enumerable=false,configurable=true +key: 2, desc: none +key: 3, desc: none +key: 4, desc: none +key: 5, desc: get=function,set=function,enumerable=true,configurable=true +key: 6, desc: none +key: 7, desc: get=function,set=function,enumerable=true,configurable=true get 0 get 7 set 0 val7 @@ -172,18 +151,18 @@ set 7 val0 get 1 get 5 true false true false false false true true -key=0 value=undefined:undefined writable=undefined:undefined enumerable=boolean:false configurable=boolean:true get=function set=function -key=1 nonexistent -key=2 value=string:val5 writable=boolean:true enumerable=boolean:true configurable=boolean:true get=undefined:undefined set=undefined:undefined -key=3 nonexistent -key=4 nonexistent -key=5 nonexistent -key=6 value=string:val1 writable=boolean:true enumerable=boolean:true configurable=boolean:true get=undefined:undefined set=undefined:undefined -key=7 value=undefined:undefined writable=undefined:undefined enumerable=boolean:true configurable=boolean:true get=function set=function -key=0 value=string:foo writable=boolean:true enumerable=boolean:false configurable=boolean:true get=undefined:undefined set=undefined:undefined -key=1 nonexistent -key=0 value=string:foo writable=boolean:true enumerable=boolean:false configurable=boolean:true get=undefined:undefined set=undefined:undefined -key=1 nonexistent +key: 0, desc: get=function,set=function,enumerable=false,configurable=true +key: 1, desc: none +key: 2, desc: value="val5",writable=true,enumerable=true,configurable=true +key: 3, desc: none +key: 4, desc: none +key: 5, desc: none +key: 6, desc: value="val1",writable=true,enumerable=true,configurable=true +key: 7, desc: get=function,set=function,enumerable=true,configurable=true +key: 0, desc: value="foo",writable=true,enumerable=false,configurable=true +key: 1, desc: none +key: 0, desc: value="foo",writable=true,enumerable=false,configurable=true +key: 1, desc: none ===*/ print('attributes'); @@ -245,7 +224,7 @@ function attributesTest() { t.hasOwnProperty(6), t.hasOwnProperty(7)); for (i = 0; i < 8; i++) { - printDescriptor(t, String(i)); + printKeyPropDesc(t, String(i)); } t.reverse(); @@ -256,7 +235,7 @@ function attributesTest() { t.hasOwnProperty(6), t.hasOwnProperty(7)); for (i = 0; i < 8; i++) { - printDescriptor(t, String(i)); + printKeyPropDesc(t, String(i)); } // Here, '0' is not enumerable, but when it gets swapped to position 1, @@ -269,11 +248,11 @@ function attributesTest() { '0': { value: 'foo', writable: true, enumerable: false, configurable: true }, 'length': { value: 2 } }); - printDescriptor(t, '0'); - printDescriptor(t, '1'); + printKeyPropDesc(t, '0'); + printKeyPropDesc(t, '1'); [].reverse(); - printDescriptor(t, '0'); - printDescriptor(t, '1'); + printKeyPropDesc(t, '0'); + printKeyPropDesc(t, '1'); } try { diff --git a/tests/ecmascript/test-bi-proxy-defineproperty.js b/tests/ecmascript/test-bi-proxy-defineproperty.js new file mode 100644 index 0000000000..7ad6f3eb7b --- /dev/null +++ b/tests/ecmascript/test-bi-proxy-defineproperty.js @@ -0,0 +1,40 @@ +/* + * Proxy (ES2015) 'defineProperty'. + */ + +/*@include util-object.js@*/ + +/*=== +value=123,writable=false,enumerable=false,configurable=true +get=function,set=function,enumerable=false,configurable=true +===*/ + +function passThroughTest() { + var T = {}; + var P = new Proxy(T, {}); + var pd; + + Object.defineProperty(P, 'foo', { + value: 123, + writable: false, + enumerable: false, + configurable: true + }); + Object.defineProperty(P, 'bar', { + get: function getter() {}, + set: function setter() {}, + enumerable: false, + configurable: true + }); + + pd = Object.getOwnPropertyDescriptor(T, 'foo'); + printPropDesc(pd); + pd = Object.getOwnPropertyDescriptor(T, 'bar'); + printPropDesc(pd); +} + +try { + passThroughTest(); +} catch (e) { + print(e.stack || e); +} diff --git a/tests/ecmascript/test-bi-proxy-getownpropertydescriptor.js b/tests/ecmascript/test-bi-proxy-getownpropertydescriptor.js new file mode 100644 index 0000000000..e603eead99 --- /dev/null +++ b/tests/ecmascript/test-bi-proxy-getownpropertydescriptor.js @@ -0,0 +1,53 @@ +/* + * Proxy (ES2015) 'getOwnPropertyDescriptor'. + */ + +/*@include util-object.js@*/ + +/*=== +value=123,writable=true,enumerable=false,configurable=true +get=function,enumerable=true,configurable=false +set=function,enumerable=false,configurable=false +get=function,set=function,enumerable=true,configurable=true +value=123,writable=true,enumerable=false,configurable=true +get=function,enumerable=true,configurable=false +set=function,enumerable=false,configurable=false +get=function,set=function,enumerable=true,configurable=true +===*/ + +function passThroughTest() { + var T = {}; + var P = new Proxy(T, {}); + var pd; + + Object.defineProperty(T, 'foo', { value: 123, writable: true, enumerable: false, configurable: true }); + Object.defineProperty(T, 'bar', { get: function getter() {}, enumerable: true, configurable: false }); + Object.defineProperty(T, 'quux', { set: function setter() {}, enumerable: false, configurable: false }); + Object.defineProperty(T, 'baz', { get: function getter() {}, set: function setter() {}, enumerable: true, configurable: true }); + + pd = Object.getOwnPropertyDescriptor(T, 'foo'); + printPropDesc(pd); + pd = Object.getOwnPropertyDescriptor(T, 'bar'); + printPropDesc(pd); + pd = Object.getOwnPropertyDescriptor(T, 'quux'); + printPropDesc(pd); + pd = Object.getOwnPropertyDescriptor(T, 'baz'); + printPropDesc(pd); + + // As of Duktape 2.2 getOwnPropertyDescriptor() properly passes through + // to the target object. + pd = Object.getOwnPropertyDescriptor(P, 'foo'); + printPropDesc(pd); + pd = Object.getOwnPropertyDescriptor(P, 'bar'); + printPropDesc(pd); + pd = Object.getOwnPropertyDescriptor(P, 'quux'); + printPropDesc(pd); + pd = Object.getOwnPropertyDescriptor(P, 'baz'); + printPropDesc(pd); +} + +try { + passThroughTest(); +} catch (e) { + print(e.stack || e); +} diff --git a/tests/ecmascript/test-bi-proxy-virtualized-enum.js b/tests/ecmascript/test-bi-proxy-virtualized-enum.js new file mode 100644 index 0000000000..ec7cfb89d7 --- /dev/null +++ b/tests/ecmascript/test-bi-proxy-virtualized-enum.js @@ -0,0 +1,62 @@ +/* + * Example of virtualizing enumeration using a Proxy. + */ + +/*=== +ownKeys trap: true +getOwnPropertyDescriptor trap: true true string 0 +getOwnPropertyDescriptor trap: true true string 1 +getOwnPropertyDescriptor trap: true true string 2 +getOwnPropertyDescriptor trap: true true string 3 +getOwnPropertyDescriptor trap: true true string 4 +getOwnPropertyDescriptor trap: true true string noSuch +getOwnPropertyDescriptor trap: true true string length +0 +1 +2 +3 +4 +noSuch +===*/ + +function test() { + var target = [ 'foo', 'bar', 'quux' ]; + var handler = { + ownKeys: function () { + // The ownKeys result set is validated against the Proxy to ensure + // enumerated keys are enumerable; unless a getOwnPropertyDescriptor + // trap exists these checks will be made against the target which + // means non-existent properties won't be enumerated.ยง + print('ownKeys trap:', this === handler); + return [ '0', '1', '2', '3', '4', 'noSuch', 'length' ] + }, + getOwnPropertyDescriptor: function (targ, key) { + // Cannot report 'length' as enumerable (that would violate + // getOwnPropertyDescriptor trap constraints). However, + // Duktape 2.2 (at least) won't enforce that constraint yet. + print('getOwnPropertyDescriptor trap:', this === handler, targ === target, typeof key, key); + if (key === 'length') { + return Object.getOwnPropertyDescriptor(target, key); + } + return { + value: target[key], + enumerable: true, + writable: true, + configurable: true + }; + } + }; + var proxy = new Proxy(target, handler); + + // Without 'getOwnPropertyDescriptor' trap the only keys visible would be + // '0', '1', and '2' which backing in the target object. + for (var k in proxy) { + print(k); + } +} + +try { + test(); +} catch (e) { + print(e.stack || e); +} diff --git a/tests/ecmascript/test-dev-array-property-attrs.js b/tests/ecmascript/test-dev-array-property-attrs.js index 006b823006..3fba640c17 100644 --- a/tests/ecmascript/test-dev-array-property-attrs.js +++ b/tests/ecmascript/test-dev-array-property-attrs.js @@ -3,31 +3,29 @@ * and without an internal "array part". */ -function printDesc(desc) { - print(desc.writable, desc.enumerable, desc.configurable); -} +/*@include util-object.js@*/ /*=== -true true true -true true true -true true true -true true true -true true true -true true true -true true true +value=1,writable=true,enumerable=true,configurable=true +value=2,writable=true,enumerable=true,configurable=true +value=3,writable=true,enumerable=true,configurable=true +value=1,writable=true,enumerable=true,configurable=true +value=2,writable=true,enumerable=true,configurable=true +value=3,writable=true,enumerable=true,configurable=true +value=4,writable=true,enumerable=true,configurable=true ===*/ /* array is initially dense (array part exists) */ a = [1,2,3]; -printDesc(Object.getOwnPropertyDescriptor(a, '0')); -printDesc(Object.getOwnPropertyDescriptor(a, '1')); -printDesc(Object.getOwnPropertyDescriptor(a, '2')); +printPropDesc(Object.getOwnPropertyDescriptor(a, '0')); +printPropDesc(Object.getOwnPropertyDescriptor(a, '1')); +printPropDesc(Object.getOwnPropertyDescriptor(a, '2')); /* force array to be sparse (array part is abandoned) */ a[10000] = 4; -printDesc(Object.getOwnPropertyDescriptor(a, '0')); -printDesc(Object.getOwnPropertyDescriptor(a, '1')); -printDesc(Object.getOwnPropertyDescriptor(a, '2')); -printDesc(Object.getOwnPropertyDescriptor(a, '10000')); +printPropDesc(Object.getOwnPropertyDescriptor(a, '0')); +printPropDesc(Object.getOwnPropertyDescriptor(a, '1')); +printPropDesc(Object.getOwnPropertyDescriptor(a, '2')); +printPropDesc(Object.getOwnPropertyDescriptor(a, '10000')); diff --git a/tests/ecmascript/util-object.js b/tests/ecmascript/util-object.js index 0441f6129f..9fbc834759 100644 --- a/tests/ecmascript/util-object.js +++ b/tests/ecmascript/util-object.js @@ -47,3 +47,50 @@ function getValuePublicType(val) { function getValueInternalTag(val) { return getDuktapeInfoField(val, 1, 'itag'); } + +// String convert a descriptor object. +function propDescToString(pd) { + function fmt(v) { + if (typeof v === 'function') { + return 'function'; + } + return Duktape.enc('jx', v); + } + + if (!pd) { + return 'none'; + } + + var res = []; + if (pd.value !== void 0) { + res.push('value=' + fmt(pd.value)); + } + if (pd.get !== void 0) { + res.push('get=' + fmt(pd.get)); + } + if (pd.set !== void 0) { + res.push('set=' + fmt(pd.set)); + } + if (pd.writable !== void 0) { + res.push('writable=' + fmt(pd.writable)); + } + if (pd.enumerable !== void 0) { + res.push('enumerable=' + fmt(pd.enumerable)); + } + if (pd.configurable !== void 0) { + res.push('configurable=' + fmt(pd.configurable)); + } + + return res.join(','); +} + +// Print a descriptor object. +function printPropDesc(pd) { + print(propDescToString(pd)); +} + +// Print a key and a related property descriptor. +function printKeyPropDesc(obj, key) { + var pd = Object.getOwnPropertyDescriptor(obj, key); + print('key: ' + key + ', desc: ' + propDescToString(pd)); +}