Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement logical assigment operators ||= and &&= #1597

Merged
merged 1 commit into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions rhino/src/main/java/org/mozilla/javascript/IRFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -2066,12 +2066,18 @@ private Node createAssignment(int assignType, Node left, Node right) {
case Token.ASSIGN_BITOR:
assignOp = Token.BITOR;
break;
case Token.ASSIGN_LOGICAL_OR:
assignOp = Token.OR;
break;
case Token.ASSIGN_BITXOR:
assignOp = Token.BITXOR;
break;
case Token.ASSIGN_BITAND:
assignOp = Token.BITAND;
break;
case Token.ASSIGN_LOGICAL_AND:
assignOp = Token.AND;
break;
case Token.ASSIGN_LSH:
assignOp = Token.LSH;
break;
Expand Down
2 changes: 2 additions & 0 deletions rhino/src/main/java/org/mozilla/javascript/Node.java
Original file line number Diff line number Diff line change
Expand Up @@ -932,8 +932,10 @@ public boolean hasSideEffects() {
case Token.ASSIGN_DIV:
case Token.ASSIGN_MOD:
case Token.ASSIGN_BITOR:
case Token.ASSIGN_LOGICAL_OR:
case Token.ASSIGN_BITXOR:
case Token.ASSIGN_BITAND:
case Token.ASSIGN_LOGICAL_AND:
case Token.ASSIGN_LSH:
case Token.ASSIGN_RSH:
case Token.ASSIGN_URSH:
Expand Down
170 changes: 88 additions & 82 deletions rhino/src/main/java/org/mozilla/javascript/Token.java
Original file line number Diff line number Diff line change
Expand Up @@ -135,99 +135,101 @@ public static enum CommentType {
COMMA = 92, // comma operator
ASSIGN = 93, // simple assignment (=)
ASSIGN_BITOR = 94, // |=
ASSIGN_BITXOR = 95, // ^=
ASSIGN_BITAND = 96, // |=
ASSIGN_LSH = 97, // <<=
ASSIGN_RSH = 98, // >>=
ASSIGN_URSH = 99, // >>>=
ASSIGN_ADD = 100, // +=
ASSIGN_SUB = 101, // -=
ASSIGN_MUL = 102, // *=
ASSIGN_DIV = 103, // /=
ASSIGN_MOD = 104, // %=
ASSIGN_EXP = 105; // **=
ASSIGN_LOGICAL_OR = 95, // ||=
ASSIGN_BITXOR = 96, // ^=
ASSIGN_BITAND = 97, // |=
ASSIGN_LOGICAL_AND = 98, // &&=
ASSIGN_LSH = 99, // <<=
ASSIGN_RSH = 100, // >>=
ASSIGN_URSH = 101, // >>>=
ASSIGN_ADD = 102, // +=
ASSIGN_SUB = 103, // -=
ASSIGN_MUL = 104, // *=
ASSIGN_DIV = 105, // /=
ASSIGN_MOD = 106, // %=
ASSIGN_EXP = 107; // **=
public static final int FIRST_ASSIGN = ASSIGN,
LAST_ASSIGN = ASSIGN_EXP,
HOOK = 106, // conditional (?:)
COLON = 107,
OR = 108, // logical or (||)
AND = 109, // logical and (&&)
INC = 110, // increment/decrement (++ --)
DEC = 111,
DOT = 112, // member operator (.)
FUNCTION = 113, // function keyword
EXPORT = 114, // export keyword
IMPORT = 115, // import keyword
IF = 116, // if keyword
ELSE = 117, // else keyword
SWITCH = 118, // switch keyword
CASE = 119, // case keyword
DEFAULT = 120, // default keyword
WHILE = 121, // while keyword
DO = 122, // do keyword
FOR = 123, // for keyword
BREAK = 124, // break keyword
CONTINUE = 125, // continue keyword
VAR = 126, // var keyword
WITH = 127, // with keyword
CATCH = 128, // catch keyword
FINALLY = 129, // finally keyword
VOID = 130, // void keyword
RESERVED = 131, // reserved keywords
EMPTY = 132,
COMPUTED_PROPERTY = 133, // computed property in object initializer [x]
HOOK = 108, // conditional (?:)
COLON = 109,
OR = 110, // logical or (||)
AND = 111, // logical and (&&)
INC = 112, // increment/decrement (++ --)
DEC = 113,
DOT = 114, // member operator (.)
FUNCTION = 115, // function keyword
EXPORT = 116, // export keyword
IMPORT = 117, // import keyword
IF = 118, // if keyword
ELSE = 119, // else keyword
SWITCH = 120, // switch keyword
CASE = 121, // case keyword
DEFAULT = 122, // default keyword
WHILE = 123, // while keyword
DO = 124, // do keyword
FOR = 125, // for keyword
BREAK = 126, // break keyword
CONTINUE = 127, // continue keyword
VAR = 128, // var keyword
WITH = 129, // with keyword
CATCH = 130, // catch keyword
FINALLY = 131, // finally keyword
VOID = 132, // void keyword
RESERVED = 133, // reserved keywords
EMPTY = 134,
COMPUTED_PROPERTY = 135, // computed property in object initializer [x]

/* types used for the parse tree - these never get returned
* by the scanner.
*/

BLOCK = 134, // statement block
LABEL = 135, // label
TARGET = 136,
LOOP = 137,
EXPR_VOID = 138, // expression statement in functions
EXPR_RESULT = 139, // expression statement in scripts
JSR = 140,
SCRIPT = 141, // top-level node for entire script
TYPEOFNAME = 142, // for typeof(simple-name)
USE_STACK = 143,
SETPROP_OP = 144, // x.y op= something
SETELEM_OP = 145, // x[y] op= something
LOCAL_BLOCK = 146,
SET_REF_OP = 147, // *reference op= something
BLOCK = 136, // statement block
LABEL = 137, // label
TARGET = 138,
LOOP = 139,
EXPR_VOID = 140, // expression statement in functions
EXPR_RESULT = 141, // expression statement in scripts
JSR = 142,
SCRIPT = 143, // top-level node for entire script
TYPEOFNAME = 144, // for typeof(simple-name)
USE_STACK = 145,
SETPROP_OP = 146, // x.y op= something
SETELEM_OP = 147, // x[y] op= something
LOCAL_BLOCK = 148,
SET_REF_OP = 149, // *reference op= something

// For XML support:
DOTDOT = 148, // member operator (..)
COLONCOLON = 149, // namespace::name
XML = 150, // XML type
DOTQUERY = 151, // .() -- e.g., x.emps.emp.(name == "terry")
XMLATTR = 152, // @
XMLEND = 153,
DOTDOT = 150, // member operator (..)
COLONCOLON = 151, // namespace::name
XML = 152, // XML type
DOTQUERY = 153, // .() -- e.g., x.emps.emp.(name == "terry")
XMLATTR = 154, // @
XMLEND = 155,

// Optimizer-only-tokens
TO_OBJECT = 154,
TO_DOUBLE = 155,
GET = 156, // JS 1.5 get pseudo keyword
SET = 157, // JS 1.5 set pseudo keyword
LET = 158, // JS 1.7 let pseudo keyword
CONST = 159,
SETCONST = 160,
SETCONSTVAR = 161,
ARRAYCOMP = 162, // array comprehension
LETEXPR = 163,
WITHEXPR = 164,
DEBUGGER = 165,
COMMENT = 166,
GENEXPR = 167,
METHOD = 168, // ES6 MethodDefinition
ARROW = 169, // ES6 ArrowFunction
YIELD_STAR = 170, // ES6 "yield *", a specialization of yield
TEMPLATE_LITERAL = 171, // template literal
TEMPLATE_CHARS = 172, // template literal - literal section
TEMPLATE_LITERAL_SUBST = 173, // template literal - substitution
TAGGED_TEMPLATE_LITERAL = 174, // template literal - tagged/handler
DOTDOTDOT = 175, // spread/rest ...
LAST_TOKEN = 175;
TO_OBJECT = 156,
TO_DOUBLE = 157,
GET = 158, // JS 1.5 get pseudo keyword
SET = 159, // JS 1.5 set pseudo keyword
LET = 160, // JS 1.7 let pseudo keyword
CONST = 161,
SETCONST = 162,
SETCONSTVAR = 163,
ARRAYCOMP = 164, // array comprehension
LETEXPR = 165,
WITHEXPR = 166,
DEBUGGER = 167,
COMMENT = 168,
GENEXPR = 169,
METHOD = 170, // ES6 MethodDefinition
ARROW = 171, // ES6 ArrowFunction
YIELD_STAR = 172, // ES6 "yield *", a specialization of yield
TEMPLATE_LITERAL = 173, // template literal
TEMPLATE_CHARS = 174, // template literal - literal section
TEMPLATE_LITERAL_SUBST = 175, // template literal - substitution
TAGGED_TEMPLATE_LITERAL = 176, // template literal - tagged/handler
DOTDOTDOT = 177, // spread/rest ...
LAST_TOKEN = 177;

/**
* Returns a name for the token. If Rhino is compiled with certain hardcoded debugging flags in
Expand Down Expand Up @@ -434,10 +436,14 @@ public static String typeToName(int token) {
return "ASSIGN";
case ASSIGN_BITOR:
return "ASSIGN_BITOR";
case ASSIGN_LOGICAL_OR:
return "ASSIGN_LOGICAL_OR";
case ASSIGN_BITXOR:
return "ASSIGN_BITXOR";
case ASSIGN_BITAND:
return "ASSIGN_BITAND";
case ASSIGN_LOGICAL_AND:
return "ASSIGN_LOGICAL_AND";
case ASSIGN_LSH:
return "ASSIGN_LSH";
case ASSIGN_RSH:
Expand Down
6 changes: 4 additions & 2 deletions rhino/src/main/java/org/mozilla/javascript/TokenStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -1167,7 +1167,8 @@ && matchChar('.')) {

case '|':
if (matchChar('|')) {
return Token.OR;
if (matchChar('=')) return Token.ASSIGN_LOGICAL_OR;
else return Token.OR;
} else if (matchChar('=')) {
return Token.ASSIGN_BITOR;
} else {
Expand All @@ -1182,7 +1183,8 @@ && matchChar('.')) {

case '&':
if (matchChar('&')) {
return Token.AND;
if (matchChar('=')) return Token.ASSIGN_LOGICAL_AND;
else return Token.AND;
} else if (matchChar('=')) {
return Token.ASSIGN_BITAND;
} else {
Expand Down
4 changes: 4 additions & 0 deletions rhino/src/main/java/org/mozilla/javascript/ast/AstNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,9 @@ public abstract class AstNode extends Node implements Comparable<AstNode> {
operatorNames.put(Token.SHNE, "!==");
operatorNames.put(Token.ASSIGN, "=");
operatorNames.put(Token.ASSIGN_BITOR, "|=");
operatorNames.put(Token.ASSIGN_LOGICAL_OR, "||=");
operatorNames.put(Token.ASSIGN_BITAND, "&=");
operatorNames.put(Token.ASSIGN_LOGICAL_AND, "&&=");
operatorNames.put(Token.ASSIGN_LSH, "<<=");
operatorNames.put(Token.ASSIGN_RSH, ">>=");
operatorNames.put(Token.ASSIGN_URSH, ">>>=");
Expand Down Expand Up @@ -359,7 +361,9 @@ public boolean hasSideEffects() {
case Token.ASSIGN:
case Token.ASSIGN_ADD:
case Token.ASSIGN_BITAND:
case Token.ASSIGN_LOGICAL_AND:
case Token.ASSIGN_BITOR:
case Token.ASSIGN_LOGICAL_OR:
case Token.ASSIGN_BITXOR:
case Token.ASSIGN_DIV:
case Token.ASSIGN_LSH:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* 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.tests.es6;

import org.mozilla.javascript.Context;
import org.mozilla.javascript.drivers.LanguageVersion;
import org.mozilla.javascript.drivers.RhinoTest;
import org.mozilla.javascript.drivers.ScriptTestsBase;

@RhinoTest("testsrc/jstests/es6/logical-or-and-assignment.js")
@LanguageVersion(Context.VERSION_ES6)
public class LogicalOrAndAssignmentTest extends ScriptTestsBase {}
43 changes: 43 additions & 0 deletions tests/testsrc/jstests/es6/logical-or-and-assignment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* 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/. */

load('testsrc/assert.js');

(function basicTests() {
var a = false;
var b = true;
a ||= b;
assertTrue(a);

var c = false;
a &&= c;
assertFalse(a);
})();

(function shortCircuits() {
var counter = 0;
function incCounter() { ++ counter; return true; }

var a = true;
counter = 0;
a ||= incCounter();
assertEquals(0, counter);

a = false;
counter = 0;
a ||= incCounter();
assertEquals(1, counter);

a = true;
counter = 0;
a &&= incCounter();
assertEquals(1, counter);

a = false;
counter = 0;
a &&= incCounter();
assertEquals(0, counter);
})();

"success";
Loading
Loading