Skip to content

Commit 88d472a

Browse files
authored
Nullish coalescing with preceding statements (#1172)
* Nullish coalescing with preceding statements * Add test for #1165
1 parent f624a6e commit 88d472a

File tree

2 files changed

+27
-33
lines changed

2 files changed

+27
-33
lines changed

src/transformation/visitors/binary-expression/index.ts

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ function transformBinaryOperationWithNoPrecedingStatements(
6565

6666
if (operator === ts.SyntaxKind.QuestionQuestionToken) {
6767
assert(ts.isBinaryExpression(node));
68-
return transformNullishCoalescingExpression(context, node, left, right);
68+
return transformNullishCoalescingOperationNoPrecedingStatements(context, node, left, right);
6969
}
7070

7171
let luaOperator = simpleOperatorsToLua[operator];
@@ -138,21 +138,7 @@ function transformShortCircuitBinaryExpression(
138138
const [rightPrecedingStatements, rhs] = transformInPrecedingStatementScope(context, () =>
139139
context.transformExpression(node.right)
140140
);
141-
if (rightPrecedingStatements.length > 0) {
142-
return createShortCircuitBinaryExpressionPrecedingStatements(
143-
context,
144-
lhs,
145-
rhs,
146-
rightPrecedingStatements,
147-
operator,
148-
node
149-
);
150-
} else {
151-
return [
152-
rightPrecedingStatements,
153-
transformBinaryOperationWithNoPrecedingStatements(context, lhs, rhs, operator, node),
154-
];
155-
}
141+
return transformBinaryOperation(context, lhs, rhs, rightPrecedingStatements, operator, node);
156142
}
157143

158144
export function transformBinaryOperation(
@@ -274,7 +260,7 @@ export function transformBinaryExpressionStatement(
274260
}
275261
}
276262

277-
function transformNullishCoalescingExpression(
263+
function transformNullishCoalescingOperationNoPrecedingStatements(
278264
context: TransformationContext,
279265
node: ts.BinaryExpression,
280266
transformedLeft: lua.Expression,
@@ -287,23 +273,17 @@ function transformNullishCoalescingExpression(
287273
(type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.Boolean)) !== 0 ||
288274
(type.flags & ts.TypeFlags.BooleanLiteral & ts.TypeFlags.PossiblyFalsy) !== 0;
289275
if (typeCanSatisfy(context, lhsType, typeCanBeFalse)) {
290-
// lhs can be false, transform to IIFE
291-
const lhsIdentifier = lua.createIdentifier("____lhs");
292-
const nilComparison = lua.createBinaryExpression(
293-
lua.cloneIdentifier(lhsIdentifier),
294-
lua.createNilLiteral(),
295-
lua.SyntaxKind.EqualityOperator
296-
);
297-
// if ____ == nil then return rhs else return ____ end
298-
const ifStatement = lua.createIfStatement(
299-
nilComparison,
300-
lua.createBlock([lua.createReturnStatement([transformedRight])]),
301-
lua.createBlock([lua.createReturnStatement([lua.cloneIdentifier(lhsIdentifier)])])
302-
);
303-
// (function(lhs') if lhs' == nil then return rhs else return lhs' end)(lhs)
304-
return lua.createCallExpression(lua.createFunctionExpression(lua.createBlock([ifStatement]), [lhsIdentifier]), [
276+
// reuse logic from case with preceding statements
277+
const [precedingStatements, result] = createShortCircuitBinaryExpressionPrecedingStatements(
278+
context,
305279
transformedLeft,
306-
]);
280+
transformedRight,
281+
[],
282+
ts.SyntaxKind.QuestionQuestionToken,
283+
node
284+
);
285+
context.addPrecedingStatements(precedingStatements);
286+
return result;
307287
} else {
308288
// lhs or rhs
309289
return lua.createBinaryExpression(transformedLeft, transformedRight, lua.SyntaxKind.OrOperator, node);

test/unit/nullishCoalescing.spec.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,17 @@ test("nullish-coalescing operator with side effect rhs", () => {
4040
return [i, undefined ?? incI(), i];
4141
`.expectToMatchJsResult();
4242
});
43+
44+
test("nullish-coalescing operator with vararg", () => {
45+
util.testFunction`
46+
47+
function foo(...args: any[]){
48+
return args
49+
}
50+
function bar(...args: any[]) {
51+
let x: boolean | undefined = false
52+
const y = x ?? foo(...args)
53+
}
54+
return bar(1, 2)
55+
`.expectToMatchJsResult();
56+
});

0 commit comments

Comments
 (0)