From 9b7bcd083f6498b17bbb275f693edc2557754e10 Mon Sep 17 00:00:00 2001 From: tuchida Date: Thu, 11 Feb 2021 22:30:42 +0900 Subject: [PATCH 1/8] Parse Exponentiation Operator --- src/org/mozilla/javascript/IRFactory.java | 1 + src/org/mozilla/javascript/Parser.java | 21 ++- src/org/mozilla/javascript/Token.java | 192 ++++++++++---------- src/org/mozilla/javascript/TokenStream.java | 8 + 4 files changed, 126 insertions(+), 96 deletions(-) diff --git a/src/org/mozilla/javascript/IRFactory.java b/src/org/mozilla/javascript/IRFactory.java index 1dd6d855bd..61256cf71a 100644 --- a/src/org/mozilla/javascript/IRFactory.java +++ b/src/org/mozilla/javascript/IRFactory.java @@ -2253,6 +2253,7 @@ private Node createAssignment(int assignType, Node left, Node right) case Token.ASSIGN_MUL: assignOp = Token.MUL; break; case Token.ASSIGN_DIV: assignOp = Token.DIV; break; case Token.ASSIGN_MOD: assignOp = Token.MOD; break; + case Token.ASSIGN_EXP: assignOp = Token.EXP; break; default: throw Kit.codeBug(); } diff --git a/src/org/mozilla/javascript/Parser.java b/src/org/mozilla/javascript/Parser.java index 70a47d9807..c5750002dc 100644 --- a/src/org/mozilla/javascript/Parser.java +++ b/src/org/mozilla/javascript/Parser.java @@ -2579,7 +2579,7 @@ private AstNode addExpr() private AstNode mulExpr() throws IOException { - AstNode pn = unaryExpr(); + AstNode pn = expExpr(); for (;;) { int tt = peekToken(), opPos = ts.tokenBeg; switch (tt) { @@ -2587,7 +2587,24 @@ private AstNode mulExpr() case Token.DIV: case Token.MOD: consumeToken(); - pn = new InfixExpression(tt, pn, unaryExpr(), opPos); + pn = new InfixExpression(tt, pn, expExpr(), opPos); + continue; + } + break; + } + return pn; + } + + private AstNode expExpr() + throws IOException + { + AstNode pn = unaryExpr(); + for (;;) { + int tt = peekToken(), opPos = ts.tokenBeg; + switch (tt) { + case Token.EXP: + consumeToken(); + pn = new InfixExpression(tt, pn, expExpr(), opPos); continue; } break; diff --git a/src/org/mozilla/javascript/Token.java b/src/org/mozilla/javascript/Token.java index b66bdfbd8c..22608bda4d 100644 --- a/src/org/mozilla/javascript/Token.java +++ b/src/org/mozilla/javascript/Token.java @@ -116,123 +116,125 @@ public static enum CommentType { REF_SPECIAL = 72, // reference for special properties like __proto YIELD = 73, // JS 1.7 yield pseudo keyword STRICT_SETNAME = 74, + EXP = 75, // Exponentiation Operator // For XML support: - DEFAULTNAMESPACE = 75, // default xml namespace = - ESCXMLATTR = 76, - ESCXMLTEXT = 77, - REF_MEMBER = 78, // Reference for x.@y, x..y etc. - REF_NS_MEMBER = 79, // Reference for x.ns::y, x..ns::y etc. - REF_NAME = 80, // Reference for @y, @[y] etc. - REF_NS_NAME = 81; // Reference for ns::y, @ns::y@[y] etc. + DEFAULTNAMESPACE = 76, // default xml namespace = + ESCXMLATTR = 77, + ESCXMLTEXT = 78, + REF_MEMBER = 79, // Reference for x.@y, x..y etc. + REF_NS_MEMBER = 80, // Reference for x.ns::y, x..ns::y etc. + REF_NAME = 81, // Reference for @y, @[y] etc. + REF_NS_NAME = 82; // Reference for ns::y, @ns::y@[y] etc. // End of interpreter bytecodes public final static int LAST_BYTECODE_TOKEN = REF_NS_NAME, - TRY = 82, - SEMI = 83, // semicolon - LB = 84, // left and right brackets - RB = 85, - LC = 86, // left and right curlies (braces) - RC = 87, - LP = 88, // left and right parentheses - RP = 89, - COMMA = 90, // comma operator + TRY = 83, + SEMI = 84, // semicolon + LB = 85, // left and right brackets + RB = 86, + LC = 87, // left and right curlies (braces) + RC = 88, + LP = 89, // left and right parentheses + RP = 90, + COMMA = 91, // comma operator - ASSIGN = 91, // simple assignment (=) - ASSIGN_BITOR = 92, // |= - ASSIGN_BITXOR = 93, // ^= - ASSIGN_BITAND = 94, // |= - ASSIGN_LSH = 95, // <<= - ASSIGN_RSH = 96, // >>= - ASSIGN_URSH = 97, // >>>= - ASSIGN_ADD = 98, // += - ASSIGN_SUB = 99, // -= - ASSIGN_MUL = 100, // *= - ASSIGN_DIV = 101, // /= - ASSIGN_MOD = 102; // %= + ASSIGN = 92, // simple assignment (=) + ASSIGN_BITOR = 93, // |= + ASSIGN_BITXOR = 94, // ^= + ASSIGN_BITAND = 95, // |= + ASSIGN_LSH = 96, // <<= + ASSIGN_RSH = 97, // >>= + ASSIGN_URSH = 98, // >>>= + ASSIGN_ADD = 99, // += + ASSIGN_SUB = 100, // -= + ASSIGN_MUL = 101, // *= + ASSIGN_DIV = 102, // /= + ASSIGN_MOD = 103, // %= + ASSIGN_EXP = 104; // **= public final static int FIRST_ASSIGN = ASSIGN, - LAST_ASSIGN = ASSIGN_MOD, + LAST_ASSIGN = ASSIGN_EXP, - HOOK = 103, // conditional (?:) - COLON = 104, - OR = 105, // logical or (||) - AND = 106, // logical and (&&) - INC = 107, // increment/decrement (++ --) - DEC = 108, - DOT = 109, // member operator (.) - FUNCTION = 110, // function keyword - EXPORT = 111, // export keyword - IMPORT = 112, // import keyword - IF = 113, // if keyword - ELSE = 114, // else keyword - SWITCH = 115, // switch keyword - CASE = 116, // case keyword - DEFAULT = 117, // default keyword - WHILE = 118, // while keyword - DO = 119, // do keyword - FOR = 120, // for keyword - BREAK = 121, // break keyword - CONTINUE = 122, // continue keyword - VAR = 123, // var keyword - WITH = 124, // with keyword - CATCH = 125, // catch keyword - FINALLY = 126, // finally keyword - VOID = 127, // void keyword - RESERVED = 128, // reserved keywords + HOOK = 105, // conditional (?:) + COLON = 106, + OR = 107, // logical or (||) + AND = 108, // logical and (&&) + INC = 109, // increment/decrement (++ --) + DEC = 110, + DOT = 111, // member operator (.) + FUNCTION = 112, // function keyword + EXPORT = 113, // export keyword + IMPORT = 114, // import keyword + IF = 115, // if keyword + ELSE = 116, // else keyword + SWITCH = 117, // switch keyword + CASE = 118, // case keyword + DEFAULT = 119, // default keyword + WHILE = 120, // while keyword + DO = 121, // do keyword + FOR = 122, // for keyword + BREAK = 123, // break keyword + CONTINUE = 124, // continue keyword + VAR = 125, // var keyword + WITH = 126, // with keyword + CATCH = 127, // catch keyword + FINALLY = 128, // finally keyword + VOID = 129, // void keyword + RESERVED = 130, // reserved keywords - EMPTY = 129, + EMPTY = 131, /* types used for the parse tree - these never get returned * by the scanner. */ - BLOCK = 130, // statement block - LABEL = 131, // label - TARGET = 132, - LOOP = 133, - EXPR_VOID = 134, // expression statement in functions - EXPR_RESULT = 135, // expression statement in scripts - JSR = 136, - SCRIPT = 137, // top-level node for entire script - TYPEOFNAME = 138, // for typeof(simple-name) - USE_STACK = 139, - SETPROP_OP = 140, // x.y op= something - SETELEM_OP = 141, // x[y] op= something - LOCAL_BLOCK = 142, - SET_REF_OP = 143, // *reference op= something + BLOCK = 132, // statement block + LABEL = 133, // label + TARGET = 134, + LOOP = 135, + EXPR_VOID = 136, // expression statement in functions + EXPR_RESULT = 137, // expression statement in scripts + JSR = 138, + SCRIPT = 139, // top-level node for entire script + TYPEOFNAME = 140, // for typeof(simple-name) + USE_STACK = 141, + SETPROP_OP = 142, // x.y op= something + SETELEM_OP = 143, // x[y] op= something + LOCAL_BLOCK = 144, + SET_REF_OP = 145, // *reference op= something // For XML support: - DOTDOT = 144, // member operator (..) - COLONCOLON = 145, // namespace::name - XML = 146, // XML type - DOTQUERY = 147, // .() -- e.g., x.emps.emp.(name == "terry") - XMLATTR = 148, // @ - XMLEND = 149, + DOTDOT = 146, // member operator (..) + COLONCOLON = 147, // namespace::name + XML = 148, // XML type + DOTQUERY = 149, // .() -- e.g., x.emps.emp.(name == "terry") + XMLATTR = 150, // @ + XMLEND = 151, // Optimizer-only-tokens - TO_OBJECT = 150, - TO_DOUBLE = 151, + TO_OBJECT = 152, + TO_DOUBLE = 153, - GET = 152, // JS 1.5 get pseudo keyword - SET = 153, // JS 1.5 set pseudo keyword - LET = 154, // JS 1.7 let pseudo keyword - CONST = 155, - SETCONST = 156, - SETCONSTVAR = 157, - ARRAYCOMP = 158, // array comprehension - LETEXPR = 159, - WITHEXPR = 160, - DEBUGGER = 161, - COMMENT = 162, - GENEXPR = 163, - METHOD = 164, // ES6 MethodDefinition - ARROW = 165, // ES6 ArrowFunction - YIELD_STAR = 166, // ES6 "yield *", a specialization of yield - LAST_TOKEN = 167; + GET = 154, // JS 1.5 get pseudo keyword + SET = 155, // JS 1.5 set pseudo keyword + LET = 156, // JS 1.7 let pseudo keyword + CONST = 157, + SETCONST = 158, + SETCONSTVAR = 159, + ARRAYCOMP = 160, // array comprehension + LETEXPR = 161, + WITHEXPR = 162, + DEBUGGER = 163, + COMMENT = 164, + GENEXPR = 165, + METHOD = 166, // ES6 MethodDefinition + ARROW = 167, // ES6 ArrowFunction + YIELD_STAR = 168, // ES6 "yield *", a specialization of yield + LAST_TOKEN = 169; /** @@ -358,6 +360,7 @@ public static String typeToName(int token) { case ASSIGN_MUL: return "ASSIGN_MUL"; case ASSIGN_DIV: return "ASSIGN_DIV"; case ASSIGN_MOD: return "ASSIGN_MOD"; + case ASSIGN_EXP: return "ASSIGN_EXP"; case HOOK: return "HOOK"; case COLON: return "COLON"; case OR: return "OR"; @@ -411,6 +414,7 @@ public static String typeToName(int token) { case SET: return "SET"; case LET: return "LET"; case YIELD: return "YIELD"; + case EXP: return "EXP"; case CONST: return "CONST"; case SETCONST: return "SETCONST"; case ARRAYCOMP: return "ARRAYCOMP"; diff --git a/src/org/mozilla/javascript/TokenStream.java b/src/org/mozilla/javascript/TokenStream.java index adba7488f8..fc77e49e6e 100644 --- a/src/org/mozilla/javascript/TokenStream.java +++ b/src/org/mozilla/javascript/TokenStream.java @@ -928,6 +928,14 @@ final int getToken() throws IOException return Token.GT; case '*': + if (parser.compilerEnv.getLanguageVersion() >= Context.VERSION_ES6) { + if (matchChar('*')) { + if (matchChar('=')) { + return Token.ASSIGN_EXP; + } + return Token.EXP; + } + } if (matchChar('=')) { return Token.ASSIGN_MUL; } From 2438628a2114ce5844dda307a45baed0372d6b45 Mon Sep 17 00:00:00 2001 From: tuchida Date: Thu, 11 Feb 2021 22:38:54 +0900 Subject: [PATCH 2/8] Exponentiation Operator for Interpreter --- src/org/mozilla/javascript/CodeGenerator.java | 1 + src/org/mozilla/javascript/Interpreter.java | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/org/mozilla/javascript/CodeGenerator.java b/src/org/mozilla/javascript/CodeGenerator.java index 98391f2701..589386584d 100644 --- a/src/org/mozilla/javascript/CodeGenerator.java +++ b/src/org/mozilla/javascript/CodeGenerator.java @@ -694,6 +694,7 @@ private void visitExpression(Node node, int contextFlags) case Token.MOD: case Token.DIV: case Token.MUL: + case Token.EXP: case Token.EQ: case Token.NE: case Token.SHEQ: diff --git a/src/org/mozilla/javascript/Interpreter.java b/src/org/mozilla/javascript/Interpreter.java index 9c2a8d4dc3..0b02ddfb9a 100644 --- a/src/org/mozilla/javascript/Interpreter.java +++ b/src/org/mozilla/javascript/Interpreter.java @@ -1405,7 +1405,8 @@ private static Object interpretLoop(Context cx, CallFrame frame, case Token.SUB : case Token.MUL : case Token.DIV : - case Token.MOD : { + case Token.MOD : + case Token.EXP : { stackTop = doArithmetic(frame, op, stack, sDbl, stackTop); continue Loop; } @@ -3223,9 +3224,9 @@ private static void doAdd(Object[] stack, double[] sDbl, int stackTop, private static int doArithmetic(CallFrame frame, int op, Object[] stack, double[] sDbl, int stackTop) { + double lDbl = stack_double(frame, stackTop - 1); double rDbl = stack_double(frame, stackTop); --stackTop; - double lDbl = stack_double(frame, stackTop); stack[stackTop] = DOUBLE_MARK; switch (op) { case Token.SUB: @@ -3240,6 +3241,9 @@ private static int doArithmetic(CallFrame frame, int op, Object[] stack, case Token.MOD: lDbl %= rDbl; break; + case Token.EXP: + lDbl = Math.pow(lDbl, rDbl); + break; } sDbl[stackTop] = lDbl; return stackTop; From d02cff98b66bbc9347874720a6d1dbca8195ab8f Mon Sep 17 00:00:00 2001 From: tuchida Date: Thu, 11 Feb 2021 22:51:13 +0900 Subject: [PATCH 3/8] Exponentiation Operator for bytecode --- .../mozilla/javascript/optimizer/Block.java | 1 + .../javascript/optimizer/BodyCodegen.java | 26 +++++++++++++++++++ .../javascript/optimizer/Optimizer.java | 3 ++- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/org/mozilla/javascript/optimizer/Block.java b/src/org/mozilla/javascript/optimizer/Block.java index 7d674f26fc..d9c0744c81 100644 --- a/src/org/mozilla/javascript/optimizer/Block.java +++ b/src/org/mozilla/javascript/optimizer/Block.java @@ -484,6 +484,7 @@ private static int findExpressionType(OptFunctionNode fn, Node n, case Token.MUL: case Token.DIV: case Token.MOD: + case Token.EXP: case Token.BITOR: case Token.BITXOR: case Token.BITAND: diff --git a/src/org/mozilla/javascript/optimizer/BodyCodegen.java b/src/org/mozilla/javascript/optimizer/BodyCodegen.java index 07624bd319..2b8d3f3ba4 100644 --- a/src/org/mozilla/javascript/optimizer/BodyCodegen.java +++ b/src/org/mozilla/javascript/optimizer/BodyCodegen.java @@ -1258,6 +1258,10 @@ private void generateExpression(Node node, Node parent) : ByteCode.DREM, child, parent); break; + case Token.EXP: + visitExponentiation(node, child, parent); + break; + case Token.BITOR: case Token.BITXOR: case Token.BITAND: @@ -3445,6 +3449,28 @@ private void visitArithmetic(Node node, int opCode, Node child, } } + private void visitExponentiation(Node node, Node child, Node parent) + { + int childNumberFlag = node.getIntProp(Node.ISNUMBER_PROP, -1); + if (childNumberFlag != -1) { + generateExpression(child, node); + generateExpression(child.getNext(), node); + cfw.addInvoke(ByteCode.INVOKESTATIC, "java/lang/Math", "pow", "(DD)D"); + } else { + generateExpression(child, node); + generateExpression(child.getNext(), node); + + short reg = getNewWordLocal(); + cfw.addAStore(reg); + addObjectToDouble(); + cfw.addALoad(reg); + addObjectToDouble(); + + cfw.addInvoke(ByteCode.INVOKESTATIC, "java/lang/Math", "pow", "(DD)D"); + addDoubleWrap(); + } + } + private void visitBitOp(Node node, int type, Node child) { int childNumberFlag = node.getIntProp(Node.ISNUMBER_PROP, -1); diff --git a/src/org/mozilla/javascript/optimizer/Optimizer.java b/src/org/mozilla/javascript/optimizer/Optimizer.java index 25aaee4b2c..6fa79e8b21 100644 --- a/src/org/mozilla/javascript/optimizer/Optimizer.java +++ b/src/org/mozilla/javascript/optimizer/Optimizer.java @@ -295,7 +295,8 @@ else if (convertParameter(rChild)) { case Token.SUB : case Token.MUL : case Token.DIV : - case Token.MOD : { + case Token.MOD : + case Token.EXP : { Node lChild = n.getFirstChild(); Node rChild = lChild.getNext(); int lType = rewriteForNumberVariables(lChild, NumberType); From 3646c86d4f58846f6ed04f99b7d43d545e799d1b Mon Sep 17 00:00:00 2001 From: tuchida Date: Thu, 11 Feb 2021 22:56:37 +0900 Subject: [PATCH 4/8] Decompile Exponentiation Operator --- src/org/mozilla/javascript/Decompiler.java | 4 ++++ src/org/mozilla/javascript/ast/AstNode.java | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/org/mozilla/javascript/Decompiler.java b/src/org/mozilla/javascript/Decompiler.java index 0dfcbbd794..afa84c035c 100644 --- a/src/org/mozilla/javascript/Decompiler.java +++ b/src/org/mozilla/javascript/Decompiler.java @@ -778,6 +778,10 @@ else if (nextToken == Token.NAME) { result.append(" % "); break; + case Token.EXP: + result.append(" ** "); + break; + case Token.COLONCOLON: result.append("::"); break; diff --git a/src/org/mozilla/javascript/ast/AstNode.java b/src/org/mozilla/javascript/ast/AstNode.java index 4abd755e81..81944d27bc 100644 --- a/src/org/mozilla/javascript/ast/AstNode.java +++ b/src/org/mozilla/javascript/ast/AstNode.java @@ -110,6 +110,7 @@ public abstract class AstNode extends Node implements Comparable { operatorNames.put(Token.MUL, "*"); operatorNames.put(Token.DIV, "/"); operatorNames.put(Token.MOD, "%"); + operatorNames.put(Token.EXP, "**"); operatorNames.put(Token.NOT, "!"); operatorNames.put(Token.BITNOT, "~"); operatorNames.put(Token.POS, "+"); @@ -128,6 +129,7 @@ public abstract class AstNode extends Node implements Comparable { operatorNames.put(Token.ASSIGN_DIV, "/="); operatorNames.put(Token.ASSIGN_MOD, "%="); operatorNames.put(Token.ASSIGN_BITXOR, "^="); + operatorNames.put(Token.ASSIGN_EXP, "**="); operatorNames.put(Token.VOID, "void"); } From cf9192f3be762c0a2e3d79afc4a5bac213873378 Mon Sep 17 00:00:00 2001 From: tuchida Date: Sat, 13 Feb 2021 12:49:14 +0900 Subject: [PATCH 5/8] UpdateExpression --- src/org/mozilla/javascript/IRFactory.java | 17 +- src/org/mozilla/javascript/Parser.java | 17 +- .../javascript/ast/UnaryExpression.java | 63 ++------ .../javascript/ast/UpdateExpression.java | 146 ++++++++++++++++++ .../javascript/resources/Messages.properties | 3 + .../mozilla/javascript/tests/ParserTest.java | 8 +- 6 files changed, 188 insertions(+), 66 deletions(-) create mode 100644 src/org/mozilla/javascript/ast/UpdateExpression.java diff --git a/src/org/mozilla/javascript/IRFactory.java b/src/org/mozilla/javascript/IRFactory.java index 61256cf71a..0ca1dd1377 100644 --- a/src/org/mozilla/javascript/IRFactory.java +++ b/src/org/mozilla/javascript/IRFactory.java @@ -56,6 +56,7 @@ import org.mozilla.javascript.ast.ThrowStatement; import org.mozilla.javascript.ast.TryStatement; import org.mozilla.javascript.ast.UnaryExpression; +import org.mozilla.javascript.ast.UpdateExpression; import org.mozilla.javascript.ast.VariableDeclaration; import org.mozilla.javascript.ast.VariableInitializer; import org.mozilla.javascript.ast.WhileLoop; @@ -215,6 +216,9 @@ public Node transform(AstNode node) { if (node instanceof UnaryExpression) { return transformUnary((UnaryExpression)node); } + if (node instanceof UpdateExpression) { + return transformUpdate((UpdateExpression)node); + } if (node instanceof XmlMemberGet) { return transformXmlMemberGet((XmlMemberGet)node); } @@ -1185,6 +1189,14 @@ private Node transformUnary(UnaryExpression node) { if (type == Token.DEFAULTNAMESPACE) { return transformDefaultXmlNamepace(node); } + decompiler.addToken(type); + + Node child = transform(node.getOperand()); + return createUnary(type, child); + } + + private Node transformUpdate(UpdateExpression node) { + int type = node.getType(); if (node.isPrefix()) { decompiler.addToken(type); } @@ -1192,10 +1204,7 @@ private Node transformUnary(UnaryExpression node) { if (node.isPostfix()) { decompiler.addToken(type); } - if (type == Token.INC || type == Token.DEC) { - return createIncDec(type, node.isPostfix(), child); - } - return createUnary(type, child); + return createIncDec(type, node.isPostfix(), child); } private Node transformVariables(VariableDeclaration node) { diff --git a/src/org/mozilla/javascript/Parser.java b/src/org/mozilla/javascript/Parser.java index c5750002dc..bf93847148 100644 --- a/src/org/mozilla/javascript/Parser.java +++ b/src/org/mozilla/javascript/Parser.java @@ -67,6 +67,7 @@ import org.mozilla.javascript.ast.ThrowStatement; import org.mozilla.javascript.ast.TryStatement; import org.mozilla.javascript.ast.UnaryExpression; +import org.mozilla.javascript.ast.UpdateExpression; import org.mozilla.javascript.ast.VariableDeclaration; import org.mozilla.javascript.ast.VariableInitializer; import org.mozilla.javascript.ast.WhileLoop; @@ -2602,7 +2603,11 @@ private AstNode expExpr() for (;;) { int tt = peekToken(), opPos = ts.tokenBeg; switch (tt) { - case Token.EXP: + case Token.EXP: + if (pn instanceof UnaryExpression) { + reportError("msg.no.unary.expr.on.left.exp", AstNode.operatorToString(pn.getType())); + return makeErrorNode(); + } consumeToken(); pn = new InfixExpression(tt, pn, expExpr(), opPos); continue; @@ -2650,8 +2655,8 @@ private AstNode unaryExpr() case Token.INC: case Token.DEC: consumeToken(); - UnaryExpression expr = new UnaryExpression(tt, ts.tokenBeg, - memberExpr(true)); + UpdateExpression expr = new UpdateExpression(tt, ts.tokenBeg, + memberExpr(true)); expr.setLineno(line); checkBadIncDec(expr); return expr; @@ -2682,8 +2687,8 @@ private AstNode unaryExpr() return pn; } consumeToken(); - UnaryExpression uexpr = - new UnaryExpression(tt, ts.tokenBeg, pn, true); + UpdateExpression uexpr = + new UpdateExpression(tt, ts.tokenBeg, pn, true); uexpr.setLineno(line); checkBadIncDec(uexpr); return uexpr; @@ -3878,7 +3883,7 @@ protected void setIsGenerator() { } } - private void checkBadIncDec(UnaryExpression expr) { + private void checkBadIncDec(UpdateExpression expr) { AstNode op = removeParens(expr.getOperand()); int tt = op.getType(); if (!(tt == Token.NAME diff --git a/src/org/mozilla/javascript/ast/UnaryExpression.java b/src/org/mozilla/javascript/ast/UnaryExpression.java index 2cd89d3f3b..1128e296d1 100644 --- a/src/org/mozilla/javascript/ast/UnaryExpression.java +++ b/src/org/mozilla/javascript/ast/UnaryExpression.java @@ -9,11 +9,9 @@ import org.mozilla.javascript.Token; /** - * AST node representing unary operators such as {@code ++}, - * {@code ~}, {@code typeof} and {@code delete}. The type field - * is set to the appropriate Token type for the operator. The node length spans - * from the operator to the end of the operand (for prefix operators) or from - * the start of the operand to the operator (for postfix).

+ * AST node representing unary operators such as {@code typeof} and {@code delete}. + * The type field is set to the appropriate Token type for the operator. + * The node length spans from the operator to the end of the operand.

* * The {@code default xml namespace = <expr>} statement in E4X * (JavaScript 1.6) is represented as a {@code UnaryExpression} of node @@ -23,7 +21,6 @@ public class UnaryExpression extends AstNode { private AstNode operand; - private boolean isPostfix; public UnaryExpression() { } @@ -33,20 +30,12 @@ public UnaryExpression(int pos) { } /** - * Constructs a new postfix UnaryExpression + * Constructs a new UnaryExpression */ public UnaryExpression(int pos, int len) { super(pos, len); } - /** - * Constructs a new prefix UnaryExpression. - */ - public UnaryExpression(int operator, int operatorPosition, - AstNode operand) { - this(operator, operatorPosition, operand, false); - } - /** * Constructs a new UnaryExpression with the specified operator * and operand. It sets the parent of the operand, and sets its own bounds @@ -54,21 +43,16 @@ public UnaryExpression(int operator, int operatorPosition, * @param operator the node type * @param operatorPosition the absolute position of the operator. * @param operand the operand expression - * @param postFix true if the operator follows the operand. Int * @throws IllegalArgumentException} if {@code operand} is {@code null} */ - public UnaryExpression(int operator, int operatorPosition, - AstNode operand, boolean postFix) { + public UnaryExpression(int operator, int operatorPosition, AstNode operand) { assertNotNull(operand); - int beg = postFix ? operand.getPosition() : operatorPosition; + int beg = operand.getPosition(); // JavaScript only has ++ and -- postfix operators, so length is 2 - int end = postFix - ? operatorPosition + 2 - : operand.getPosition() + operand.getLength(); + int end = operand.getPosition() + operand.getLength(); setBounds(beg, end); setOperator(operator); setOperand(operand); - isPostfix = postFix; } /** @@ -104,42 +88,17 @@ public void setOperand(AstNode operand) { operand.setParent(this); } - /** - * Returns whether the operator is postfix - */ - public boolean isPostfix() { - return isPostfix; - } - - /** - * Returns whether the operator is prefix - */ - public boolean isPrefix() { - return !isPostfix; - } - - /** - * Sets whether the operator is postfix - */ - public void setIsPostfix(boolean isPostfix) { - this.isPostfix = isPostfix; - } - @Override public String toSource(int depth) { StringBuilder sb = new StringBuilder(); sb.append(makeIndent(depth)); int type = getType(); - if (!isPostfix) { - sb.append(operatorToString(type)); - if (type == Token.TYPEOF || type == Token.DELPROP || type == Token.VOID) { - sb.append(" "); - } + sb.append(operatorToString(type)); + if (type == Token.TYPEOF || type == Token.DELPROP || type == Token.VOID) { + sb.append(" "); } sb.append(operand.toSource()); - if (isPostfix) { - sb.append(operatorToString(type)); - } + return sb.toString(); } diff --git a/src/org/mozilla/javascript/ast/UpdateExpression.java b/src/org/mozilla/javascript/ast/UpdateExpression.java new file mode 100644 index 0000000000..20ca047e4e --- /dev/null +++ b/src/org/mozilla/javascript/ast/UpdateExpression.java @@ -0,0 +1,146 @@ +/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.javascript.ast; + +import org.mozilla.javascript.Token; + +/** + * AST node representing update operators such as {@code ++}. The type field + * is set to the appropriate Token type for the operator. The node length spans + * from the operator to the end of the operand (for prefix operators) or from + * the start of the operand to the operator (for postfix).

+ */ +public class UpdateExpression extends AstNode { + + private AstNode operand; + private boolean isPostfix; + + public UpdateExpression() { + } + + public UpdateExpression(int pos) { + super(pos); + } + + /** + * Constructs a new postfix UpdateExpression + */ + public UpdateExpression(int pos, int len) { + super(pos, len); + } + + /** + * Constructs a new prefix UpdateExpression. + */ + public UpdateExpression(int operator, int operatorPosition, + AstNode operand) { + this(operator, operatorPosition, operand, false); + } + + /** + * Constructs a new UpdateExpression with the specified operator + * and operand. It sets the parent of the operand, and sets its own bounds + * to encompass the operator and operand. + * @param operator the node type + * @param operatorPosition the absolute position of the operator. + * @param operand the operand expression + * @param postFix true if the operator follows the operand. Int + * @throws IllegalArgumentException} if {@code operand} is {@code null} + */ + public UpdateExpression(int operator, int operatorPosition, + AstNode operand, boolean postFix) { + assertNotNull(operand); + int beg = postFix ? operand.getPosition() : operatorPosition; + // JavaScript only has ++ and -- postfix operators, so length is 2 + int end = postFix + ? operatorPosition + 2 + : operand.getPosition() + operand.getLength(); + setBounds(beg, end); + setOperator(operator); + setOperand(operand); + isPostfix = postFix; + } + + /** + * Returns operator token – alias for {@link #getType} + */ + public int getOperator() { + return type; + } + + /** + * Sets operator – same as {@link #setType}, but throws an + * exception if the operator is invalid + * @throws IllegalArgumentException if operator is not a valid + * Token code + */ + public void setOperator(int operator) { + if (!Token.isValidToken(operator)) + throw new IllegalArgumentException("Invalid token: " + operator); + setType(operator); + } + + public AstNode getOperand() { + return operand; + } + + /** + * Sets the operand, and sets its parent to be this node. + * @throws IllegalArgumentException} if {@code operand} is {@code null} + */ + public void setOperand(AstNode operand) { + assertNotNull(operand); + this.operand = operand; + operand.setParent(this); + } + + /** + * Returns whether the operator is postfix + */ + public boolean isPostfix() { + return isPostfix; + } + + /** + * Returns whether the operator is prefix + */ + public boolean isPrefix() { + return !isPostfix; + } + + /** + * Sets whether the operator is postfix + */ + public void setIsPostfix(boolean isPostfix) { + this.isPostfix = isPostfix; + } + + @Override + public String toSource(int depth) { + StringBuilder sb = new StringBuilder(); + sb.append(makeIndent(depth)); + int type = getType(); + if (!isPostfix) { + sb.append(operatorToString(type)); + } + sb.append(operand.toSource()); + if (isPostfix) { + sb.append(operatorToString(type)); + } + return sb.toString(); + } + + /** + * Visits this node, then the operand. + */ + @Override + public void visit(NodeVisitor v) { + if (v.visit(this)) { + operand.visit(v); + } + } +} diff --git a/src/org/mozilla/javascript/resources/Messages.properties b/src/org/mozilla/javascript/resources/Messages.properties index 1ea9566073..db1e57e8d6 100644 --- a/src/org/mozilla/javascript/resources/Messages.properties +++ b/src/org/mozilla/javascript/resources/Messages.properties @@ -524,6 +524,9 @@ msg.dup.param.strict =\ msg.bad.id.strict =\ "{0}" is not a valid identifier for this use in strict mode. +msg.no.unary.expr.on.left.exp =\ + "{0}" is not allowed on the left-hand side of "**". + # ScriptRuntime # is there a better message for this? diff --git a/testsrc/org/mozilla/javascript/tests/ParserTest.java b/testsrc/org/mozilla/javascript/tests/ParserTest.java index 2a49019f77..0e0a4866fc 100644 --- a/testsrc/org/mozilla/javascript/tests/ParserTest.java +++ b/testsrc/org/mozilla/javascript/tests/ParserTest.java @@ -41,7 +41,7 @@ import org.mozilla.javascript.ast.SwitchCase; import org.mozilla.javascript.ast.SwitchStatement; import org.mozilla.javascript.ast.TryStatement; -import org.mozilla.javascript.ast.UnaryExpression; +import org.mozilla.javascript.ast.UpdateExpression; import org.mozilla.javascript.ast.VariableDeclaration; import org.mozilla.javascript.ast.VariableInitializer; import org.mozilla.javascript.ast.WithStatement; @@ -314,7 +314,7 @@ public void testLinenoSwitch() { AstNode caseArg = firstCase.getExpression(); List caseBody = firstCase.getStatements(); ExpressionStatement exprStmt = (ExpressionStatement) caseBody.get(0); - UnaryExpression incrExpr = (UnaryExpression) exprStmt.getExpression(); + UpdateExpression incrExpr = (UpdateExpression) exprStmt.getExpression(); AstNode incrVar = incrExpr.getOperand(); SwitchCase secondCase = cases.get(1); @@ -479,8 +479,8 @@ public void testLinenoPrefix() { ExpressionStatement first = (ExpressionStatement) root.getFirstChild(); ExpressionStatement secondStmt = (ExpressionStatement) first.getNext(); - UnaryExpression firstOp = (UnaryExpression) first.getExpression(); - UnaryExpression secondOp = (UnaryExpression) secondStmt.getExpression(); + UpdateExpression firstOp = (UpdateExpression) first.getExpression(); + UpdateExpression secondOp = (UpdateExpression) secondStmt.getExpression(); AstNode firstVarRef = firstOp.getOperand(); AstNode secondVarRef = secondOp.getOperand(); From 457d13bfd97644b606c467ce8c575e8b2dfe00fc Mon Sep 17 00:00:00 2001 From: tuchida Date: Sat, 13 Feb 2021 17:57:49 +0900 Subject: [PATCH 6/8] Array length limit check --- src/org/mozilla/javascript/NativeArray.java | 103 +++++++++++------- .../javascript/NativeArrayIterator.java | 2 +- src/org/mozilla/javascript/ScriptRuntime.java | 2 +- 3 files changed, 64 insertions(+), 43 deletions(-) diff --git a/src/org/mozilla/javascript/NativeArray.java b/src/org/mozilla/javascript/NativeArray.java index d059452137..2f66bb8eec 100644 --- a/src/org/mozilla/javascript/NativeArray.java +++ b/src/org/mozilla/javascript/NativeArray.java @@ -723,7 +723,7 @@ private static Object js_from(Context cx, Scriptable scope, Scriptable thisObj, } } - final long length = getLengthProperty(cx, items, false); + final long length = getLengthProperty(cx, items); final Scriptable result = callConstructorOrCreateArray(cx, scope, thisObj, length, true); for (long k = 0; k < length; k++) { Object temp = getRawElem(items, k); @@ -846,7 +846,7 @@ private void setLength(Object val) { * getLengthProperty returns 0 if obj does not have the length property * or its value is not convertible to a number. */ - static long getLengthProperty(Context cx, Scriptable obj, boolean throwIfTooLarge) { + static long getLengthProperty(Context cx, Scriptable obj) { // These will both give numeric lengths within Uint32 range. if (obj instanceof NativeString) { return ((NativeString)obj).getLength(); @@ -862,17 +862,15 @@ static long getLengthProperty(Context cx, Scriptable obj, boolean throwIfTooLarg } double doubleLen = ScriptRuntime.toNumber(len); + + // ToLength if (doubleLen > NativeNumber.MAX_SAFE_INTEGER) { - if (throwIfTooLarge) { - String msg = ScriptRuntime.getMessageById("msg.arraylength.bad"); - throw ScriptRuntime.rangeError(msg); - } - return (int) NativeNumber.MAX_SAFE_INTEGER; + return (long) NativeNumber.MAX_SAFE_INTEGER; } if (doubleLen < 0) { return 0; } - return ScriptRuntime.toUint32(len); + return (long)doubleLen; } private static Object setLengthProperty(Context cx, Scriptable target, @@ -949,7 +947,7 @@ private static String toStringHelper(Context cx, Scriptable scope, /* It's probably redundant to handle long lengths in this * function; StringBuilders are limited to 2^31 in java. */ - long length = getLengthProperty(cx, o, false); + long length = getLengthProperty(cx, o); StringBuilder result = new StringBuilder(256); @@ -1044,7 +1042,7 @@ private static String js_join(Context cx, Scriptable scope, Scriptable thisObj, { Scriptable o = ScriptRuntime.toObject(cx, scope, thisObj); - long llength = getLengthProperty(cx, o, false); + long llength = getLengthProperty(cx, o); int length = (int)llength; if (llength != length) { throw Context.reportRuntimeErrorById( @@ -1120,7 +1118,7 @@ private static Scriptable js_reverse(Context cx, Scriptable scope, Scriptable th return o; } } - long len = getLengthProperty(cx, o, false); + long len = getLengthProperty(cx, o); long half = len / 2; for(long i=0; i < half; i++) { @@ -1170,7 +1168,7 @@ public int compare(final Object x, final Object y) { comparator = DEFAULT_COMPARATOR; } - long llength = getLengthProperty(cx, o, false); + long llength = getLengthProperty(cx, o); final int length = (int) llength; if (llength != length) { throw Context.reportRuntimeErrorById( @@ -1209,7 +1207,7 @@ private static Object js_push(Context cx, Scriptable scope, Scriptable thisObj, return ScriptRuntime.wrapNumber(na.length); } } - long length = getLengthProperty(cx, o, false); + long length = getLengthProperty(cx, o); for (int i = 0; i < args.length; i++) { setElem(cx, o, length + i, args[i]); } @@ -1245,7 +1243,7 @@ private static Object js_pop(Context cx, Scriptable scope, Scriptable thisObj, return result; } } - long length = getLengthProperty(cx, o, false); + long length = getLengthProperty(cx, o); if (length > 0) { length--; @@ -1280,7 +1278,7 @@ private static Object js_shift(Context cx, Scriptable scope, Scriptable thisObj, } } Object result; - long length = getLengthProperty(cx, o, false); + long length = getLengthProperty(cx, o); if (length > 0) { long i = 0; length--; @@ -1326,10 +1324,14 @@ private static Object js_unshift(Context cx, Scriptable scope, Scriptable thisOb return ScriptRuntime.wrapNumber(na.length); } } - long length = getLengthProperty(cx, o, false); + long length = getLengthProperty(cx, o); int argc = args.length; - if (args.length > 0) { + if (argc > 0) { + if (length + argc > NativeNumber.MAX_SAFE_INTEGER) { + throw ScriptRuntime.typeErrorById("msg.arraylength.too.big", length + argc); + } + /* Slide up the array to make room for args at the bottom */ if (length > 0) { for (long last = length - 1; last >= 0; last--) { @@ -1344,17 +1346,17 @@ private static Object js_unshift(Context cx, Scriptable scope, Scriptable thisOb } } /* Follow Perl by returning the new array length. */ - length += args.length; + length += argc; return setLengthProperty(cx, o, length); } private static Object js_splice(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { - Scriptable o = ScriptRuntime.toObject(cx, scope, thisObj); + Scriptable o = ScriptRuntime.toObject(cx, scope, thisObj); - NativeArray na = null; - boolean denseMode = false; + NativeArray na = null; + boolean denseMode = false; if (o instanceof NativeArray) { na = (NativeArray) o; denseMode = na.denseOnly; @@ -1365,34 +1367,43 @@ private static Object js_splice(Context cx, Scriptable scope, int argc = args.length; if (argc == 0) return cx.newArray(scope, 0); - long length = getLengthProperty(cx, o, false); + long length = getLengthProperty(cx, o); /* Convert the first argument into a starting index. */ long begin = toSliceIndex(ScriptRuntime.toInteger(args[0]), length); argc--; /* Convert the second argument into count */ - long count; + long actualDeleteCount; if (args.length == 1) { - count = length - begin; + actualDeleteCount = length - begin; } else { double dcount = ScriptRuntime.toInteger(args[1]); if (dcount < 0) { - count = 0; + actualDeleteCount = 0; } else if (dcount > (length - begin)) { - count = length - begin; + actualDeleteCount = length - begin; } else { - count = (long)dcount; + actualDeleteCount = (long)dcount; } argc--; } - long end = begin + count; + long end = begin + actualDeleteCount; + long delta = argc - actualDeleteCount; + + if (length + delta > NativeNumber.MAX_SAFE_INTEGER) { + throw ScriptRuntime.typeErrorById("msg.arraylength.too.big", length + delta); + } + if (actualDeleteCount > Integer.MAX_VALUE) { + String msg = ScriptRuntime.getMessageById("msg.arraylength.bad"); + throw ScriptRuntime.rangeError(msg); + } /* If there are elements to remove, put them into the return value. */ Object result; - if (count != 0) { - if (count == 1 + if (actualDeleteCount != 0) { + if (actualDeleteCount == 1 && (cx.getLanguageVersion() == Context.VERSION_1_2)) { /* @@ -1426,7 +1437,7 @@ private static Object js_splice(Context cx, Scriptable scope, result = resultArray; } } - } else { // (count == 0) + } else { // (actualDeleteCount == 0) if (cx.getLanguageVersion() == Context.VERSION_1_2) { /* Emulate C JS1.2; if no elements are removed, return undefined. */ result = Undefined.instance; @@ -1436,7 +1447,6 @@ private static Object js_splice(Context cx, Scriptable scope, } /* Find the direction (up or down) to copy and make way for argv. */ - long delta = argc - count; if (denseMode && length + delta < Integer.MAX_VALUE && na.ensureCapacity((int) (length + delta))) { @@ -1512,7 +1522,7 @@ private static boolean isConcatSpreadable(Context cx, Scriptable scope, Object v // dense arrays. private static long concatSpreadArg(Context cx, Scriptable result, Scriptable arg, long offset) { - long srclen = getLengthProperty(cx, arg, false); + long srclen = getLengthProperty(cx, arg); long newlen = srclen + offset; // First, optimize for a pair of native, dense arrays @@ -1577,8 +1587,7 @@ private static Scriptable js_slice(Context cx, Scriptable scope, Scriptable this { Scriptable o = ScriptRuntime.toObject(cx, scope, thisObj); - Scriptable result = cx.newArray(scope, 0); - long len = getLengthProperty(cx, o, false); + long len = getLengthProperty(cx, o); long begin, end; if (args.length == 0) { @@ -1593,6 +1602,12 @@ private static Scriptable js_slice(Context cx, Scriptable scope, Scriptable this } } + if (end - begin > Integer.MAX_VALUE) { + String msg = ScriptRuntime.getMessageById("msg.arraylength.bad"); + throw ScriptRuntime.rangeError(msg); + } + + Scriptable result = cx.newArray(scope, 0); for (long slot = begin; slot < end; slot++) { Object temp = getRawElem(o, slot); if (temp != NOT_FOUND) { @@ -1625,7 +1640,7 @@ private static Object js_indexOf(Context cx, Scriptable scope, Scriptable thisOb Object compareTo = args.length > 0 ? args[0] : Undefined.instance; Scriptable o = ScriptRuntime.toObject(cx, scope, thisObj); - long length = getLengthProperty(cx, o, false); + long length = getLengthProperty(cx, o); /* * From http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:indexOf * The index at which to begin the search. Defaults to 0, i.e. the @@ -1681,7 +1696,7 @@ private static Object js_lastIndexOf(Context cx, Scriptable scope, Scriptable th Object compareTo = args.length > 0 ? args[0] : Undefined.instance; Scriptable o = ScriptRuntime.toObject(cx, scope, thisObj); - long length = getLengthProperty(cx, o, false); + long length = getLengthProperty(cx, o); /* * From http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:lastIndexOf * The index at which to start searching backwards. Defaults to the @@ -1788,7 +1803,7 @@ private static Boolean js_includes(Context cx, Scriptable scope, Scriptable this private static Object js_fill(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { Scriptable o = ScriptRuntime.toObject(cx, scope, thisObj); - long len = getLengthProperty(cx, o, false); + long len = getLengthProperty(cx, o); long relativeStart = 0; if (args.length >= 2) { @@ -1825,7 +1840,7 @@ private static Object js_fill(Context cx, Scriptable scope, Scriptable thisObj, private static Object js_copyWithin(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { Scriptable o = ScriptRuntime.toObject(cx, scope, thisObj); - long len = getLengthProperty(cx, o, false); + long len = getLengthProperty(cx, o); Object targetArg = (args.length >= 1) ? args[0] : Undefined.instance; long relativeTarget = (long) ScriptRuntime.toInteger(targetArg); @@ -1914,7 +1929,13 @@ private static Object iterativeMethod(Context cx, IdFunctionObject idFunctionObj requireObjectCoercible(cx, o, idFunctionObject); } - long length = getLengthProperty(cx, o, id == Id_map); + long length = getLengthProperty(cx, o); + // TODO: In the case of Id_filter, CreateDataPropertyOrThrow throws a TypeError instead of ArraySpeciesCreate. + if ((id == Id_map || id == Id_filter) && length > Integer.MAX_VALUE) { + String msg = ScriptRuntime.getMessageById("msg.arraylength.bad"); + throw ScriptRuntime.rangeError(msg); + } + Object callbackArg = args.length > 0 ? args[0] : Undefined.instance; if (callbackArg == null || !(callbackArg instanceof Function)) { throw ScriptRuntime.notFunctionError(callbackArg); @@ -2009,7 +2030,7 @@ private static Object reduceMethod(Context cx, int id, Scriptable scope, { Scriptable o = ScriptRuntime.toObject(cx, scope, thisObj); - long length = getLengthProperty(cx, o, false); + long length = getLengthProperty(cx, o); Object callbackArg = args.length > 0 ? args[0] : Undefined.instance; if (callbackArg == null || !(callbackArg instanceof Function)) { throw ScriptRuntime.notFunctionError(callbackArg); diff --git a/src/org/mozilla/javascript/NativeArrayIterator.java b/src/org/mozilla/javascript/NativeArrayIterator.java index 714da05295..08e6645bbe 100644 --- a/src/org/mozilla/javascript/NativeArrayIterator.java +++ b/src/org/mozilla/javascript/NativeArrayIterator.java @@ -43,7 +43,7 @@ public String getClassName() { @Override protected boolean isDone(Context cx, Scriptable scope) { - return index >= NativeArray.getLengthProperty(cx, arrayLike, false); + return index >= NativeArray.getLengthProperty(cx, arrayLike); } @Override diff --git a/src/org/mozilla/javascript/ScriptRuntime.java b/src/org/mozilla/javascript/ScriptRuntime.java index 0976d6fa5f..a361d5b58c 100644 --- a/src/org/mozilla/javascript/ScriptRuntime.java +++ b/src/org/mozilla/javascript/ScriptRuntime.java @@ -4131,7 +4131,7 @@ public static boolean isArrayObject(Object obj) public static Object[] getArrayElements(Scriptable object) { Context cx = Context.getContext(); - long longLen = NativeArray.getLengthProperty(cx, object, false); + long longLen = NativeArray.getLengthProperty(cx, object); if (longLen > Integer.MAX_VALUE) { // arrays beyond MAX_INT is not in Java in any case throw new IllegalArgumentException(); From c61469d7a17fbaf96c29d77172b4c3552f4bc1ad Mon Sep 17 00:00:00 2001 From: tuchida Date: Sat, 13 Feb 2021 17:58:26 +0900 Subject: [PATCH 7/8] Enable test262 for Exponentiation Operator --- testsrc/test262.properties | 33 +++++---------------------------- 1 file changed, 5 insertions(+), 28 deletions(-) diff --git a/testsrc/test262.properties b/testsrc/test262.properties index 035853317e..e071f6acd7 100644 --- a/testsrc/test262.properties +++ b/testsrc/test262.properties @@ -18,23 +18,9 @@ built-ins/Array # incorrect length handling - ! every/15.4.4.16-3-29.js - ! indexOf/15.4.4.14-3-28.js - ! indexOf/15.4.4.14-3-29.js - ! lastIndexOf/15.4.4.15-3-28.js - ! map/15.4.4.19-3-28.js - ! map/15.4.4.19-3-29.js - ! pop/S15.4.4.6_A2_T2.js - ! pop/S15.4.4.6_A3_T1.js - ! pop/S15.4.4.6_A3_T2.js - ! push/S15.4.4.7_A2_T2.js - ! push/S15.4.4.7_A4_T1.js - ! slice/S15.4.4.10_A3_T1.js - ! slice/S15.4.4.10_A3_T2.js - ! some/15.4.4.17-3-28.js - ! some/15.4.4.17-3-29.js - ! splice/S15.4.4.12_A3_T1.js - ! splice/S15.4.4.12_A6.1_T2.js + ! prototype/push/S15.4.4.7_A2_T2.js + ! prototype/push/throws-if-integer-limit-exceeded.js + ! prototype/splice/S15.4.4.12_A6.1_T2.js # bugs? ! splice/S15.4.4.12_A6.1_T3.js # strictness issues @@ -97,20 +83,12 @@ built-ins/Array # No class support yet ! prototype/concat/Array.prototype.concat_non-array.js ! prototype/concat/Array.prototype.concat_small-typed-array.js - ! prototype/map/create-non-array-invalid-len.js - ! prototype/reverse/length-exceeding-integer-limit-with-object.js ! prototype/reverse/length-exceeding-integer-limit-with-proxy.js - ! prototype/slice/create-non-array-invalid-len.js ! prototype/slice/create-species-neg-zero.js ! prototype/slice/length-exceeding-integer-limit-proxied-array.js - ! prototype/slice/length-exceeding-integer-limit.js ! prototype/splice/clamps-length-to-integer-limit.js - ! prototype/splice/create-non-array-invalid-len.js ! prototype/splice/create-species-length-exceeding-integer-limit.js ! prototype/splice/create-species-neg-zero.js - ! prototype/splice/length-and-deleteCount-exceeding-integer-limit.js - ! prototype/splice/length-exceeding-integer-limit-shrink-array.js - ! prototype/splice/length-near-integer-limit-grow-array.js # several similar tests for filter, map, etc. ! create-ctor-non-object.js ! create-ctor-poisoned.js @@ -118,9 +96,6 @@ built-ins/Array ! create-species-non-ctor.js ! create-species-poisoned.js ! create-species.js - ! clamps-to-integer-limit.js - ! length-near-integer-limit.js - ! throws-if-integer-limit-exceeded.js built-ins/ArrayBuffer ! prototype/byteLength/detached-buffer.js @@ -2425,6 +2400,8 @@ language/expressions/delete ! 11.4.1-5-a-8-s.js ! 11.4.1-5-a-9-s.js +language/expressions/exponentiation + language/expressions/generators ! arguments-with-arguments-fn.js ! arguments-with-arguments-lex.js From 25f317e3cdce44a5e035f203af5816ca58cda139 Mon Sep 17 00:00:00 2001 From: tuchida Date: Sun, 21 Feb 2021 11:02:23 +0900 Subject: [PATCH 8/8] Do not throw error with Id_filter --- src/org/mozilla/javascript/NativeArray.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/org/mozilla/javascript/NativeArray.java b/src/org/mozilla/javascript/NativeArray.java index 2f66bb8eec..5c80b8a2a7 100644 --- a/src/org/mozilla/javascript/NativeArray.java +++ b/src/org/mozilla/javascript/NativeArray.java @@ -1930,8 +1930,7 @@ private static Object iterativeMethod(Context cx, IdFunctionObject idFunctionObj } long length = getLengthProperty(cx, o); - // TODO: In the case of Id_filter, CreateDataPropertyOrThrow throws a TypeError instead of ArraySpeciesCreate. - if ((id == Id_map || id == Id_filter) && length > Integer.MAX_VALUE) { + if (id == Id_map && length > Integer.MAX_VALUE) { String msg = ScriptRuntime.getMessageById("msg.arraylength.bad"); throw ScriptRuntime.rangeError(msg); }