Skip to content

Commit b73411c

Browse files
committed
Fix type and simplify code
1 parent b59e4c5 commit b73411c

20 files changed

+136
-148
lines changed

src/compiler/checker.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20813,7 +20813,6 @@ namespace ts {
2081320813
case SyntaxKind.AmpersandAmpersandEqualsToken:
2081420814
case SyntaxKind.QuestionQuestionEqualsToken:
2081520815
return narrowTypeByTruthiness(narrowType(type, expr.right, assumeTrue), expr.left, assumeTrue);
20816-
2081720816
case SyntaxKind.EqualsEqualsToken:
2081820817
case SyntaxKind.ExclamationEqualsToken:
2081920818
case SyntaxKind.EqualsEqualsEqualsToken:
@@ -22437,6 +22436,9 @@ namespace ts {
2243722436
const { left, operatorToken, right } = binaryExpression;
2243822437
switch (operatorToken.kind) {
2243922438
case SyntaxKind.EqualsToken:
22439+
case SyntaxKind.AmpersandAmpersandEqualsToken:
22440+
case SyntaxKind.BarBarEqualsToken:
22441+
case SyntaxKind.QuestionQuestionEqualsToken:
2244022442
if (node !== right) {
2244122443
return undefined;
2244222444
}
@@ -22447,8 +22449,6 @@ namespace ts {
2244722449
return contextSensitive === true ? getTypeOfExpression(left) : contextSensitive;
2244822450
case SyntaxKind.BarBarToken:
2244922451
case SyntaxKind.QuestionQuestionToken:
22450-
case SyntaxKind.BarBarEqualsToken:
22451-
case SyntaxKind.QuestionQuestionEqualsToken:
2245222452
// When an || expression has a contextual type, the operands are contextually typed by that type, except
2245322453
// when that type originates in a binding pattern, the right operand is contextually typed by the type of
2245422454
// the left operand. When an || expression has no contextual type, the right operand is contextually typed

src/compiler/transformers/esnext.ts

Lines changed: 42 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -21,65 +21,61 @@ namespace ts {
2121
switch (node.kind) {
2222
case SyntaxKind.BinaryExpression:
2323
const binaryExpression = <BinaryExpression>node;
24-
if (isLogicalOrCoalescingAssignmentOperator(binaryExpression.operatorToken.kind)) {
25-
return transformLogicalAssignmentOperators(binaryExpression);
24+
if (isLogicalOrCoalescingAssignmentExpression(binaryExpression)) {
25+
return transformLogicalAssignmentOperator(binaryExpression);
2626
}
2727
// falls through
2828
default:
2929
return visitEachChild(node, visitor, context);
3030
}
3131
}
3232

33-
function transformLogicalAssignmentOperators(binaryExpression: BinaryExpression): VisitResult<Node> {
33+
function transformLogicalAssignmentOperator(binaryExpression: AssignmentExpression<Token<LogicalOrCoalescingAssignmentOperator>>): VisitResult<Node> {
3434
const operator = binaryExpression.operatorToken;
35-
if (isCompoundAssignment(operator.kind) && isLogicalOrCoalescingAssignmentOperator(operator.kind)) {
36-
const nonAssignmentOperator = getNonAssignmentOperatorForCompoundAssignment(operator.kind);
37-
let left = skipParentheses(visitNode(binaryExpression.left, visitor, isLeftHandSideExpression));
38-
let assignmentTarget = left;
39-
const right = skipParentheses(visitNode(binaryExpression.right, visitor, isExpression));
40-
if (isPropertyAccessExpression(left) || isElementAccessExpression(left)) {
41-
const tempVariable = createTempVariable(hoistVariableDeclaration);
42-
if (isPropertyAccessExpression(left)) {
43-
assignmentTarget = createPropertyAccess(
35+
const nonAssignmentOperator = getNonAssignmentOperatorForCompoundAssignment(operator.kind);
36+
let left = skipParentheses(visitNode(binaryExpression.left, visitor, isLeftHandSideExpression));
37+
let assignmentTarget = left;
38+
const right = skipParentheses(visitNode(binaryExpression.right, visitor, isExpression));
39+
if (isAccessExpression(left)) {
40+
const tempVariable = createTempVariable(hoistVariableDeclaration);
41+
if (isPropertyAccessExpression(left)) {
42+
assignmentTarget = createPropertyAccess(
43+
tempVariable,
44+
left.name
45+
);
46+
left = createPropertyAccess(
47+
createAssignment(
4448
tempVariable,
45-
left.name
46-
);
47-
left = createPropertyAccess(
48-
createAssignment(
49-
tempVariable,
50-
left.expression
51-
),
52-
left.name
53-
);
54-
}
55-
else {
56-
assignmentTarget = createElementAccess(
49+
left.expression
50+
),
51+
left.name
52+
);
53+
}
54+
else {
55+
assignmentTarget = createElementAccess(
56+
tempVariable,
57+
left.argumentExpression
58+
);
59+
left = createElementAccess(
60+
createAssignment(
5761
tempVariable,
58-
left.argumentExpression
59-
);
60-
left = createElementAccess(
61-
createAssignment(
62-
tempVariable,
63-
left.expression
64-
),
65-
left.argumentExpression
66-
);
67-
}
62+
left.expression
63+
),
64+
left.argumentExpression
65+
);
6866
}
67+
}
6968

70-
return createBinary(
71-
left,
72-
nonAssignmentOperator,
73-
createParen(
74-
createAssignment(
75-
assignmentTarget,
76-
right
77-
)
69+
return createBinary(
70+
left,
71+
nonAssignmentOperator,
72+
createParen(
73+
createAssignment(
74+
assignmentTarget,
75+
right
7876
)
79-
);
80-
81-
}
82-
Debug.fail("unexpected operator: " + operator.kind);
77+
)
78+
);
8379
}
8480
}
8581
}

src/compiler/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1635,6 +1635,12 @@ namespace ts {
16351635
| SyntaxKind.CommaToken
16361636
;
16371637

1638+
export type LogicalOrCoalescingAssignmentOperator
1639+
= SyntaxKind.AmpersandAmpersandEqualsToken
1640+
| SyntaxKind.BarBarEqualsToken
1641+
| SyntaxKind.QuestionQuestionEqualsToken
1642+
;
1643+
16381644
export type BinaryOperatorToken = Token<BinaryOperator>;
16391645

16401646
export interface BinaryExpression extends Expression, Declaration {

src/compiler/utilities.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4450,12 +4450,16 @@ namespace ts {
44504450
|| token === SyntaxKind.ExclamationToken;
44514451
}
44524452

4453-
export function isLogicalOrCoalescingAssignmentOperator(token: SyntaxKind): boolean {
4453+
export function isLogicalOrCoalescingAssignmentOperator(token: SyntaxKind): token is LogicalOrCoalescingAssignmentOperator {
44544454
return token === SyntaxKind.BarBarEqualsToken
44554455
|| token === SyntaxKind.AmpersandAmpersandEqualsToken
44564456
|| token === SyntaxKind.QuestionQuestionEqualsToken;
44574457
}
44584458

4459+
export function isLogicalOrCoalescingAssignmentExpression(expr: BinaryExpression): expr is AssignmentExpression<Token<LogicalOrCoalescingAssignmentOperator>> {
4460+
return isLogicalOrCoalescingAssignmentOperator(expr.operatorToken.kind);
4461+
}
4462+
44594463
export function isAssignmentOperator(token: SyntaxKind): boolean {
44604464
return token >= SyntaxKind.FirstAssignment && token <= SyntaxKind.LastAssignment;
44614465
}

tests/baselines/reference/logicalAssignment2(target=es2015).js

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ b.baz ||= result.baz
1919
c.baz ??= result.baz
2020

2121
a.foo["baz"] &&= result.foo.baz
22-
b.foo["baz"] &&= result.foo.baz
23-
c.foo["baz"] &&= result.foo.baz
22+
b.foo["baz"] ||= result.foo.baz
23+
c.foo["baz"] ??= result.foo.baz
2424

2525
a.foo.bar().baz &&= result.foo.bar().baz
2626
b.foo.bar().baz ||= result.foo.bar().baz
@@ -30,14 +30,14 @@ c.foo.bar().baz ??= result.foo.bar().baz
3030

3131
//// [logicalAssignment2.js]
3232
"use strict";
33-
var _a, _b;
34-
var _c, _d, _e, _f, _g, _h, _j, _k, _l;
35-
(_c = a).baz && (_c.baz = result.baz);
36-
(_d = b).baz || (_d.baz = result.baz);
37-
(_a = (_e = c).baz) !== null && _a !== void 0 ? _a : (_e.baz = result.baz);
38-
(_f = a.foo)["baz"] && (_f["baz"] = result.foo.baz);
39-
(_g = b.foo)["baz"] && (_g["baz"] = result.foo.baz);
40-
(_h = c.foo)["baz"] && (_h["baz"] = result.foo.baz);
41-
(_j = a.foo.bar()).baz && (_j.baz = result.foo.bar().baz);
42-
(_k = b.foo.bar()).baz || (_k.baz = result.foo.bar().baz);
43-
(_b = (_l = c.foo.bar()).baz) !== null && _b !== void 0 ? _b : (_l.baz = result.foo.bar().baz);
33+
var _a, _b, _c;
34+
var _d, _e, _f, _g, _h, _j, _k, _l, _m;
35+
(_d = a).baz && (_d.baz = result.baz);
36+
(_e = b).baz || (_e.baz = result.baz);
37+
(_a = (_f = c).baz) !== null && _a !== void 0 ? _a : (_f.baz = result.baz);
38+
(_g = a.foo)["baz"] && (_g["baz"] = result.foo.baz);
39+
(_h = b.foo)["baz"] || (_h["baz"] = result.foo.baz);
40+
(_b = (_j = c.foo)["baz"]) !== null && _b !== void 0 ? _b : (_j["baz"] = result.foo.baz);
41+
(_k = a.foo.bar()).baz && (_k.baz = result.foo.bar().baz);
42+
(_l = b.foo.bar()).baz || (_l.baz = result.foo.bar().baz);
43+
(_c = (_m = c.foo.bar()).baz) !== null && _c !== void 0 ? _c : (_m.baz = result.foo.bar().baz);

tests/baselines/reference/logicalAssignment2(target=es2015).symbols

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ a.foo["baz"] &&= result.foo.baz
6969
>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13))
7070
>baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9))
7171

72-
b.foo["baz"] &&= result.foo.baz
72+
b.foo["baz"] ||= result.foo.baz
7373
>b.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13))
7474
>b : Symbol(b, Decl(logicalAssignment2.ts, 12, 13))
7575
>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13))
@@ -80,7 +80,7 @@ b.foo["baz"] &&= result.foo.baz
8080
>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13))
8181
>baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9))
8282

83-
c.foo["baz"] &&= result.foo.baz
83+
c.foo["baz"] ??= result.foo.baz
8484
>c.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13))
8585
>c : Symbol(c, Decl(logicalAssignment2.ts, 13, 13))
8686
>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13))

tests/baselines/reference/logicalAssignment2(target=es2015).types

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ a.foo["baz"] &&= result.foo.baz
6868
>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; }
6969
>baz : "" | 0 | 1 | 42 | undefined
7070

71-
b.foo["baz"] &&= result.foo.baz
72-
>b.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined
71+
b.foo["baz"] ||= result.foo.baz
72+
>b.foo["baz"] ||= result.foo.baz : "" | 0 | 1 | 42 | undefined
7373
>b.foo["baz"] : "" | 0 | 1 | 42 | undefined
7474
>b.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; }
7575
>b : A
@@ -81,8 +81,8 @@ b.foo["baz"] &&= result.foo.baz
8181
>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; }
8282
>baz : "" | 0 | 1 | 42 | undefined
8383

84-
c.foo["baz"] &&= result.foo.baz
85-
>c.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined
84+
c.foo["baz"] ??= result.foo.baz
85+
>c.foo["baz"] ??= result.foo.baz : "" | 0 | 1 | 42 | undefined
8686
>c.foo["baz"] : "" | 0 | 1 | 42 | undefined
8787
>c.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; }
8888
>c : A

tests/baselines/reference/logicalAssignment2(target=es2020).js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ b.baz ||= result.baz
1919
c.baz ??= result.baz
2020

2121
a.foo["baz"] &&= result.foo.baz
22-
b.foo["baz"] &&= result.foo.baz
23-
c.foo["baz"] &&= result.foo.baz
22+
b.foo["baz"] ||= result.foo.baz
23+
c.foo["baz"] ??= result.foo.baz
2424

2525
a.foo.bar().baz &&= result.foo.bar().baz
2626
b.foo.bar().baz ||= result.foo.bar().baz
@@ -35,8 +35,8 @@ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
3535
(_b = b).baz || (_b.baz = result.baz);
3636
(_c = c).baz ?? (_c.baz = result.baz);
3737
(_d = a.foo)["baz"] && (_d["baz"] = result.foo.baz);
38-
(_e = b.foo)["baz"] && (_e["baz"] = result.foo.baz);
39-
(_f = c.foo)["baz"] && (_f["baz"] = result.foo.baz);
38+
(_e = b.foo)["baz"] || (_e["baz"] = result.foo.baz);
39+
(_f = c.foo)["baz"] ?? (_f["baz"] = result.foo.baz);
4040
(_g = a.foo.bar()).baz && (_g.baz = result.foo.bar().baz);
4141
(_h = b.foo.bar()).baz || (_h.baz = result.foo.bar().baz);
4242
(_j = c.foo.bar()).baz ?? (_j.baz = result.foo.bar().baz);

tests/baselines/reference/logicalAssignment2(target=es2020).symbols

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ a.foo["baz"] &&= result.foo.baz
6969
>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13))
7070
>baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9))
7171

72-
b.foo["baz"] &&= result.foo.baz
72+
b.foo["baz"] ||= result.foo.baz
7373
>b.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13))
7474
>b : Symbol(b, Decl(logicalAssignment2.ts, 12, 13))
7575
>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13))
@@ -80,7 +80,7 @@ b.foo["baz"] &&= result.foo.baz
8080
>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13))
8181
>baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9))
8282

83-
c.foo["baz"] &&= result.foo.baz
83+
c.foo["baz"] ??= result.foo.baz
8484
>c.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13))
8585
>c : Symbol(c, Decl(logicalAssignment2.ts, 13, 13))
8686
>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13))

tests/baselines/reference/logicalAssignment2(target=es2020).types

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ a.foo["baz"] &&= result.foo.baz
6868
>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; }
6969
>baz : "" | 0 | 1 | 42 | undefined
7070

71-
b.foo["baz"] &&= result.foo.baz
72-
>b.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined
71+
b.foo["baz"] ||= result.foo.baz
72+
>b.foo["baz"] ||= result.foo.baz : "" | 0 | 1 | 42 | undefined
7373
>b.foo["baz"] : "" | 0 | 1 | 42 | undefined
7474
>b.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; }
7575
>b : A
@@ -81,8 +81,8 @@ b.foo["baz"] &&= result.foo.baz
8181
>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; }
8282
>baz : "" | 0 | 1 | 42 | undefined
8383

84-
c.foo["baz"] &&= result.foo.baz
85-
>c.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined
84+
c.foo["baz"] ??= result.foo.baz
85+
>c.foo["baz"] ??= result.foo.baz : "" | 0 | 1 | 42 | undefined
8686
>c.foo["baz"] : "" | 0 | 1 | 42 | undefined
8787
>c.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; }
8888
>c : A

0 commit comments

Comments
 (0)