Skip to content

Commit 742fcd2

Browse files
authored
Port es2021 transform (#1372)
1 parent b630b33 commit 742fcd2

File tree

49 files changed

+284
-384
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+284
-384
lines changed

internal/transformers/estransforms/logicalassignment.go

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,101 @@ type logicalAssignmentTransformer struct {
1111
}
1212

1313
func (ch *logicalAssignmentTransformer) visit(node *ast.Node) *ast.Node {
14-
return node // !!!
14+
if node.SubtreeFacts()&ast.SubtreeContainsLogicalAssignments == 0 {
15+
return node
16+
}
17+
switch node.Kind {
18+
case ast.KindBinaryExpression:
19+
return ch.visitBinaryExpression(node.AsBinaryExpression())
20+
default:
21+
return ch.Visitor().VisitEachChild(node)
22+
}
23+
}
24+
25+
func (ch *logicalAssignmentTransformer) visitBinaryExpression(node *ast.BinaryExpression) *ast.Node {
26+
var nonAssignmentOperator ast.Kind
27+
switch node.OperatorToken.Kind {
28+
case ast.KindBarBarEqualsToken:
29+
nonAssignmentOperator = ast.KindBarBarToken
30+
case ast.KindAmpersandAmpersandEqualsToken:
31+
nonAssignmentOperator = ast.KindAmpersandAmpersandToken
32+
case ast.KindQuestionQuestionEqualsToken:
33+
nonAssignmentOperator = ast.KindQuestionQuestionToken
34+
default:
35+
return ch.Visitor().VisitEachChild(node.AsNode())
36+
}
37+
38+
left := ast.SkipParentheses(ch.Visitor().VisitNode(node.Left))
39+
assignmentTarget := left
40+
right := ast.SkipParentheses(ch.Visitor().VisitNode(node.Right))
41+
42+
if ast.IsAccessExpression(left) {
43+
propertyAccessTargetSimpleCopiable := transformers.IsSimpleCopiableExpression(left.Expression())
44+
propertyAccessTarget := left.Expression()
45+
propertyAccessTargetAssignment := left.Expression()
46+
if !propertyAccessTargetSimpleCopiable {
47+
propertyAccessTarget = ch.Factory().NewTempVariable()
48+
ch.EmitContext().AddVariableDeclaration(propertyAccessTarget)
49+
propertyAccessTargetAssignment = ch.Factory().NewAssignmentExpression(
50+
propertyAccessTarget,
51+
left.Expression(),
52+
)
53+
}
54+
55+
if ast.IsPropertyAccessExpression(left) {
56+
assignmentTarget = ch.Factory().NewPropertyAccessExpression(
57+
propertyAccessTarget,
58+
nil,
59+
left.Name(),
60+
ast.NodeFlagsNone,
61+
)
62+
left = ch.Factory().NewPropertyAccessExpression(
63+
propertyAccessTargetAssignment,
64+
nil,
65+
left.Name(),
66+
ast.NodeFlagsNone,
67+
)
68+
} else {
69+
elementAccessArgumentSimpleCopiable := transformers.IsSimpleCopiableExpression(left.AsElementAccessExpression().ArgumentExpression)
70+
elementAccessArgument := left.AsElementAccessExpression().ArgumentExpression
71+
argumentExpr := elementAccessArgument
72+
if !elementAccessArgumentSimpleCopiable {
73+
elementAccessArgument = ch.Factory().NewTempVariable()
74+
ch.EmitContext().AddVariableDeclaration(elementAccessArgument)
75+
argumentExpr = ch.Factory().NewAssignmentExpression(
76+
elementAccessArgument,
77+
left.AsElementAccessExpression().ArgumentExpression,
78+
)
79+
}
80+
81+
assignmentTarget = ch.Factory().NewElementAccessExpression(
82+
propertyAccessTarget,
83+
nil,
84+
elementAccessArgument,
85+
ast.NodeFlagsNone,
86+
)
87+
left = ch.Factory().NewElementAccessExpression(
88+
propertyAccessTargetAssignment,
89+
nil,
90+
argumentExpr,
91+
ast.NodeFlagsNone,
92+
)
93+
}
94+
95+
}
96+
97+
return ch.Factory().NewBinaryExpression(
98+
nil,
99+
left,
100+
nil,
101+
ch.Factory().NewToken(nonAssignmentOperator),
102+
ch.Factory().NewParenthesizedExpression(
103+
ch.Factory().NewAssignmentExpression(
104+
assignmentTarget,
105+
right,
106+
),
107+
),
108+
)
15109
}
16110

17111
func newLogicalAssignmentTransformer(emitContext *printer.EmitContext) *transformers.Transformer {

internal/transformers/moduletransforms/utilities.go

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"github.com/microsoft/typescript-go/internal/core"
66
"github.com/microsoft/typescript-go/internal/outputpaths"
77
"github.com/microsoft/typescript-go/internal/printer"
8+
"github.com/microsoft/typescript-go/internal/transformers"
89
"github.com/microsoft/typescript-go/internal/tspath"
910
)
1011

@@ -113,20 +114,9 @@ func isFileLevelReservedGeneratedIdentifier(emitContext *printer.EmitContext, na
113114
info.Flags.IsReservedInNestedScopes()
114115
}
115116

116-
// Used in the module transformer to check if an expression is reasonably without sideeffect,
117-
//
118-
// and thus better to copy into multiple places rather than to cache in a temporary variable
119-
// - this is mostly subjective beyond the requirement that the expression not be sideeffecting
120-
func isSimpleCopiableExpression(expression *ast.Expression) bool {
121-
return ast.IsStringLiteralLike(expression) ||
122-
ast.IsNumericLiteral(expression) ||
123-
ast.IsKeywordKind(expression.Kind) ||
124-
ast.IsIdentifier(expression)
125-
}
126-
127117
// A simple inlinable expression is an expression which can be copied into multiple locations
128118
// without risk of repeating any sideeffects and whose value could not possibly change between
129119
// any such locations
130120
func isSimpleInlineableExpression(expression *ast.Expression) bool {
131-
return !ast.IsIdentifier(expression) && isSimpleCopiableExpression(expression)
121+
return !ast.IsIdentifier(expression) && transformers.IsSimpleCopiableExpression(expression)
132122
}

internal/transformers/utilities.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,17 @@ func SingleOrMany(nodes []*ast.Node, factory *printer.NodeFactory) *ast.Node {
231231
}
232232
return factory.NewSyntaxList(nodes)
233233
}
234+
235+
// Used in the module transformer to check if an expression is reasonably without sideeffect,
236+
//
237+
// and thus better to copy into multiple places rather than to cache in a temporary variable
238+
// - this is mostly subjective beyond the requirement that the expression not be sideeffecting
239+
//
240+
// Also used by the logical assignment downleveling transform to skip temp variables when they're
241+
// not needed.
242+
func IsSimpleCopiableExpression(expression *ast.Expression) bool {
243+
return ast.IsStringLiteralLike(expression) ||
244+
ast.IsNumericLiteral(expression) ||
245+
ast.IsKeywordKind(expression.Kind) ||
246+
ast.IsIdentifier(expression)
247+
}

testdata/baselines/reference/submodule/conformance/equalityWithtNullishCoalescingAssignment(strict=false).js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ function f2() {
2121

2222
//// [equalityWithtNullishCoalescingAssignment.js]
2323
function f1(a) {
24-
a ??= true;
24+
a ?? (a = true);
2525
if (a === false) {
2626
console.log(a);
2727
}
2828
}
2929
f1(false);
3030
function f2() {
3131
let x = 0;
32-
x ??= 1;
32+
x ?? (x = 1);
3333
if (x === 0) {
3434
console.log(x);
3535
}

testdata/baselines/reference/submodule/conformance/equalityWithtNullishCoalescingAssignment(strict=false).js.diff

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
//// [equalityWithtNullishCoalescingAssignment.js]
66
function f1(a) {
77
- a !== null && a !== void 0 ? a : (a = true);
8-
+ a ??= true;
8+
+ a ?? (a = true);
99
if (a === false) {
1010
console.log(a);
1111
}
@@ -14,7 +14,7 @@
1414
function f2() {
1515
let x = 0;
1616
- x !== null && x !== void 0 ? x : (x = 1);
17-
+ x ??= 1;
17+
+ x ?? (x = 1);
1818
if (x === 0) {
1919
console.log(x);
2020
}

testdata/baselines/reference/submodule/conformance/equalityWithtNullishCoalescingAssignment(strict=true).js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ function f2() {
2121

2222
//// [equalityWithtNullishCoalescingAssignment.js]
2323
function f1(a) {
24-
a ??= true;
24+
a ?? (a = true);
2525
if (a === false) {
2626
console.log(a);
2727
}
2828
}
2929
f1(false);
3030
function f2() {
3131
let x = 0;
32-
x ??= 1;
32+
x ?? (x = 1);
3333
if (x === 0) {
3434
console.log(x);
3535
}

testdata/baselines/reference/submodule/conformance/equalityWithtNullishCoalescingAssignment(strict=true).js.diff

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
-"use strict";
88
function f1(a) {
99
- a !== null && a !== void 0 ? a : (a = true);
10-
+ a ??= true;
10+
+ a ?? (a = true);
1111
if (a === false) {
1212
console.log(a);
1313
}
@@ -16,7 +16,7 @@
1616
function f2() {
1717
let x = 0;
1818
- x !== null && x !== void 0 ? x : (x = 1);
19-
+ x ??= 1;
19+
+ x ?? (x = 1);
2020
if (x === 0) {
2121
console.log(x);
2222
}

testdata/baselines/reference/submodule/conformance/logicalAssignment1(target=es2015).js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ i ??= 42
2929

3030

3131
//// [logicalAssignment1.js]
32-
a &&= "foo";
33-
b ||= "foo";
34-
c ??= "foo";
35-
d &&= 42;
36-
e ||= 42;
37-
f ??= 42;
38-
g &&= 42;
39-
h ||= 42;
40-
i ??= 42;
32+
a && (a = "foo");
33+
b || (b = "foo");
34+
c ?? (c = "foo");
35+
d && (d = 42);
36+
e || (e = 42);
37+
f ?? (f = 42);
38+
g && (g = 42);
39+
h || (h = 42);
40+
i ?? (i = 42);

testdata/baselines/reference/submodule/conformance/logicalAssignment1(target=es2015).js.diff

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,15 @@
55

66
//// [logicalAssignment1.js]
77
-"use strict";
8-
-a && (a = "foo");
9-
-b || (b = "foo");
8+
a && (a = "foo");
9+
b || (b = "foo");
1010
-c !== null && c !== void 0 ? c : (c = "foo");
11-
-d && (d = 42);
12-
-e || (e = 42);
11+
+c ?? (c = "foo");
12+
d && (d = 42);
13+
e || (e = 42);
1314
-f !== null && f !== void 0 ? f : (f = 42);
14-
-g && (g = 42);
15-
-h || (h = 42);
15+
+f ?? (f = 42);
16+
g && (g = 42);
17+
h || (h = 42);
1618
-i !== null && i !== void 0 ? i : (i = 42);
17-
+a &&= "foo";
18-
+b ||= "foo";
19-
+c ??= "foo";
20-
+d &&= 42;
21-
+e ||= 42;
22-
+f ??= 42;
23-
+g &&= 42;
24-
+h ||= 42;
25-
+i ??= 42;
19+
+i ?? (i = 42);

testdata/baselines/reference/submodule/conformance/logicalAssignment1(target=es2020).js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ i ??= 42
2929

3030

3131
//// [logicalAssignment1.js]
32-
a &&= "foo";
33-
b ||= "foo";
34-
c ??= "foo";
35-
d &&= 42;
36-
e ||= 42;
37-
f ??= 42;
38-
g &&= 42;
39-
h ||= 42;
40-
i ??= 42;
32+
a && (a = "foo");
33+
b || (b = "foo");
34+
c ?? (c = "foo");
35+
d && (d = 42);
36+
e || (e = 42);
37+
f ?? (f = 42);
38+
g && (g = 42);
39+
h || (h = 42);
40+
i ?? (i = 42);

0 commit comments

Comments
 (0)