Skip to content
Open
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
4 changes: 3 additions & 1 deletion acorn-loose/src/expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ lp.checkLVal = function(expr) {
switch (expr.type) {
case "Identifier":
case "MemberExpression":
case "CallExpression":
return expr

case "ParenthesizedExpression":
Expand Down Expand Up @@ -551,7 +552,8 @@ lp.initFunction = function(node) {
// if possible.

lp.toAssignable = function(node, binding) {
if (!node || node.type === "Identifier" || (node.type === "MemberExpression" && !binding)) {
if (!node || node.type === "Identifier" ||
!binding && (node.type === "MemberExpression" || node.type === "CallExpression")) {
// Okay
} else if (node.type === "ParenthesizedExpression") {
this.toAssignable(node.expression, binding)
Expand Down
4 changes: 2 additions & 2 deletions acorn/src/expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ pp.parseMaybeAssign = function(forInit, refDestructuringErrors, afterLeftParse)
if (afterLeftParse) left = afterLeftParse.call(this, left, startPos, startLoc)
if (this.type.isAssign) {
let node = this.startNodeAt(startPos, startLoc)
node.operator = this.value
const op = node.operator = this.value
if (this.type === tt.eq)
left = this.toAssignable(left, false, refDestructuringErrors)
if (!ownDestructuringErrors) {
Expand All @@ -147,7 +147,7 @@ pp.parseMaybeAssign = function(forInit, refDestructuringErrors, afterLeftParse)
if (this.type === tt.eq)
this.checkLValPattern(left)
else
this.checkLValSimple(left)
this.checkLValSimple(left, undefined, undefined, op === "??=" || op === "||=" || op === "&&=")
node.left = left
this.next()
node.right = this.parseMaybeAssign(forInit)
Expand Down
13 changes: 8 additions & 5 deletions acorn/src/lval.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@ pp.toAssignable = function(node, isBinding, refDestructuringErrors) {
this.raiseRecoverable(node.start, "Optional chaining cannot appear in left-hand side")
break

case "MemberExpression":
if (!isBinding) break

default:
if (!isBinding && (node.type === "MemberExpression" || !this.strict && node.type === "CallExpression")) {
break
}
this.raise(node.start, "Assigning to rvalue")
}
} else if (refDestructuringErrors) this.checkPatternErrors(refDestructuringErrors, true)
Expand Down Expand Up @@ -249,7 +249,7 @@ pp.parseMaybeDefault = function(startPos, startLoc, left) {
// duplicate argument names. checkClashes is ignored if the provided construct
// is an assignment (i.e., bindingType is BIND_NONE).

pp.checkLValSimple = function(expr, bindingType = BIND_NONE, checkClashes) {
pp.checkLValSimple = function(expr, bindingType = BIND_NONE, checkClashes, isLogicalAssignment) {
const isBind = bindingType !== BIND_NONE

switch (expr.type) {
Expand Down Expand Up @@ -278,9 +278,12 @@ pp.checkLValSimple = function(expr, bindingType = BIND_NONE, checkClashes) {

case "ParenthesizedExpression":
if (isBind) this.raiseRecoverable(expr.start, "Binding parenthesized expression")
return this.checkLValSimple(expr.expression, bindingType, checkClashes)
return this.checkLValSimple(expr.expression, bindingType, checkClashes, isLogicalAssignment)

default:
if (!isBind && !this.strict && !isLogicalAssignment && expr.type === "CallExpression") {
break
}
this.raise(expr.start, (isBind ? "Binding" : "Assigning to") + " rvalue")
}
}
Expand Down
7 changes: 0 additions & 7 deletions bin/test262.whitelist
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,3 @@ staging/explicit-resource-management/await-using-in-switch-case-block.js (defaul
staging/explicit-resource-management/await-using-in-switch-case-block.js (strict mode)
staging/explicit-resource-management/call-dispose-methods.js (default)
staging/explicit-resource-management/call-dispose-methods.js (strict mode)
annexB/language/expressions/assignmenttargettype/callexpression-as-for-in-lhs.js (default)
annexB/language/expressions/assignmenttargettype/callexpression-as-for-of-lhs.js (default)
annexB/language/expressions/assignmenttargettype/callexpression-in-compound-assignment.js (default)
annexB/language/expressions/assignmenttargettype/callexpression-in-prefix-update.js (default)
annexB/language/expressions/assignmenttargettype/callexpression.js (default)
annexB/language/expressions/assignmenttargettype/callexpression-in-postfix-update.js (default)
annexB/language/expressions/assignmenttargettype/cover-callexpression-and-asyncarrowhead.js (default)
44 changes: 43 additions & 1 deletion test/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -27170,8 +27170,50 @@ testFail("var x = /[a-z]/\\ux",
testFail("3 = 4",
"Assigning to rvalue (1:0)");

test("func() = 4", {
"type": "Program",
"start": 0,
"end": 10,
"body": [
{
"type": "ExpressionStatement",
"start": 0,
"end": 10,
"expression": {
"type": "AssignmentExpression",
"start": 0,
"end": 10,
"operator": "=",
"left": {
"type": "CallExpression",
"start": 0,
"end": 6,
"callee": {
"type": "Identifier",
"start": 0,
"end": 4,
"name": "func"
},
"arguments": []
},
"right": {
"type": "Literal",
"start": 9,
"end": 10,
"value": 4,
"raw": "4"
}
}
}
],
"sourceType": "script"
});

testFail("'use strict'; func() = 4",
"Assigning to rvalue (1:14)");

testFail("func() = 4",
"Assigning to rvalue (1:0)");
"Assigning to rvalue (1:0)", {sourceType: "module"});

testFail("(1 + 1) = 10",
"Assigning to rvalue (1:0)");
Expand Down
Loading