Skip to content

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

Merged
merged 34 commits into from
Sep 30, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
2ef3e0f
migrate nullish coalescing commit
Kingwl Aug 2, 2019
91a04ed
add more test case
Kingwl Aug 14, 2019
ba39ae8
add branch type check test
Kingwl Aug 14, 2019
079d002
add more tests
Kingwl Aug 14, 2019
3822fde
fix nullish precedence
Kingwl Aug 14, 2019
f67e524
update public api
Kingwl Aug 14, 2019
2327b3b
add rescan question question token to fix regression
Kingwl Aug 15, 2019
fb0d3c9
update public api baseline
Kingwl Aug 15, 2019
06149d0
Added tests that emit for nullish coalescing operator conforming with…
dragomirtitian Aug 15, 2019
3d94652
Fixed emit to hoist temporary variables (they previously went undecla…
dragomirtitian Aug 15, 2019
65b2008
Merge branch 'nullish-coalescing-operator' of https://github.com/King…
dragomirtitian Aug 15, 2019
e4497b8
Merge pull request #1 from dragomirtitian/nullish-coalescing-operator
Kingwl Aug 16, 2019
c2e336b
use not equal to null
Kingwl Aug 16, 2019
b714a01
rename factory
Kingwl Aug 16, 2019
323ebf0
add grammar check
Kingwl Aug 16, 2019
d659c83
fix more cases
Kingwl Aug 16, 2019
55dd6ae
Fix handling of nullish coalescing oprator in expando objects.
dragomirtitian Aug 18, 2019
22d1c07
Fixed classifier to support ?? operator.
dragomirtitian Aug 18, 2019
8427eca
Merge pull request #2 from dragomirtitian/nullish-coalescing-operator
Kingwl Aug 19, 2019
cb76a3e
Merge branch 'master' into nullish-coalescing-operator
Aug 19, 2019
7d3ccae
update baseline
Kingwl Aug 20, 2019
b412e50
accept baseline
Kingwl Aug 20, 2019
8227034
Merge branch 'master' into nullish-coalescing-operator
Kingwl Sep 13, 2019
57be95d
fix review
Kingwl Sep 13, 2019
78df31b
update baseline
Kingwl Sep 27, 2019
9e3852e
Merge branch 'nullish-coalescing-operator' of github.com:Kingwl/TypeS…
Kingwl Sep 27, 2019
de81520
update emitter and more testcase
Kingwl Sep 27, 2019
6418943
update control flow
Kingwl Sep 27, 2019
a719f66
make linter happy
Kingwl Sep 27, 2019
cb187cb
update libs
Kingwl Sep 27, 2019
7fd8658
avoid unnecessary assert
Kingwl Sep 27, 2019
6ef160f
fix typooo
Kingwl Sep 27, 2019
8c572b1
Merge branch 'master' into nullish-coalescing-operator
rbuckton Sep 30, 2019
b030f73
Fixes for control-flow analysis
rbuckton Sep 30, 2019
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
Prev Previous commit
Next Next commit
add more test case
  • Loading branch information
Kingwl committed Aug 14, 2019
commit 91a04ed5c92288739e4607c8601768d3e9cef4d6
1 change: 1 addition & 0 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1366,6 +1366,7 @@ namespace ts {
}
}

// TODO(rbuckton): Determine how to hook ?? into flow typing
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you going to address this?

function bindBinaryExpressionFlow(node: BinaryExpression) {
const operator = node.operatorToken.kind;
if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: This if-chain would be easier to read as a switch

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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.

Expand Down
15 changes: 15 additions & 0 deletions tests/baselines/reference/nullishCoalescingOperator3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//// [nullishCoalescingOperator3.ts]
declare const a1: 'literal' | undefined | null
declare const a2: '' | undefined | null
declare const a3: 1 | undefined | null
declare const a4: 0 | undefined | null
declare const a5: true | undefined | null
declare const a6: false | undefined | null


const aa1 = a1 ?? a2 ?? a3 ?? a4 ?? a5 ?? a6 ?? 'whatever'


//// [nullishCoalescingOperator3.js]
"use strict";
var aa1 = (_a = (_b = (_c = (_d = (_e = typeof a1 !== "undefined" && a1 !== null ? a1 : a2, _e !== void 0 && _e !== null ? _e : a3), _d !== void 0 && _d !== null ? _d : a4), _c !== void 0 && _c !== null ? _c : a5), _b !== void 0 && _b !== null ? _b : a6), _a !== void 0 && _a !== null ? _a : 'whatever');
29 changes: 29 additions & 0 deletions tests/baselines/reference/nullishCoalescingOperator3.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator3.ts ===
declare const a1: 'literal' | undefined | null
>a1 : Symbol(a1, Decl(nullishCoalescingOperator3.ts, 0, 13))

declare const a2: '' | undefined | null
>a2 : Symbol(a2, Decl(nullishCoalescingOperator3.ts, 1, 13))

declare const a3: 1 | undefined | null
>a3 : Symbol(a3, Decl(nullishCoalescingOperator3.ts, 2, 13))

declare const a4: 0 | undefined | null
>a4 : Symbol(a4, Decl(nullishCoalescingOperator3.ts, 3, 13))

declare const a5: true | undefined | null
>a5 : Symbol(a5, Decl(nullishCoalescingOperator3.ts, 4, 13))

declare const a6: false | undefined | null
>a6 : Symbol(a6, Decl(nullishCoalescingOperator3.ts, 5, 13))


const aa1 = a1 ?? a2 ?? a3 ?? a4 ?? a5 ?? a6 ?? 'whatever'
>aa1 : Symbol(aa1, Decl(nullishCoalescingOperator3.ts, 8, 5))
>a1 : Symbol(a1, Decl(nullishCoalescingOperator3.ts, 0, 13))
>a2 : Symbol(a2, Decl(nullishCoalescingOperator3.ts, 1, 13))
>a3 : Symbol(a3, Decl(nullishCoalescingOperator3.ts, 2, 13))
>a4 : Symbol(a4, Decl(nullishCoalescingOperator3.ts, 3, 13))
>a5 : Symbol(a5, Decl(nullishCoalescingOperator3.ts, 4, 13))
>a6 : Symbol(a6, Decl(nullishCoalescingOperator3.ts, 5, 13))

44 changes: 44 additions & 0 deletions tests/baselines/reference/nullishCoalescingOperator3.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator3.ts ===
declare const a1: 'literal' | undefined | null
>a1 : "literal" | null | undefined
>null : null

declare const a2: '' | undefined | null
>a2 : "" | null | undefined
>null : null

declare const a3: 1 | undefined | null
>a3 : 1 | null | undefined
>null : null

declare const a4: 0 | undefined | null
>a4 : 0 | null | undefined
>null : null

declare const a5: true | undefined | null
>a5 : true | null | undefined
>true : true
>null : null

declare const a6: false | undefined | null
>a6 : false | null | undefined
>false : false
>null : null


const aa1 = a1 ?? a2 ?? a3 ?? a4 ?? a5 ?? a6 ?? 'whatever'
>aa1 : boolean | "" | 0 | "literal" | 1 | "whatever"
>a1 ?? a2 ?? a3 ?? a4 ?? a5 ?? a6 ?? 'whatever' : boolean | "" | 0 | "literal" | 1 | "whatever"
>a1 ?? a2 ?? a3 ?? a4 ?? a5 ?? a6 : boolean | "" | 0 | "literal" | 1 | null | undefined
>a1 ?? a2 ?? a3 ?? a4 ?? a5 : true | "" | 0 | "literal" | 1 | null | undefined
>a1 ?? a2 ?? a3 ?? a4 : "" | 0 | "literal" | 1 | null | undefined
>a1 ?? a2 ?? a3 : "" | "literal" | 1 | null | undefined
>a1 ?? a2 : "" | "literal" | null | undefined
>a1 : "literal" | null | undefined
>a2 : "" | null | undefined
>a3 : 1 | null | undefined
>a4 : 0 | null | undefined
>a5 : true | null | undefined
>a6 : false | null | undefined
>'whatever' : "whatever"

36 changes: 36 additions & 0 deletions tests/baselines/reference/nullishCoalescingOperator_esnext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//// [nullishCoalescingOperator_esnext.ts]
// target: esnext

declare const a1: 'literal' | undefined | null
declare const a2: '' | undefined | null
declare const a3: 1 | undefined | null
declare const a4: 0 | undefined | null
declare const a5: true | undefined | null
declare const a6: false | undefined | null
declare const a7: unknown | null
declare const a8: never | null
declare const a9: any | null


const aa1 = a1 ?? 'whatever'
const aa2 = a2 ?? 'whatever'
const aa3 = a3 ?? 'whatever'
const aa4 = a4 ?? 'whatever'
const aa5 = a5 ?? 'whatever'
const aa6 = a6 ?? 'whatever'
const aa7 = a7 ?? 'whatever'
const aa8 = a8 ?? 'whatever'
const aa9 = a9 ?? 'whatever'

//// [nullishCoalescingOperator_esnext.js]
"use strict";
// target: esnext
var aa1 = typeof a1 !== "undefined" && a1 !== null ? a1 : 'whatever';
var aa2 = typeof a2 !== "undefined" && a2 !== null ? a2 : 'whatever';
var aa3 = typeof a3 !== "undefined" && a3 !== null ? a3 : 'whatever';
var aa4 = typeof a4 !== "undefined" && a4 !== null ? a4 : 'whatever';
var aa5 = typeof a5 !== "undefined" && a5 !== null ? a5 : 'whatever';
var aa6 = typeof a6 !== "undefined" && a6 !== null ? a6 : 'whatever';
var aa7 = typeof a7 !== "undefined" && a7 !== null ? a7 : 'whatever';
var aa8 = typeof a8 !== "undefined" && a8 !== null ? a8 : 'whatever';
var aa9 = typeof a9 !== "undefined" && a9 !== null ? a9 : 'whatever';
67 changes: 67 additions & 0 deletions tests/baselines/reference/nullishCoalescingOperator_esnext.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_esnext.ts ===
// target: esnext

declare const a1: 'literal' | undefined | null
>a1 : Symbol(a1, Decl(nullishCoalescingOperator_esnext.ts, 2, 13))

declare const a2: '' | undefined | null
>a2 : Symbol(a2, Decl(nullishCoalescingOperator_esnext.ts, 3, 13))

declare const a3: 1 | undefined | null
>a3 : Symbol(a3, Decl(nullishCoalescingOperator_esnext.ts, 4, 13))

declare const a4: 0 | undefined | null
>a4 : Symbol(a4, Decl(nullishCoalescingOperator_esnext.ts, 5, 13))

declare const a5: true | undefined | null
>a5 : Symbol(a5, Decl(nullishCoalescingOperator_esnext.ts, 6, 13))

declare const a6: false | undefined | null
>a6 : Symbol(a6, Decl(nullishCoalescingOperator_esnext.ts, 7, 13))

declare const a7: unknown | null
>a7 : Symbol(a7, Decl(nullishCoalescingOperator_esnext.ts, 8, 13))

declare const a8: never | null
>a8 : Symbol(a8, Decl(nullishCoalescingOperator_esnext.ts, 9, 13))

declare const a9: any | null
>a9 : Symbol(a9, Decl(nullishCoalescingOperator_esnext.ts, 10, 13))


const aa1 = a1 ?? 'whatever'
>aa1 : Symbol(aa1, Decl(nullishCoalescingOperator_esnext.ts, 13, 5))
>a1 : Symbol(a1, Decl(nullishCoalescingOperator_esnext.ts, 2, 13))

const aa2 = a2 ?? 'whatever'
>aa2 : Symbol(aa2, Decl(nullishCoalescingOperator_esnext.ts, 14, 5))
>a2 : Symbol(a2, Decl(nullishCoalescingOperator_esnext.ts, 3, 13))

const aa3 = a3 ?? 'whatever'
>aa3 : Symbol(aa3, Decl(nullishCoalescingOperator_esnext.ts, 15, 5))
>a3 : Symbol(a3, Decl(nullishCoalescingOperator_esnext.ts, 4, 13))

const aa4 = a4 ?? 'whatever'
>aa4 : Symbol(aa4, Decl(nullishCoalescingOperator_esnext.ts, 16, 5))
>a4 : Symbol(a4, Decl(nullishCoalescingOperator_esnext.ts, 5, 13))

const aa5 = a5 ?? 'whatever'
>aa5 : Symbol(aa5, Decl(nullishCoalescingOperator_esnext.ts, 17, 5))
>a5 : Symbol(a5, Decl(nullishCoalescingOperator_esnext.ts, 6, 13))

const aa6 = a6 ?? 'whatever'
>aa6 : Symbol(aa6, Decl(nullishCoalescingOperator_esnext.ts, 18, 5))
>a6 : Symbol(a6, Decl(nullishCoalescingOperator_esnext.ts, 7, 13))

const aa7 = a7 ?? 'whatever'
>aa7 : Symbol(aa7, Decl(nullishCoalescingOperator_esnext.ts, 19, 5))
>a7 : Symbol(a7, Decl(nullishCoalescingOperator_esnext.ts, 8, 13))

const aa8 = a8 ?? 'whatever'
>aa8 : Symbol(aa8, Decl(nullishCoalescingOperator_esnext.ts, 20, 5))
>a8 : Symbol(a8, Decl(nullishCoalescingOperator_esnext.ts, 9, 13))

const aa9 = a9 ?? 'whatever'
>aa9 : Symbol(aa9, Decl(nullishCoalescingOperator_esnext.ts, 21, 5))
>a9 : Symbol(a9, Decl(nullishCoalescingOperator_esnext.ts, 10, 13))

96 changes: 96 additions & 0 deletions tests/baselines/reference/nullishCoalescingOperator_esnext.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_esnext.ts ===
// target: esnext

declare const a1: 'literal' | undefined | null
>a1 : "literal" | null | undefined
>null : null

declare const a2: '' | undefined | null
>a2 : "" | null | undefined
>null : null

declare const a3: 1 | undefined | null
>a3 : 1 | null | undefined
>null : null

declare const a4: 0 | undefined | null
>a4 : 0 | null | undefined
>null : null

declare const a5: true | undefined | null
>a5 : true | null | undefined
>true : true
>null : null

declare const a6: false | undefined | null
>a6 : false | null | undefined
>false : false
>null : null

declare const a7: unknown | null
>a7 : unknown
>null : null

declare const a8: never | null
>a8 : null
>null : null

declare const a9: any | null
>a9 : any
>null : null


const aa1 = a1 ?? 'whatever'
>aa1 : "literal" | "whatever"
>a1 ?? 'whatever' : "literal" | "whatever"
>a1 : "literal" | null | undefined
>'whatever' : "whatever"

const aa2 = a2 ?? 'whatever'
>aa2 : "" | "whatever"
>a2 ?? 'whatever' : "" | "whatever"
>a2 : "" | null | undefined
>'whatever' : "whatever"

const aa3 = a3 ?? 'whatever'
>aa3 : 1 | "whatever"
>a3 ?? 'whatever' : 1 | "whatever"
>a3 : 1 | null | undefined
>'whatever' : "whatever"

const aa4 = a4 ?? 'whatever'
>aa4 : 0 | "whatever"
>a4 ?? 'whatever' : 0 | "whatever"
>a4 : 0 | null | undefined
>'whatever' : "whatever"

const aa5 = a5 ?? 'whatever'
>aa5 : true | "whatever"
>a5 ?? 'whatever' : true | "whatever"
>a5 : true | null | undefined
>'whatever' : "whatever"

const aa6 = a6 ?? 'whatever'
>aa6 : false | "whatever"
>a6 ?? 'whatever' : false | "whatever"
>a6 : false | null | undefined
>'whatever' : "whatever"

const aa7 = a7 ?? 'whatever'
>aa7 : unknown
>a7 ?? 'whatever' : unknown
>a7 : unknown
>'whatever' : "whatever"

const aa8 = a8 ?? 'whatever'
>aa8 : "whatever"
>a8 ?? 'whatever' : "whatever"
>a8 : null
>'whatever' : "whatever"

const aa9 = a9 ?? 'whatever'
>aa9 : any
>a9 ?? 'whatever' : any
>a9 : any
>'whatever' : "whatever"

32 changes: 32 additions & 0 deletions tests/baselines/reference/nullishCoalescingOperator_not_strict.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//// [nullishCoalescingOperator_not_strict.ts]
declare const a1: 'literal' | undefined | null
declare const a2: '' | undefined | null
declare const a3: 1 | undefined | null
declare const a4: 0 | undefined | null
declare const a5: true | undefined | null
declare const a6: false | undefined | null
declare const a7: unknown | null
declare const a8: never | null
declare const a9: any | null


const aa1 = a1 ?? 'whatever'
const aa2 = a2 ?? 'whatever'
const aa3 = a3 ?? 'whatever'
const aa4 = a4 ?? 'whatever'
const aa5 = a5 ?? 'whatever'
const aa6 = a6 ?? 'whatever'
const aa7 = a7 ?? 'whatever'
const aa8 = a8 ?? 'whatever'
const aa9 = a9 ?? 'whatever'

//// [nullishCoalescingOperator_not_strict.js]
var aa1 = typeof a1 !== "undefined" && a1 !== null ? a1 : 'whatever';
var aa2 = typeof a2 !== "undefined" && a2 !== null ? a2 : 'whatever';
var aa3 = typeof a3 !== "undefined" && a3 !== null ? a3 : 'whatever';
var aa4 = typeof a4 !== "undefined" && a4 !== null ? a4 : 'whatever';
var aa5 = typeof a5 !== "undefined" && a5 !== null ? a5 : 'whatever';
var aa6 = typeof a6 !== "undefined" && a6 !== null ? a6 : 'whatever';
var aa7 = typeof a7 !== "undefined" && a7 !== null ? a7 : 'whatever';
var aa8 = typeof a8 !== "undefined" && a8 !== null ? a8 : 'whatever';
var aa9 = typeof a9 !== "undefined" && a9 !== null ? a9 : 'whatever';
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_not_strict.ts ===
declare const a1: 'literal' | undefined | null
>a1 : Symbol(a1, Decl(nullishCoalescingOperator_not_strict.ts, 0, 13))

declare const a2: '' | undefined | null
>a2 : Symbol(a2, Decl(nullishCoalescingOperator_not_strict.ts, 1, 13))

declare const a3: 1 | undefined | null
>a3 : Symbol(a3, Decl(nullishCoalescingOperator_not_strict.ts, 2, 13))

declare const a4: 0 | undefined | null
>a4 : Symbol(a4, Decl(nullishCoalescingOperator_not_strict.ts, 3, 13))

declare const a5: true | undefined | null
>a5 : Symbol(a5, Decl(nullishCoalescingOperator_not_strict.ts, 4, 13))

declare const a6: false | undefined | null
>a6 : Symbol(a6, Decl(nullishCoalescingOperator_not_strict.ts, 5, 13))

declare const a7: unknown | null
>a7 : Symbol(a7, Decl(nullishCoalescingOperator_not_strict.ts, 6, 13))

declare const a8: never | null
>a8 : Symbol(a8, Decl(nullishCoalescingOperator_not_strict.ts, 7, 13))

declare const a9: any | null
>a9 : Symbol(a9, Decl(nullishCoalescingOperator_not_strict.ts, 8, 13))


const aa1 = a1 ?? 'whatever'
>aa1 : Symbol(aa1, Decl(nullishCoalescingOperator_not_strict.ts, 11, 5))
>a1 : Symbol(a1, Decl(nullishCoalescingOperator_not_strict.ts, 0, 13))

const aa2 = a2 ?? 'whatever'
>aa2 : Symbol(aa2, Decl(nullishCoalescingOperator_not_strict.ts, 12, 5))
>a2 : Symbol(a2, Decl(nullishCoalescingOperator_not_strict.ts, 1, 13))

const aa3 = a3 ?? 'whatever'
>aa3 : Symbol(aa3, Decl(nullishCoalescingOperator_not_strict.ts, 13, 5))
>a3 : Symbol(a3, Decl(nullishCoalescingOperator_not_strict.ts, 2, 13))

const aa4 = a4 ?? 'whatever'
>aa4 : Symbol(aa4, Decl(nullishCoalescingOperator_not_strict.ts, 14, 5))
>a4 : Symbol(a4, Decl(nullishCoalescingOperator_not_strict.ts, 3, 13))

const aa5 = a5 ?? 'whatever'
>aa5 : Symbol(aa5, Decl(nullishCoalescingOperator_not_strict.ts, 15, 5))
>a5 : Symbol(a5, Decl(nullishCoalescingOperator_not_strict.ts, 4, 13))

const aa6 = a6 ?? 'whatever'
>aa6 : Symbol(aa6, Decl(nullishCoalescingOperator_not_strict.ts, 16, 5))
>a6 : Symbol(a6, Decl(nullishCoalescingOperator_not_strict.ts, 5, 13))

const aa7 = a7 ?? 'whatever'
>aa7 : Symbol(aa7, Decl(nullishCoalescingOperator_not_strict.ts, 17, 5))
>a7 : Symbol(a7, Decl(nullishCoalescingOperator_not_strict.ts, 6, 13))

const aa8 = a8 ?? 'whatever'
>aa8 : Symbol(aa8, Decl(nullishCoalescingOperator_not_strict.ts, 18, 5))
>a8 : Symbol(a8, Decl(nullishCoalescingOperator_not_strict.ts, 7, 13))

const aa9 = a9 ?? 'whatever'
>aa9 : Symbol(aa9, Decl(nullishCoalescingOperator_not_strict.ts, 19, 5))
>a9 : Symbol(a9, Decl(nullishCoalescingOperator_not_strict.ts, 8, 13))

Loading