From f5541530a4df2b79148c6575f2f319fe2845165e Mon Sep 17 00:00:00 2001 From: Grzegorz Caban Date: Thu, 29 Aug 2024 21:42:31 +0100 Subject: [PATCH 1/9] optional chaining operator by transforming into conditional expression in IRFactory --- .../org/mozilla/javascript/IRFactory.java | 15 ++++++ .../java/org/mozilla/javascript/Parser.java | 10 ++++ .../java/org/mozilla/javascript/Token.java | 5 +- .../org/mozilla/javascript/TokenStream.java | 5 +- .../tests/OptionalChainingOperatorTests.java | 49 +++++++++++++++++++ 5 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 rhino/src/test/java/org/mozilla/javascript/tests/OptionalChainingOperatorTests.java diff --git a/rhino/src/main/java/org/mozilla/javascript/IRFactory.java b/rhino/src/main/java/org/mozilla/javascript/IRFactory.java index b8ec566228..933ea4db14 100644 --- a/rhino/src/main/java/org/mozilla/javascript/IRFactory.java +++ b/rhino/src/main/java/org/mozilla/javascript/IRFactory.java @@ -2088,6 +2088,21 @@ private static Node createBinary(int nodeType, Node left, Node right) { } break; } + case Token.DOT_QUESTION: + { + // a?.b == (a == null || a == undefined) ? undefined : a.b + Node undefinedNode = new Name(0, "undefined"); + Node nullNode = new Node(Token.NULL); + + Node conditional = + new Node( + Token.OR, + new Node(Token.SHEQ, nullNode, left), + new Node(Token.SHEQ, undefinedNode, left)); + + Node node = new Node(Token.HOOK, conditional, new Name(0, "undefined"), right); + return node; + } } return new Node(nodeType, left, right); diff --git a/rhino/src/main/java/org/mozilla/javascript/Parser.java b/rhino/src/main/java/org/mozilla/javascript/Parser.java index aa87884228..9ea9bad89f 100644 --- a/rhino/src/main/java/org/mozilla/javascript/Parser.java +++ b/rhino/src/main/java/org/mozilla/javascript/Parser.java @@ -2887,6 +2887,7 @@ private AstNode memberExprTail(boolean allowCallSyntax, AstNode pn) throws IOExc int tt = peekToken(); switch (tt) { case Token.DOT: + case Token.DOT_QUESTION: case Token.DOTDOT: lineno = ts.lineno; pn = propertyAccess(tt, pn); @@ -3074,6 +3075,15 @@ private AstNode propertyAccess(int tt, AstNode pn) throws IOException { result.setLineno(pn.getLineno()); result.setLeft(pn); // do this after setting position result.setRight(ref); + + if (tt == Token.DOT_QUESTION && result instanceof PropertyGet) { + result = + new InfixExpression( + Token.DOT_QUESTION, + ((PropertyGet) result).getTarget(), + result, + result.lineno); + } return result; } diff --git a/rhino/src/main/java/org/mozilla/javascript/Token.java b/rhino/src/main/java/org/mozilla/javascript/Token.java index daf8139cc0..8a44071065 100644 --- a/rhino/src/main/java/org/mozilla/javascript/Token.java +++ b/rhino/src/main/java/org/mozilla/javascript/Token.java @@ -231,7 +231,8 @@ public static enum CommentType { TEMPLATE_LITERAL_SUBST + 1, // template literal - tagged/handler DOTDOTDOT = TAGGED_TEMPLATE_LITERAL + 1, // spread/rest ... NULLISH_COALESCING = DOTDOTDOT + 1, // nullish coalescing (??) - LAST_TOKEN = NULLISH_COALESCING; + DOT_QUESTION = NULLISH_COALESCING + 1, // optional chaining operator (?.) + LAST_TOKEN = DOT_QUESTION + 1; /** * Returns a name for the token. If Rhino is compiled with certain hardcoded debugging flags in @@ -610,6 +611,8 @@ public static String typeToName(int token) { return "TEMPLATE_LITERAL_SUBST"; case TAGGED_TEMPLATE_LITERAL: return "TAGGED_TEMPLATE_LITERAL"; + case DOT_QUESTION: + return "DOT_QUESTION"; } // Token without name diff --git a/rhino/src/main/java/org/mozilla/javascript/TokenStream.java b/rhino/src/main/java/org/mozilla/javascript/TokenStream.java index 9ea5aedeab..d290a0af63 100644 --- a/rhino/src/main/java/org/mozilla/javascript/TokenStream.java +++ b/rhino/src/main/java/org/mozilla/javascript/TokenStream.java @@ -1147,9 +1147,12 @@ && peekChar() == '!' case ',': return Token.COMMA; case '?': + if (matchChar('.')) { + return Token.DOT_QUESTION; + } if (matchChar('?')) { return Token.NULLISH_COALESCING; - } + }n return Token.HOOK; case ':': if (matchChar(':')) { diff --git a/rhino/src/test/java/org/mozilla/javascript/tests/OptionalChainingOperatorTests.java b/rhino/src/test/java/org/mozilla/javascript/tests/OptionalChainingOperatorTests.java new file mode 100644 index 0000000000..deefeccbfd --- /dev/null +++ b/rhino/src/test/java/org/mozilla/javascript/tests/OptionalChainingOperatorTests.java @@ -0,0 +1,49 @@ +package org.mozilla.javascript.tests; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.Undefined; + +public class OptionalChainingOperatorTests { + + @Test + public void testOptionalChainingOperator() { + + Utils.runWithAllOptimizationLevels( + cx -> { + String sourceName = "optionalChainingOperator"; + Scriptable scope = cx.initStandardObjects(); + + String script = " var a = {name: 'val'}; a.outerProp?.innerProp"; + assertEquals( + Undefined.instance, + cx.evaluateString(scope, script, sourceName, 1, null)); + + String script2 = + " var a = {outerProp: {innerProp: 'val' } }; a.outerProp?.innerProp"; + assertEquals("val", cx.evaluateString(scope, script2, sourceName, 1, null)); + + String script3 = + " var a = {outerProp: {innerProp: { innerInnerProp: {name: 'val' } } } }; a.outerProp?.innerProp?.missingProp?.name"; + assertEquals( + Undefined.instance, + cx.evaluateString(scope, script3, sourceName, 1, null)); + + String script4 = + " var a = {outerProp: {innerProp: { innerInnerProp: {name: 'val' } } } }; a.outerProp?.innerProp?.innerInnerProp?.name"; + assertEquals("val", cx.evaluateString(scope, script4, sourceName, 1, null)); + + // NOT WORKING YET + // String script5 = " var a = {}; + // a.someNonExistentMethod?.()"; + // assertEquals( + // Undefined.instance, + // cx.evaluateString(scope, script5, sourceName, 1, + // null)); + + return null; + }); + } +} From dc4951dd1ed3c748892a40cd6947ecf37d01d252 Mon Sep 17 00:00:00 2001 From: Grzegorz Caban Date: Mon, 2 Sep 2024 12:43:48 +0100 Subject: [PATCH 2/9] handling optional method call (i.e. a.method?.()) in parser. Enabling language/expressions/optional-chaining section in test262 and reworking the solution to pass them, including the necessity to clone ASTNode to avoid problems introduced due to structural sharing betweek left and right of left.?rigth. --- .../org/mozilla/javascript/IRFactory.java | 15 ----- .../java/org/mozilla/javascript/Parser.java | 58 +++++++++++++++---- .../java/org/mozilla/javascript/Token.java | 2 +- .../org/mozilla/javascript/TokenStream.java | 2 +- .../org/mozilla/javascript/ast/AstNode.java | 1 + .../tests/OptionalChainingOperatorTests.java | 56 +++++++++++++++--- tests/testsrc/test262.properties | 28 ++++++++- 7 files changed, 127 insertions(+), 35 deletions(-) diff --git a/rhino/src/main/java/org/mozilla/javascript/IRFactory.java b/rhino/src/main/java/org/mozilla/javascript/IRFactory.java index 933ea4db14..b8ec566228 100644 --- a/rhino/src/main/java/org/mozilla/javascript/IRFactory.java +++ b/rhino/src/main/java/org/mozilla/javascript/IRFactory.java @@ -2088,21 +2088,6 @@ private static Node createBinary(int nodeType, Node left, Node right) { } break; } - case Token.DOT_QUESTION: - { - // a?.b == (a == null || a == undefined) ? undefined : a.b - Node undefinedNode = new Name(0, "undefined"); - Node nullNode = new Node(Token.NULL); - - Node conditional = - new Node( - Token.OR, - new Node(Token.SHEQ, nullNode, left), - new Node(Token.SHEQ, undefinedNode, left)); - - Node node = new Node(Token.HOOK, conditional, new Name(0, "undefined"), right); - return node; - } } return new Node(nodeType, left, right); diff --git a/rhino/src/main/java/org/mozilla/javascript/Parser.java b/rhino/src/main/java/org/mozilla/javascript/Parser.java index 9ea9bad89f..fee0a917b4 100644 --- a/rhino/src/main/java/org/mozilla/javascript/Parser.java +++ b/rhino/src/main/java/org/mozilla/javascript/Parser.java @@ -2887,7 +2887,7 @@ private AstNode memberExprTail(boolean allowCallSyntax, AstNode pn) throws IOExc int tt = peekToken(); switch (tt) { case Token.DOT: - case Token.DOT_QUESTION: + case Token.QUESTION_DOT: case Token.DOTDOT: lineno = ts.lineno; pn = propertyAccess(tt, pn); @@ -3017,8 +3017,27 @@ private AstNode propertyAccess(int tt, AstNode pn) throws IOException { } AstNode ref = null; // right side of . or .. operator - int token = nextToken(); + if (token == Token.LP && tt == Token.QUESTION_DOT) { + // optional chaining operator method call, o.func.?() + var pos = pn.getPosition(); + consumeToken(); + checkCallRequiresActivation(pn); + FunctionCall f = new FunctionCall(pos); + f.setTarget(pn); + // Assign the line number for the function call to where + // the paren appeared, not where the name expression started. + f.setLineno(lineno); + f.setLp(ts.tokenBeg - pos); + List args = argumentList(); + if (args != null && args.size() > ARGC_LIMIT) reportError("msg.too.many.function.args"); + f.setArguments(args); + f.setRp(ts.tokenBeg - pos); + f.setLength(ts.tokenEnd - pos); + + return conditionalPropertyAccess(pn, f); + } + switch (token) { case Token.THROW: // needed for generator.throw(); @@ -3050,7 +3069,6 @@ private AstNode propertyAccess(int tt, AstNode pn) throws IOException { ref = propertyName(-1, memberTypeFlags); break; } - default: if (compilerEnv.isReservedKeywordAsIdentifier()) { // allow keywords as property names, e.g. ({if: 1}) @@ -3076,17 +3094,37 @@ private AstNode propertyAccess(int tt, AstNode pn) throws IOException { result.setLeft(pn); // do this after setting position result.setRight(ref); - if (tt == Token.DOT_QUESTION && result instanceof PropertyGet) { - result = - new InfixExpression( - Token.DOT_QUESTION, - ((PropertyGet) result).getTarget(), - result, - result.lineno); + if (tt == Token.QUESTION_DOT && result instanceof PropertyGet) { + return conditionalPropertyAccess(pn, result); } return result; } + private static AstNode conditionalPropertyAccess(AstNode target, AstNode propAccessNode) { + var targetCopy = cloneNode(target); + var targetCopy2 = cloneNode(target); + + AstNode undefinedNode = new Name(0, "undefined"); + AstNode nullNode = new KeywordLiteral(0, 4, Token.NULL); + + AstNode nullEq = new InfixExpression(Token.SHEQ, targetCopy, nullNode, 0); + + AstNode undefinedEq = new InfixExpression(Token.SHEQ, targetCopy2, undefinedNode, 0); + var conditionalExpr = new ConditionalExpression(); + conditionalExpr.setTestExpression(new InfixExpression(Token.OR, nullEq, undefinedEq, 0)); + conditionalExpr.setTrueExpression(new Name(0, "undefined")); + conditionalExpr.setFalseExpression(propAccessNode); + + return conditionalExpr; + } + + private static AstNode cloneNode(AstNode target) { + var newParser = new Parser(); + var root = newParser.parse(target.toSource(), "", 1); + var targetCopy = ((ExpressionStatement) root.first).getExpression(); + return targetCopy; + } + /** * Xml attribute expression: * diff --git a/rhino/src/main/java/org/mozilla/javascript/Token.java b/rhino/src/main/java/org/mozilla/javascript/Token.java index 8a44071065..2ac4881f54 100644 --- a/rhino/src/main/java/org/mozilla/javascript/Token.java +++ b/rhino/src/main/java/org/mozilla/javascript/Token.java @@ -611,7 +611,7 @@ public static String typeToName(int token) { return "TEMPLATE_LITERAL_SUBST"; case TAGGED_TEMPLATE_LITERAL: return "TAGGED_TEMPLATE_LITERAL"; - case DOT_QUESTION: + case QUESTION_DOT: return "DOT_QUESTION"; } diff --git a/rhino/src/main/java/org/mozilla/javascript/TokenStream.java b/rhino/src/main/java/org/mozilla/javascript/TokenStream.java index d290a0af63..6481f15a7d 100644 --- a/rhino/src/main/java/org/mozilla/javascript/TokenStream.java +++ b/rhino/src/main/java/org/mozilla/javascript/TokenStream.java @@ -1148,7 +1148,7 @@ && peekChar() == '!' return Token.COMMA; case '?': if (matchChar('.')) { - return Token.DOT_QUESTION; + return Token.QUESTION_DOT; } if (matchChar('?')) { return Token.NULLISH_COALESCING; diff --git a/rhino/src/main/java/org/mozilla/javascript/ast/AstNode.java b/rhino/src/main/java/org/mozilla/javascript/ast/AstNode.java index f5465dbaef..da70271446 100644 --- a/rhino/src/main/java/org/mozilla/javascript/ast/AstNode.java +++ b/rhino/src/main/java/org/mozilla/javascript/ast/AstNode.java @@ -126,6 +126,7 @@ public abstract class AstNode extends Node implements Comparable { operatorNames.put(Token.ASSIGN_BITXOR, "^="); operatorNames.put(Token.ASSIGN_EXP, "**="); operatorNames.put(Token.VOID, "void"); + operatorNames.put(Token.QUESTION_DOT, "?."); StringBuilder sb = new StringBuilder(); INDENTATIONS[0] = sb.toString(); diff --git a/rhino/src/test/java/org/mozilla/javascript/tests/OptionalChainingOperatorTests.java b/rhino/src/test/java/org/mozilla/javascript/tests/OptionalChainingOperatorTests.java index deefeccbfd..b39fa56a44 100644 --- a/rhino/src/test/java/org/mozilla/javascript/tests/OptionalChainingOperatorTests.java +++ b/rhino/src/test/java/org/mozilla/javascript/tests/OptionalChainingOperatorTests.java @@ -15,6 +15,10 @@ public void testOptionalChainingOperator() { cx -> { String sourceName = "optionalChainingOperator"; Scriptable scope = cx.initStandardObjects(); + assertEquals( + Undefined.instance, + cx.evaluateString( + scope, "var nul = null; nul?.a", sourceName, 1, null)); String script = " var a = {name: 'val'}; a.outerProp?.innerProp"; assertEquals( @@ -26,22 +30,60 @@ public void testOptionalChainingOperator() { assertEquals("val", cx.evaluateString(scope, script2, sourceName, 1, null)); String script3 = - " var a = {outerProp: {innerProp: { innerInnerProp: {name: 'val' } } } }; a.outerProp?.innerProp?.missingProp?.name"; + "var a = {outerProp: {innerProp: { innerInnerProp: {name: 'val' } } } }; " + + "a.outerProp?.innerProp?.missingProp?.name"; assertEquals( Undefined.instance, cx.evaluateString(scope, script3, sourceName, 1, null)); String script4 = - " var a = {outerProp: {innerProp: { innerInnerProp: {name: 'val' } } } }; a.outerProp?.innerProp?.innerInnerProp?.name"; + " var a = {outerProp: {innerProp: { innerInnerProp: {name: 'val' } } } }; " + + "a.outerProp?.innerProp?.innerInnerProp?.name"; assertEquals("val", cx.evaluateString(scope, script4, sourceName, 1, null)); - // NOT WORKING YET - // String script5 = " var a = {}; - // a.someNonExistentMethod?.()"; + String script5 = " var a = {}; a.someNonExistentMethod?.()"; + assertEquals( + Undefined.instance, + cx.evaluateString(scope, script5, sourceName, 1, null)); + assertEquals( + Undefined.instance, + cx.evaluateString( + scope, + "function fn3 () {\n" + + " return () => {\n" + + " return null;\n" + + " };\n" + + "}" + + " fn3()()?.a", + sourceName, + 1, + null)); + assertEquals( + Undefined.instance, + cx.evaluateString( + scope, + " var a = {}; a.someNonExistentMethod?.()", + sourceName, + 1, + null)); + + // NOT WORKING + // assertEquals( + // Undefined.instance, + // cx.evaluateString( + // scope, + // "{}?.a", + // sourceName, + // 1, + // null)); // assertEquals( // Undefined.instance, - // cx.evaluateString(scope, script5, sourceName, 1, - // null)); + // cx.evaluateString( + // scope, + // "var b = {}; for (const key of b.a) ", + // sourceName, + // 1, + // null)); return null; }); diff --git a/tests/testsrc/test262.properties b/tests/testsrc/test262.properties index 0009ef96c1..d0a636faf6 100644 --- a/tests/testsrc/test262.properties +++ b/tests/testsrc/test262.properties @@ -5978,7 +5978,33 @@ language/expressions/object 809/1169 (69.2%) yield-non-strict-access.js non-strict yield-non-strict-syntax.js non-strict -~language/expressions/optional-chaining +language/expressions/optional-chaining 26/38 (68.42%) + call-expression.js + early-errors-tail-position-null-optchain-template-string.js + early-errors-tail-position-null-optchain-template-string-esi.js + early-errors-tail-position-optchain-template-string.js + early-errors-tail-position-optchain-template-string-esi.js + eval-optional-call.js + iteration-statement-for.js + iteration-statement-for-await-of.js {unsupported: [async]} + iteration-statement-for-in.js + iteration-statement-for-of-type-error.js + member-expression.js + member-expression-async-identifier.js {unsupported: [async]} + member-expression-async-literal.js {unsupported: [async]} + member-expression-async-this.js {unsupported: [async]} + new-target-optional-call.js + optional-call-preserves-this.js + optional-chain.js + optional-chain-async-optional-chain-square-brackets.js {unsupported: [async]} + optional-chain-async-square-brackets.js {unsupported: [async]} + optional-chain-expression-optional-expression.js + optional-chain-prod-arguments.js + optional-chain-prod-expression.js + punctuator-decimal-lookahead.js + short-circuiting.js + static-semantics-simple-assignment.js + super-property-optional-call.js language/expressions/postfix-decrement 9/37 (24.32%) arguments.js strict From a853625ea8e08fb211a4de9550ebf7f640acf2f2 Mon Sep 17 00:00:00 2001 From: nabacg Date: Thu, 5 Sep 2024 18:19:04 +0100 Subject: [PATCH 3/9] adding few new rhino ByteCodes to handle Optional property get and optional method call for `?.` operator --- .../org/mozilla/javascript/CodeGenerator.java | 12 +++++ .../org/mozilla/javascript/IRFactory.java | 29 +++++++--- .../java/org/mozilla/javascript/Icode.java | 6 ++- .../org/mozilla/javascript/Interpreter.java | 24 +++++++++ .../java/org/mozilla/javascript/Parser.java | 9 ++-- .../org/mozilla/javascript/ScriptRuntime.java | 22 ++++++++ .../java/org/mozilla/javascript/Token.java | 5 +- .../javascript/optimizer/BodyCodegen.java | 54 +++++++++++++++++-- .../javascript/optimizer/OptRuntime.java | 8 +++ tests/testsrc/test262.properties | 3 +- 10 files changed, 152 insertions(+), 20 deletions(-) diff --git a/rhino/src/main/java/org/mozilla/javascript/CodeGenerator.java b/rhino/src/main/java/org/mozilla/javascript/CodeGenerator.java index aa1e40b8ab..06269793a8 100644 --- a/rhino/src/main/java/org/mozilla/javascript/CodeGenerator.java +++ b/rhino/src/main/java/org/mozilla/javascript/CodeGenerator.java @@ -603,6 +603,7 @@ private void visitExpression(Node node, int contextFlags) { case Token.REF_CALL: case Token.CALL: + case Token.CALL_OPTIONAL: case Token.NEW: { if (type == Token.NEW) { @@ -687,6 +688,11 @@ private void visitExpression(Node node, int contextFlags) { resolveForwardGoto(afterElseJumpStart); } break; + case Token.GETPROP_OPTIONAL: + visitExpression(child, 0); + child = child.getNext(); + addStringOp(type, child.getString()); + break; case Token.GETPROP: case Token.GETPROPNOWARN: @@ -1058,6 +1064,7 @@ private void generateCallFunAndThis(Node left) { stackChange(2); break; } + case Token.GETPROP_OPTIONAL: case Token.GETPROP: case Token.GETELEM: { @@ -1069,6 +1076,11 @@ private void generateCallFunAndThis(Node left) { // stack: ... target -> ... function thisObj addStringOp(Icode_PROP_AND_THIS, property); stackChange(1); + } else if (type == Token.GETPROP_OPTIONAL) { + String property = id.getString(); + // stack: ... target -> ... function thisObj + addStringOp(Icode_PROP_AND_THIS_OPTIONAL, property); + stackChange(1); } else { visitExpression(id, 0); // stack: ... target id -> ... function thisObj diff --git a/rhino/src/main/java/org/mozilla/javascript/IRFactory.java b/rhino/src/main/java/org/mozilla/javascript/IRFactory.java index b8ec566228..8e108c38c5 100644 --- a/rhino/src/main/java/org/mozilla/javascript/IRFactory.java +++ b/rhino/src/main/java/org/mozilla/javascript/IRFactory.java @@ -141,6 +141,7 @@ private Node transform(AstNode node) { return transformBlock(node); case Token.BREAK: return transformBreak((BreakStatement) node); + case Token.CALL_OPTIONAL: case Token.CALL: return transformFunctionCall((FunctionCall) node); case Token.CONTINUE: @@ -161,6 +162,7 @@ private Node transform(AstNode node) { return transformGenExpr((GeneratorExpression) node); case Token.GETELEM: return transformElementGet((ElementGet) node); + case Token.QUESTION_DOT: case Token.GETPROP: return transformPropertyGet((PropertyGet) node); case Token.HOOK: @@ -347,7 +349,8 @@ private Node arrayCompTransformHelper(ArrayComprehension node, String arrayName) Node call = createCallOrNew( Token.CALL, - createPropertyGet(parser.createName(arrayName), null, "push", 0)); + createPropertyGet( + parser.createName(arrayName), null, "push", 0, node.type)); Node body = new Node(Token.EXPR_VOID, call, lineno); @@ -641,7 +644,10 @@ private Node transformFunction(FunctionNode fn) { } private Node transformFunctionCall(FunctionCall node) { - Node call = createCallOrNew(Token.CALL, transform(node.getTarget())); + Node call = + createCallOrNew( + node.type == Token.CALL_OPTIONAL ? Token.CALL_OPTIONAL : Token.CALL, + transform(node.getTarget())); call.setLineno(node.getLineno()); List args = node.getArguments(); for (int i = 0; i < args.size(); i++) { @@ -938,7 +944,7 @@ private Node transformComputedPropertyKey(ComputedPropertyKey node) { private Node transformPropertyGet(PropertyGet node) { Node target = transform(node.getTarget()); String name = node.getProperty().getIdentifier(); - return createPropertyGet(target, null, name, 0); + return createPropertyGet(target, null, name, 0, node.type); } private Node transformTemplateLiteral(TemplateLiteral node) { @@ -1262,7 +1268,7 @@ private Node transformXmlRef(Node pn, XmlRef node, int memberTypeFlags) { String ns = namespace != null ? namespace.getIdentifier() : null; if (node instanceof XmlPropRef) { String name = ((XmlPropRef) node).getPropName().getIdentifier(); - return createPropertyGet(pn, ns, name, memberTypeFlags); + return createPropertyGet(pn, ns, name, memberTypeFlags, node.type); } Node expr = transform(((XmlElemRef) node).getExpression()); return createElementGet(pn, ns, expr, memberTypeFlags); @@ -1897,18 +1903,27 @@ private static Node createIncDec(int nodeType, boolean post, Node child) { } private Node createPropertyGet( - Node target, String namespace, String name, int memberTypeFlags) { + Node target, String namespace, String name, int memberTypeFlags, int type) { if (namespace == null && memberTypeFlags == 0) { if (target == null) { return parser.createName(name); } parser.checkActivationName(name, Token.GETPROP); if (ScriptRuntime.isSpecialProperty(name)) { - Node ref = new Node(Token.REF_SPECIAL, target); + Node ref = + new Node( + type == Token.QUESTION_DOT + ? Token.REF_SPECIAL_OPTIONAL + : Token.REF_SPECIAL, + target); ref.putProp(Node.NAME_PROP, name); return new Node(Token.GET_REF, ref); } - return new Node(Token.GETPROP, target, Node.newString(name)); + + return new Node( + type == Token.QUESTION_DOT ? Token.GETPROP_OPTIONAL : Token.GETPROP, + target, + Node.newString(name)); } Node elem = Node.newString(name); memberTypeFlags |= Node.PROPERTY_FLAG; diff --git a/rhino/src/main/java/org/mozilla/javascript/Icode.java b/rhino/src/main/java/org/mozilla/javascript/Icode.java index cf10b46032..13662a356c 100644 --- a/rhino/src/main/java/org/mozilla/javascript/Icode.java +++ b/rhino/src/main/java/org/mozilla/javascript/Icode.java @@ -142,9 +142,9 @@ abstract class Icode { Icode_TEMPLATE_LITERAL_CALLSITE = Icode_REG_BIGINT4 - 1, Icode_LITERAL_KEYS = Icode_TEMPLATE_LITERAL_CALLSITE - 1, Icode_LITERAL_KEY_SET = Icode_LITERAL_KEYS - 1, - + Icode_PROP_AND_THIS_OPTIONAL = Icode_LITERAL_KEY_SET - 1, // Last icode - MIN_ICODE = Icode_LITERAL_KEY_SET; + MIN_ICODE = Icode_PROP_AND_THIS_OPTIONAL; static String bytecodeName(int bytecode) { if (!validBytecode(bytecode)) { @@ -190,6 +190,8 @@ static String bytecodeName(int bytecode) { return "NAME_AND_THIS"; case Icode_PROP_AND_THIS: return "PROP_AND_THIS"; + case Icode_PROP_AND_THIS_OPTIONAL: + return "PROP_AND_THIS_OPTIONAL"; case Icode_ELEM_AND_THIS: return "ELEM_AND_THIS"; case Icode_VALUE_AND_THIS: diff --git a/rhino/src/main/java/org/mozilla/javascript/Interpreter.java b/rhino/src/main/java/org/mozilla/javascript/Interpreter.java index 3ac7bd2d30..dbb831f423 100644 --- a/rhino/src/main/java/org/mozilla/javascript/Interpreter.java +++ b/rhino/src/main/java/org/mozilla/javascript/Interpreter.java @@ -1598,6 +1598,16 @@ private static Object interpretLoop(Context cx, CallFrame frame, Object throwabl lhs, stringReg, cx, frame.scope); continue Loop; } + case Token.GETPROP_OPTIONAL: + { + Object lhs = stack[stackTop]; + if (lhs == DBL_MRK) + lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); + stack[stackTop] = + ScriptRuntime.getObjectPropOptional( + lhs, stringReg, cx, frame.scope); + continue Loop; + } case Token.SETPROP: { Object rhs = stack[stackTop]; @@ -1694,6 +1704,19 @@ private static Object interpretLoop(Context cx, CallFrame frame, Object throwabl ++stackTop; stack[stackTop] = ScriptRuntime.lastStoredScriptable(cx); continue Loop; + case Icode_PROP_AND_THIS_OPTIONAL: + { + Object obj = stack[stackTop]; + if (obj == DBL_MRK) + obj = ScriptRuntime.wrapNumber(sDbl[stackTop]); + // stringReg: property + stack[stackTop] = + ScriptRuntime.getPropFunctionAndThisOptional( + obj, stringReg, cx, frame.scope); + ++stackTop; + stack[stackTop] = ScriptRuntime.lastStoredScriptable(cx); + continue Loop; + } case Icode_PROP_AND_THIS: { Object obj = stack[stackTop]; @@ -1744,6 +1767,7 @@ private static Object interpretLoop(Context cx, CallFrame frame, Object throwabl continue Loop; } case Token.CALL: + case Token.CALL_OPTIONAL: case Icode_TAIL_CALL: case Token.REF_CALL: { diff --git a/rhino/src/main/java/org/mozilla/javascript/Parser.java b/rhino/src/main/java/org/mozilla/javascript/Parser.java index fee0a917b4..f1540ed6d0 100644 --- a/rhino/src/main/java/org/mozilla/javascript/Parser.java +++ b/rhino/src/main/java/org/mozilla/javascript/Parser.java @@ -3019,8 +3019,9 @@ private AstNode propertyAccess(int tt, AstNode pn) throws IOException { AstNode ref = null; // right side of . or .. operator int token = nextToken(); if (token == Token.LP && tt == Token.QUESTION_DOT) { - // optional chaining operator method call, o.func.?() + // optional chaining operator method call, o.func?.() var pos = pn.getPosition(); + pn.setType(Token.QUESTION_DOT); consumeToken(); checkCallRequiresActivation(pn); FunctionCall f = new FunctionCall(pos); @@ -3034,8 +3035,8 @@ private AstNode propertyAccess(int tt, AstNode pn) throws IOException { f.setArguments(args); f.setRp(ts.tokenBeg - pos); f.setLength(ts.tokenEnd - pos); - - return conditionalPropertyAccess(pn, f); + f.setType(Token.CALL_OPTIONAL); + return f; } switch (token) { @@ -3095,7 +3096,7 @@ private AstNode propertyAccess(int tt, AstNode pn) throws IOException { result.setRight(ref); if (tt == Token.QUESTION_DOT && result instanceof PropertyGet) { - return conditionalPropertyAccess(pn, result); + result.setType(Token.QUESTION_DOT); } return result; } diff --git a/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java b/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java index d7baba50ff..b53c5bebf3 100644 --- a/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java +++ b/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java @@ -1747,6 +1747,14 @@ public static Object getObjectProp(Object obj, String property, Context cx, Scri return getObjectProp(sobj, property, cx); } + public static Object getObjectPropOptional( + Object obj, String property, Context cx, Scriptable scope) { + if (obj == null || Undefined.isUndefined(obj)) { + return Undefined.instance; + } + return getObjectProp(obj, property, cx, scope); + } + public static Object getObjectProp(Scriptable obj, String property, Context cx) { Object result = ScriptableObject.getProperty(obj, property); @@ -2637,6 +2645,20 @@ public static Callable getElemFunctionAndThis( return (Callable) value; } + public static Callable getPropFunctionAndThisOptional( + Object obj, String property, Context cx, Scriptable scope) { + + Scriptable thisObj = toObjectOrNull(cx, obj, scope); + if (thisObj == null) { + throw undefCallError(obj, property); + } + + Object value = ScriptableObject.getProperty(thisObj, property); + if (Scriptable.NOT_FOUND == value || Undefined.isUndefined(value) || value == null) + return (cx1, scope1, thisObj2, args) -> Undefined.instance; + return getPropFunctionAndThisHelper(obj, property, cx, thisObj); + } + /** * Prepare for calling obj.property(...): return function corresponding to obj.property and make * obj properly converted to Scriptable available as ScriptRuntime.lastStoredScriptable() for diff --git a/rhino/src/main/java/org/mozilla/javascript/Token.java b/rhino/src/main/java/org/mozilla/javascript/Token.java index 2ac4881f54..7924fa7d9d 100644 --- a/rhino/src/main/java/org/mozilla/javascript/Token.java +++ b/rhino/src/main/java/org/mozilla/javascript/Token.java @@ -121,9 +121,12 @@ public static enum CommentType { REF_NAME = REF_NS_MEMBER + 1, // Reference for @y, @[y] etc. REF_NS_NAME = REF_NAME + 1, // Reference for ns::y, @ns::y@[y] etc. BIGINT = REF_NS_NAME + 1; // ES2020 BigInt + GETPROP_OPTIONAL = BIGINT + 1, + REF_SPECIAL_OPTIONAL = GETPROP_OPTIONAL + 1, + CALL_OPTIONAL = REF_SPECIAL_OPTIONAL + 1; // End of interpreter bytecodes - public static final int LAST_BYTECODE_TOKEN = BIGINT, + public static final int LAST_BYTECODE_TOKEN = CALL_OPTIONAL, TRY = LAST_BYTECODE_TOKEN + 1, SEMI = TRY + 1, // semicolon LB = SEMI + 1, // left and right brackets diff --git a/rhino/src/main/java/org/mozilla/javascript/optimizer/BodyCodegen.java b/rhino/src/main/java/org/mozilla/javascript/optimizer/BodyCodegen.java index c0c4aeb90f..193b10acde 100644 --- a/rhino/src/main/java/org/mozilla/javascript/optimizer/BodyCodegen.java +++ b/rhino/src/main/java/org/mozilla/javascript/optimizer/BodyCodegen.java @@ -997,6 +997,7 @@ private void generateExpression(Node node, Node parent) { break; case Token.CALL: + case Token.CALL_OPTIONAL: case Token.NEW: { int specialType = node.getIntProp(Node.SPECIALCALL_PROP, Node.NON_SPECIALCALL); @@ -1006,7 +1007,7 @@ private void generateExpression(Node node, Node parent) { if (target != null) { visitOptimizedCall(node, target, type, child); - } else if (type == Token.CALL) { + } else if (type == Token.CALL || type == Token.CALL_OPTIONAL) { visitStandardCall(node, child); } else { visitStandardNew(node, child); @@ -1359,6 +1360,9 @@ private void generateExpression(Node node, Node parent) { case Token.GETPROPNOWARN: visitGetProp(node, child); break; + case Token.GETPROP_OPTIONAL: + visitGetPropOptional(node, child); + break; case Token.GETELEM: generateExpression(child, node); // object @@ -2317,7 +2321,8 @@ private void visitSpecialCall(Node node, int type, int specialType, Node child) } private void visitStandardCall(Node node, Node child) { - if (node.getType() != Token.CALL) throw Codegen.badTree(); + if (node.getType() != Token.CALL && node.getType() != Token.CALL_OPTIONAL) + throw Codegen.badTree(); Node firstArgChild = child.getNext(); int childType = child.getType(); @@ -2336,14 +2341,14 @@ private void visitStandardCall(Node node, Node child) { + "Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + ")Ljava/lang/Object;"; - } else if (childType == Token.GETPROP) { + } else if (childType == Token.GETPROP || childType == Token.GETPROP_OPTIONAL) { // x.name() call Node propTarget = child.getFirstChild(); generateExpression(propTarget, node); Node id = propTarget.getNext(); String property = id.getString(); cfw.addPush(property); - methodName = "callProp0"; + methodName = childType == Token.GETPROP ? "callProp0" : "callProp0Optional"; signature = "(Ljava/lang/Object;" + "Ljava/lang/String;" @@ -4079,6 +4084,47 @@ private void visitGetProp(Node node, Node child) { } } + private void visitGetPropOptional(Node node, Node child) { + generateExpression(child, node); // object + Node nameChild = child.getNext(); + generateExpression(nameChild, node); // the name + + cfw.addALoad(contextLocal); + cfw.addALoad(variableObjectLocal); + addScriptRuntimeInvoke( + "getObjectPropOptional", + "(Ljava/lang/Object;" + + "Ljava/lang/String;" + + "Lorg/mozilla/javascript/Context;" + + "Lorg/mozilla/javascript/Scriptable;" + + ")Ljava/lang/Object;"); + // TODO - check if we can skip those casts too + /* + for 'this.foo' we call getObjectProp(Scriptable...) which can + skip some casting overhead. + */ + // int childType = child.getType(); + // if (childType == Token.THIS && nameChild.getType() == Token.STRING) { + // cfw.addALoad(contextLocal); + // addScriptRuntimeInvoke( + // "getObjectProp", + // "(Lorg/mozilla/javascript/Scriptable;" + // + "Ljava/lang/String;" + // + "Lorg/mozilla/javascript/Context;" + // + ")Ljava/lang/Object;"); + // } else { + // cfw.addALoad(contextLocal); + // cfw.addALoad(variableObjectLocal); + // addScriptRuntimeInvoke( + // "getObjectPropOptional", + // "(Ljava/lang/Object;" + // + "Ljava/lang/String;" + // + "Lorg/mozilla/javascript/Context;" + // + "Lorg/mozilla/javascript/Scriptable;" + // + ")Ljava/lang/Object;"); + // } + } + private void visitSetProp(int type, Node node, Node child) { Node objectChild = child; generateExpression(child, node); diff --git a/rhino/src/main/java/org/mozilla/javascript/optimizer/OptRuntime.java b/rhino/src/main/java/org/mozilla/javascript/optimizer/OptRuntime.java index 80ae3ae1bd..7d5688cbf1 100644 --- a/rhino/src/main/java/org/mozilla/javascript/optimizer/OptRuntime.java +++ b/rhino/src/main/java/org/mozilla/javascript/optimizer/OptRuntime.java @@ -73,6 +73,14 @@ public static Object callProp0(Object value, String property, Context cx, Script return f.call(cx, scope, thisObj, ScriptRuntime.emptyArgs); } + /** Implement x?.property() call shrinking optimizer code. */ + public static Object callProp0Optional( + Object value, String property, Context cx, Scriptable scope) { + Callable f = getPropFunctionAndThisOptional(value, property, cx, scope); + Scriptable thisObj = lastStoredScriptable(cx); + return f.call(cx, scope, thisObj, ScriptRuntime.emptyArgs); + } + public static Object add(Object val1, double val2, Context cx) { if (val1 instanceof Double) { return ((Double) val1) + val2; diff --git a/tests/testsrc/test262.properties b/tests/testsrc/test262.properties index d0a636faf6..2e8102ee2a 100644 --- a/tests/testsrc/test262.properties +++ b/tests/testsrc/test262.properties @@ -5978,7 +5978,7 @@ language/expressions/object 809/1169 (69.2%) yield-non-strict-access.js non-strict yield-non-strict-syntax.js non-strict -language/expressions/optional-chaining 26/38 (68.42%) +language/expressions/optional-chaining 25/38 (65.79%) call-expression.js early-errors-tail-position-null-optchain-template-string.js early-errors-tail-position-null-optchain-template-string-esi.js @@ -6003,7 +6003,6 @@ language/expressions/optional-chaining 26/38 (68.42%) optional-chain-prod-expression.js punctuator-decimal-lookahead.js short-circuiting.js - static-semantics-simple-assignment.js super-property-optional-call.js language/expressions/postfix-decrement 9/37 (24.32%) From a9a5d7b09ff2f8431017057c6d2cec6f8d156a05 Mon Sep 17 00:00:00 2001 From: Grzegorz Caban Date: Sun, 8 Sep 2024 14:33:11 +0100 Subject: [PATCH 4/9] support for ?. for REF_SPECIAL property access --- .../org/mozilla/javascript/CodeGenerator.java | 1 + .../org/mozilla/javascript/Interpreter.java | 11 ++++++++ .../org/mozilla/javascript/ScriptRuntime.java | 9 ++++-- .../javascript/SpecialOptionalRef.java | 28 +++++++++++++++++++ .../javascript/optimizer/BodyCodegen.java | 17 ++++++++++- .../tests/OptionalChainingOperatorTests.java | 13 +++++++++ 6 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 rhino/src/main/java/org/mozilla/javascript/SpecialOptionalRef.java diff --git a/rhino/src/main/java/org/mozilla/javascript/CodeGenerator.java b/rhino/src/main/java/org/mozilla/javascript/CodeGenerator.java index 06269793a8..f01832ead3 100644 --- a/rhino/src/main/java/org/mozilla/javascript/CodeGenerator.java +++ b/rhino/src/main/java/org/mozilla/javascript/CodeGenerator.java @@ -969,6 +969,7 @@ private void visitExpression(Node node, int contextFlags) { visitArrayComprehension(node, child, child.getNext()); break; + case Token.REF_SPECIAL_OPTIONAL: case Token.REF_SPECIAL: visitExpression(child, 0); addStringOp(type, (String) node.getProp(Node.NAME_PROP)); diff --git a/rhino/src/main/java/org/mozilla/javascript/Interpreter.java b/rhino/src/main/java/org/mozilla/javascript/Interpreter.java index dbb831f423..0bcb7fadaa 100644 --- a/rhino/src/main/java/org/mozilla/javascript/Interpreter.java +++ b/rhino/src/main/java/org/mozilla/javascript/Interpreter.java @@ -2284,6 +2284,17 @@ private static Object interpretLoop(Context cx, CallFrame frame, Object throwabl obj, stringReg, cx, frame.scope); continue Loop; } + case Token.REF_SPECIAL_OPTIONAL: + { + // stringReg: name of special property + Object obj = stack[stackTop]; + if (obj == DBL_MRK) + obj = ScriptRuntime.wrapNumber(sDbl[stackTop]); + stack[stackTop] = + ScriptRuntime.optionalSpecialRef( + obj, stringReg, cx, frame.scope); + continue Loop; + } case Token.REF_MEMBER: { // indexReg: flags diff --git a/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java b/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java index b53c5bebf3..9173c7af68 100644 --- a/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java +++ b/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java @@ -1993,9 +1993,12 @@ public static Ref specialRef(Object obj, String specialProperty, Context cx, Scr return SpecialRef.createSpecial(cx, scope, obj, specialProperty); } - /** - * @deprecated Use {@link #delete(Object, Object, Context, Scriptable, boolean)} instead - */ + public static Ref optionalSpecialRef( + Object obj, String specialProperty, Context cx, Scriptable scope) { + return SpecialOptionalRef.create(cx, scope, obj, specialProperty); + } + + /** @deprecated Use {@link #delete(Object, Object, Context, Scriptable, boolean)} instead */ @Deprecated public static Object delete(Object obj, Object id, Context cx) { return delete(obj, id, cx, false); diff --git a/rhino/src/main/java/org/mozilla/javascript/SpecialOptionalRef.java b/rhino/src/main/java/org/mozilla/javascript/SpecialOptionalRef.java new file mode 100644 index 0000000000..8098e81e53 --- /dev/null +++ b/rhino/src/main/java/org/mozilla/javascript/SpecialOptionalRef.java @@ -0,0 +1,28 @@ +package org.mozilla.javascript; + +class SpecialOptionalRef extends Ref { + Ref specialRef; + + private SpecialOptionalRef(Ref specialRef) { + this.specialRef = specialRef; + } + + public static Ref create(Context cx, Scriptable scope, Object object, String name) { + Scriptable target = ScriptRuntime.toObjectOrNull(cx, object, scope); + if (target != null && target != Undefined.instance) { + return new SpecialOptionalRef(SpecialRef.createSpecial(cx, scope, object, name)); + } + return new SpecialOptionalRef(null); + } + + @Override + public Object get(Context cx) { + if (specialRef == null) return Undefined.instance; + return specialRef.get(cx); + } + + @Override + public Object set(Context cx, Object value) { + throw new IllegalStateException(); + } +} diff --git a/rhino/src/main/java/org/mozilla/javascript/optimizer/BodyCodegen.java b/rhino/src/main/java/org/mozilla/javascript/optimizer/BodyCodegen.java index 193b10acde..4fab1fe85e 100644 --- a/rhino/src/main/java/org/mozilla/javascript/optimizer/BodyCodegen.java +++ b/rhino/src/main/java/org/mozilla/javascript/optimizer/BodyCodegen.java @@ -1521,7 +1521,22 @@ private void generateExpression(Node node, Node parent) { + ")Lorg/mozilla/javascript/Ref;"); } break; - + case Token.REF_SPECIAL_OPTIONAL: + { + String special = (String) node.getProp(Node.NAME_PROP); + generateExpression(child, node); + cfw.addPush(special); + cfw.addALoad(contextLocal); + cfw.addALoad(variableObjectLocal); + addScriptRuntimeInvoke( + "optionalSpecialRef", + "(Ljava/lang/Object;" + + "Ljava/lang/String;" + + "Lorg/mozilla/javascript/Context;" + + "Lorg/mozilla/javascript/Scriptable;" + + ")Lorg/mozilla/javascript/Ref;"); + } + break; case Token.REF_MEMBER: case Token.REF_NS_MEMBER: case Token.REF_NAME: diff --git a/rhino/src/test/java/org/mozilla/javascript/tests/OptionalChainingOperatorTests.java b/rhino/src/test/java/org/mozilla/javascript/tests/OptionalChainingOperatorTests.java index b39fa56a44..95ea83c554 100644 --- a/rhino/src/test/java/org/mozilla/javascript/tests/OptionalChainingOperatorTests.java +++ b/rhino/src/test/java/org/mozilla/javascript/tests/OptionalChainingOperatorTests.java @@ -67,6 +67,19 @@ public void testOptionalChainingOperator() { 1, null)); + // SpecialRef and Optional Chaining operator + assertEquals( + Undefined.instance, + cx.evaluateString( + scope, " var a = null; a?.__proto__", sourceName, 1, null)); + assertEquals( + Undefined.instance, + cx.evaluateString(scope, "a?.__proto__", sourceName, 1, null)); + + assertEquals( + Undefined.instance, + cx.evaluateString(scope, "a?.__parent__", sourceName, 1, null)); + // NOT WORKING // assertEquals( // Undefined.instance, From ba8bee5b4b85628cb69443901f9216f7afb2260d Mon Sep 17 00:00:00 2001 From: nabacg Date: Thu, 19 Sep 2024 12:35:07 +0100 Subject: [PATCH 5/9] code cleanup and potential BodyGen visitGetPropOptional optimistion similar to visitGetProp --- .../java/org/mozilla/javascript/Parser.java | 18 ------- .../org/mozilla/javascript/ScriptRuntime.java | 8 +++ .../javascript/SpecialOptionalRef.java | 1 + .../javascript/optimizer/BodyCodegen.java | 53 ++++++++----------- 4 files changed, 30 insertions(+), 50 deletions(-) diff --git a/rhino/src/main/java/org/mozilla/javascript/Parser.java b/rhino/src/main/java/org/mozilla/javascript/Parser.java index f1540ed6d0..7e3b5aa767 100644 --- a/rhino/src/main/java/org/mozilla/javascript/Parser.java +++ b/rhino/src/main/java/org/mozilla/javascript/Parser.java @@ -3101,24 +3101,6 @@ private AstNode propertyAccess(int tt, AstNode pn) throws IOException { return result; } - private static AstNode conditionalPropertyAccess(AstNode target, AstNode propAccessNode) { - var targetCopy = cloneNode(target); - var targetCopy2 = cloneNode(target); - - AstNode undefinedNode = new Name(0, "undefined"); - AstNode nullNode = new KeywordLiteral(0, 4, Token.NULL); - - AstNode nullEq = new InfixExpression(Token.SHEQ, targetCopy, nullNode, 0); - - AstNode undefinedEq = new InfixExpression(Token.SHEQ, targetCopy2, undefinedNode, 0); - var conditionalExpr = new ConditionalExpression(); - conditionalExpr.setTestExpression(new InfixExpression(Token.OR, nullEq, undefinedEq, 0)); - conditionalExpr.setTrueExpression(new Name(0, "undefined")); - conditionalExpr.setFalseExpression(propAccessNode); - - return conditionalExpr; - } - private static AstNode cloneNode(AstNode target) { var newParser = new Parser(); var root = newParser.parse(target.toSource(), "", 1); diff --git a/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java b/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java index 9173c7af68..1ced3c67e1 100644 --- a/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java +++ b/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java @@ -1755,6 +1755,14 @@ public static Object getObjectPropOptional( return getObjectProp(obj, property, cx, scope); } + public static Object getObjectPropOptional( + Scriptable obj, String property, Context cx, Scriptable scope) { + if (obj == null || Undefined.isUndefined(obj)) { + return Undefined.instance; + } + return getObjectProp(obj, property, cx); + } + public static Object getObjectProp(Scriptable obj, String property, Context cx) { Object result = ScriptableObject.getProperty(obj, property); diff --git a/rhino/src/main/java/org/mozilla/javascript/SpecialOptionalRef.java b/rhino/src/main/java/org/mozilla/javascript/SpecialOptionalRef.java index 8098e81e53..d2f88cd1ee 100644 --- a/rhino/src/main/java/org/mozilla/javascript/SpecialOptionalRef.java +++ b/rhino/src/main/java/org/mozilla/javascript/SpecialOptionalRef.java @@ -21,6 +21,7 @@ public Object get(Context cx) { return specialRef.get(cx); } + @Deprecated @Override public Object set(Context cx, Object value) { throw new IllegalStateException(); diff --git a/rhino/src/main/java/org/mozilla/javascript/optimizer/BodyCodegen.java b/rhino/src/main/java/org/mozilla/javascript/optimizer/BodyCodegen.java index 4fab1fe85e..cfcdd9318d 100644 --- a/rhino/src/main/java/org/mozilla/javascript/optimizer/BodyCodegen.java +++ b/rhino/src/main/java/org/mozilla/javascript/optimizer/BodyCodegen.java @@ -4103,41 +4103,30 @@ private void visitGetPropOptional(Node node, Node child) { generateExpression(child, node); // object Node nameChild = child.getNext(); generateExpression(nameChild, node); // the name - - cfw.addALoad(contextLocal); - cfw.addALoad(variableObjectLocal); - addScriptRuntimeInvoke( - "getObjectPropOptional", - "(Ljava/lang/Object;" - + "Ljava/lang/String;" - + "Lorg/mozilla/javascript/Context;" - + "Lorg/mozilla/javascript/Scriptable;" - + ")Ljava/lang/Object;"); - // TODO - check if we can skip those casts too /* - for 'this.foo' we call getObjectProp(Scriptable...) which can + for 'this.foo' we call getObjectPropOptional(Scriptable...) which can skip some casting overhead. */ - // int childType = child.getType(); - // if (childType == Token.THIS && nameChild.getType() == Token.STRING) { - // cfw.addALoad(contextLocal); - // addScriptRuntimeInvoke( - // "getObjectProp", - // "(Lorg/mozilla/javascript/Scriptable;" - // + "Ljava/lang/String;" - // + "Lorg/mozilla/javascript/Context;" - // + ")Ljava/lang/Object;"); - // } else { - // cfw.addALoad(contextLocal); - // cfw.addALoad(variableObjectLocal); - // addScriptRuntimeInvoke( - // "getObjectPropOptional", - // "(Ljava/lang/Object;" - // + "Ljava/lang/String;" - // + "Lorg/mozilla/javascript/Context;" - // + "Lorg/mozilla/javascript/Scriptable;" - // + ")Ljava/lang/Object;"); - // } + int childType = child.getType(); + if (childType == Token.THIS && nameChild.getType() == Token.STRING) { + cfw.addALoad(contextLocal); + addScriptRuntimeInvoke( + "getObjectPropOptional", + "(Lorg/mozilla/javascript/Scriptable;" + + "Ljava/lang/String;" + + "Lorg/mozilla/javascript/Context;" + + ")Ljava/lang/Object;"); + } else { + cfw.addALoad(contextLocal); + cfw.addALoad(variableObjectLocal); + addScriptRuntimeInvoke( + "getObjectPropOptional", + "(Ljava/lang/Object;" + + "Ljava/lang/String;" + + "Lorg/mozilla/javascript/Context;" + + "Lorg/mozilla/javascript/Scriptable;" + + ")Ljava/lang/Object;"); + } } private void visitSetProp(int type, Node node, Node child) { From 383656bb21188090ccc5961e200162709c3fd74e Mon Sep 17 00:00:00 2001 From: nabacg Date: Thu, 19 Sep 2024 12:47:01 +0100 Subject: [PATCH 6/9] updated test262.properties --- tests/testsrc/test262.properties | 127 +++++-------------------------- 1 file changed, 20 insertions(+), 107 deletions(-) diff --git a/tests/testsrc/test262.properties b/tests/testsrc/test262.properties index 2e8102ee2a..d678f0ccd2 100644 --- a/tests/testsrc/test262.properties +++ b/tests/testsrc/test262.properties @@ -2,7 +2,7 @@ ~annexB -harness 23/115 (20.0%) +harness 22/115 (19.13%) assert-notsamevalue-tostring.js {unsupported: [async-functions]} assert-samevalue-tostring.js {unsupported: [async-functions]} assert-tostring.js {unsupported: [async-functions]} @@ -11,7 +11,6 @@ harness 23/115 (20.0%) asyncHelpers-asyncTest-then-resolves.js {unsupported: [async]} asyncHelpers-throwsAsync-custom.js {unsupported: [async]} asyncHelpers-throwsAsync-custom-typeerror.js {unsupported: [async]} - asyncHelpers-throwsAsync-func-never-settles.js {unsupported: [async]} asyncHelpers-throwsAsync-func-throws-sync.js {unsupported: [async]} asyncHelpers-throwsAsync-incorrect-ctor.js {unsupported: [async]} asyncHelpers-throwsAsync-invalid-func.js {unsupported: [async]} @@ -27,7 +26,7 @@ harness 23/115 (20.0%) isConstructor.js {unsupported: [Reflect.construct]} nativeFunctionMatcher.js -built-ins/Array 383/3074 (12.46%) +built-ins/Array 364/3055 (11.91%) fromAsync 94/94 (100.0%) from/calling-from-valid-1-noStrict.js non-strict Spec pretty clearly says this should be undefined from/elements-deleted-after.js Checking to see if length changed, but spec says it should not @@ -225,9 +224,6 @@ built-ins/Array 383/3074 (12.46%) prototype/reduce/15.4.4.21-9-c-ii-4-s.js non-strict prototype/reduce/callbackfn-resize-arraybuffer.js {unsupported: [resizable-arraybuffer]} prototype/reduce/not-a-constructor.js {unsupported: [Reflect.construct]} - prototype/reduce/resizable-buffer.js {unsupported: [resizable-arraybuffer]} - prototype/reduce/resizable-buffer-grow-mid-iteration.js {unsupported: [resizable-arraybuffer]} - prototype/reduce/resizable-buffer-shrink-mid-iteration.js {unsupported: [resizable-arraybuffer]} prototype/reverse/length-exceeding-integer-limit-with-proxy.js prototype/reverse/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/reverse/resizable-buffer.js {unsupported: [resizable-arraybuffer]} @@ -237,8 +233,6 @@ built-ins/Array 383/3074 (12.46%) prototype/shift/set-length-zero-array-is-frozen.js prototype/shift/set-length-zero-array-length-is-non-writable.js prototype/shift/throws-when-this-value-length-is-writable-false.js - prototype/slice/coerced-start-end-grow.js {unsupported: [resizable-arraybuffer]} - prototype/slice/coerced-start-end-shrink.js {unsupported: [resizable-arraybuffer]} prototype/slice/create-ctor-non-object.js prototype/slice/create-ctor-poisoned.js prototype/slice/create-proto-from-ctor-realm-non-array.js @@ -252,20 +246,12 @@ built-ins/Array 383/3074 (12.46%) prototype/slice/create-species-poisoned.js prototype/slice/length-exceeding-integer-limit-proxied-array.js prototype/slice/not-a-constructor.js {unsupported: [Reflect.construct]} - prototype/slice/resizable-buffer.js {unsupported: [resizable-arraybuffer]} prototype/slice/target-array-non-extensible.js prototype/slice/target-array-with-non-configurable-property.js prototype/some/15.4.4.17-5-1-s.js non-strict prototype/some/callbackfn-resize-arraybuffer.js {unsupported: [resizable-arraybuffer]} prototype/some/not-a-constructor.js {unsupported: [Reflect.construct]} - prototype/some/resizable-buffer.js {unsupported: [resizable-arraybuffer]} - prototype/some/resizable-buffer-grow-mid-iteration.js {unsupported: [resizable-arraybuffer]} - prototype/some/resizable-buffer-shrink-mid-iteration.js {unsupported: [resizable-arraybuffer]} - prototype/sort/comparefn-grow.js {unsupported: [resizable-arraybuffer]} - prototype/sort/comparefn-resizable-buffer.js {unsupported: [resizable-arraybuffer]} - prototype/sort/comparefn-shrink.js {unsupported: [resizable-arraybuffer]} prototype/sort/not-a-constructor.js {unsupported: [Reflect.construct]} - prototype/sort/resizable-buffer-default-comparator.js {unsupported: [resizable-arraybuffer]} prototype/sort/S15.4.4.11_A8.js non-strict prototype/splice/clamps-length-to-integer-limit.js prototype/splice/create-ctor-non-object.js @@ -293,9 +279,6 @@ built-ins/Array 383/3074 (12.46%) prototype/toLocaleString/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/toLocaleString/primitive_this_value.js strict prototype/toLocaleString/primitive_this_value_getter.js strict - prototype/toLocaleString/resizable-buffer.js {unsupported: [resizable-arraybuffer]} - prototype/toLocaleString/user-provided-tolocalestring-grow.js {unsupported: [resizable-arraybuffer]} - prototype/toLocaleString/user-provided-tolocalestring-shrink.js {unsupported: [resizable-arraybuffer]} prototype/toReversed/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/toSorted/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/toSpliced/not-a-constructor.js {unsupported: [Reflect.construct]} @@ -309,9 +292,6 @@ built-ins/Array 383/3074 (12.46%) prototype/unshift/set-length-zero-array-length-is-non-writable.js prototype/unshift/throws-with-string-receiver.js prototype/values/not-a-constructor.js {unsupported: [Reflect.construct]} - prototype/values/resizable-buffer.js {unsupported: [resizable-arraybuffer]} - prototype/values/resizable-buffer-grow-mid-iteration.js {unsupported: [resizable-arraybuffer]} - prototype/values/resizable-buffer-shrink-mid-iteration.js {unsupported: [resizable-arraybuffer]} prototype/with/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/methods-called-as-functions.js is-a-constructor.js {unsupported: [Reflect.construct]} @@ -769,7 +749,7 @@ built-ins/Error 6/41 (14.63%) ~built-ins/FinalizationRegistry -built-ins/Function 186/508 (36.61%) +built-ins/Function 186/507 (36.69%) internals/Call 2/2 (100.0%) internals/Construct 6/6 (100.0%) length/S15.3.5.1_A1_T3.js strict @@ -782,7 +762,6 @@ built-ins/Function 186/508 (36.61%) prototype/apply/argarray-not-object.js prototype/apply/argarray-not-object-realm.js prototype/apply/not-a-constructor.js {unsupported: [Reflect.construct]} - prototype/apply/resizable-buffer.js {unsupported: [resizable-arraybuffer]} prototype/apply/S15.3.4.3_A3_T1.js non-interpreted prototype/apply/S15.3.4.3_A3_T2.js non-interpreted prototype/apply/S15.3.4.3_A3_T3.js non-interpreted @@ -1029,7 +1008,7 @@ built-ins/Map 13/171 (7.6%) built-ins/MapIteratorPrototype 0/11 (0.0%) -built-ins/Math 51/327 (15.6%) +built-ins/Math 51/326 (15.64%) abs/not-a-constructor.js {unsupported: [Reflect.construct]} acosh/not-a-constructor.js {unsupported: [Reflect.construct]} acos/not-a-constructor.js {unsupported: [Reflect.construct]} @@ -1071,7 +1050,7 @@ built-ins/Math 51/327 (15.6%) built-ins/NaN 0/6 (0.0%) -built-ins/NativeErrors 31/123 (25.2%) +built-ins/NativeErrors 25/117 (21.37%) AggregateError/errors-iterabletolist-failures.js AggregateError/is-a-constructor.js {unsupported: [Reflect.construct]} AggregateError/message-tostring-abrupt.js @@ -1088,8 +1067,6 @@ built-ins/NativeErrors 31/123 (25.2%) ReferenceError/prototype/not-error-object.js ReferenceError/is-a-constructor.js {unsupported: [Reflect.construct]} ReferenceError/proto-from-ctor-realm.js {unsupported: [Reflect]} - SuppressedError/prototype 2/2 (100.0%) - SuppressedError 4/4 (100.0%) SyntaxError/prototype/not-error-object.js SyntaxError/is-a-constructor.js {unsupported: [Reflect.construct]} SyntaxError/proto-from-ctor-realm.js {unsupported: [Reflect]} @@ -1126,7 +1103,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 222/3408 (6.51%) +built-ins/Object 217/3403 (6.38%) 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]} @@ -1162,7 +1139,6 @@ built-ins/Object 222/3408 (6.51%) defineProperties/not-a-constructor.js {unsupported: [Reflect.construct]} defineProperties/property-description-must-be-an-object-not-symbol.js defineProperties/proxy-no-ownkeys-returned-keys-order.js {unsupported: [Proxy]} - defineProperties/typedarray-backed-by-resizable-buffer.js {unsupported: [resizable-arraybuffer]} defineProperty/15.2.3.6-4-116.js non-strict defineProperty/15.2.3.6-4-117.js non-strict defineProperty/15.2.3.6-4-122.js @@ -1181,11 +1157,8 @@ built-ins/Object 222/3408 (6.51%) defineProperty/15.2.3.6-4-293-3.js non-strict defineProperty/15.2.3.6-4-293-4.js strict defineProperty/15.2.3.6-4-336.js - defineProperty/coerced-P-grow.js {unsupported: [resizable-arraybuffer]} - defineProperty/coerced-P-shrink.js {unsupported: [resizable-arraybuffer]} defineProperty/not-a-constructor.js {unsupported: [Reflect.construct]} defineProperty/property-description-must-be-an-object-not-symbol.js - defineProperty/typedarray-backed-by-resizable-buffer.js {unsupported: [resizable-arraybuffer]} entries/not-a-constructor.js {unsupported: [Reflect.construct]} entries/observable-operations.js {unsupported: [Proxy]} entries/order-after-define-property-with-function.js @@ -1194,7 +1167,6 @@ built-ins/Object 222/3408 (6.51%) freeze/proxy-no-ownkeys-returned-keys-order.js {unsupported: [Proxy, Reflect]} freeze/proxy-with-defineProperty-handler.js {unsupported: [Proxy, Reflect]} freeze/throws-when-false.js - freeze/typedarray-backed-by-resizable-buffer.js {unsupported: [resizable-arraybuffer]} fromEntries/not-a-constructor.js {unsupported: [Reflect.construct]} fromEntries/to-property-key.js fromEntries/uses-keys-not-iterator.js @@ -1748,7 +1720,7 @@ built-ins/Promise 406/631 (64.34%) ~built-ins/Reflect -built-ins/RegExp 1169/1854 (63.05%) +built-ins/RegExp 1169/1853 (63.09%) CharacterClassEscapes 24/24 (100.0%) dotall 4/4 (100.0%) escape 20/20 (100.0%) @@ -2310,10 +2282,8 @@ built-ins/String 128/1182 (10.83%) built-ins/StringIteratorPrototype 0/7 (0.0%) -built-ins/Symbol 36/94 (38.3%) - asyncDispose/prop-desc.js +built-ins/Symbol 34/92 (36.96%) asyncIterator/prop-desc.js - dispose/prop-desc.js for/cross-realm.js for/description.js for/not-a-constructor.js {unsupported: [Reflect.construct]} @@ -2357,7 +2327,7 @@ built-ins/ThrowTypeError 8/14 (57.14%) unique-per-realm-non-simple.js unique-per-realm-unmapped-args.js -built-ins/TypedArray 1091/1422 (76.72%) +built-ins/TypedArray 1055/1386 (76.12%) from/arylk-get-length-error.js from/arylk-to-length-error.js from/from-array-mapper-detaches-result.js @@ -2751,9 +2721,6 @@ built-ins/TypedArray 1091/1422 (76.72%) prototype/reduce/name.js prototype/reduce/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/reduce/prop-desc.js - prototype/reduce/resizable-buffer.js {unsupported: [resizable-arraybuffer]} - prototype/reduce/resizable-buffer-grow-mid-iteration.js {unsupported: [resizable-arraybuffer]} - prototype/reduce/resizable-buffer-shrink-mid-iteration.js {unsupported: [resizable-arraybuffer]} prototype/reduce/return-abrupt-from-this-out-of-bounds.js {unsupported: [resizable-arraybuffer]} prototype/reduce/this-is-not-object.js prototype/reduce/this-is-not-typedarray-instance.js @@ -2788,7 +2755,6 @@ built-ins/TypedArray 1091/1422 (76.72%) prototype/set/array-arg-targetbuffer-detached-on-get-src-value-no-throw.js prototype/set/array-arg-targetbuffer-detached-on-tointeger-offset-throws.js prototype/set/array-arg-targetbuffer-detached-throws.js - prototype/set/array-arg-value-conversion-resizes-array-buffer.js {unsupported: [resizable-arraybuffer]} prototype/set/invoked-as-func.js prototype/set/invoked-as-method.js prototype/set/length.js @@ -2796,11 +2762,6 @@ built-ins/TypedArray 1091/1422 (76.72%) prototype/set/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/set/prop-desc.js prototype/set/src-typedarray-big-throws.js - prototype/set/target-grow-mid-iteration.js {unsupported: [resizable-arraybuffer]} - prototype/set/target-grow-source-length-getter.js {unsupported: [resizable-arraybuffer]} - prototype/set/target-shrink-mid-iteration.js {unsupported: [resizable-arraybuffer]} - prototype/set/target-shrink-source-length-getter.js {unsupported: [resizable-arraybuffer]} - prototype/set/this-backed-by-resizable-buffer.js {unsupported: [resizable-arraybuffer]} prototype/set/this-is-not-object.js prototype/set/this-is-not-typedarray-instance.js prototype/set/typedarray-arg-negative-integer-offset-throws.js @@ -2811,7 +2772,6 @@ built-ins/TypedArray 1091/1422 (76.72%) prototype/set/typedarray-arg-set-values-same-buffer-same-type-resized.js {unsupported: [resizable-arraybuffer]} prototype/set/typedarray-arg-set-values-same-buffer-same-type-sab.js {unsupported: [SharedArrayBuffer]} prototype/set/typedarray-arg-src-arraylength-internal.js - prototype/set/typedarray-arg-src-backed-by-resizable-buffer.js {unsupported: [resizable-arraybuffer]} prototype/set/typedarray-arg-src-byteoffset-internal.js prototype/set/typedarray-arg-src-range-greather-than-target-throws-rangeerror.js prototype/set/typedarray-arg-srcbuffer-detached-during-tointeger-offset-throws.js @@ -2821,8 +2781,6 @@ built-ins/TypedArray 1091/1422 (76.72%) prototype/set/typedarray-arg-targetbuffer-detached-during-tointeger-offset-throws.js prototype/slice/BigInt 38/38 (100.0%) prototype/slice/arraylength-internal.js - prototype/slice/coerced-start-end-grow.js {unsupported: [resizable-arraybuffer]} - prototype/slice/coerced-start-end-shrink.js {unsupported: [resizable-arraybuffer]} prototype/slice/detached-buffer.js prototype/slice/detached-buffer-custom-ctor-other-targettype.js prototype/slice/detached-buffer-custom-ctor-same-targettype.js @@ -2836,7 +2794,6 @@ built-ins/TypedArray 1091/1422 (76.72%) prototype/slice/name.js prototype/slice/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/slice/prop-desc.js - prototype/slice/resizable-buffer.js {unsupported: [resizable-arraybuffer]} prototype/slice/return-abrupt-from-this-out-of-bounds.js {unsupported: [resizable-arraybuffer]} prototype/slice/set-values-from-different-ctor-type.js prototype/slice/speciesctor-destination-resizable.js {unsupported: [resizable-arraybuffer]} @@ -2844,7 +2801,6 @@ built-ins/TypedArray 1091/1422 (76.72%) prototype/slice/speciesctor-get-species-custom-ctor-invocation.js prototype/slice/speciesctor-get-species-custom-ctor-length-throws.js prototype/slice/speciesctor-get-species-custom-ctor-length-throws-resizable-arraybuffer.js {unsupported: [resizable-arraybuffer]} - prototype/slice/speciesctor-resize.js {unsupported: [resizable-arraybuffer]} prototype/slice/this-is-not-object.js prototype/slice/this-is-not-typedarray-instance.js prototype/some/BigInt 16/16 (100.0%) @@ -2859,17 +2815,11 @@ built-ins/TypedArray 1091/1422 (76.72%) prototype/some/name.js prototype/some/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/some/prop-desc.js - prototype/some/resizable-buffer.js {unsupported: [resizable-arraybuffer]} - prototype/some/resizable-buffer-grow-mid-iteration.js {unsupported: [resizable-arraybuffer]} - prototype/some/resizable-buffer-shrink-mid-iteration.js {unsupported: [resizable-arraybuffer]} prototype/some/return-abrupt-from-this-out-of-bounds.js {unsupported: [resizable-arraybuffer]} prototype/some/this-is-not-object.js prototype/some/this-is-not-typedarray-instance.js prototype/sort/BigInt 10/10 (100.0%) prototype/sort/arraylength-internal.js - prototype/sort/comparefn-grow.js {unsupported: [resizable-arraybuffer]} - prototype/sort/comparefn-resizable-buffer.js {unsupported: [resizable-arraybuffer]} - prototype/sort/comparefn-shrink.js {unsupported: [resizable-arraybuffer]} prototype/sort/detached-buffer.js prototype/sort/invoked-as-func.js prototype/sort/invoked-as-method.js @@ -2877,14 +2827,11 @@ built-ins/TypedArray 1091/1422 (76.72%) prototype/sort/name.js prototype/sort/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/sort/prop-desc.js - prototype/sort/resizable-buffer-default-comparator.js {unsupported: [resizable-arraybuffer]} prototype/sort/return-abrupt-from-this-out-of-bounds.js {unsupported: [resizable-arraybuffer]} prototype/sort/sort-tonumber.js prototype/sort/this-is-not-object.js prototype/sort/this-is-not-typedarray-instance.js prototype/subarray/BigInt 27/27 (100.0%) - prototype/subarray/coerced-begin-end-grow.js {unsupported: [resizable-arraybuffer]} - prototype/subarray/coerced-begin-end-shrink.js {unsupported: [resizable-arraybuffer]} prototype/subarray/detached-buffer.js prototype/subarray/infinity.js prototype/subarray/invoked-as-func.js @@ -2893,7 +2840,6 @@ built-ins/TypedArray 1091/1422 (76.72%) prototype/subarray/name.js prototype/subarray/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/subarray/prop-desc.js - prototype/subarray/resizable-buffer.js {unsupported: [resizable-arraybuffer]} prototype/subarray/result-byteOffset-from-out-of-bounds.js {unsupported: [resizable-arraybuffer]} prototype/subarray/speciesctor-get-ctor.js prototype/subarray/speciesctor-get-ctor-abrupt.js @@ -2927,12 +2873,9 @@ built-ins/TypedArray 1091/1422 (76.72%) prototype/toLocaleString/name.js prototype/toLocaleString/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/toLocaleString/prop-desc.js - prototype/toLocaleString/resizable-buffer.js {unsupported: [resizable-arraybuffer]} prototype/toLocaleString/return-abrupt-from-this-out-of-bounds.js {unsupported: [resizable-arraybuffer]} prototype/toLocaleString/this-is-not-object.js prototype/toLocaleString/this-is-not-typedarray-instance.js - prototype/toLocaleString/user-provided-tolocalestring-grow.js {unsupported: [resizable-arraybuffer]} - prototype/toLocaleString/user-provided-tolocalestring-shrink.js {unsupported: [resizable-arraybuffer]} prototype/toReversed/metadata 3/3 (100.0%) prototype/toReversed/length-property-ignored.js prototype/toReversed/not-a-constructor.js {unsupported: [Reflect.construct]} @@ -2953,9 +2896,6 @@ built-ins/TypedArray 1091/1422 (76.72%) prototype/values/name.js prototype/values/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/values/prop-desc.js - prototype/values/resizable-buffer.js {unsupported: [resizable-arraybuffer]} - prototype/values/resizable-buffer-grow-mid-iteration.js {unsupported: [resizable-arraybuffer]} - prototype/values/resizable-buffer-shrink-mid-iteration.js {unsupported: [resizable-arraybuffer]} prototype/values/return-abrupt-from-this-out-of-bounds.js {unsupported: [resizable-arraybuffer]} prototype/values/this-is-not-object.js prototype/values/this-is-not-typedarray-instance.js @@ -2964,18 +2904,13 @@ built-ins/TypedArray 1091/1422 (76.72%) prototype/with/index-validated-against-current-length.js {unsupported: [resizable-arraybuffer]} prototype/with/length-property-ignored.js prototype/with/not-a-constructor.js {unsupported: [Reflect.construct]} - prototype 4/4 (100.0%) + prototype 3/3 (100.0%) Symbol.species 4/4 (100.0%) invoked.js name.js - out-of-bounds-behaves-like-detached.js {unsupported: [resizable-arraybuffer]} - out-of-bounds-get-and-set.js {unsupported: [resizable-arraybuffer]} - out-of-bounds-has.js {unsupported: [resizable-arraybuffer]} prototype.js - resizable-buffer-length-tracking-1.js {unsupported: [resizable-arraybuffer]} - resizable-buffer-length-tracking-2.js {unsupported: [resizable-arraybuffer]} -built-ins/TypedArrayConstructors 597/735 (81.22%) +built-ins/TypedArrayConstructors 583/721 (80.86%) BigInt64Array/prototype 4/4 (100.0%) BigInt64Array 8/8 (100.0%) BigUint64Array/prototype 4/4 (100.0%) @@ -3012,7 +2947,6 @@ built-ins/TypedArrayConstructors 597/735 (81.22%) ctors/buffer-arg/new-instance-extensibility-sab.js {unsupported: [SharedArrayBuffer]} ctors/buffer-arg/proto-from-ctor-realm.js {unsupported: [Reflect]} ctors/buffer-arg/proto-from-ctor-realm-sab.js {unsupported: [SharedArrayBuffer, Reflect]} - ctors/buffer-arg/resizable-out-of-bounds.js {unsupported: [resizable-arraybuffer]} ctors/buffer-arg/returns-new-instance-sab.js {unsupported: [SharedArrayBuffer]} ctors/buffer-arg/toindex-bytelength-sab.js {unsupported: [SharedArrayBuffer]} ctors/buffer-arg/toindex-byteoffset-sab.js {unsupported: [SharedArrayBuffer]} @@ -3057,7 +2991,6 @@ built-ins/TypedArrayConstructors 597/735 (81.22%) ctors/typedarray-arg/custom-proto-access-throws.js {unsupported: [Reflect]} ctors/typedarray-arg/proto-from-ctor-realm.js {unsupported: [Reflect]} ctors/typedarray-arg/src-typedarray-big-throws.js - ctors/typedarray-arg/src-typedarray-resizable-buffer.js {unsupported: [resizable-arraybuffer]} ctors/typedarray-arg/use-custom-proto-if-object.js {unsupported: [Reflect]} ctors/typedarray-arg/use-default-proto-if-custom-proto-is-not-object.js ctors/no-species.js @@ -3173,26 +3106,18 @@ built-ins/TypedArrayConstructors 597/735 (81.22%) internals/HasProperty 17/17 (100.0%) internals/OwnPropertyKeys/BigInt 4/4 (100.0%) internals/OwnPropertyKeys 6/6 (100.0%) - internals/Set/BigInt 27/27 (100.0%) + internals/Set/BigInt 23/23 (100.0%) internals/Set/detached-buffer.js internals/Set/detached-buffer-key-is-not-numeric-index.js {unsupported: [Reflect]} internals/Set/detached-buffer-key-is-symbol.js {unsupported: [Reflect]} internals/Set/detached-buffer-realm.js internals/Set/indexed-value.js {unsupported: [Reflect]} - internals/Set/key-is-canonical-invalid-index-prototype-chain-set.js {unsupported: [Proxy]} - internals/Set/key-is-canonical-invalid-index-reflect-set.js {unsupported: [Reflect]} - internals/Set/key-is-in-bounds-receiver-is-not-typed-array.js {unsupported: [Reflect.set]} internals/Set/key-is-minus-zero.js {unsupported: [Reflect]} internals/Set/key-is-not-canonical-index.js {unsupported: [Reflect]} internals/Set/key-is-not-integer.js {unsupported: [Reflect]} internals/Set/key-is-not-numeric-index.js {unsupported: [Reflect]} internals/Set/key-is-out-of-bounds.js {unsupported: [Reflect]} - internals/Set/key-is-out-of-bounds-receiver-is-not-object.js {unsupported: [Reflect.set]} - internals/Set/key-is-out-of-bounds-receiver-is-not-typed-array.js {unsupported: [Reflect.set]} - internals/Set/key-is-out-of-bounds-receiver-is-proto.js {unsupported: [Reflect.set]} internals/Set/key-is-symbol.js {unsupported: [Reflect]} - internals/Set/key-is-valid-index-prototype-chain-set.js {unsupported: [Proxy]} - internals/Set/key-is-valid-index-reflect-set.js {unsupported: [Reflect]} internals/Set/resized-out-of-bounds-to-in-bounds-index.js {unsupported: [resizable-arraybuffer]} internals/Set/tonumber-value-detached-buffer.js {unsupported: [Reflect]} internals/Set/tonumber-value-throws.js @@ -3614,20 +3539,20 @@ language/comments 9/52 (17.31%) multi-line-asi-line-separator.js multi-line-asi-paragraph-separator.js -language/computed-property-names 37/48 (77.08%) +language/computed-property-names 35/48 (72.92%) class/accessor 4/4 (100.0%) class/method 11/11 (100.0%) class/static 14/14 (100.0%) - object/accessor/getter.js object/accessor/getter-super.js - object/accessor/setter.js object/accessor/setter-super.js object/method/generator.js object/method/super.js to-name-side-effects/class.js to-name-side-effects/numbers-class.js -language/destructuring 8/18 (44.44%) +language/destructuring 11/17 (64.71%) + binding/syntax/array-elements-with-initializer.js + binding/syntax/array-elements-with-object-patterns.js binding/syntax/array-rest-elements.js binding/syntax/destructuring-array-parameters-function-arguments-length.js binding/syntax/destructuring-object-parameters-function-arguments-length.js @@ -3635,7 +3560,6 @@ language/destructuring 8/18 (44.44%) binding/syntax/recursive-array-and-object-patterns.js binding/initialization-requires-object-coercible-null.js binding/initialization-requires-object-coercible-undefined.js - binding/typedarray-backed-by-resizable-buffer.js {unsupported: [resizable-arraybuffer]} language/directive-prologue 18/62 (29.03%) 14.1-1-s.js {non-strict: [-1]} @@ -6844,7 +6768,7 @@ language/statements/for 244/385 (63.38%) ~language/statements/for-await-of -language/statements/for-in 40/115 (34.78%) +language/statements/for-in 39/114 (34.21%) dstr/obj-rest-not-last-element-invalid.js {unsupported: [object-rest]} 12.6.4-2.js cptn-decl-abrupt-empty.js @@ -6877,7 +6801,6 @@ language/statements/for-in 40/115 (34.78%) let-block-with-newline.js non-strict let-identifier-with-newline.js non-strict order-enumerable-shadowed.js - resizable-buffer.js {unsupported: [resizable-arraybuffer]} scope-body-lex-boundary.js scope-body-lex-close.js scope-body-lex-open.js @@ -6886,7 +6809,8 @@ language/statements/for-in 40/115 (34.78%) scope-head-lex-open.js scope-head-var-none.js non-strict -language/statements/for-of 453/741 (61.13%) +language/statements/for-of 477/736 (64.81%) + dstr/array-elem-init-assignment.js dstr/array-elem-init-evaluation.js dstr/array-elem-init-fn-name-arrow.js dstr/array-elem-init-fn-name-class.js {unsupported: [class]} @@ -7335,11 +7259,6 @@ language/statements/for-of 453/741 (61.13%) scope-head-lex-close.js scope-head-lex-open.js scope-head-var-none.js non-strict - typedarray-backed-by-resizable-buffer.js {unsupported: [resizable-arraybuffer]} - typedarray-backed-by-resizable-buffer-grow-before-end.js {unsupported: [resizable-arraybuffer]} - typedarray-backed-by-resizable-buffer-grow-mid-iteration.js {unsupported: [resizable-arraybuffer]} - typedarray-backed-by-resizable-buffer-shrink-mid-iteration.js {unsupported: [resizable-arraybuffer]} - typedarray-backed-by-resizable-buffer-shrink-to-zero-mid-iteration.js {unsupported: [resizable-arraybuffer]} language/statements/function 183/451 (40.58%) dstr/ary-init-iter-close.js @@ -8143,7 +8062,7 @@ language/statements/while 13/38 (34.21%) let-identifier-with-newline.js non-strict tco-body.js {unsupported: [tail-call-optimization]} -language/statements/with 26/175 (14.86%) +language/statements/with 20/169 (11.83%) 12.10.1-8-s.js non-strict binding-blocked-by-unscopables.js non-strict cptn-abrupt-empty.js non-strict @@ -8154,16 +8073,10 @@ language/statements/with 26/175 (14.86%) decl-fun.js non-strict decl-gen.js non-strict decl-let.js non-strict - get-mutable-binding-binding-deleted-in-get-unscopables.js non-strict - get-mutable-binding-binding-deleted-in-get-unscopables-strict-mode.js non-strict has-property-err.js {unsupported: [Proxy]} labelled-fn-stmt.js non-strict let-array-with-newline.js non-strict let-block-with-newline.js non-strict - set-mutable-binding-binding-deleted-in-get-unscopables.js non-strict - set-mutable-binding-binding-deleted-in-get-unscopables-strict-mode.js non-strict - set-mutable-binding-binding-deleted-with-typed-array-in-proto-chain.js non-strict - set-mutable-binding-binding-deleted-with-typed-array-in-proto-chain-strict-mode.js non-strict strict-fn-decl-nested-1.js non-strict strict-fn-expr.js strict strict-fn-method.js strict From f9ea6d000802de38912d76e50fcc7428a5fda5e6 Mon Sep 17 00:00:00 2001 From: nabacg Date: Wed, 25 Sep 2024 18:56:57 +0100 Subject: [PATCH 7/9] throwing invalid assignment error when lhs is an optional chain operator --- .../main/java/org/mozilla/javascript/Parser.java | 6 ++++++ .../javascript/resources/Messages.properties | 3 +++ .../tests/OptionalChainingOperatorTests.java | 13 +++++++++++++ tests/testsrc/test262.properties | 2 +- 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/rhino/src/main/java/org/mozilla/javascript/Parser.java b/rhino/src/main/java/org/mozilla/javascript/Parser.java index 7e3b5aa767..fb1cfd2ce4 100644 --- a/rhino/src/main/java/org/mozilla/javascript/Parser.java +++ b/rhino/src/main/java/org/mozilla/javascript/Parser.java @@ -2439,6 +2439,8 @@ private AstNode assignExpr() throws IOException { markDestructuring(pn); int opPos = ts.tokenBeg; + if (isNotValidSimpleAssignmentTarget(pn)) + reportError("msg.syntax.invalid.assignment.lhs"); pn = new Assignment(tt, pn, assignExpr(), opPos); @@ -2461,6 +2463,10 @@ private AstNode assignExpr() throws IOException { return pn; } + private static boolean isNotValidSimpleAssignmentTarget(AstNode pn) { + return pn.getType() == Token.QUESTION_DOT; + } + private AstNode condExpr() throws IOException { AstNode pn = nullishCoalescingExpr(); if (matchToken(Token.HOOK, true)) { diff --git a/rhino/src/main/resources/org/mozilla/javascript/resources/Messages.properties b/rhino/src/main/resources/org/mozilla/javascript/resources/Messages.properties index ada8b827ca..28c462e794 100644 --- a/rhino/src/main/resources/org/mozilla/javascript/resources/Messages.properties +++ b/rhino/src/main/resources/org/mozilla/javascript/resources/Messages.properties @@ -480,6 +480,9 @@ msg.generator.returns =\ msg.anon.generator.returns =\ anonymous generator function returns a value +msg.syntax.invalid.assignment.lhs =\ + syntax error: Invalid left-hand side in assignment + msg.syntax =\ syntax error diff --git a/rhino/src/test/java/org/mozilla/javascript/tests/OptionalChainingOperatorTests.java b/rhino/src/test/java/org/mozilla/javascript/tests/OptionalChainingOperatorTests.java index 95ea83c554..36bdc48744 100644 --- a/rhino/src/test/java/org/mozilla/javascript/tests/OptionalChainingOperatorTests.java +++ b/rhino/src/test/java/org/mozilla/javascript/tests/OptionalChainingOperatorTests.java @@ -2,7 +2,10 @@ import static org.junit.Assert.assertEquals; +import org.junit.Assert; import org.junit.Test; +import org.mozilla.javascript.EcmaError; +import org.mozilla.javascript.EvaluatorException; import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.Undefined; @@ -80,6 +83,16 @@ public void testOptionalChainingOperator() { Undefined.instance, cx.evaluateString(scope, "a?.__parent__", sourceName, 1, null)); + var err = Assert.assertThrows(EvaluatorException.class, () -> + cx.evaluateString(scope, "var y = {};\n" + + "0, { x: y?.z = 42 } = { x: 23 };", sourceName, 1, null)); + Assert.assertTrue(err.getMessage().contains("Invalid left-hand side in assignment")); + + err = Assert.assertThrows(EvaluatorException.class, () -> + cx.evaluateString(scope, + "y?.z = 42", sourceName, 1, null)); + Assert.assertTrue(err.getMessage().contains("Invalid left-hand side in assignment")); + // NOT WORKING // assertEquals( // Undefined.instance, diff --git a/tests/testsrc/test262.properties b/tests/testsrc/test262.properties index d678f0ccd2..a30130dc45 100644 --- a/tests/testsrc/test262.properties +++ b/tests/testsrc/test262.properties @@ -749,7 +749,7 @@ built-ins/Error 6/41 (14.63%) ~built-ins/FinalizationRegistry -built-ins/Function 186/507 (36.69%) +built-ins/Function 185/507 (36.49%) internals/Call 2/2 (100.0%) internals/Construct 6/6 (100.0%) length/S15.3.5.1_A1_T3.js strict From 3a8fc851af670bf207fe3a030ef6a5fa2d891048 Mon Sep 17 00:00:00 2001 From: nabacg Date: Wed, 25 Sep 2024 19:27:15 +0100 Subject: [PATCH 8/9] making sure we scan entire lhs of assigmnent AstNode for ?. operator --- .../java/org/mozilla/javascript/Parser.java | 2 ++ .../tests/OptionalChainingOperatorTests.java | 19 +++++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/rhino/src/main/java/org/mozilla/javascript/Parser.java b/rhino/src/main/java/org/mozilla/javascript/Parser.java index fb1cfd2ce4..8b5ac7ce1f 100644 --- a/rhino/src/main/java/org/mozilla/javascript/Parser.java +++ b/rhino/src/main/java/org/mozilla/javascript/Parser.java @@ -2464,6 +2464,8 @@ private AstNode assignExpr() throws IOException { } private static boolean isNotValidSimpleAssignmentTarget(AstNode pn) { + if (pn.getType() == Token.GETPROP ) + return isNotValidSimpleAssignmentTarget(((PropertyGet) pn).getLeft()); return pn.getType() == Token.QUESTION_DOT; } diff --git a/rhino/src/test/java/org/mozilla/javascript/tests/OptionalChainingOperatorTests.java b/rhino/src/test/java/org/mozilla/javascript/tests/OptionalChainingOperatorTests.java index 36bdc48744..526ab215cb 100644 --- a/rhino/src/test/java/org/mozilla/javascript/tests/OptionalChainingOperatorTests.java +++ b/rhino/src/test/java/org/mozilla/javascript/tests/OptionalChainingOperatorTests.java @@ -83,15 +83,26 @@ public void testOptionalChainingOperator() { Undefined.instance, cx.evaluateString(scope, "a?.__parent__", sourceName, 1, null)); - var err = Assert.assertThrows(EvaluatorException.class, () -> + var e = Assert.assertThrows(EvaluatorException.class, () -> cx.evaluateString(scope, "var y = {};\n" + "0, { x: y?.z = 42 } = { x: 23 };", sourceName, 1, null)); - Assert.assertTrue(err.getMessage().contains("Invalid left-hand side in assignment")); + Assert.assertTrue(e.getMessage().contains("Invalid left-hand side in assignment")); - err = Assert.assertThrows(EvaluatorException.class, () -> + e = Assert.assertThrows(EvaluatorException.class, () -> cx.evaluateString(scope, "y?.z = 42", sourceName, 1, null)); - Assert.assertTrue(err.getMessage().contains("Invalid left-hand side in assignment")); + Assert.assertTrue(e.getMessage().contains("Invalid left-hand side in assignment")); + + e = Assert.assertThrows(EvaluatorException.class, () -> + cx.evaluateString(scope, + "y.z?.x = 42", sourceName, 1, null)); + Assert.assertTrue(e.getMessage().contains("Invalid left-hand side in assignment")); + + e = Assert.assertThrows(EvaluatorException.class, () -> + cx.evaluateString(scope, + "y?.z.x = 42", sourceName, 1, null)); + Assert.assertTrue(e.getMessage().contains("Invalid left-hand side in assignment")); + // NOT WORKING // assertEquals( From f150caf2da8d6c9deb1c50906ea1096a237745e6 Mon Sep 17 00:00:00 2001 From: nabacg Date: Wed, 25 Sep 2024 19:57:32 +0100 Subject: [PATCH 9/9] clean up and spotlessApply, update test262.properties --- .../java/org/mozilla/javascript/Parser.java | 13 +- .../org/mozilla/javascript/ScriptRuntime.java | 4 +- .../java/org/mozilla/javascript/Token.java | 6 +- .../org/mozilla/javascript/TokenStream.java | 2 +- .../tests/OptionalChainingOperatorTests.java | 79 +++++------ tests/testsrc/test262.properties | 127 +++++++++++++++--- 6 files changed, 157 insertions(+), 74 deletions(-) diff --git a/rhino/src/main/java/org/mozilla/javascript/Parser.java b/rhino/src/main/java/org/mozilla/javascript/Parser.java index 8b5ac7ce1f..27ff2e8afb 100644 --- a/rhino/src/main/java/org/mozilla/javascript/Parser.java +++ b/rhino/src/main/java/org/mozilla/javascript/Parser.java @@ -2464,7 +2464,7 @@ private AstNode assignExpr() throws IOException { } private static boolean isNotValidSimpleAssignmentTarget(AstNode pn) { - if (pn.getType() == Token.GETPROP ) + if (pn.getType() == Token.GETPROP) return isNotValidSimpleAssignmentTarget(((PropertyGet) pn).getLeft()); return pn.getType() == Token.QUESTION_DOT; } @@ -2878,8 +2878,8 @@ private AstNode memberExpr(boolean allowCallSyntax) throws IOException { } /** - * Parse any number of "(expr)", "[expr]" ".expr", "..expr", or ".(expr)" constructs trailing - * the passed expression. + * Parse any number of "(expr)", "[expr]" ".expr", "?.expr", "..expr", ".(expr)" or "?.(expr)" + * constructs trailing the passed expression. * * @param pn the non-null parent node * @return the outermost (lexically last occurring) expression, which will have the passed @@ -3109,13 +3109,6 @@ private AstNode propertyAccess(int tt, AstNode pn) throws IOException { return result; } - private static AstNode cloneNode(AstNode target) { - var newParser = new Parser(); - var root = newParser.parse(target.toSource(), "", 1); - var targetCopy = ((ExpressionStatement) root.first).getExpression(); - return targetCopy; - } - /** * Xml attribute expression: * diff --git a/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java b/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java index 1ced3c67e1..203bc36f6e 100644 --- a/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java +++ b/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java @@ -2006,7 +2006,9 @@ public static Ref optionalSpecialRef( return SpecialOptionalRef.create(cx, scope, obj, specialProperty); } - /** @deprecated Use {@link #delete(Object, Object, Context, Scriptable, boolean)} instead */ + /** + * @deprecated Use {@link #delete(Object, Object, Context, Scriptable, boolean)} instead + */ @Deprecated public static Object delete(Object obj, Object id, Context cx) { return delete(obj, id, cx, false); diff --git a/rhino/src/main/java/org/mozilla/javascript/Token.java b/rhino/src/main/java/org/mozilla/javascript/Token.java index 7924fa7d9d..3405f3885f 100644 --- a/rhino/src/main/java/org/mozilla/javascript/Token.java +++ b/rhino/src/main/java/org/mozilla/javascript/Token.java @@ -120,7 +120,7 @@ public static enum CommentType { REF_NS_MEMBER = REF_MEMBER + 1, // Reference for x.ns::y, x..ns::y etc. REF_NAME = REF_NS_MEMBER + 1, // Reference for @y, @[y] etc. REF_NS_NAME = REF_NAME + 1, // Reference for ns::y, @ns::y@[y] etc. - BIGINT = REF_NS_NAME + 1; // ES2020 BigInt + BIGINT = REF_NS_NAME + 1, // ES2020 BigInt GETPROP_OPTIONAL = BIGINT + 1, REF_SPECIAL_OPTIONAL = GETPROP_OPTIONAL + 1, CALL_OPTIONAL = REF_SPECIAL_OPTIONAL + 1; @@ -234,8 +234,8 @@ public static enum CommentType { TEMPLATE_LITERAL_SUBST + 1, // template literal - tagged/handler DOTDOTDOT = TAGGED_TEMPLATE_LITERAL + 1, // spread/rest ... NULLISH_COALESCING = DOTDOTDOT + 1, // nullish coalescing (??) - DOT_QUESTION = NULLISH_COALESCING + 1, // optional chaining operator (?.) - LAST_TOKEN = DOT_QUESTION + 1; + QUESTION_DOT = NULLISH_COALESCING + 1, // optional chaining operator (?.) + LAST_TOKEN = QUESTION_DOT; /** * Returns a name for the token. If Rhino is compiled with certain hardcoded debugging flags in diff --git a/rhino/src/main/java/org/mozilla/javascript/TokenStream.java b/rhino/src/main/java/org/mozilla/javascript/TokenStream.java index 6481f15a7d..c227d4fa84 100644 --- a/rhino/src/main/java/org/mozilla/javascript/TokenStream.java +++ b/rhino/src/main/java/org/mozilla/javascript/TokenStream.java @@ -1152,7 +1152,7 @@ && peekChar() == '!' } if (matchChar('?')) { return Token.NULLISH_COALESCING; - }n + } return Token.HOOK; case ':': if (matchChar(':')) { diff --git a/rhino/src/test/java/org/mozilla/javascript/tests/OptionalChainingOperatorTests.java b/rhino/src/test/java/org/mozilla/javascript/tests/OptionalChainingOperatorTests.java index 526ab215cb..482b64a97c 100644 --- a/rhino/src/test/java/org/mozilla/javascript/tests/OptionalChainingOperatorTests.java +++ b/rhino/src/test/java/org/mozilla/javascript/tests/OptionalChainingOperatorTests.java @@ -4,7 +4,6 @@ import org.junit.Assert; import org.junit.Test; -import org.mozilla.javascript.EcmaError; import org.mozilla.javascript.EvaluatorException; import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.Undefined; @@ -83,44 +82,46 @@ public void testOptionalChainingOperator() { Undefined.instance, cx.evaluateString(scope, "a?.__parent__", sourceName, 1, null)); - var e = Assert.assertThrows(EvaluatorException.class, () -> - cx.evaluateString(scope, "var y = {};\n" + - "0, { x: y?.z = 42 } = { x: 23 };", sourceName, 1, null)); - Assert.assertTrue(e.getMessage().contains("Invalid left-hand side in assignment")); - - e = Assert.assertThrows(EvaluatorException.class, () -> - cx.evaluateString(scope, - "y?.z = 42", sourceName, 1, null)); - Assert.assertTrue(e.getMessage().contains("Invalid left-hand side in assignment")); - - e = Assert.assertThrows(EvaluatorException.class, () -> - cx.evaluateString(scope, - "y.z?.x = 42", sourceName, 1, null)); - Assert.assertTrue(e.getMessage().contains("Invalid left-hand side in assignment")); - - e = Assert.assertThrows(EvaluatorException.class, () -> - cx.evaluateString(scope, - "y?.z.x = 42", sourceName, 1, null)); - Assert.assertTrue(e.getMessage().contains("Invalid left-hand side in assignment")); - - - // NOT WORKING - // assertEquals( - // Undefined.instance, - // cx.evaluateString( - // scope, - // "{}?.a", - // sourceName, - // 1, - // null)); - // assertEquals( - // Undefined.instance, - // cx.evaluateString( - // scope, - // "var b = {}; for (const key of b.a) ", - // sourceName, - // 1, - // null)); + var e = + Assert.assertThrows( + EvaluatorException.class, + () -> + cx.evaluateString( + scope, + "var y = {};\n" + + "0, { x: y?.z = 42 } = { x: 23 };", + sourceName, + 1, + null)); + Assert.assertTrue( + e.getMessage().contains("Invalid left-hand side in assignment")); + + e = + Assert.assertThrows( + EvaluatorException.class, + () -> + cx.evaluateString( + scope, "y?.z = 42", sourceName, 1, null)); + Assert.assertTrue( + e.getMessage().contains("Invalid left-hand side in assignment")); + + e = + Assert.assertThrows( + EvaluatorException.class, + () -> + cx.evaluateString( + scope, "y.z?.x = 42", sourceName, 1, null)); + Assert.assertTrue( + e.getMessage().contains("Invalid left-hand side in assignment")); + + e = + Assert.assertThrows( + EvaluatorException.class, + () -> + cx.evaluateString( + scope, "y?.z.x = 42", sourceName, 1, null)); + Assert.assertTrue( + e.getMessage().contains("Invalid left-hand side in assignment")); return null; }); diff --git a/tests/testsrc/test262.properties b/tests/testsrc/test262.properties index a30130dc45..2e8102ee2a 100644 --- a/tests/testsrc/test262.properties +++ b/tests/testsrc/test262.properties @@ -2,7 +2,7 @@ ~annexB -harness 22/115 (19.13%) +harness 23/115 (20.0%) assert-notsamevalue-tostring.js {unsupported: [async-functions]} assert-samevalue-tostring.js {unsupported: [async-functions]} assert-tostring.js {unsupported: [async-functions]} @@ -11,6 +11,7 @@ harness 22/115 (19.13%) asyncHelpers-asyncTest-then-resolves.js {unsupported: [async]} asyncHelpers-throwsAsync-custom.js {unsupported: [async]} asyncHelpers-throwsAsync-custom-typeerror.js {unsupported: [async]} + asyncHelpers-throwsAsync-func-never-settles.js {unsupported: [async]} asyncHelpers-throwsAsync-func-throws-sync.js {unsupported: [async]} asyncHelpers-throwsAsync-incorrect-ctor.js {unsupported: [async]} asyncHelpers-throwsAsync-invalid-func.js {unsupported: [async]} @@ -26,7 +27,7 @@ harness 22/115 (19.13%) isConstructor.js {unsupported: [Reflect.construct]} nativeFunctionMatcher.js -built-ins/Array 364/3055 (11.91%) +built-ins/Array 383/3074 (12.46%) fromAsync 94/94 (100.0%) from/calling-from-valid-1-noStrict.js non-strict Spec pretty clearly says this should be undefined from/elements-deleted-after.js Checking to see if length changed, but spec says it should not @@ -224,6 +225,9 @@ built-ins/Array 364/3055 (11.91%) prototype/reduce/15.4.4.21-9-c-ii-4-s.js non-strict prototype/reduce/callbackfn-resize-arraybuffer.js {unsupported: [resizable-arraybuffer]} prototype/reduce/not-a-constructor.js {unsupported: [Reflect.construct]} + prototype/reduce/resizable-buffer.js {unsupported: [resizable-arraybuffer]} + prototype/reduce/resizable-buffer-grow-mid-iteration.js {unsupported: [resizable-arraybuffer]} + prototype/reduce/resizable-buffer-shrink-mid-iteration.js {unsupported: [resizable-arraybuffer]} prototype/reverse/length-exceeding-integer-limit-with-proxy.js prototype/reverse/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/reverse/resizable-buffer.js {unsupported: [resizable-arraybuffer]} @@ -233,6 +237,8 @@ built-ins/Array 364/3055 (11.91%) prototype/shift/set-length-zero-array-is-frozen.js prototype/shift/set-length-zero-array-length-is-non-writable.js prototype/shift/throws-when-this-value-length-is-writable-false.js + prototype/slice/coerced-start-end-grow.js {unsupported: [resizable-arraybuffer]} + prototype/slice/coerced-start-end-shrink.js {unsupported: [resizable-arraybuffer]} prototype/slice/create-ctor-non-object.js prototype/slice/create-ctor-poisoned.js prototype/slice/create-proto-from-ctor-realm-non-array.js @@ -246,12 +252,20 @@ built-ins/Array 364/3055 (11.91%) prototype/slice/create-species-poisoned.js prototype/slice/length-exceeding-integer-limit-proxied-array.js prototype/slice/not-a-constructor.js {unsupported: [Reflect.construct]} + prototype/slice/resizable-buffer.js {unsupported: [resizable-arraybuffer]} prototype/slice/target-array-non-extensible.js prototype/slice/target-array-with-non-configurable-property.js prototype/some/15.4.4.17-5-1-s.js non-strict prototype/some/callbackfn-resize-arraybuffer.js {unsupported: [resizable-arraybuffer]} prototype/some/not-a-constructor.js {unsupported: [Reflect.construct]} + prototype/some/resizable-buffer.js {unsupported: [resizable-arraybuffer]} + prototype/some/resizable-buffer-grow-mid-iteration.js {unsupported: [resizable-arraybuffer]} + prototype/some/resizable-buffer-shrink-mid-iteration.js {unsupported: [resizable-arraybuffer]} + prototype/sort/comparefn-grow.js {unsupported: [resizable-arraybuffer]} + prototype/sort/comparefn-resizable-buffer.js {unsupported: [resizable-arraybuffer]} + prototype/sort/comparefn-shrink.js {unsupported: [resizable-arraybuffer]} prototype/sort/not-a-constructor.js {unsupported: [Reflect.construct]} + prototype/sort/resizable-buffer-default-comparator.js {unsupported: [resizable-arraybuffer]} prototype/sort/S15.4.4.11_A8.js non-strict prototype/splice/clamps-length-to-integer-limit.js prototype/splice/create-ctor-non-object.js @@ -279,6 +293,9 @@ built-ins/Array 364/3055 (11.91%) prototype/toLocaleString/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/toLocaleString/primitive_this_value.js strict prototype/toLocaleString/primitive_this_value_getter.js strict + prototype/toLocaleString/resizable-buffer.js {unsupported: [resizable-arraybuffer]} + prototype/toLocaleString/user-provided-tolocalestring-grow.js {unsupported: [resizable-arraybuffer]} + prototype/toLocaleString/user-provided-tolocalestring-shrink.js {unsupported: [resizable-arraybuffer]} prototype/toReversed/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/toSorted/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/toSpliced/not-a-constructor.js {unsupported: [Reflect.construct]} @@ -292,6 +309,9 @@ built-ins/Array 364/3055 (11.91%) prototype/unshift/set-length-zero-array-length-is-non-writable.js prototype/unshift/throws-with-string-receiver.js prototype/values/not-a-constructor.js {unsupported: [Reflect.construct]} + prototype/values/resizable-buffer.js {unsupported: [resizable-arraybuffer]} + prototype/values/resizable-buffer-grow-mid-iteration.js {unsupported: [resizable-arraybuffer]} + prototype/values/resizable-buffer-shrink-mid-iteration.js {unsupported: [resizable-arraybuffer]} prototype/with/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/methods-called-as-functions.js is-a-constructor.js {unsupported: [Reflect.construct]} @@ -749,7 +769,7 @@ built-ins/Error 6/41 (14.63%) ~built-ins/FinalizationRegistry -built-ins/Function 185/507 (36.49%) +built-ins/Function 186/508 (36.61%) internals/Call 2/2 (100.0%) internals/Construct 6/6 (100.0%) length/S15.3.5.1_A1_T3.js strict @@ -762,6 +782,7 @@ built-ins/Function 185/507 (36.49%) prototype/apply/argarray-not-object.js prototype/apply/argarray-not-object-realm.js prototype/apply/not-a-constructor.js {unsupported: [Reflect.construct]} + prototype/apply/resizable-buffer.js {unsupported: [resizable-arraybuffer]} prototype/apply/S15.3.4.3_A3_T1.js non-interpreted prototype/apply/S15.3.4.3_A3_T2.js non-interpreted prototype/apply/S15.3.4.3_A3_T3.js non-interpreted @@ -1008,7 +1029,7 @@ built-ins/Map 13/171 (7.6%) built-ins/MapIteratorPrototype 0/11 (0.0%) -built-ins/Math 51/326 (15.64%) +built-ins/Math 51/327 (15.6%) abs/not-a-constructor.js {unsupported: [Reflect.construct]} acosh/not-a-constructor.js {unsupported: [Reflect.construct]} acos/not-a-constructor.js {unsupported: [Reflect.construct]} @@ -1050,7 +1071,7 @@ built-ins/Math 51/326 (15.64%) built-ins/NaN 0/6 (0.0%) -built-ins/NativeErrors 25/117 (21.37%) +built-ins/NativeErrors 31/123 (25.2%) AggregateError/errors-iterabletolist-failures.js AggregateError/is-a-constructor.js {unsupported: [Reflect.construct]} AggregateError/message-tostring-abrupt.js @@ -1067,6 +1088,8 @@ built-ins/NativeErrors 25/117 (21.37%) ReferenceError/prototype/not-error-object.js ReferenceError/is-a-constructor.js {unsupported: [Reflect.construct]} ReferenceError/proto-from-ctor-realm.js {unsupported: [Reflect]} + SuppressedError/prototype 2/2 (100.0%) + SuppressedError 4/4 (100.0%) SyntaxError/prototype/not-error-object.js SyntaxError/is-a-constructor.js {unsupported: [Reflect.construct]} SyntaxError/proto-from-ctor-realm.js {unsupported: [Reflect]} @@ -1103,7 +1126,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 217/3403 (6.38%) +built-ins/Object 222/3408 (6.51%) 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]} @@ -1139,6 +1162,7 @@ built-ins/Object 217/3403 (6.38%) defineProperties/not-a-constructor.js {unsupported: [Reflect.construct]} defineProperties/property-description-must-be-an-object-not-symbol.js defineProperties/proxy-no-ownkeys-returned-keys-order.js {unsupported: [Proxy]} + defineProperties/typedarray-backed-by-resizable-buffer.js {unsupported: [resizable-arraybuffer]} defineProperty/15.2.3.6-4-116.js non-strict defineProperty/15.2.3.6-4-117.js non-strict defineProperty/15.2.3.6-4-122.js @@ -1157,8 +1181,11 @@ built-ins/Object 217/3403 (6.38%) defineProperty/15.2.3.6-4-293-3.js non-strict defineProperty/15.2.3.6-4-293-4.js strict defineProperty/15.2.3.6-4-336.js + defineProperty/coerced-P-grow.js {unsupported: [resizable-arraybuffer]} + defineProperty/coerced-P-shrink.js {unsupported: [resizable-arraybuffer]} defineProperty/not-a-constructor.js {unsupported: [Reflect.construct]} defineProperty/property-description-must-be-an-object-not-symbol.js + defineProperty/typedarray-backed-by-resizable-buffer.js {unsupported: [resizable-arraybuffer]} entries/not-a-constructor.js {unsupported: [Reflect.construct]} entries/observable-operations.js {unsupported: [Proxy]} entries/order-after-define-property-with-function.js @@ -1167,6 +1194,7 @@ built-ins/Object 217/3403 (6.38%) freeze/proxy-no-ownkeys-returned-keys-order.js {unsupported: [Proxy, Reflect]} freeze/proxy-with-defineProperty-handler.js {unsupported: [Proxy, Reflect]} freeze/throws-when-false.js + freeze/typedarray-backed-by-resizable-buffer.js {unsupported: [resizable-arraybuffer]} fromEntries/not-a-constructor.js {unsupported: [Reflect.construct]} fromEntries/to-property-key.js fromEntries/uses-keys-not-iterator.js @@ -1720,7 +1748,7 @@ built-ins/Promise 406/631 (64.34%) ~built-ins/Reflect -built-ins/RegExp 1169/1853 (63.09%) +built-ins/RegExp 1169/1854 (63.05%) CharacterClassEscapes 24/24 (100.0%) dotall 4/4 (100.0%) escape 20/20 (100.0%) @@ -2282,8 +2310,10 @@ built-ins/String 128/1182 (10.83%) built-ins/StringIteratorPrototype 0/7 (0.0%) -built-ins/Symbol 34/92 (36.96%) +built-ins/Symbol 36/94 (38.3%) + asyncDispose/prop-desc.js asyncIterator/prop-desc.js + dispose/prop-desc.js for/cross-realm.js for/description.js for/not-a-constructor.js {unsupported: [Reflect.construct]} @@ -2327,7 +2357,7 @@ built-ins/ThrowTypeError 8/14 (57.14%) unique-per-realm-non-simple.js unique-per-realm-unmapped-args.js -built-ins/TypedArray 1055/1386 (76.12%) +built-ins/TypedArray 1091/1422 (76.72%) from/arylk-get-length-error.js from/arylk-to-length-error.js from/from-array-mapper-detaches-result.js @@ -2721,6 +2751,9 @@ built-ins/TypedArray 1055/1386 (76.12%) prototype/reduce/name.js prototype/reduce/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/reduce/prop-desc.js + prototype/reduce/resizable-buffer.js {unsupported: [resizable-arraybuffer]} + prototype/reduce/resizable-buffer-grow-mid-iteration.js {unsupported: [resizable-arraybuffer]} + prototype/reduce/resizable-buffer-shrink-mid-iteration.js {unsupported: [resizable-arraybuffer]} prototype/reduce/return-abrupt-from-this-out-of-bounds.js {unsupported: [resizable-arraybuffer]} prototype/reduce/this-is-not-object.js prototype/reduce/this-is-not-typedarray-instance.js @@ -2755,6 +2788,7 @@ built-ins/TypedArray 1055/1386 (76.12%) prototype/set/array-arg-targetbuffer-detached-on-get-src-value-no-throw.js prototype/set/array-arg-targetbuffer-detached-on-tointeger-offset-throws.js prototype/set/array-arg-targetbuffer-detached-throws.js + prototype/set/array-arg-value-conversion-resizes-array-buffer.js {unsupported: [resizable-arraybuffer]} prototype/set/invoked-as-func.js prototype/set/invoked-as-method.js prototype/set/length.js @@ -2762,6 +2796,11 @@ built-ins/TypedArray 1055/1386 (76.12%) prototype/set/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/set/prop-desc.js prototype/set/src-typedarray-big-throws.js + prototype/set/target-grow-mid-iteration.js {unsupported: [resizable-arraybuffer]} + prototype/set/target-grow-source-length-getter.js {unsupported: [resizable-arraybuffer]} + prototype/set/target-shrink-mid-iteration.js {unsupported: [resizable-arraybuffer]} + prototype/set/target-shrink-source-length-getter.js {unsupported: [resizable-arraybuffer]} + prototype/set/this-backed-by-resizable-buffer.js {unsupported: [resizable-arraybuffer]} prototype/set/this-is-not-object.js prototype/set/this-is-not-typedarray-instance.js prototype/set/typedarray-arg-negative-integer-offset-throws.js @@ -2772,6 +2811,7 @@ built-ins/TypedArray 1055/1386 (76.12%) prototype/set/typedarray-arg-set-values-same-buffer-same-type-resized.js {unsupported: [resizable-arraybuffer]} prototype/set/typedarray-arg-set-values-same-buffer-same-type-sab.js {unsupported: [SharedArrayBuffer]} prototype/set/typedarray-arg-src-arraylength-internal.js + prototype/set/typedarray-arg-src-backed-by-resizable-buffer.js {unsupported: [resizable-arraybuffer]} prototype/set/typedarray-arg-src-byteoffset-internal.js prototype/set/typedarray-arg-src-range-greather-than-target-throws-rangeerror.js prototype/set/typedarray-arg-srcbuffer-detached-during-tointeger-offset-throws.js @@ -2781,6 +2821,8 @@ built-ins/TypedArray 1055/1386 (76.12%) prototype/set/typedarray-arg-targetbuffer-detached-during-tointeger-offset-throws.js prototype/slice/BigInt 38/38 (100.0%) prototype/slice/arraylength-internal.js + prototype/slice/coerced-start-end-grow.js {unsupported: [resizable-arraybuffer]} + prototype/slice/coerced-start-end-shrink.js {unsupported: [resizable-arraybuffer]} prototype/slice/detached-buffer.js prototype/slice/detached-buffer-custom-ctor-other-targettype.js prototype/slice/detached-buffer-custom-ctor-same-targettype.js @@ -2794,6 +2836,7 @@ built-ins/TypedArray 1055/1386 (76.12%) prototype/slice/name.js prototype/slice/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/slice/prop-desc.js + prototype/slice/resizable-buffer.js {unsupported: [resizable-arraybuffer]} prototype/slice/return-abrupt-from-this-out-of-bounds.js {unsupported: [resizable-arraybuffer]} prototype/slice/set-values-from-different-ctor-type.js prototype/slice/speciesctor-destination-resizable.js {unsupported: [resizable-arraybuffer]} @@ -2801,6 +2844,7 @@ built-ins/TypedArray 1055/1386 (76.12%) prototype/slice/speciesctor-get-species-custom-ctor-invocation.js prototype/slice/speciesctor-get-species-custom-ctor-length-throws.js prototype/slice/speciesctor-get-species-custom-ctor-length-throws-resizable-arraybuffer.js {unsupported: [resizable-arraybuffer]} + prototype/slice/speciesctor-resize.js {unsupported: [resizable-arraybuffer]} prototype/slice/this-is-not-object.js prototype/slice/this-is-not-typedarray-instance.js prototype/some/BigInt 16/16 (100.0%) @@ -2815,11 +2859,17 @@ built-ins/TypedArray 1055/1386 (76.12%) prototype/some/name.js prototype/some/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/some/prop-desc.js + prototype/some/resizable-buffer.js {unsupported: [resizable-arraybuffer]} + prototype/some/resizable-buffer-grow-mid-iteration.js {unsupported: [resizable-arraybuffer]} + prototype/some/resizable-buffer-shrink-mid-iteration.js {unsupported: [resizable-arraybuffer]} prototype/some/return-abrupt-from-this-out-of-bounds.js {unsupported: [resizable-arraybuffer]} prototype/some/this-is-not-object.js prototype/some/this-is-not-typedarray-instance.js prototype/sort/BigInt 10/10 (100.0%) prototype/sort/arraylength-internal.js + prototype/sort/comparefn-grow.js {unsupported: [resizable-arraybuffer]} + prototype/sort/comparefn-resizable-buffer.js {unsupported: [resizable-arraybuffer]} + prototype/sort/comparefn-shrink.js {unsupported: [resizable-arraybuffer]} prototype/sort/detached-buffer.js prototype/sort/invoked-as-func.js prototype/sort/invoked-as-method.js @@ -2827,11 +2877,14 @@ built-ins/TypedArray 1055/1386 (76.12%) prototype/sort/name.js prototype/sort/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/sort/prop-desc.js + prototype/sort/resizable-buffer-default-comparator.js {unsupported: [resizable-arraybuffer]} prototype/sort/return-abrupt-from-this-out-of-bounds.js {unsupported: [resizable-arraybuffer]} prototype/sort/sort-tonumber.js prototype/sort/this-is-not-object.js prototype/sort/this-is-not-typedarray-instance.js prototype/subarray/BigInt 27/27 (100.0%) + prototype/subarray/coerced-begin-end-grow.js {unsupported: [resizable-arraybuffer]} + prototype/subarray/coerced-begin-end-shrink.js {unsupported: [resizable-arraybuffer]} prototype/subarray/detached-buffer.js prototype/subarray/infinity.js prototype/subarray/invoked-as-func.js @@ -2840,6 +2893,7 @@ built-ins/TypedArray 1055/1386 (76.12%) prototype/subarray/name.js prototype/subarray/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/subarray/prop-desc.js + prototype/subarray/resizable-buffer.js {unsupported: [resizable-arraybuffer]} prototype/subarray/result-byteOffset-from-out-of-bounds.js {unsupported: [resizable-arraybuffer]} prototype/subarray/speciesctor-get-ctor.js prototype/subarray/speciesctor-get-ctor-abrupt.js @@ -2873,9 +2927,12 @@ built-ins/TypedArray 1055/1386 (76.12%) prototype/toLocaleString/name.js prototype/toLocaleString/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/toLocaleString/prop-desc.js + prototype/toLocaleString/resizable-buffer.js {unsupported: [resizable-arraybuffer]} prototype/toLocaleString/return-abrupt-from-this-out-of-bounds.js {unsupported: [resizable-arraybuffer]} prototype/toLocaleString/this-is-not-object.js prototype/toLocaleString/this-is-not-typedarray-instance.js + prototype/toLocaleString/user-provided-tolocalestring-grow.js {unsupported: [resizable-arraybuffer]} + prototype/toLocaleString/user-provided-tolocalestring-shrink.js {unsupported: [resizable-arraybuffer]} prototype/toReversed/metadata 3/3 (100.0%) prototype/toReversed/length-property-ignored.js prototype/toReversed/not-a-constructor.js {unsupported: [Reflect.construct]} @@ -2896,6 +2953,9 @@ built-ins/TypedArray 1055/1386 (76.12%) prototype/values/name.js prototype/values/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/values/prop-desc.js + prototype/values/resizable-buffer.js {unsupported: [resizable-arraybuffer]} + prototype/values/resizable-buffer-grow-mid-iteration.js {unsupported: [resizable-arraybuffer]} + prototype/values/resizable-buffer-shrink-mid-iteration.js {unsupported: [resizable-arraybuffer]} prototype/values/return-abrupt-from-this-out-of-bounds.js {unsupported: [resizable-arraybuffer]} prototype/values/this-is-not-object.js prototype/values/this-is-not-typedarray-instance.js @@ -2904,13 +2964,18 @@ built-ins/TypedArray 1055/1386 (76.12%) prototype/with/index-validated-against-current-length.js {unsupported: [resizable-arraybuffer]} prototype/with/length-property-ignored.js prototype/with/not-a-constructor.js {unsupported: [Reflect.construct]} - prototype 3/3 (100.0%) + prototype 4/4 (100.0%) Symbol.species 4/4 (100.0%) invoked.js name.js + out-of-bounds-behaves-like-detached.js {unsupported: [resizable-arraybuffer]} + out-of-bounds-get-and-set.js {unsupported: [resizable-arraybuffer]} + out-of-bounds-has.js {unsupported: [resizable-arraybuffer]} prototype.js + resizable-buffer-length-tracking-1.js {unsupported: [resizable-arraybuffer]} + resizable-buffer-length-tracking-2.js {unsupported: [resizable-arraybuffer]} -built-ins/TypedArrayConstructors 583/721 (80.86%) +built-ins/TypedArrayConstructors 597/735 (81.22%) BigInt64Array/prototype 4/4 (100.0%) BigInt64Array 8/8 (100.0%) BigUint64Array/prototype 4/4 (100.0%) @@ -2947,6 +3012,7 @@ built-ins/TypedArrayConstructors 583/721 (80.86%) ctors/buffer-arg/new-instance-extensibility-sab.js {unsupported: [SharedArrayBuffer]} ctors/buffer-arg/proto-from-ctor-realm.js {unsupported: [Reflect]} ctors/buffer-arg/proto-from-ctor-realm-sab.js {unsupported: [SharedArrayBuffer, Reflect]} + ctors/buffer-arg/resizable-out-of-bounds.js {unsupported: [resizable-arraybuffer]} ctors/buffer-arg/returns-new-instance-sab.js {unsupported: [SharedArrayBuffer]} ctors/buffer-arg/toindex-bytelength-sab.js {unsupported: [SharedArrayBuffer]} ctors/buffer-arg/toindex-byteoffset-sab.js {unsupported: [SharedArrayBuffer]} @@ -2991,6 +3057,7 @@ built-ins/TypedArrayConstructors 583/721 (80.86%) ctors/typedarray-arg/custom-proto-access-throws.js {unsupported: [Reflect]} ctors/typedarray-arg/proto-from-ctor-realm.js {unsupported: [Reflect]} ctors/typedarray-arg/src-typedarray-big-throws.js + ctors/typedarray-arg/src-typedarray-resizable-buffer.js {unsupported: [resizable-arraybuffer]} ctors/typedarray-arg/use-custom-proto-if-object.js {unsupported: [Reflect]} ctors/typedarray-arg/use-default-proto-if-custom-proto-is-not-object.js ctors/no-species.js @@ -3106,18 +3173,26 @@ built-ins/TypedArrayConstructors 583/721 (80.86%) internals/HasProperty 17/17 (100.0%) internals/OwnPropertyKeys/BigInt 4/4 (100.0%) internals/OwnPropertyKeys 6/6 (100.0%) - internals/Set/BigInt 23/23 (100.0%) + internals/Set/BigInt 27/27 (100.0%) internals/Set/detached-buffer.js internals/Set/detached-buffer-key-is-not-numeric-index.js {unsupported: [Reflect]} internals/Set/detached-buffer-key-is-symbol.js {unsupported: [Reflect]} internals/Set/detached-buffer-realm.js internals/Set/indexed-value.js {unsupported: [Reflect]} + internals/Set/key-is-canonical-invalid-index-prototype-chain-set.js {unsupported: [Proxy]} + internals/Set/key-is-canonical-invalid-index-reflect-set.js {unsupported: [Reflect]} + internals/Set/key-is-in-bounds-receiver-is-not-typed-array.js {unsupported: [Reflect.set]} internals/Set/key-is-minus-zero.js {unsupported: [Reflect]} internals/Set/key-is-not-canonical-index.js {unsupported: [Reflect]} internals/Set/key-is-not-integer.js {unsupported: [Reflect]} internals/Set/key-is-not-numeric-index.js {unsupported: [Reflect]} internals/Set/key-is-out-of-bounds.js {unsupported: [Reflect]} + internals/Set/key-is-out-of-bounds-receiver-is-not-object.js {unsupported: [Reflect.set]} + internals/Set/key-is-out-of-bounds-receiver-is-not-typed-array.js {unsupported: [Reflect.set]} + internals/Set/key-is-out-of-bounds-receiver-is-proto.js {unsupported: [Reflect.set]} internals/Set/key-is-symbol.js {unsupported: [Reflect]} + internals/Set/key-is-valid-index-prototype-chain-set.js {unsupported: [Proxy]} + internals/Set/key-is-valid-index-reflect-set.js {unsupported: [Reflect]} internals/Set/resized-out-of-bounds-to-in-bounds-index.js {unsupported: [resizable-arraybuffer]} internals/Set/tonumber-value-detached-buffer.js {unsupported: [Reflect]} internals/Set/tonumber-value-throws.js @@ -3539,20 +3614,20 @@ language/comments 9/52 (17.31%) multi-line-asi-line-separator.js multi-line-asi-paragraph-separator.js -language/computed-property-names 35/48 (72.92%) +language/computed-property-names 37/48 (77.08%) class/accessor 4/4 (100.0%) class/method 11/11 (100.0%) class/static 14/14 (100.0%) + object/accessor/getter.js object/accessor/getter-super.js + object/accessor/setter.js object/accessor/setter-super.js object/method/generator.js object/method/super.js to-name-side-effects/class.js to-name-side-effects/numbers-class.js -language/destructuring 11/17 (64.71%) - binding/syntax/array-elements-with-initializer.js - binding/syntax/array-elements-with-object-patterns.js +language/destructuring 8/18 (44.44%) binding/syntax/array-rest-elements.js binding/syntax/destructuring-array-parameters-function-arguments-length.js binding/syntax/destructuring-object-parameters-function-arguments-length.js @@ -3560,6 +3635,7 @@ language/destructuring 11/17 (64.71%) binding/syntax/recursive-array-and-object-patterns.js binding/initialization-requires-object-coercible-null.js binding/initialization-requires-object-coercible-undefined.js + binding/typedarray-backed-by-resizable-buffer.js {unsupported: [resizable-arraybuffer]} language/directive-prologue 18/62 (29.03%) 14.1-1-s.js {non-strict: [-1]} @@ -6768,7 +6844,7 @@ language/statements/for 244/385 (63.38%) ~language/statements/for-await-of -language/statements/for-in 39/114 (34.21%) +language/statements/for-in 40/115 (34.78%) dstr/obj-rest-not-last-element-invalid.js {unsupported: [object-rest]} 12.6.4-2.js cptn-decl-abrupt-empty.js @@ -6801,6 +6877,7 @@ language/statements/for-in 39/114 (34.21%) let-block-with-newline.js non-strict let-identifier-with-newline.js non-strict order-enumerable-shadowed.js + resizable-buffer.js {unsupported: [resizable-arraybuffer]} scope-body-lex-boundary.js scope-body-lex-close.js scope-body-lex-open.js @@ -6809,8 +6886,7 @@ language/statements/for-in 39/114 (34.21%) scope-head-lex-open.js scope-head-var-none.js non-strict -language/statements/for-of 477/736 (64.81%) - dstr/array-elem-init-assignment.js +language/statements/for-of 453/741 (61.13%) dstr/array-elem-init-evaluation.js dstr/array-elem-init-fn-name-arrow.js dstr/array-elem-init-fn-name-class.js {unsupported: [class]} @@ -7259,6 +7335,11 @@ language/statements/for-of 477/736 (64.81%) scope-head-lex-close.js scope-head-lex-open.js scope-head-var-none.js non-strict + typedarray-backed-by-resizable-buffer.js {unsupported: [resizable-arraybuffer]} + typedarray-backed-by-resizable-buffer-grow-before-end.js {unsupported: [resizable-arraybuffer]} + typedarray-backed-by-resizable-buffer-grow-mid-iteration.js {unsupported: [resizable-arraybuffer]} + typedarray-backed-by-resizable-buffer-shrink-mid-iteration.js {unsupported: [resizable-arraybuffer]} + typedarray-backed-by-resizable-buffer-shrink-to-zero-mid-iteration.js {unsupported: [resizable-arraybuffer]} language/statements/function 183/451 (40.58%) dstr/ary-init-iter-close.js @@ -8062,7 +8143,7 @@ language/statements/while 13/38 (34.21%) let-identifier-with-newline.js non-strict tco-body.js {unsupported: [tail-call-optimization]} -language/statements/with 20/169 (11.83%) +language/statements/with 26/175 (14.86%) 12.10.1-8-s.js non-strict binding-blocked-by-unscopables.js non-strict cptn-abrupt-empty.js non-strict @@ -8073,10 +8154,16 @@ language/statements/with 20/169 (11.83%) decl-fun.js non-strict decl-gen.js non-strict decl-let.js non-strict + get-mutable-binding-binding-deleted-in-get-unscopables.js non-strict + get-mutable-binding-binding-deleted-in-get-unscopables-strict-mode.js non-strict has-property-err.js {unsupported: [Proxy]} labelled-fn-stmt.js non-strict let-array-with-newline.js non-strict let-block-with-newline.js non-strict + set-mutable-binding-binding-deleted-in-get-unscopables.js non-strict + set-mutable-binding-binding-deleted-in-get-unscopables-strict-mode.js non-strict + set-mutable-binding-binding-deleted-with-typed-array-in-proto-chain.js non-strict + set-mutable-binding-binding-deleted-with-typed-array-in-proto-chain-strict-mode.js non-strict strict-fn-decl-nested-1.js non-strict strict-fn-expr.js strict strict-fn-method.js strict