From 272d4322b8bfba188d9b2e61b521a811051a4a03 Mon Sep 17 00:00:00 2001 From: Satish Srinivasan Date: Fri, 6 Sep 2024 07:19:18 +0530 Subject: [PATCH] FIX: Arrow functions --- .../java/org/mozilla/javascript/Node.java | 5 ++- .../mozilla/javascript/NodeTransformer.java | 11 +++++ .../java/org/mozilla/javascript/Parser.java | 22 ++++++---- .../java/org/mozilla/javascript/Token.java | 2 + .../tests/DefaultParametersTest.java | 28 ++++++------- tests/testsrc/test262.properties | 41 ++++--------------- 6 files changed, 53 insertions(+), 56 deletions(-) diff --git a/rhino/src/main/java/org/mozilla/javascript/Node.java b/rhino/src/main/java/org/mozilla/javascript/Node.java index 10e962e59f..298491fa42 100644 --- a/rhino/src/main/java/org/mozilla/javascript/Node.java +++ b/rhino/src/main/java/org/mozilla/javascript/Node.java @@ -65,8 +65,9 @@ public class Node implements Iterable { ARROW_FUNCTION_PROP = 26, TEMPLATE_LITERAL_PROP = 27, TRAILING_COMMA = 28, - DESTRUCTURING_RVALUES = 29, - LAST_PROP = 29; + OBJECT_LITERAL_DESTRUCTURING = 29, + DESTRUCTURING_RVALUES = 30, + LAST_PROP = 30; // values of ISNUMBER_PROP to specify // which of the children are Number types diff --git a/rhino/src/main/java/org/mozilla/javascript/NodeTransformer.java b/rhino/src/main/java/org/mozilla/javascript/NodeTransformer.java index 46c717cb99..67a8d3a777 100644 --- a/rhino/src/main/java/org/mozilla/javascript/NodeTransformer.java +++ b/rhino/src/main/java/org/mozilla/javascript/NodeTransformer.java @@ -6,12 +6,15 @@ package org.mozilla.javascript; +import static org.mozilla.javascript.Context.reportError; + import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; import java.util.List; import org.mozilla.javascript.ast.FunctionNode; import org.mozilla.javascript.ast.Jump; +import org.mozilla.javascript.ast.Name; import org.mozilla.javascript.ast.Scope; import org.mozilla.javascript.ast.ScriptNode; @@ -343,6 +346,14 @@ private void transformCompilationUnit_r( case Token.SETNAME: if (inStrictMode) { node.setType(Token.STRICT_SETNAME); + if (node.getFirstChild().getType() == Token.BINDNAME) { + Node name = node.getFirstChild(); + if (name instanceof Name + && ((Name) name).getIdentifier().equals("eval")) { + // Don't allow set of `eval` in strict mode + reportError("syntax error"); + } + } } /* fall through */ case Token.NAME: diff --git a/rhino/src/main/java/org/mozilla/javascript/Parser.java b/rhino/src/main/java/org/mozilla/javascript/Parser.java index b72f07577d..3ed5e1c846 100644 --- a/rhino/src/main/java/org/mozilla/javascript/Parser.java +++ b/rhino/src/main/java/org/mozilla/javascript/Parser.java @@ -2448,6 +2448,9 @@ private AstNode assignExpr() throws IOException { } else if (!hasEOL && tt == Token.ARROW) { consumeToken(); pn = arrowFunction(pn); + } else if (pn.getIntProp(Node.OBJECT_LITERAL_DESTRUCTURING, 0) == 1 + && !inDestructuringAssignment) { + reportError("msg.syntax"); } return pn; } @@ -3282,8 +3285,11 @@ private AstNode parenExpr() throws IOException { int length = ts.tokenEnd - begin; + boolean hasObjectLiteralDestructuring = + e.getIntProp(Node.OBJECT_LITERAL_DESTRUCTURING, 0) == 1; boolean hasTrailingComma = e.getIntProp(Node.TRAILING_COMMA, 0) == 1; - if ((hasTrailingComma || e.getType() == Token.EMPTY) && peekToken() != Token.ARROW) { + if ((hasTrailingComma || hasObjectLiteralDestructuring || e.getType() == Token.EMPTY) + && peekToken() != Token.ARROW) { reportError("msg.syntax"); return makeErrorNode(); } @@ -3588,7 +3594,7 @@ private ObjectLiteral objectLiteral() throws IOException { setterNames = new HashSet<>(); } Comment objJsdocNode = getAndResetJsDoc(); - + boolean objectLiteralDestructuringDefault = false; commaLoop: for (; ; ) { String propertyName = null; @@ -3621,10 +3627,9 @@ private ObjectLiteral objectLiteral() throws IOException { // many tokens.) int peeked = peekToken(); if (peeked != Token.COMMA && peeked != Token.COLON && peeked != Token.RC) { - if (peeked == Token.ASSIGN - && inDestructuringAssignment) { // we have an object literal with - // destructuring assignment and a - // default + if (peeked == Token.ASSIGN) { // we have an object literal with + // destructuring assignment and a default value + objectLiteralDestructuringDefault = true; if (compilerEnv.getLanguageVersion() >= Context.VERSION_ES6) { elems.add(plainProperty(pname, tt)); if (matchToken(Token.COMMA, true)) { @@ -3705,6 +3710,9 @@ private ObjectLiteral objectLiteral() throws IOException { mustMatchToken(Token.RC, "msg.no.brace.prop", true); ObjectLiteral pn = new ObjectLiteral(pos, ts.tokenEnd - pos); + if (objectLiteralDestructuringDefault) { + pn.putIntProp(Node.OBJECT_LITERAL_DESTRUCTURING, 1); + } if (objJsdocNode != null) { pn.setJsDocNode(objJsdocNode); } @@ -3782,7 +3790,7 @@ private ObjectProperty plainProperty(AstNode property, int ptt) throws IOExcepti pn.setIsShorthand(true); pn.setLeftAndRight(property, nn); return pn; - } else if (tt == Token.ASSIGN && inDestructuringAssignment) { + } else if (tt == Token.ASSIGN) { /* we're in destructuring with defaults in a object literal; treat defaults as values */ ObjectProperty pn = new ObjectProperty(); consumeToken(); // consume the `=` diff --git a/rhino/src/main/java/org/mozilla/javascript/Token.java b/rhino/src/main/java/org/mozilla/javascript/Token.java index 9f26730ae4..f008227ebc 100644 --- a/rhino/src/main/java/org/mozilla/javascript/Token.java +++ b/rhino/src/main/java/org/mozilla/javascript/Token.java @@ -272,6 +272,8 @@ public static String typeToName(int token) { return "IFNE"; case SETNAME: return "SETNAME"; + case STRICT_SETNAME: + return "STRICT_SETNAME"; case BITOR: return "BITOR"; case BITXOR: diff --git a/tests/src/test/java/org/mozilla/javascript/tests/DefaultParametersTest.java b/tests/src/test/java/org/mozilla/javascript/tests/DefaultParametersTest.java index 15ff5d04f2..7cb1228209 100644 --- a/tests/src/test/java/org/mozilla/javascript/tests/DefaultParametersTest.java +++ b/tests/src/test/java/org/mozilla/javascript/tests/DefaultParametersTest.java @@ -36,16 +36,6 @@ public void functionDefaultArgsArrayArrow() throws Exception { assertIntEvaluates(6, script + "([,4])"); } - @Test - @Ignore("wip") // TODO TODO TODO!! - public void functionDefaultArgsObjectArrow() throws Exception { - final String script = "(({x = 1} = {x: 2}) => {\n return x;\n})"; - - assertIntEvaluates(1, script + "({})"); // TODO(satish): parsing errors with arrow fns - assertIntEvaluates(2, script + "()"); // TODO(satish): returns 1 - assertIntEvaluates(3, script + "({x: 3})"); - } - @Test public void functionDefaultArgsMulti() throws Exception { final String script = "function foo(a = 2, b = 23) { return a + b; }"; @@ -65,20 +55,30 @@ public void functionDefaultArgsUsage() throws Exception { @Test public void ObjIdInitSimpleStrictExpr() throws Exception { - final String script = "(0, { eval = 0 } = {});"; - assertThrows("missing ( before function parameters.", script); + final String script = + "(function () { \n " + "'use strict'; \n " + "(0, { eval = 0 } = {}) })()"; + assertThrows("syntax error", script); } @Test public void ObjIdInitSimpleStrictForOf() throws Exception { final String script = "for ({ eval = 0 } of [{}]) ;"; - assertThrows("missing ( before function parameters.", script); + assertThrows("syntax error", script); } @Test public void CoverInitName() throws Exception { final String script = "({ a = 1 });"; - assertThrows("missing ( before function parameters.", script); + assertThrows("syntax error", script); + } + + @Test + public void functionDefaultArgsObjectArrow() throws Exception { + final String script = "(({x = 1} = {x: 2}) => {\n return x;\n})"; + + assertIntEvaluates(1, script + "({})"); + assertIntEvaluates(2, script + "()"); + assertIntEvaluates(3, script + "({x: 3})"); } @Test diff --git a/tests/testsrc/test262.properties b/tests/testsrc/test262.properties index f36e8b2ee4..41f26a8978 100644 --- a/tests/testsrc/test262.properties +++ b/tests/testsrc/test262.properties @@ -3903,7 +3903,7 @@ language/expressions/array 41/52 (78.85%) spread-sngl-literal.js spread-sngl-obj-ident.js -language/expressions/arrow-function 168/343 (48.98%) +language/expressions/arrow-function 167/343 (48.69%) dstr/ary-init-iter-close.js dstr/ary-init-iter-get-err.js dstr/ary-init-iter-get-err-array-prototype.js @@ -3992,7 +3992,6 @@ language/expressions/arrow-function 168/343 (48.98%) dstr/dflt-obj-ptrn-id-init-fn-name-gen.js dstr/dflt-obj-ptrn-id-init-skipped.js dstr/dflt-obj-ptrn-id-init-throws.js - dstr/dflt-obj-ptrn-id-init-unresolvable.js dstr/dflt-obj-ptrn-list-err.js dstr/dflt-obj-ptrn-prop-ary.js dstr/dflt-obj-ptrn-prop-ary-init.js @@ -4072,7 +4071,7 @@ language/expressions/arrow-function 168/343 (48.98%) unscopables-with.js non-strict unscopables-with-in-nested-fn.js non-strict -language/expressions/assignment 199/480 (41.46%) +language/expressions/assignment 193/480 (40.21%) destructuring 3/3 (100.0%) dstr/array-elem-init-evaluation.js dstr/array-elem-init-fn-name-arrow.js @@ -4192,10 +4191,6 @@ language/expressions/assignment 199/480 (41.46%) dstr/obj-empty-null.js dstr/obj-empty-undef.js dstr/obj-id-identifier-yield-ident-valid.js non-strict - dstr/obj-id-init-assignment-missing.js - dstr/obj-id-init-assignment-null.js - dstr/obj-id-init-assignment-truthy.js - dstr/obj-id-init-assignment-undef.js dstr/obj-id-init-evaluation.js dstr/obj-id-init-fn-name-arrow.js dstr/obj-id-init-fn-name-class.js {unsupported: [class]} @@ -4206,11 +4201,9 @@ language/expressions/assignment 199/480 (41.46%) dstr/obj-id-init-let.js dstr/obj-id-init-order.js dstr/obj-id-init-simple-no-strict.js non-strict - dstr/obj-id-init-yield-expr.js dstr/obj-id-init-yield-ident-valid.js non-strict dstr/obj-id-put-const.js non-strict dstr/obj-id-put-let.js - dstr/obj-id-simple-strict.js strict dstr/obj-prop-elem-init-evaluation.js dstr/obj-prop-elem-init-fn-name-arrow.js dstr/obj-prop-elem-init-fn-name-class.js {unsupported: [class]} @@ -4410,7 +4403,7 @@ language/expressions/call 60/92 (65.22%) language/expressions/comma 1/6 (16.67%) tco-final.js {unsupported: [tail-call-optimization]} -language/expressions/compound-assignment 137/454 (30.18%) +language/expressions/compound-assignment 125/454 (27.53%) 11.13.2-34-s.js strict 11.13.2-35-s.js strict 11.13.2-36-s.js strict @@ -4422,11 +4415,8 @@ language/expressions/compound-assignment 137/454 (30.18%) 11.13.2-42-s.js strict 11.13.2-43-s.js strict 11.13.2-44-s.js strict - 11.13.2-6-1gs.js strict add-arguments-strict.js strict - add-eval-strict.js strict and-arguments-strict.js strict - and-eval-strict.js strict compound-assignment-operator-calls-putvalue-lref--v-.js non-strict compound-assignment-operator-calls-putvalue-lref--v--1.js non-strict compound-assignment-operator-calls-putvalue-lref--v--10.js non-strict @@ -4450,7 +4440,6 @@ language/expressions/compound-assignment 137/454 (30.18%) compound-assignment-operator-calls-putvalue-lref--v--8.js non-strict compound-assignment-operator-calls-putvalue-lref--v--9.js non-strict div-arguments-strict.js strict - div-eval-strict.js strict left-hand-side-private-reference-accessor-property-add.js {unsupported: [class-fields-private]} left-hand-side-private-reference-accessor-property-bitand.js {unsupported: [class-fields-private]} left-hand-side-private-reference-accessor-property-bitor.js {unsupported: [class-fields-private]} @@ -4500,13 +4489,9 @@ language/expressions/compound-assignment 137/454 (30.18%) left-hand-side-private-reference-readonly-accessor-property-srshift.js {unsupported: [class-fields-private]} left-hand-side-private-reference-readonly-accessor-property-sub.js {unsupported: [class-fields-private]} lshift-arguments-strict.js strict - lshift-eval-strict.js strict mod-arguments-strict.js strict - mod-eval-strict.js strict mult-arguments-strict.js strict - mult-eval-strict.js strict or-arguments-strict.js strict - or-eval-strict.js strict S11.13.2_A7.10_T1.js S11.13.2_A7.10_T2.js S11.13.2_A7.10_T4.js @@ -4541,13 +4526,9 @@ language/expressions/compound-assignment 137/454 (30.18%) S11.13.2_A7.9_T2.js S11.13.2_A7.9_T4.js srshift-arguments-strict.js strict - srshift-eval-strict.js strict sub-arguments-strict.js strict - sub-eval-strict.js strict urshift-arguments-strict.js strict - urshift-eval-strict.js strict xor-arguments-strict.js strict - xor-eval-strict.js strict language/expressions/concatenation 0/5 (0.0%) @@ -4585,7 +4566,7 @@ language/expressions/exponentiation 3/44 (6.82%) bigint-wrapped-values.js order-of-evaluation.js -language/expressions/function 169/264 (64.02%) +language/expressions/function 168/264 (63.64%) dstr/ary-init-iter-close.js dstr/ary-init-iter-get-err.js dstr/ary-init-iter-get-err-array-prototype.js @@ -4726,7 +4707,6 @@ language/expressions/function 169/264 (64.02%) eval-var-scope-syntax-err.js non-strict length-dflt.js name-arguments-strict-body.js non-strict - name-eval-strict-body.js non-strict named-no-strict-reassign-fn-name-in-body.js non-strict named-no-strict-reassign-fn-name-in-body-in-arrow.js non-strict named-no-strict-reassign-fn-name-in-body-in-eval.js non-strict @@ -5006,7 +4986,7 @@ language/expressions/less-than-or-equal 2/47 (4.26%) language/expressions/logical-and 1/18 (5.56%) tco-right.js {unsupported: [tail-call-optimization]} -language/expressions/logical-assignment 55/78 (70.51%) +language/expressions/logical-assignment 53/78 (67.95%) left-hand-side-private-reference-accessor-property-and.js {unsupported: [class-fields-private]} left-hand-side-private-reference-accessor-property-nullish.js {unsupported: [class-fields-private]} left-hand-side-private-reference-accessor-property-or.js {unsupported: [class-fields-private]} @@ -5037,7 +5017,6 @@ language/expressions/logical-assignment 55/78 (70.51%) lgcl-and-assignment-operator-non-extensible.js strict lgcl-and-assignment-operator-non-simple-lhs.js lgcl-and-assignment-operator-non-writeable.js strict - lgcl-and-eval-strict.js strict lgcl-nullish-assignment-operator.js lgcl-nullish-assignment-operator-bigint.js lgcl-nullish-assignment-operator-lhs-before-rhs.js @@ -5061,7 +5040,6 @@ language/expressions/logical-assignment 55/78 (70.51%) lgcl-or-assignment-operator-no-set-put.js strict lgcl-or-assignment-operator-non-simple-lhs.js lgcl-or-assignment-operator-non-writeable.js strict - lgcl-or-eval-strict.js strict language/expressions/logical-not 0/19 (0.0%) @@ -5123,7 +5101,7 @@ language/expressions/new 41/59 (69.49%) ~language/expressions/new.target -language/expressions/object 812/1169 (69.46%) +language/expressions/object 810/1169 (69.29%) dstr/async-gen-meth-ary-init-iter-close.js {unsupported: [async-iteration, async]} dstr/async-gen-meth-ary-init-iter-get-err.js {unsupported: [async-iteration]} dstr/async-gen-meth-ary-init-iter-get-err-array-prototype.js {unsupported: [async-iteration]} @@ -6817,7 +6795,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 449/736 (61.01%) +language/statements/for-of 448/736 (60.87%) dstr/array-elem-init-evaluation.js dstr/array-elem-init-fn-name-arrow.js dstr/array-elem-init-fn-name-class.js {unsupported: [class]} @@ -7105,7 +7083,6 @@ language/statements/for-of 449/736 (61.01%) dstr/obj-id-init-yield-ident-valid.js non-strict dstr/obj-id-put-const.js non-strict dstr/obj-id-put-let.js - dstr/obj-id-simple-strict.js strict dstr/obj-prop-elem-init-evaluation.js dstr/obj-prop-elem-init-fn-name-arrow.js dstr/obj-prop-elem-init-fn-name-class.js {unsupported: [class]} @@ -7268,7 +7245,7 @@ language/statements/for-of 449/736 (61.01%) scope-head-lex-open.js scope-head-var-none.js non-strict -language/statements/function 185/451 (41.02%) +language/statements/function 183/451 (40.58%) dstr/ary-init-iter-close.js dstr/ary-init-iter-get-err.js dstr/ary-init-iter-get-err-array-prototype.js @@ -7428,8 +7405,6 @@ language/statements/function 185/451 (41.02%) dflt-params-ref-self.js dflt-params-rest.js dflt-params-trailing-comma.js - enable-strict-via-body.js non-strict - enable-strict-via-outer-body.js non-strict eval-var-scope-syntax-err.js non-strict length-dflt.js name-arguments-strict-body.js non-strict