Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged

Conversation

Kingwl
Copy link
Contributor

@KingwlKingwl commentedAug 14, 2019
edited
Loading

followhttps://tc39.es/proposal-nullish-coalescing/

Introduction
This document specifies the nullish coalescing operator ??. See the explainer for an introduction.

The main design decisions made in this specification are:

The right argument of ?? is evaluated only if needed ("short circuiting").
?? haslower precedence than ||.
??cannot immediately contain, or be contained within, an && or || operation.
The right argument is selected if the left argument is null or undefined.

Fixes#26578

TODO:

jack-williams, HairyRabbit, fuafa, AlCalzone, dragomirtitian, j-oliveras, alitaheri, DanielRosenwasser, phenomnomnominal, juanpicado, and 44 more reacted with thumbs up emojifatcerberus, j-oliveras, alitaheri, DanielRosenwasser, mucsi96, alexdresko, nathanph, MattiasBuelens, styfle, ExE-Boss, and 19 more reacted with hooray emojiAlCalzone, dragomirtitian, j-oliveras, alitaheri, DanielRosenwasser, juanpicado, pilioussis, aleclarson, ra100, alexdresko, and 20 more reacted with heart emojiAviVahl, j-oliveras, alitaheri, DanielRosenwasser, juanpicado, aleclarson, strax, alexdresko, nathanph, styfle, and 11 more reacted with rocket emojiihailong, NE-SmallTown, and aiherrera reacted with eyes emoji
@KingwlKingwl changed the titlemigrate nullish coalescing commitnullish coalescing commitAug 14, 2019
@KingwlKingwlforce-pushed thenullish-coalescing-operator branch fromb33eeac to2ef3e0fCompareAugust 14, 2019 08:47
@AlCalzone
Copy link
Contributor

Is this the real life? 😍

jpvillaseca, mickdekkers, alexdresko, acshef, xorets, rossleonardy, ronhuang, OG84, a-x-, agrinko, and 7 more reacted with laugh emoji

@sheetalkamatsheetalkamat self-assigned thisAug 14, 2019
@Kingwl
Copy link
ContributorAuthor

@typescript-bot test this.

@typescript-bot
Copy link
Collaborator

typescript-bot commentedAug 15, 2019
edited
Loading

Heya@Kingwl, I've started to run the extended test suite on this PR at2327b3b. You can monitor the buildhere. It should now contribute to this PR's status checks.

@@ -23917,6 +23918,10 @@ namespace ts {
return getTypeFacts(leftType) & TypeFacts.Falsy ?
getUnionType([removeDefinitelyFalsyTypes(leftType), rightType], UnionReduction.Subtype) :
leftType;
case SyntaxKind.QuestionQuestionToken:
return getTypeFacts(leftType) & TypeFacts.EQUndefinedOrNull ?
getUnionType([getNonNullableType(leftType), rightType], UnionReduction.Subtype) :

Choose a reason for hiding this comment

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

Does it make sense to also return a union type for whenstrictNullChecks is off?

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

I'd like to say yes, every value could be null/undefined if strictNullChecks is off and we cannot detect that.

same as:

declareconsta:stringletb=a||1// b is string || number

@@ -3044,6 +3044,10 @@ namespace ts {
return createBinary(left, SyntaxKind.BarBarToken, right);
}

export function createNullishCoalescing(left: Expression, right: Expression) {

Choose a reason for hiding this comment

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

Nit:createNullishCoalesce? I dunno, what do you think@rbuckton?

Copy link
Member

@DanielRosenwasserDanielRosenwasser left a comment

Choose a reason for hiding this comment

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

Progress looks great!


//// [nullishCoalescingOperator1.js]
"use strict";
var aa1 = typeof a1 !== "undefined" && a1 !== null ? a1 : 'whatever';
Copy link
Member

@DanielRosenwasserDanielRosenwasserAug 15, 2019
edited
Loading

Choose a reason for hiding this comment

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

Just as a heads up, we might want to just go witha1 != null, sincedocument.all is a weird anomaly of the language anyway that should ideally never be used in a?? expression.

Copy link
Contributor

@arusakovarusakovNov 6, 2019
edited
Loading

Choose a reason for hiding this comment

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

@DanielRosenwasser
Sorry for the late comment after TypeScript 3.7 release.
But what about the shorter implementation of?? operator that you have suggested?
This implementation with less code is better for all of us, I think.

@DanielRosenwasser
Copy link
Member

DanielRosenwasser commentedAug 15, 2019
edited
Loading

.js emit test cases I'd like you to consider when targeting ESNext:

declareleta:any,b:any,c:any;letx1=(a??basany)||c;letx2=c||(a??basany);letx3=((a??b)asany)||c;letx4=c||((a??b)asany);letx5=(a??b)asany||c;letx6=c||(a??b)asany;lety1=(a??basany)&&c;lety2=c&&(a??basany);lety3=((a??b)asany)&&c;lety4=c&&((a??b)asany);lety5=(a??b)asany&&c;lety6=c&&(a??b)asany;

@dragomirtitian
Copy link
Contributor

@DanielRosenwasser I've added the tests, emit appears to work as expected keeping the() around thea ?? b. So as to conform to the grammar requirement that:

?? cannot immediately contain, or be contained within, an&& or|| operation.

Hope I didn't miss the point of the tests 😅

@rbuckton or@DanielRosenwasser
One thing I noticed was that emit is using the actual identifier in the down level version of??. Sox ?? 0 becomestypeof x !== undefined && x !== null ? x : 0.

But ifx comes from an import, because of the order in which the transformations are applied, we might get side effects on the access tox:

//test2.tsletx={y:1,x:0}letv=0;Object.defineProperty(x,"x",{get(){returnv++;}})export=x;//usage.tsimport{x,y}from'./test2'letxo=x??"NO"console.log(xo);letyo=y??"NO"console.log(yo);

This will output2 and1 becauselet xo = x ?? "NO" becomesvar xo = typeof test2_1.x !== "undefined" && test2_1.x !== null ? test2_1.x : "NO"; which will call the getter multiple times.

I would just use the approach babel uses, use a temporary variable alwaysex. Thoughts ?

DanielRosenwasser, ckknight, Kingwl, and DioneMo reacted with thumbs up emoji

@DanielRosenwasser
Copy link
Member

I think "use a temporary unless it's an identifier" is usually the approach we take.

@dragomirtitian
Copy link
Contributor

@DanielRosenwasser Mkay 😕, so ignore the corner case above ?

Just to make sure I was clear in what I was trying to sayx ?? "NO" is seen as using an identifier in theesnext transform, but thecommonJS transformation will effectively turn it intotest2_1.x ?? "NO" (with the actual result beingtypeof test2_1.x !== "undefined" && test2_1.x !== null ? test2_1.x : "NO";)

@Kingwl
Copy link
ContributorAuthor

Kingwl commentedAug 16, 2019
edited
Loading

@dragomirtitian
I prefer it to be a side effect (or feature) of cjs.
not only this one but also many other syntaxes.

But i felt assign to temp variable is better

@Kingwl
Copy link
ContributorAuthor

@typescript-bot pack this.

@typescript-bot
Copy link
Collaborator

typescript-bot commentedSep 20, 2019
edited
Loading

Heya@Kingwl, I've started to run the tarball bundle task on this PR at57be95d. You can monitor the buildhere. It should now contribute to this PR's status checks.

@typescript-bot
Copy link
Collaborator

Hey@Kingwl, I've packed this intoan installable tgz. You can install it for testing by referencing it in yourpackage.json like so:

{    "devDependencies": {        "typescript": "https://typescript.visualstudio.com/cf7ac146-d525-443c-b23c-0d58337efebc/_apis/build/builds/44785/artifacts?artifactName=tgz&fileId=64FF4F06CBE74357042C0E22BEF9D252966E889A57B59FEB9CE7822F7DA3784002&fileName=/typescript-3.7.0-insiders.20190920.tgz"    }}

and then runningnpm install.

@@ -1502,6 +1503,7 @@ namespace ts {
export type LogicalOperator

Choose a reason for hiding this comment

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

This is actually kind of strange because it's notreally a LogicalOperator. Should it be moved out?

Copy link
Member

@DanielRosenwasserDanielRosenwasser left a comment
edited
Loading

Choose a reason for hiding this comment

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

Would you be able to update the API baselines?

We'd really like to merge this in by tomorrow for the beta. There seem to be only minor issues (control flow analysis not being entirely correct), but those can be fixed by the RC.

default:
return visitEachChild(node, visitor, context);
}
}

function createNotNullCondition(node: Expression) {
return createBinary(

Choose a reason for hiding this comment

The 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(tempcreateToken(SyntaxKind.ExclamationEqualsEqualsToken),createNull()),createToken(SyntaxKind.AmpersandAmpersandToken),createBinary(temp,createToken(SyntaxKind.ExclamationEqualsEqualsToken),createVoidZero()));

(@rbuckton)

@@ -943,7 +943,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);
Copy link
Contributor

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.

@Kingwl
Copy link
ContributorAuthor

I’ll update that today

Copy link

@robpalmerobpalme left a comment

Choose a reason for hiding this comment

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

Some trivial things.

@@ -1435,6 +1435,14 @@ namespace ts {
bindCondition(node.right, trueTarget, falseTarget);
}

function bindNullishCollasingExpression(node: BinaryExpression, trueTarget: FlowLabel, falseTarget: FlowLabel) {

Choose a reason for hiding this comment

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

Typo:bindNullishCollasingExpression ->bindNullishCoalescingExpression

Kingwl reacted with laugh emoji
@@ -1461,12 +1469,15 @@ 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) {

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 aswitch

mklef121 and nxpatterns reacted with thumbs up emoji
Copy link
ContributorAuthor

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.

@@ -1828,6 +1831,9 @@ namespace ts {
pos++;
return token = SyntaxKind.GreaterThanToken;
case CharacterCodes.question:
if (text.charCodeAt(pos + 1) === CharacterCodes.question) {

Choose a reason for hiding this comment

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

Nit: If you re-order thepos++ before theif, the code become marginally simpler.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

I prefer to be consistent with the existed code.

@RyanCavanaughRyanCavanaugh added this to theTypeScript 3.7.0 milestoneSep 30, 2019
# Conflicts:#src/compiler/scanner.ts#src/compiler/transformers/esnext.ts#src/compiler/utilities.ts#tests/baselines/reference/api/tsserverlibrary.d.ts#tests/baselines/reference/api/typescript.d.ts
@RyanCavanaughRyanCavanaugh merged commit7c50bcc intomicrosoft:masterSep 30, 2019
@rbuckton
Copy link
Contributor

@Kingwl: Thanks for the contribution!

My changes were mostly to merge the control-flow behavior of nullish-coalesce with the control-flow behavior of optional chaining and to resolve merge conflicts so that this could be merged with master for the 3.7 beta. Thanks again for all of the hard work!

ExE-Boss, Kingwl, and kirintwn reacted with thumbs up emojiKingwl reacted with laugh emojiKingwl reacted with hooray emojiKingwl reacted with heart emoji

@wsmd
Copy link

wsmd commentedNov 6, 2019

Thank you all for your hard work on this and congrats on the 3.7 release!

I have a small question out of curiosity. Forfoo ?? bar, wasdocument.all the reason for choosingfoo !== null && foo !== void 0 as the conditional expression in the compiled output, as opposed to theabstract equality comparisonfoo != null? 😅

letx=(foo!==null&&foo!==undefined) ?foo :bar;// vsletx=foo!=null ?foo :bar;

@KingwlKingwl deleted the nullish-coalescing-operator branchNovember 6, 2019 11:20
@Kingwl
Copy link
ContributorAuthor

was document.all the reason for
@wsmd
#32883 (comment)
#32883 (comment)

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@arusakovarusakovarusakov left review comments

@robpalmerobpalmerobpalme left review comments

@sheetalkamatsheetalkamatsheetalkamat requested changes

@DanielRosenwasserDanielRosenwasserDanielRosenwasser approved these changes

@rbucktonrbucktonrbuckton approved these changes

Assignees

@sheetalkamatsheetalkamat

Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Nullish coalescing operator (??)
12 participants
@Kingwl@AlCalzone@typescript-bot@DanielRosenwasser@dragomirtitian@weswigham@rbuckton@wsmd@arusakov@robpalme@sheetalkamat@RyanCavanaugh

[8]ページ先頭

©2009-2025 Movatter.jp