diff --git a/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java b/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java index 2f4212dd33..a810d8cd13 100644 --- a/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java +++ b/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java @@ -5063,7 +5063,10 @@ public static void fillObjectLiteral( Callable getterOrSetter = (Callable) value; boolean isSetter = getterSetter == 1; Integer index = id instanceof Integer ? (Integer) id : null; - String key = index == null ? ScriptRuntime.toString(id) : null; + Object key = + index != null + ? null + : (id instanceof Symbol ? id : ScriptRuntime.toString(id)); so.setGetterOrSetter(key, index == null ? 0 : index, getterOrSetter, isSetter); } } diff --git a/rhino/src/main/java/org/mozilla/javascript/ScriptableObject.java b/rhino/src/main/java/org/mozilla/javascript/ScriptableObject.java index 439af07d0d..82f7946e3d 100644 --- a/rhino/src/main/java/org/mozilla/javascript/ScriptableObject.java +++ b/rhino/src/main/java/org/mozilla/javascript/ScriptableObject.java @@ -559,8 +559,8 @@ public void setAttributes(Symbol key, int attributes) { /** Implement the legacy "__defineGetter__" and "__defineSetter__" methods. */ public void setGetterOrSetter( - String name, int index, Callable getterOrSetter, boolean isSetter) { - if (name != null && index != 0) throw new IllegalArgumentException(name); + Object name, int index, Callable getterOrSetter, boolean isSetter) { + if (name != null && index != 0) throw new IllegalArgumentException(name.toString()); checkNotSealed(name, index); AccessorSlot aSlot; diff --git a/tests/src/test/java/org/mozilla/javascript/tests/ComputedPropertiesTest.java b/tests/src/test/java/org/mozilla/javascript/tests/ComputedPropertiesTest.java index b338f6f232..09daa0850d 100644 --- a/tests/src/test/java/org/mozilla/javascript/tests/ComputedPropertiesTest.java +++ b/tests/src/test/java/org/mozilla/javascript/tests/ComputedPropertiesTest.java @@ -15,215 +15,135 @@ public class ComputedPropertiesTest { @Test - public void objectWithComputedPropertiesWorkInInterpretedMode() { - try (Context cx = Context.enter()) { - cx.setLanguageVersion(Context.VERSION_ES6); - cx.setOptimizationLevel(-1); - assertObjectWithMixedPropertiesWorks(cx); - } - } - - @Test - public void objectWithComputedPropertiesWorkInCompiledMode() { - try (Context cx = Context.enter()) { - cx.setLanguageVersion(Context.VERSION_ES6); - cx.setOptimizationLevel(0); - assertObjectWithMixedPropertiesWorks(cx); - } - } - - @Test - public void objectWithComputedPropertiesWorkInOptimizedMode() { - try (Context cx = Context.enter()) { - cx.setLanguageVersion(Context.VERSION_ES6); - cx.setOptimizationLevel(9); - assertObjectWithMixedPropertiesWorks(cx); - } - } - - private static void assertObjectWithMixedPropertiesWorks(Context cx) { - String script = - "\n" - + "function f(x) { return x; }\n" - + "\n" - + "var o = {\n" - + " a: 1,\n" - + " 0: 2,\n" - + " [-1]: 3\n," - + " [f('b')]: 4\n" - + "};\n" - + "o.a + o[0] + o['-1'] + o.b"; - - ScriptableObject scope = cx.initStandardObjects(); - Object value = cx.evaluateString(scope, script, "test", 1, null); - assertTrue(value instanceof Number); - assertEquals(10, ((Number) value).intValue()); - } - - @Test - public void canCoerceFunctionToStringInInterpretedMode() { - try (Context cx = Context.enter()) { - cx.setLanguageVersion(Context.VERSION_ES6); - cx.setOptimizationLevel(-1); - assertCanCoerceFunctionWithComputedPropertiesToString(cx); - } - } - - @Test - public void canCoerceFunctionToStringInCompiledMode() { - try (Context cx = Context.enter()) { - cx.setLanguageVersion(Context.VERSION_ES6); - cx.setOptimizationLevel(0); - assertCanCoerceFunctionWithComputedPropertiesToString(cx); - } - } - - private static void assertCanCoerceFunctionWithComputedPropertiesToString(Context cx) { - String script = - "\n" - + "function f(x) {\n" - + " var o = {\n" - + " 1: true,\n" - + " [2]: false,\n" - + " [g(x)]: 3\n" - + " };\n" - + "}\n" - + "f.toString()"; - - ScriptableObject scope = cx.initStandardObjects(); - Object value = cx.evaluateString(scope, script, "test", 1, null); - assertTrue(value instanceof String); - assertEquals( - "function f(x) {\n" - + " var o = {\n" - + " 1: true,\n" - + " [2]: false,\n" - + " [g(x)]: 3\n" - + " };\n" - + "}", - value); - } - - @Test - public void computedPropertiesWithSideEffectsWorkInInterpretedMode() { - try (Context cx = Context.enter()) { - cx.setLanguageVersion(Context.VERSION_ES6); - cx.setOptimizationLevel(-1); - assertComputedPropertiesWithSideEffectsWork(cx); - } - } - - @Test - public void computedPropertiesWithSideEffectsWorkInCompiledMode() { - try (Context cx = Context.enter()) { - cx.setLanguageVersion(Context.VERSION_ES6); - cx.setOptimizationLevel(0); - assertComputedPropertiesWithSideEffectsWork(cx); - } - } - - @Test - public void computedPropertiesWithSideEffectsWorkInOptimizedMode() { - try (Context cx = Context.enter()) { - cx.setLanguageVersion(Context.VERSION_ES6); - cx.setOptimizationLevel(9); - assertComputedPropertiesWithSideEffectsWork(cx); - } - } - - private static void assertComputedPropertiesWithSideEffectsWork(Context cx) { - String script = - "'use strict';\n" - + "var x = 0;\n" - + "var o = {\n" - + " [++x]: 'x',\n" - + " a: ++x,\n" - + " [++x]: 'y'\n" - + "};\n" - + "o[1] + o.a + o[3]"; - - ScriptableObject scope = cx.initStandardObjects(); - Object value = cx.evaluateString(scope, script, "test", 1, null); - assertEquals("x2y", value); - } - - @Test - public void computedPropertyNameForGetterSetterWorkInInterpretedMode() { - try (Context cx = Context.enter()) { - cx.setLanguageVersion(Context.VERSION_ES6); - cx.setOptimizationLevel(-1); - assertComputedPropertyNameForGetterSetterWorks(cx); - } - } - - @Test - public void computedPropertyNameForGetterSetterWorkInCompiled() { - try (Context cx = Context.enter()) { - cx.setLanguageVersion(Context.VERSION_ES6); - cx.setOptimizationLevel(0); - assertComputedPropertyNameForGetterSetterWorks(cx); - } - } - - @Test - public void computedPropertyNameForGetterSetterWorkInOptimizedMode() { - try (Context cx = Context.enter()) { - cx.setLanguageVersion(Context.VERSION_ES6); - cx.setOptimizationLevel(9); - assertComputedPropertyNameForGetterSetterWorks(cx); - } - } - - private static void assertComputedPropertyNameForGetterSetterWorks(Context cx) { - String script = "var o = { get ['x' + 1]() { return 42; }}; o.x1"; - - ScriptableObject scope = cx.initStandardObjects(); - Object value = cx.evaluateString(scope, script, "test", 1, null); - assertTrue(value instanceof Number); - assertEquals(42, ((Number) value).intValue()); - } - - @Test - public void yieldWorksForPropertyValuesInInterpretedMode() { - try (Context cx = Context.enter()) { - cx.setLanguageVersion(Context.VERSION_ES6); - cx.setOptimizationLevel(-1); - assertYieldWorksForPropertyValues(cx); - } - } - - @Test - public void yieldWorksForPropertyValuesInCompiledMode() { - try (Context cx = Context.enter()) { - cx.setLanguageVersion(Context.VERSION_ES6); - cx.setOptimizationLevel(0); - assertYieldWorksForPropertyValues(cx); - } - } - - @Test - public void yieldWorksForPropertyValuesInOptimizedMode() { - try (Context cx = Context.enter()) { - cx.setLanguageVersion(Context.VERSION_ES6); - cx.setOptimizationLevel(9); - assertYieldWorksForPropertyValues(cx); - } - } - - private static void assertYieldWorksForPropertyValues(Context cx) { - String script = - "\n" - + "function *gen() {\n" - + " ({x: yield 1});\n" - + "}\n" - + "var g = gen()\n" - + "var res1 = g.next();\n" - + "var res2 = g.next();\n" - + "res1.value === 1 && !res1.done && res2.done\n"; - - ScriptableObject scope = cx.initStandardObjects(); - Object value = cx.evaluateString(scope, script, "test", 1, null); - assertEquals(Boolean.TRUE, value); + public void objectWithComputedPropertiesWorks() { + Utils.runWithAllOptimizationLevels( + cx -> { + cx.setLanguageVersion(Context.VERSION_ES6); + String script = + "\n" + + "function f(x) { return x; }\n" + + "\n" + + "var o = {\n" + + " a: 1,\n" + + " 0: 2,\n" + + " [-1]: 3\n," + + " [f('b')]: 4\n" + + "};\n" + + "o.a + o[0] + o['-1'] + o.b"; + + ScriptableObject scope = cx.initStandardObjects(); + Object value = cx.evaluateString(scope, script, "test", 1, null); + assertTrue(value instanceof Number); + assertEquals(10, ((Number) value).intValue()); + return null; + }); + } + + @Test + public void canCoerceFunctionToString() { + Utils.runWithAllOptimizationLevels( + cx -> { + cx.setLanguageVersion(Context.VERSION_ES6); + String script = + "\n" + + "function f(x) {\n" + + " var o = {\n" + + " 1: true,\n" + + " [2]: false,\n" + + " [g(x)]: 3\n" + + " };\n" + + "}\n" + + "f.toString()"; + + ScriptableObject scope = cx.initStandardObjects(); + Object value = cx.evaluateString(scope, script, "test", 1, null); + assertTrue(value instanceof String); + assertEquals( + "function f(x) {\n" + + " var o = {\n" + + " 1: true,\n" + + " [2]: false,\n" + + " [g(x)]: 3\n" + + " };\n" + + "}", + value); + return null; + }); + } + + @Test + public void computedPropertiesWithSideEffectsWork() { + Utils.runWithAllOptimizationLevels( + cx -> { + ; + cx.setLanguageVersion(Context.VERSION_ES6); + String script = + "'use strict';\n" + + "var x = 0;\n" + + "var o = {\n" + + " [++x]: 'x',\n" + + " a: ++x,\n" + + " [++x]: 'y'\n" + + "};\n" + + "o[1] + o.a + o[3]"; + + ScriptableObject scope = cx.initStandardObjects(); + Object value = cx.evaluateString(scope, script, "test", 1, null); + assertEquals("x2y", value); + return null; + }); + } + + @Test + public void computedPropertyNameForGetterSetterWork() { + Utils.runWithAllOptimizationLevels( + cx -> { + cx.setLanguageVersion(Context.VERSION_ES6); + String script = "var o = { get ['x' + 1]() { return 42; }}; o.x1"; + + ScriptableObject scope = cx.initStandardObjects(); + Object value = cx.evaluateString(scope, script, "test", 1, null); + assertTrue(value instanceof Number); + assertEquals(42, ((Number) value).intValue()); + return null; + }); + } + + @Test + public void computedPropertyNameAsSymbolForGetterSetterWork() { + Utils.runWithAllOptimizationLevels( + cx -> { + cx.setLanguageVersion(Context.VERSION_ES6); + String script = + "var o = { get [Symbol.toStringTag]() { return 'foo'; }}; o.toString()"; + + ScriptableObject scope = cx.initStandardObjects(); + Object value = cx.evaluateString(scope, script, "test", 1, null); + assertEquals("[object foo]", value); + return null; + }); + } + + @Test + public void yieldWorksForPropertyValues() { + Utils.runWithAllOptimizationLevels( + cx -> { + cx.setLanguageVersion(Context.VERSION_ES6); + String script = + "\n" + + "function *gen() {\n" + + " ({x: yield 1});\n" + + "}\n" + + "var g = gen()\n" + + "var res1 = g.next();\n" + + "var res2 = g.next();\n" + + "res1.value === 1 && !res1.done && res2.done\n"; + + ScriptableObject scope = cx.initStandardObjects(); + Object value = cx.evaluateString(scope, script, "test", 1, null); + assertEquals(Boolean.TRUE, value); + return null; + }); } @Test diff --git a/tests/testsrc/test262.properties b/tests/testsrc/test262.properties index f9b3ff9eb2..46ef8daa68 100644 --- a/tests/testsrc/test262.properties +++ b/tests/testsrc/test262.properties @@ -1010,8 +1010,7 @@ built-ins/Math 51/327 (15.6%) built-ins/NaN 0/6 (0.0%) -built-ins/NativeErrors 29/123 (23.58%) - AggregateError/errors-iterabletolist-failures.js +built-ins/NativeErrors 28/123 (22.76%) AggregateError/is-a-constructor.js {unsupported: [Reflect.construct]} AggregateError/newtarget-proto-custom.js {unsupported: [Reflect.construct]} AggregateError/newtarget-proto-fallback.js @@ -1063,7 +1062,7 @@ built-ins/Number 24/335 (7.16%) S9.3.1_A3_T1_U180E.js {unsupported: [u180e]} S9.3.1_A3_T2_U180E.js {unsupported: [u180e]} -built-ins/Object 216/3408 (6.34%) +built-ins/Object 215/3408 (6.31%) assign/assignment-to-readonly-property-of-target-must-throw-a-typeerror-exception.js assign/not-a-constructor.js {unsupported: [Reflect.construct]} assign/source-own-prop-desc-missing.js {unsupported: [Proxy]} @@ -1133,7 +1132,6 @@ built-ins/Object 216/3408 (6.34%) freeze/throws-when-false.js freeze/typedarray-backed-by-resizable-buffer.js {unsupported: [resizable-arraybuffer]} fromEntries/not-a-constructor.js {unsupported: [Reflect.construct]} - fromEntries/uses-keys-not-iterator.js getOwnPropertyDescriptors/not-a-constructor.js {unsupported: [Reflect.construct]} getOwnPropertyDescriptors/observable-operations.js {unsupported: [Proxy]} getOwnPropertyDescriptors/order-after-define-property.js {unsupported: [Reflect]} @@ -1679,7 +1677,7 @@ built-ins/Promise 406/631 (64.34%) ~built-ins/Reflect -built-ins/RegExp 1152/1854 (62.14%) +built-ins/RegExp 1151/1854 (62.08%) CharacterClassEscapes 24/24 (100.0%) dotall 4/4 (100.0%) escape 20/20 (100.0%) @@ -1762,7 +1760,6 @@ built-ins/RegExp 1152/1854 (62.14%) prototype/Symbol.matchAll/isregexp-this-throws.js prototype/Symbol.matchAll/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/Symbol.matchAll/species-constructor.js - prototype/Symbol.matchAll/species-constructor-get-species-throws.js prototype/Symbol.matchAll/this-get-flags.js prototype/Symbol.matchAll/this-not-object-throws.js prototype/Symbol.matchAll/this-tostring-flags.js @@ -2136,7 +2133,7 @@ built-ins/SetIteratorPrototype 0/11 (0.0%) ~built-ins/SharedArrayBuffer -built-ins/String 101/1182 (8.54%) +built-ins/String 93/1182 (7.87%) fromCharCode/not-a-constructor.js {unsupported: [Reflect.construct]} fromCodePoint/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/charAt/not-a-constructor.js {unsupported: [Reflect.construct]} @@ -2222,15 +2219,7 @@ built-ins/String 101/1182 (8.54%) prototype/toWellFormed/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/toWellFormed/to-string-primitive.js prototype/trimEnd/not-a-constructor.js {unsupported: [Reflect.construct]} - prototype/trimEnd/this-value-object-toprimitive-call-err.js - prototype/trimEnd/this-value-object-toprimitive-meth-priority.js - prototype/trimEnd/this-value-object-tostring-meth-priority.js - prototype/trimEnd/this-value-object-valueof-meth-priority.js prototype/trimStart/not-a-constructor.js {unsupported: [Reflect.construct]} - prototype/trimStart/this-value-object-toprimitive-call-err.js - prototype/trimStart/this-value-object-toprimitive-meth-priority.js - prototype/trimStart/this-value-object-tostring-meth-priority.js - prototype/trimStart/this-value-object-valueof-meth-priority.js prototype/trim/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/trim/u180e.js {unsupported: [u180e]} prototype/valueOf/non-generic-realm.js @@ -3508,12 +3497,10 @@ language/comments 9/52 (17.31%) multi-line-asi-line-separator.js multi-line-asi-paragraph-separator.js -language/computed-property-names 33/48 (68.75%) +language/computed-property-names 31/48 (64.58%) class/accessor 4/4 (100.0%) class/method 11/11 (100.0%) class/static 14/14 (100.0%) - object/accessor/getter.js - object/accessor/setter.js to-name-side-effects/class.js to-name-side-effects/numbers-class.js