Skip to content

🤖 Cherry-pick PR #34702 into release-3.7 #34710

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

Merged
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
10 changes: 5 additions & 5 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

/* @internal */
namespace ts {
export const enum ModuleInstanceState {
Expand Down Expand Up @@ -951,11 +952,10 @@ namespace ts {
if (!expression) {
return flags & FlowFlags.TrueCondition ? antecedent : unreachableFlow;
}
if (expression.kind === SyntaxKind.TrueKeyword && flags & FlowFlags.FalseCondition ||
expression.kind === SyntaxKind.FalseKeyword && flags & FlowFlags.TrueCondition) {
if (!isExpressionOfOptionalChainRoot(expression)) {
return unreachableFlow;
}
if ((expression.kind === SyntaxKind.TrueKeyword && flags & FlowFlags.FalseCondition ||
expression.kind === SyntaxKind.FalseKeyword && flags & FlowFlags.TrueCondition) &&
!isExpressionOfOptionalChainRoot(expression) && !isNullishCoalesce(expression.parent)) {
return unreachableFlow;
}
if (!isNarrowingExpression(expression)) {
return antecedent;
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5925,6 +5925,10 @@ namespace ts {
return isOptionalChainRoot(node.parent) && node.parent.expression === node;
}

export function isNullishCoalesce(node: Node) {
return node.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>node).operatorToken.kind === SyntaxKind.QuestionQuestionToken;
}

export function isNewExpression(node: Node): node is NewExpression {
return node.kind === SyntaxKind.NewExpression;
}
Expand Down
1 change: 1 addition & 0 deletions tests/baselines/reference/api/tsserverlibrary.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3525,6 +3525,7 @@ declare namespace ts {
function isCallExpression(node: Node): node is CallExpression;
function isCallChain(node: Node): node is CallChain;
function isOptionalChain(node: Node): node is PropertyAccessChain | ElementAccessChain | CallChain;
function isNullishCoalesce(node: Node): boolean;
function isNewExpression(node: Node): node is NewExpression;
function isTaggedTemplateExpression(node: Node): node is TaggedTemplateExpression;
function isTypeAssertion(node: Node): node is TypeAssertion;
Expand Down
1 change: 1 addition & 0 deletions tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3525,6 +3525,7 @@ declare namespace ts {
function isCallExpression(node: Node): node is CallExpression;
function isCallChain(node: Node): node is CallChain;
function isOptionalChain(node: Node): node is PropertyAccessChain | ElementAccessChain | CallChain;
function isNullishCoalesce(node: Node): boolean;
function isNewExpression(node: Node): node is NewExpression;
function isTaggedTemplateExpression(node: Node): node is TaggedTemplateExpression;
function isTypeAssertion(node: Node): node is TypeAssertion;
Expand Down
44 changes: 43 additions & 1 deletion tests/baselines/reference/nullishCoalescingOperator1.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,36 @@ const cc4 = c4 ?? true;
const dd1 = d1 ?? {b: 1};
const dd2 = d2 ?? {b: 1};
const dd3 = d3 ?? {b: 1};
const dd4 = d4 ?? {b: 1};
const dd4 = d4 ?? {b: 1};

// Repro from #34635

declare function foo(): void;

const maybeBool = false;

if (!(maybeBool ?? true)) {
foo();
}

if (maybeBool ?? true) {
foo();
}
else {
foo();
}

if (false ?? true) {
foo();
}
else {
foo();
}


//// [nullishCoalescingOperator1.js]
"use strict";
var _a;
var aa1 = (a1 !== null && a1 !== void 0 ? a1 : 'whatever');
var aa2 = (a2 !== null && a2 !== void 0 ? a2 : 'whatever');
var aa3 = (a3 !== null && a3 !== void 0 ? a3 : 'whatever');
Expand All @@ -58,3 +84,19 @@ var dd1 = (d1 !== null && d1 !== void 0 ? d1 : { b: 1 });
var dd2 = (d2 !== null && d2 !== void 0 ? d2 : { b: 1 });
var dd3 = (d3 !== null && d3 !== void 0 ? d3 : { b: 1 });
var dd4 = (d4 !== null && d4 !== void 0 ? d4 : { b: 1 });
var maybeBool = false;
if (!((maybeBool !== null && maybeBool !== void 0 ? maybeBool : true))) {
foo();
}
if ((maybeBool !== null && maybeBool !== void 0 ? maybeBool : true)) {
foo();
}
else {
foo();
}
if (_a = false, (_a !== null && _a !== void 0 ? _a : true)) {
foo();
}
else {
foo();
}
35 changes: 35 additions & 0 deletions tests/baselines/reference/nullishCoalescingOperator1.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,38 @@ const dd4 = d4 ?? {b: 1};
>d4 : Symbol(d4, Decl(nullishCoalescingOperator1.ts, 19, 13))
>b : Symbol(b, Decl(nullishCoalescingOperator1.ts, 39, 19))

// Repro from #34635

declare function foo(): void;
>foo : Symbol(foo, Decl(nullishCoalescingOperator1.ts, 39, 25))

const maybeBool = false;
>maybeBool : Symbol(maybeBool, Decl(nullishCoalescingOperator1.ts, 45, 5))

if (!(maybeBool ?? true)) {
>maybeBool : Symbol(maybeBool, Decl(nullishCoalescingOperator1.ts, 45, 5))

foo();
>foo : Symbol(foo, Decl(nullishCoalescingOperator1.ts, 39, 25))
}

if (maybeBool ?? true) {
>maybeBool : Symbol(maybeBool, Decl(nullishCoalescingOperator1.ts, 45, 5))

foo();
>foo : Symbol(foo, Decl(nullishCoalescingOperator1.ts, 39, 25))
}
else {
foo();
>foo : Symbol(foo, Decl(nullishCoalescingOperator1.ts, 39, 25))
}

if (false ?? true) {
foo();
>foo : Symbol(foo, Decl(nullishCoalescingOperator1.ts, 39, 25))
}
else {
foo();
>foo : Symbol(foo, Decl(nullishCoalescingOperator1.ts, 39, 25))
}

51 changes: 51 additions & 0 deletions tests/baselines/reference/nullishCoalescingOperator1.types
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,54 @@ const dd4 = d4 ?? {b: 1};
>b : number
>1 : 1

// Repro from #34635

declare function foo(): void;
>foo : () => void

const maybeBool = false;
>maybeBool : false
>false : false

if (!(maybeBool ?? true)) {
>!(maybeBool ?? true) : true
>(maybeBool ?? true) : false
>maybeBool ?? true : false
>maybeBool : false
>true : true

foo();
>foo() : void
>foo : () => void
}

if (maybeBool ?? true) {
>maybeBool ?? true : false
>maybeBool : false
>true : true

foo();
>foo() : void
>foo : () => void
}
else {
foo();
>foo() : void
>foo : () => void
}

if (false ?? true) {
>false ?? true : false
>false : false
>true : true

foo();
>foo() : void
>foo : () => void
}
else {
foo();
>foo() : void
>foo : () => void
}

Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// @strict: true
// @allowUnreachableCode: false

declare const a1: string | undefined | null
declare const a2: string | undefined | null
Expand Down Expand Up @@ -39,4 +40,28 @@ const cc4 = c4 ?? true;
const dd1 = d1 ?? {b: 1};
const dd2 = d2 ?? {b: 1};
const dd3 = d3 ?? {b: 1};
const dd4 = d4 ?? {b: 1};
const dd4 = d4 ?? {b: 1};

// Repro from #34635

declare function foo(): void;

const maybeBool = false;

if (!(maybeBool ?? true)) {
foo();
}

if (maybeBool ?? true) {
foo();
}
else {
foo();
}

if (false ?? true) {
foo();
}
else {
foo();
}