119119import com .oracle .truffle .js .nodes .access .DeclareEvalVariableNode ;
120120import com .oracle .truffle .js .nodes .access .DeclareGlobalNode ;
121121import com .oracle .truffle .js .nodes .access .GetIteratorUnaryNode ;
122+ import com .oracle .truffle .js .nodes .access .GetMethodNode ;
122123import com .oracle .truffle .js .nodes .access .GlobalPropertyNode ;
124+ import com .oracle .truffle .js .nodes .access .IteratorToArrayNode ;
123125import com .oracle .truffle .js .nodes .access .JSConstantNode ;
124126import com .oracle .truffle .js .nodes .access .JSReadFrameSlotNode ;
125127import com .oracle .truffle .js .nodes .access .JSWriteFrameSlotNode ;
151153import com .oracle .truffle .js .nodes .control .SequenceNode ;
152154import com .oracle .truffle .js .nodes .control .StatementNode ;
153155import com .oracle .truffle .js .nodes .control .SuspendNode ;
156+ import com .oracle .truffle .js .nodes .extractor .InvokeCustomMatcherOrThrowNode ;
154157import com .oracle .truffle .js .nodes .function .AbstractFunctionArgumentsNode ;
155158import com .oracle .truffle .js .nodes .function .BlockScopeNode ;
156159import com .oracle .truffle .js .nodes .function .EvalNode ;
@@ -2860,6 +2863,8 @@ private JavaScriptNode transformAssignmentImpl(Expression assignmentExpression,
28602863 if (lhsExpression instanceof CallNode callNode ) {
28612864 assert callNode .isWebCompatAssignmentTargetType ();
28622865 assignedNode = factory .createDual (context , transform (lhsExpression ), factory .createThrowError (JSErrorType .ReferenceError , INVALID_LHS ));
2866+ // todo-lw: merge
2867+ // assignedNode = transformAssignmentExtractor((CallNode) lhsExpression, assignedValue, binaryOp, returnOldValue, convertLHSToNumeric, initializationAssignment);
28632868 } else {
28642869 assignedNode = transformAssignmentIdent ((IdentNode ) lhsExpression , assignedValue , binaryOp , returnOldValue , convertLHSToNumeric , initializationAssignment );
28652870 }
@@ -2907,40 +2912,38 @@ private JavaScriptNode transformAssignmentIdent(IdentNode identNode, JavaScriptN
29072912 rhs = checkMutableBinding (rhs , scopeVar .getName ());
29082913 }
29092914 return scopeVar .createWriteNode (rhs );
2915+ } else if (isLogicalOp (binaryOp )) {
2916+ assert !convertLHSToNumeric && !returnOldValue && assignedValue != null ;
2917+ if (constAssignment ) {
2918+ rhs = checkMutableBinding (rhs , scopeVar .getName ());
2919+ }
2920+ JavaScriptNode readNode = tagExpression (scopeVar .createReadNode (), identNode );
2921+ JavaScriptNode writeNode = scopeVar .createWriteNode (rhs );
2922+ return factory .createBinary (context , binaryOp , readNode , writeNode );
29102923 } else {
2911- if (isLogicalOp (binaryOp )) {
2912- assert !convertLHSToNumeric && !returnOldValue && assignedValue != null ;
2913- if (constAssignment ) {
2914- rhs = checkMutableBinding (rhs , scopeVar .getName ());
2915- }
2916- JavaScriptNode readNode = tagExpression (scopeVar .createReadNode (), identNode );
2917- JavaScriptNode writeNode = scopeVar .createWriteNode (rhs );
2918- return factory .createBinary (context , binaryOp , readNode , writeNode );
2924+ // e.g.: lhs *= rhs => lhs = lhs * rhs
2925+ // If lhs is a side-effecting getter that deletes lhs, we must not throw a
2926+ // ReferenceError at the lhs assignment since the lhs reference is already resolved.
2927+ // We also need to ensure that HasBinding is idempotent or evaluated at most once.
2928+ Pair <Supplier <JavaScriptNode >, UnaryOperator <JavaScriptNode >> pair = scopeVar .createCompoundAssignNode ();
2929+ JavaScriptNode readNode = tagExpression (pair .getFirst ().get (), identNode );
2930+ if (convertLHSToNumeric ) {
2931+ readNode = factory .createToNumericOperand (readNode );
2932+ }
2933+ VarRef prevValueTemp = null ;
2934+ if (returnOldValue ) {
2935+ prevValueTemp = environment .createTempVar ();
2936+ readNode = prevValueTemp .createWriteNode (readNode );
2937+ }
2938+ JavaScriptNode binOpNode = tagExpression (factory .createBinary (context , binaryOp , readNode , rhs ), identNode );
2939+ if (constAssignment ) {
2940+ binOpNode = checkMutableBinding (binOpNode , scopeVar .getName ());
2941+ }
2942+ JavaScriptNode writeNode = pair .getSecond ().apply (binOpNode );
2943+ if (returnOldValue ) {
2944+ return factory .createDual (context , writeNode , prevValueTemp .createReadNode ());
29192945 } else {
2920- // e.g.: lhs *= rhs => lhs = lhs * rhs
2921- // If lhs is a side-effecting getter that deletes lhs, we must not throw a
2922- // ReferenceError at the lhs assignment since the lhs reference is already resolved.
2923- // We also need to ensure that HasBinding is idempotent or evaluated at most once.
2924- Pair <Supplier <JavaScriptNode >, UnaryOperator <JavaScriptNode >> pair = scopeVar .createCompoundAssignNode ();
2925- JavaScriptNode readNode = tagExpression (pair .getFirst ().get (), identNode );
2926- if (convertLHSToNumeric ) {
2927- readNode = factory .createToNumericOperand (readNode );
2928- }
2929- VarRef prevValueTemp = null ;
2930- if (returnOldValue ) {
2931- prevValueTemp = environment .createTempVar ();
2932- readNode = prevValueTemp .createWriteNode (readNode );
2933- }
2934- JavaScriptNode binOpNode = tagExpression (factory .createBinary (context , binaryOp , readNode , rhs ), identNode );
2935- if (constAssignment ) {
2936- binOpNode = checkMutableBinding (binOpNode , scopeVar .getName ());
2937- }
2938- JavaScriptNode writeNode = pair .getSecond ().apply (binOpNode );
2939- if (returnOldValue ) {
2940- return factory .createDual (context , writeNode , prevValueTemp .createReadNode ());
2941- } else {
2942- return writeNode ;
2943- }
2946+ return writeNode ;
29442947 }
29452948 }
29462949 }
@@ -3070,14 +3073,19 @@ private JavaScriptNode transformIndexAssignment(IndexNode indexNode, JavaScriptN
30703073 }
30713074
30723075 private JavaScriptNode transformDestructuringArrayAssignment (Expression lhsExpression , JavaScriptNode assignedValue , boolean initializationAssignment ) {
3076+ VarRef valueTempVar = environment .createTempVar ();
3077+ JavaScriptNode initValue = valueTempVar .createWriteNode (assignedValue );
3078+ JavaScriptNode getIterator = factory .createGetIterator (initValue );
30733079 LiteralNode .ArrayLiteralNode arrayLiteralNode = (LiteralNode .ArrayLiteralNode ) lhsExpression ;
30743080 List <Expression > elementExpressions = arrayLiteralNode .getElementExpressions ();
3081+
3082+ return this .transformDestructuringArrayAssignment (elementExpressions , getIterator , valueTempVar , initializationAssignment );
3083+ }
3084+
3085+ private JavaScriptNode transformDestructuringArrayAssignment (List <Expression > elementExpressions , JavaScriptNode getIterator , VarRef valueTempVar , boolean initializationAssignment ) {
30753086 JavaScriptNode [] initElements = javaScriptNodeArray (elementExpressions .size ());
30763087 VarRef iteratorTempVar = environment .createTempVar ();
3077- VarRef valueTempVar = environment .createTempVar ();
3078- JavaScriptNode initValue = valueTempVar .createWriteNode (assignedValue );
30793088 // By default, we use the hint to track the type of iterator.
3080- JavaScriptNode getIterator = factory .createGetIterator (initValue );
30813089 JavaScriptNode initIteratorTempVar = iteratorTempVar .createWriteNode (getIterator );
30823090
30833091 for (int i = 0 ; i < elementExpressions .size (); i ++) {
@@ -3099,7 +3107,8 @@ private JavaScriptNode transformDestructuringArrayAssignment(Expression lhsExpre
30993107 if (init != null ) {
31003108 rhsNode = factory .createNotUndefinedOr (rhsNode , transform (init ));
31013109 }
3102- if (lhsExpr != null && lhsExpr .isTokenType (TokenType .SPREAD_ARRAY )) {
3110+ // todo-lw: this change is kind of sus
3111+ if (lhsExpr != null && (lhsExpr .isTokenType (TokenType .SPREAD_ARRAY ) || lhsExpr .isTokenType (TokenType .SPREAD_ARGUMENT ))) {
31033112 rhsNode = factory .createIteratorToArray (context , iteratorTempVar .createReadNode ());
31043113 lhsExpr = ((UnaryNode ) lhsExpr ).getExpression ();
31053114 }
@@ -3117,6 +3126,25 @@ private JavaScriptNode transformDestructuringArrayAssignment(Expression lhsExpre
31173126 factory .createExprBlock (resetIterator , resetValue ));
31183127 }
31193128
3129+ private JavaScriptNode transformAssignmentExtractor (CallNode fakeCallNode , JavaScriptNode assignedValue , BinaryOperation binaryOp , boolean returnOldValue , boolean convertToNumeric , boolean initializationAssignment ) {
3130+ // todo-lw: call node :(
3131+
3132+ final var functionExpr = fakeCallNode .getFunction ();
3133+ final var function = transform (functionExpr );
3134+
3135+ var receiver = function ;
3136+ if (functionExpr instanceof AccessNode ) {
3137+ final AccessNode accessNode = (AccessNode ) functionExpr ;
3138+ receiver = transform (accessNode .getBase ());
3139+ }
3140+
3141+ final var invokeCustomMatcherOrThrowNode = InvokeCustomMatcherOrThrowNode .create (context , function , assignedValue , receiver );
3142+
3143+ final var args = fakeCallNode .getArgs ();
3144+ VarRef valueTempVar = environment .createTempVar ();
3145+ return this .transformDestructuringArrayAssignment (args , invokeCustomMatcherOrThrowNode , valueTempVar , initializationAssignment );
3146+ }
3147+
31203148 private JavaScriptNode transformDestructuringObjectAssignment (Expression lhsExpression , JavaScriptNode assignedValue , boolean initializationAssignment ) {
31213149 ObjectNode objectLiteralNode = (ObjectNode ) lhsExpression ;
31223150 List <PropertyNode > propertyExpressions = objectLiteralNode .getElements ();
0 commit comments