diff options
Diffstat (limited to 'js/src/tests/non262/regress/regress-1383630.js')
-rw-r--r-- | js/src/tests/non262/regress/regress-1383630.js | 827 |
1 files changed, 827 insertions, 0 deletions
diff --git a/js/src/tests/non262/regress/regress-1383630.js b/js/src/tests/non262/regress/regress-1383630.js new file mode 100644 index 0000000000..8ce3074af3 --- /dev/null +++ b/js/src/tests/non262/regress/regress-1383630.js @@ -0,0 +1,827 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +/* These tests are not checking whether an exception is thrown or not for + * proxies: those tests should already exist in js/src/tests/non262/Proxy . + * We expect TypeErrors to be thrown in these tests, with a stringification + * of the error message showing whatever property name the error is being + * reported for. + * + * Beyond the presence of the property name, these tests do not care about the + * contents of the message. + * + * The reason for requiring the property name is simple: with ECMAScript + * proxies, it can be really hard to figure out what little assertion causes a + * TypeError in the first place. + */ +"use strict"; + +function assertThrowsTypeErrorIncludes(f, propStr, details) { + var fullmsg; + try { + f(); + } + catch (exc) { + if (!(exc instanceof TypeError)) + fullmsg = + "Assertion failed: expected TypeError, got " + exc; + else if (!exc.message.includes(propStr)) + fullmsg = + `Assertion failed: expected TypeError message '${exc.message}' to include '${propStr}'`; + else if (details && !exc.message.includes(details)) + fullmsg = + `Assertion failed: expected TypeError message '${exc.message}' to include '${details}'`; + else + return; + } + + if (fullmsg === undefined) { + fullmsg = + "Assertion failed: expected TypeError, no exception thrown"; + } + + throw new Error(fullmsg); +} + +const STR = "one", STR_NAME = `"one"`; +const SYM = Symbol("two"), SYM_NAME = `'Symbol("two")'`; + +function errorHasPropertyTests(test) { + assertThrowsTypeErrorIncludes(() => test(STR), STR_NAME); + assertThrowsTypeErrorIncludes(() => test(SYM), SYM_NAME); +} + +function errorHasPropertyTestsWithDetails(test) { + let [throwable, details] = test(STR); + assertThrowsTypeErrorIncludes(throwable, STR_NAME, details); + + [throwable, details] = test(SYM); + assertThrowsTypeErrorIncludes(throwable, SYM_NAME, details); +} + +// getOwnPropertyDescriptor + +function testGetOwnPropertyDescriptor_OBJORUNDEF(propName) { + // JSMSG_PROXY_GETOWN_OBJORUNDEF + const h = { + getOwnPropertyDescriptor: () => 2 + }; + + const t = {}; + const p = new Proxy(t, h); + + Reflect.getOwnPropertyDescriptor(p, propName); +} + +function testGetOwnPropertyDescriptor_NC_AS_NE(propName) { + // JSMSG_CANT_REPORT_NC_AS_NE + const h = { + getOwnPropertyDescriptor: () => undefined + }; + + const t = {}; + Reflect.defineProperty(t, propName, { + value: 1, + writable: true, + enumerable: true, + configurable: false + }); + const p = new Proxy(t, h); + + Reflect.getOwnPropertyDescriptor(p, propName); +} + +function testGetOwnPropertyDescriptor_E_AS_NE(propName) { + // JSMSG_CANT_REPORT_E_AS_NE + const h = { + getOwnPropertyDescriptor: () => undefined, + }; + + const t = {}; + Reflect.defineProperty(t, propName, { + value: 1, + writable: true, + enumerable: true, + configurable: true + }); + Reflect.preventExtensions(t); + const p = new Proxy(t, h); + + Reflect.getOwnPropertyDescriptor(p, propName); +} + +function testGetOwnPropertyDescriptor_NE_AS_NC(propName) { + // JSMSG_CANT_REPORT_NE_AS_NC + const h = { + getOwnPropertyDescriptor: function() { + return { + value: 1, + writable: true, + enumerable: true, + configurable: false + }; + } + }; + + const t = {}; + const p = new Proxy(t, h); + + Reflect.getOwnPropertyDescriptor(p, propName); +} + +function testGetOwnPropertyDescriptor_C_AS_NC(propName) { + // JSMSG_CANT_REPORT_C_AS_NC + const h = { + getOwnPropertyDescriptor: function() { + return { + value: 1, + writable: true, + enumerable: true, + configurable: false // here's the difference + }; + } + }; + + const t = {}; + Reflect.defineProperty(t, propName, { + value: 1, + writable: true, + enumerable: true, + configurable: true + }); + + const p = new Proxy(t, h); + + Reflect.getOwnPropertyDescriptor(p, propName); +} + +function testGetOwnPropertyDescriptor_INVALID_NOT_EXTENSIBLE(propName) { + // JSMSG_CANT_REPORT_INVALID, DETAILS_NOT_EXTENSIBLE + const h = { + getOwnPropertyDescriptor: function() { + return { + value: 1, + writable: true, + enumerable: true, + configurable: true + }; + } + }; + + const t = {}; + Reflect.preventExtensions(t); + + const p = new Proxy(t, h); + return [() => { Reflect.getOwnPropertyDescriptor(p, propName); }, + "proxy can't report an extensible object as non-extensible"]; +} + +function testGetOwnPropertyDescriptor_INVALID_C_AS_NC(propName) { + // JSMSG_CANT_REPORT_INVALID, DETAILS_CANT_REPORT_NC_AS_C + const h = { + getOwnPropertyDescriptor: function() { + return { + value: 1, + writable: true, + enumerable: true, + configurable: true + }; + } + }; + + const t = {}; + Reflect.defineProperty(t, propName, { + value: 1, + writable: true, + enumerable: true, + configurable: false + }); + + const p = new Proxy(t, h); + return [() => { Reflect.getOwnPropertyDescriptor(p, propName); }, + "proxy can't report an existing non-configurable property as configurable"]; +} + +function testGetOwnPropertyDescriptor_INVALID_ENUM_DIFFERENT_CURRENT(cEnumerable, propName) { + // JSMSG_CANT_REPORT_INVALID, DETAILS_ENUM_DIFFERENT + const h = { + getOwnPropertyDescriptor: function() { + return { + value: 1, + writable: true, + enumerable: !cEnumerable, + configurable: false + }; + } + }; + + const t = {}; + Reflect.defineProperty(t, propName, { + value: 1, + writable: true, + enumerable: cEnumerable, + configurable: false + }); + + const p = new Proxy(t, h); + return [() => { Reflect.getOwnPropertyDescriptor(p, propName); }, + "proxy can't report a different 'enumerable' from target when target is not configurable"]; +} + +function testGetOwnPropertyDescriptor_INVALID_CURRENT_NC_DIFF_TYPE(cAccessor, propName) { + // JSMSG_CANT_REPORT_INVALID, DETAILS_CURRENT_NC_DIFF_TYPE + const accDesc = { + get: () => 1, + enumerable: true, + configurable: false, + }; + const dataDesc = { + value: 1, + writable: true, + enumerable: true, + configurable: false + }; + + const h = { + getOwnPropertyDescriptor: () => { return (cAccessor ? dataDesc : accDesc); } + }; + + const t = {}; + Reflect.defineProperty(t, propName, cAccessor ? accDesc : dataDesc); + const p = new Proxy(t, h); + return [() => { Reflect.getOwnPropertyDescriptor(p, propName); }, + "proxy can't report a different descriptor type when target is not configurable"]; +} + +function testGetOwnPropertyDescriptor_INVALID_NW_AS_W(propName) { + // JSMSG_CANT_REPORT_INVALID, DETAILS_CANT_REPORT_NW_AS_W + const h = { + getOwnPropertyDescriptor: function() { + return { + value: 1, + writable: true, + enumerable: true, + configurable: false + }; + } + }; + + const t = {}; + Reflect.defineProperty(t, propName, { + value: 2, + writable: false, + enumerable: true, + configurable: false + }); + const p = new Proxy(t, h); + + return [() => { Reflect.getOwnPropertyDescriptor(p, propName); }, + "proxy can't report a non-configurable, non-writable property as writable"]; +} + +function testGetOwnPropertyDescriptor_INVALID_DIFFERENT_VALUE(propName) { + // JSMSG_CANT_REPORT_INVALID, DETAILS_DIFFERENT_VALUE + const h = { + getOwnPropertyDescriptor: function() { + return { + value: 1, + writable: false, + enumerable: true, + configurable: false + }; + } + }; + + const t = {}; + Reflect.defineProperty(t, propName, { + value: 2, + writable: false, + enumerable: true, + configurable: false + }); + const p = new Proxy(t, h); + + return [() => { Reflect.getOwnPropertyDescriptor(p, propName); }, + "proxy must report the same value for the non-writable, non-configurable property"]; +} + +function testGetOwnPropertyDescriptor_INVALID_SETTERS_DIFFERENT(propName) { + // JSMSG_CANT_REPORT_INVALID, DETAILS_SETTERS_DIFFERENT + const g = () => 1; + const h = { + getOwnPropertyDescriptor: function() { + return { + get: g, + set: () => 2, + enumerable: true, + configurable: false + }; + } + }; + + const t = {}; + Reflect.defineProperty(t, propName, { + get: g, + set: () => 2, + enumerable: true, + configurable: false + }); + const p = new Proxy(t, h); + + return [() => { Reflect.getOwnPropertyDescriptor(p, propName); }, + "proxy can't report different setters for a currently non-configurable property"]; +} + +function testGetOwnPropertyDescriptor_INVALID_GETTERS_DIFFERENT(propName) { + // JSMSG_CANT_REPORT_INVALID, DETAILS_GETTERS_DIFFERENT + const h = { + getOwnPropertyDescriptor: function() { + return { + get: () => 2, + enumerable: true, + configurable: false + }; + } + }; + + const t = {}; + Reflect.defineProperty(t, propName, { + get: () => 2, + enumerable: true, + configurable: false + }); + const p = new Proxy(t, h); + + return [() => { Reflect.getOwnPropertyDescriptor(p, propName); }, + "proxy can't report different getters for a currently non-configurable property"]; +} + +// defineProperty +function testDefineProperty_CANT_DEFINE_NEW(propName) { + // JSMSG_CANT_DEFINE_NEW + const h = { + defineProperty: () => true + }; + + const t = {}; + Reflect.preventExtensions(t); + + const p = new Proxy(t, h); + Reflect.defineProperty(p, propName, {}); +} + +function testDefineProperty_NE_AS_NC(propName) { + // JSMSG_CANT_DEFINE_NE_AS_NC + const h = { + defineProperty: () => true + }; + + const t = {}; + + const p = new Proxy(t, h); + Reflect.defineProperty(p, propName, { + value: 1, + enumerable: true, + writable: true, + configurable: false, + }); +} + +/* Reflect.defineProperty(proxy, propName, desc) cannot throw + * JSMSG_CANT_REPORT_INVALID with DETAILS_NOT_EXTENSIBLE. Here's why: + * + * To throw with DETAILS_NOT_EXTENSIBLE, current must be undefined and the + * target must not be extensible, inside ValidateAndApplyPropertyDescriptor. + * + * ValidateAndApplyPropertyDescriptor's current is also + * IsCompatiblePropertyDescriptor's current, and therefore also + * targetDesc in [[DefineOwnProperty]] for proxies at step 16b. + * + * BUT step 16 is not reached if targetDesc in [[DefineOwnProperty]] is + * undefined: instead step 15 is invoked. QED. + */ + +function testDefineProperty_INVALID_NC_AS_C(propName) { + // JSMSG_CANT_REPORT_INVALID, DETAILS_CANT_REPORT_NC_AS_C + const h = { + defineProperty: function() { + return true; + } + }; + + const newDesc = { + value: 1, + writable: true, + enumerable: true, + configurable: true + }; + + const t = {}; + Reflect.defineProperty(t, propName, { + value: 1, + writable: true, + enumerable: true, + configurable: false + }); + + const p = new Proxy(t, h); + return [() => { Reflect.defineProperty(p, propName, newDesc); }, + "proxy can't report an existing non-configurable property as configurable"]; +} + +function testDefineProperty_INVALID_ENUM_DIFFERENT_CURRENT(cEnumerable, propName) { + // JSMSG_CANT_REPORT_INVALID, DETAILS_ENUM_DIFFERENT + const h = { + defineProperty: function() { + return true; + } + }; + + const newDesc = { + value: 1, + writable: true, + enumerable: !cEnumerable, + configurable: false + }; + + const t = {}; + Reflect.defineProperty(t, propName, { + value: 1, + writable: true, + enumerable: cEnumerable, + configurable: false + }); + + const p = new Proxy(t, h); + return [() => { Reflect.defineProperty(p, propName, newDesc); }, + "proxy can't report a different 'enumerable' from target when target is not configurable"]; +} + +function testDefineProperty_INVALID_CURRENT_NC_DIFF_TYPE(cAccessor, propName) { + // JSMSG_CANT_REPORT_INVALID, DETAILS_CURRENT_NC_DIFF_TYPE + const accDesc = { + get: () => 1, + enumerable: true, + configurable: false, + }; + const dataDesc = { + value: 1, + writable: true, + enumerable: true, + configurable: false + }; + + const h = { + defineProperty: () => true, + }; + + const t = {}; + Reflect.defineProperty(t, propName, cAccessor ? accDesc : dataDesc); + const p = new Proxy(t, h); + return [() => { Reflect.defineProperty(p, propName, cAccessor ? dataDesc : accDesc); }, + "proxy can't report a different descriptor type when target is not configurable"]; +} + +function testDefineProperty_INVALID_NW_AS_W(propName) { + // JSMSG_CANT_REPORT_INVALID, DETAILS_CANT_REPORT_NW_AS_W + const h = { + defineProperty: function() { + return true; + } + }; + + const newDesc = { + value: 1, + writable: true, + enumerable: true, + configurable: false + }; + + const t = {}; + Reflect.defineProperty(t, propName, { + value: 2, + writable: false, + enumerable: true, + configurable: false + }); + const p = new Proxy(t, h); + + return [() => { Reflect.defineProperty(p, propName, newDesc); }, + "proxy can't report a non-configurable, non-writable property as writable"]; +} + +function testDefineProperty_INVALID_DIFFERENT_VALUE(propName) { + // JSMSG_CANT_REPORT_INVALID, DETAILS_DIFFERENT_VALUE + const h = { + defineProperty: function() { + return true; + } + }; + + const newDesc = { + value: 1, + writable: false, + enumerable: true, + configurable: false + }; + + const t = {}; + Reflect.defineProperty(t, propName, { + value: 2, + writable: false, + enumerable: true, + configurable: false + }); + const p = new Proxy(t, h); + + return [() => { Reflect.defineProperty(p, propName, newDesc); }, + "proxy must report the same value for the non-writable, non-configurable property"]; +} + +function testDefineProperty_INVALID_SETTERS_DIFFERENT(propName) { + // JSMSG_CANT_REPORT_INVALID, DETAILS_SETTERS_DIFFERENT + const g = () => 1; + const h = { + defineProperty: function() { + return true; + } + }; + + const newDesc = { + get: g, + set: () => 2, + enumerable: true, + configurable: false + }; + + const t = {}; + Reflect.defineProperty(t, propName, { + get: g, + set: () => 2, + enumerable: true, + configurable: false + }); + const p = new Proxy(t, h); + + return [() => { Reflect.defineProperty(p, propName, newDesc); }, + "proxy can't report different setters for a currently non-configurable property"]; +} + +function testDefineProperty_INVALID_GETTERS_DIFFERENT(propName) { + // JSMSG_CANT_REPORT_INVALID, DETAILS_GETTERS_DIFFERENT + const h = { + defineProperty: function() { + return true; + } + }; + + const newDesc = { + get: () => 2, + enumerable: true, + configurable: false + }; + + const t = {}; + Reflect.defineProperty(t, propName, { + get: () => 2, + enumerable: true, + configurable: false + }); + const p = new Proxy(t, h); + + return [() => { Reflect.defineProperty(p, propName, newDesc); }, + "proxy can't report different getters for a currently non-configurable property"]; +} + +function testDefineProperty_INVALID_C_AS_NC(propName) { + const h = { + defineProperty: function() { + return true; + } + }; + + const newDesc = { + value: 1, + writable: true, + enumerable: true, + configurable: false + }; + + const t = {}; + Reflect.defineProperty(t, propName, { + value: 1, + writable: true, + enumerable: true, + configurable: true + }); + const p = new Proxy(t, h); + + return [() => { Reflect.defineProperty(p, propName, newDesc); }, + "proxy can't define an existing configurable property as non-configurable"]; +} + +// ownKeys + +function testOwnKeys_CANT_SKIP_NC(propName) { + // JSMSG_CANT_SKIP_NC + const h = { + ownKeys: () => [] + }; + + const t = {}; + Reflect.defineProperty(t, propName, { + value: 1, + writable: true, + enumerable: true, + configurable: false + }); + + const p = new Proxy(t, h); + + Reflect.ownKeys(p); +} + +function testOwnKeys_E_AS_NE(propName) { + // JSMSG_CANT_REPORT_E_AS_NE + const h = { + ownKeys: () => [] + }; + + const t = {}; + Reflect.defineProperty(t, propName, { + configurable: true, + value: 1, + writable: true, + enumerable: true + }); + + Reflect.preventExtensions(t); + const p = new Proxy(t, h); + + Reflect.ownKeys(p); +} + +// has + +function testHas_NC_AS_NE(propName) { + // JSMSG_CANT_REPORT_NC_AS_NE + const h = { + has: () => undefined + }; + + const t = {}; + Reflect.defineProperty(t, propName, { + value: 1, + writable: true, + enumerable: true, + configurable: false + }); + const p = new Proxy(t, h); + + Reflect.has(p, propName); +} + +function testHas_E_AS_NE(propName) { + // JSMSG_CANT_REPORT_E_AS_NE + const h = { + has: () => undefined + }; + + const t = {}; + Reflect.defineProperty(t, propName, { + value: 1, + writable: true, + enumerable: true, + configurable: true + }); + Reflect.preventExtensions(t); + const p = new Proxy(t, h); + + Reflect.has(p, propName); +} + +// get + +function testGet_SAME_VALUE(propName) { + const h = { + get: () => 2 + }; + + const t = {}; + Reflect.defineProperty(t, propName, { + value: 1, + writable: false, + enumerable: true, + configurable: false + }); + + const p = new Proxy(t, h); + Reflect.get(p, propName); +} + +function testGet_MUST_REPORT_UNDEFINED(propName) { + // JSMSG_MUST_REPORT_UNDEFINED + const h = { + get: () => 2 + }; + + const t = {}; + Reflect.defineProperty(t, propName, { + set: () => { /* do nothing */}, + enumerable: true, + configurable: false + }); + + const p = new Proxy(t, h); + Reflect.get(p, propName); +} + +// set + +function testSet_CANT_SET_NW_NC(propName) { + // JSMSG_CANT_SET_NW_NC + const h = { + set: () => true, + }; + + const t = {}; + Reflect.defineProperty(t, propName, { + value: 1, + writable: false, + enumerable: true, + configurable: false + }); + + const p = new Proxy(t, h); + Reflect.set(p, propName, 3); +} + +function testSet_WO_SETTER(propName) { + // JSMSG_MUST_REPORT_UNDEFINED + const h = { + set: () => true + }; + + const t = {}; + Reflect.defineProperty(t, propName, { + get: () => { /* do nothing */}, + enumerable: true, + configurable: false + }); + + const p = new Proxy(t, h); + Reflect.set(p, propName, 1); +} + +// test sequence + +[ + testGetOwnPropertyDescriptor_OBJORUNDEF, + testGetOwnPropertyDescriptor_NC_AS_NE, + testGetOwnPropertyDescriptor_E_AS_NE, + testGetOwnPropertyDescriptor_NE_AS_NC, + testGetOwnPropertyDescriptor_C_AS_NC, + + testDefineProperty_CANT_DEFINE_NEW, + testDefineProperty_NE_AS_NC, + + testOwnKeys_CANT_SKIP_NC, + testOwnKeys_E_AS_NE, + + testHas_NC_AS_NE, + testHas_E_AS_NE, + + testGet_SAME_VALUE, + testGet_MUST_REPORT_UNDEFINED, + + testSet_CANT_SET_NW_NC, + testSet_WO_SETTER, +].forEach(errorHasPropertyTests); + +[ + testGetOwnPropertyDescriptor_INVALID_NOT_EXTENSIBLE, + testGetOwnPropertyDescriptor_INVALID_C_AS_NC, + testGetOwnPropertyDescriptor_INVALID_ENUM_DIFFERENT_CURRENT.bind(null, true), + testGetOwnPropertyDescriptor_INVALID_ENUM_DIFFERENT_CURRENT.bind(null, false), + testGetOwnPropertyDescriptor_INVALID_CURRENT_NC_DIFF_TYPE.bind(null, true), + testGetOwnPropertyDescriptor_INVALID_CURRENT_NC_DIFF_TYPE.bind(null, false), + testGetOwnPropertyDescriptor_INVALID_NW_AS_W, + testGetOwnPropertyDescriptor_INVALID_DIFFERENT_VALUE, + testGetOwnPropertyDescriptor_INVALID_SETTERS_DIFFERENT, + testGetOwnPropertyDescriptor_INVALID_GETTERS_DIFFERENT, + + testDefineProperty_INVALID_NC_AS_C, + testDefineProperty_INVALID_ENUM_DIFFERENT_CURRENT.bind(null, true), + testDefineProperty_INVALID_ENUM_DIFFERENT_CURRENT.bind(null, false), + testDefineProperty_INVALID_CURRENT_NC_DIFF_TYPE.bind(null, true), + testDefineProperty_INVALID_CURRENT_NC_DIFF_TYPE.bind(null, false), + testDefineProperty_INVALID_NW_AS_W, + testDefineProperty_INVALID_DIFFERENT_VALUE, + testDefineProperty_INVALID_SETTERS_DIFFERENT, + testDefineProperty_INVALID_GETTERS_DIFFERENT, + testDefineProperty_INVALID_C_AS_NC, +].forEach(errorHasPropertyTestsWithDetails); + +reportCompare(0, 0, 'ok'); |