-
Notifications
You must be signed in to change notification settings - Fork 12.9k
nullish coalescing commit #32883
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
nullish coalescing commit #32883
Changes from all commits
2ef3e0f
91a04ed
ba39ae8
079d002
3822fde
f67e524
2327b3b
fb0d3c9
06149d0
3d94652
65b2008
e4497b8
c2e336b
b714a01
323ebf0
d659c83
55dd6ae
22d1c07
8427eca
cb76a3e
7d3ccae
b412e50
8227034
57be95d
78df31b
9e3852e
de81520
6418943
a719f66
cb187cb
7fd8658
6ef160f
8c572b1
b030f73
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1015,7 +1015,8 @@ namespace ts { | |
else { | ||
return node.kind === SyntaxKind.BinaryExpression && ( | ||
(<BinaryExpression>node).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken || | ||
(<BinaryExpression>node).operatorToken.kind === SyntaxKind.BarBarToken); | ||
(<BinaryExpression>node).operatorToken.kind === SyntaxKind.BarBarToken || | ||
(<BinaryExpression>node).operatorToken.kind === SyntaxKind.QuestionQuestionToken); | ||
} | ||
} | ||
} | ||
|
@@ -1466,7 +1467,7 @@ namespace ts { | |
|
||
function bindBinaryExpressionFlow(node: BinaryExpression) { | ||
const operator = node.operatorToken.kind; | ||
if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken) { | ||
if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: This if-chain would be easier to read as a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I prefer to keep this because of so many other code similar to that. |
||
if (isTopLevelLogicalExpression(node)) { | ||
const postExpressionLabel = createBranchLabel(); | ||
bindLogicalExpression(node, postExpressionLabel, postExpressionLabel); | ||
|
@@ -2948,7 +2949,7 @@ namespace ts { | |
init = init && getRightMostAssignedExpression(init); | ||
if (init) { | ||
const isPrototypeAssignment = isPrototypeAccess(isVariableDeclaration(node) ? node.name : isBinaryExpression(node) ? node.left : node); | ||
return !!getExpandoInitializer(isBinaryExpression(init) && init.operatorToken.kind === SyntaxKind.BarBarToken ? init.right : init, isPrototypeAssignment); | ||
return !!getExpandoInitializer(isBinaryExpression(init) && (init.operatorToken.kind === SyntaxKind.BarBarToken || init.operatorToken.kind === SyntaxKind.QuestionQuestionToken) ? init.right : init, isPrototypeAssignment); | ||
} | ||
return false; | ||
} | ||
|
@@ -3424,7 +3425,10 @@ namespace ts { | |
const operatorTokenKind = node.operatorToken.kind; | ||
const leftKind = node.left.kind; | ||
|
||
if (operatorTokenKind === SyntaxKind.EqualsToken && leftKind === SyntaxKind.ObjectLiteralExpression) { | ||
if (operatorTokenKind === SyntaxKind.QuestionQuestionToken) { | ||
transformFlags |= TransformFlags.AssertESNext; | ||
} | ||
else if (operatorTokenKind === SyntaxKind.EqualsToken && leftKind === SyntaxKind.ObjectLiteralExpression) { | ||
DanielRosenwasser marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// Destructuring object assignments with are ES2015 syntax | ||
// and possibly ES2018 if they contain rest | ||
transformFlags |= TransformFlags.AssertES2018 | TransformFlags.AssertES2015 | TransformFlags.AssertDestructuringAssignment; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,7 @@ | |
namespace ts { | ||
export function transformESNext(context: TransformationContext) { | ||
const { | ||
hoistVariableDeclaration | ||
hoistVariableDeclaration, | ||
} = context; | ||
|
||
return chainBundle(transformSourceFile); | ||
|
@@ -28,7 +28,12 @@ namespace ts { | |
Debug.assertNotNode(updated, isSyntheticReference); | ||
return updated; | ||
} | ||
// falls through | ||
return visitEachChild(node, visitor, context); | ||
case SyntaxKind.BinaryExpression: | ||
if ((<BinaryExpression>node).operatorToken.kind === SyntaxKind.QuestionQuestionToken) { | ||
return transformNullishCoalescingExpression(<BinaryExpression>node); | ||
} | ||
return visitEachChild(node, visitor, context); | ||
default: | ||
return visitEachChild(node, visitor, context); | ||
} | ||
|
@@ -172,5 +177,39 @@ namespace ts { | |
); | ||
return thisArg ? createSyntheticReferenceExpression(target, thisArg) : target; | ||
} | ||
|
||
function createNotNullCondition(node: Expression) { | ||
return createBinary( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since optional chaining uses strict equality, can you switch this to strict equality? createBinary(
createBinary(
temp
createToken(SyntaxKind.ExclamationEqualsEqualsToken),
createNull()
),
createToken(SyntaxKind.AmpersandAmpersandToken),
createBinary(
temp,
createToken(SyntaxKind.ExclamationEqualsEqualsToken),
createVoidZero()
)
); |
||
createBinary( | ||
node, | ||
createToken(SyntaxKind.ExclamationEqualsEqualsToken), | ||
createNull() | ||
), | ||
createToken(SyntaxKind.AmpersandAmpersandToken), | ||
createBinary( | ||
node, | ||
createToken(SyntaxKind.ExclamationEqualsEqualsToken), | ||
createVoidZero() | ||
) | ||
); | ||
} | ||
|
||
function transformNullishCoalescingExpression(node: BinaryExpression) { | ||
const expressions: Expression[] = []; | ||
let left = visitNode(node.left, visitor, isExpression); | ||
if (!isIdentifier(left)) { | ||
const temp = createTempVariable(hoistVariableDeclaration); | ||
expressions.push(createAssignment(temp, left)); | ||
left = temp; | ||
} | ||
expressions.push( | ||
createParen( | ||
createConditional( | ||
createNotNullCondition(left), | ||
left, | ||
visitNode(node.right, visitor, isExpression))) | ||
); | ||
return inlineExpressions(expressions); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
??
isn't really a logical operator. This results in control-flow treating the branch as something "truthy" not something defined/undefined.I'd like to see some tests for control flow.