Skip to content

Commit e475191

Browse files
authored
Port JSX Emit (#1159)
1 parent c8b4dca commit e475191

File tree

448 files changed

+3283
-4258
lines changed

Some content is hidden

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

448 files changed

+3283
-4258
lines changed

internal/ast/utilities.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3609,3 +3609,16 @@ func (h *hasFileNameImpl) FileName() string {
36093609
func (h *hasFileNameImpl) Path() tspath.Path {
36103610
return h.path
36113611
}
3612+
3613+
func GetSemanticJsxChildren(children []*JsxChild) []*JsxChild {
3614+
return core.Filter(children, func(i *JsxChild) bool {
3615+
switch i.Kind {
3616+
case KindJsxExpression:
3617+
return i.Expression() != nil
3618+
case KindJsxText:
3619+
return !i.AsJsxText().ContainsOnlyTriviaWhiteSpaces
3620+
default:
3621+
return true
3622+
}
3623+
})
3624+
}

internal/checker/emitresolver.go

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ import (
1616

1717
var _ printer.EmitResolver = &emitResolver{}
1818

19+
// Links for jsx
20+
type JSXLinks struct {
21+
importRef *ast.Node
22+
}
23+
1924
// Links for declarations
2025

2126
type DeclarationLinks struct {
@@ -31,10 +36,23 @@ type emitResolver struct {
3136
checkerMu sync.Mutex
3237
isValueAliasDeclaration func(node *ast.Node) bool
3338
referenceResolver binder.ReferenceResolver
39+
jsxLinks core.LinkStore[*ast.Node, JSXLinks]
3440
declarationLinks core.LinkStore[*ast.Node, DeclarationLinks]
3541
declarationFileLinks core.LinkStore[*ast.Node, DeclarationFileLinks]
3642
}
3743

44+
func (r *emitResolver) GetJsxFactoryEntity(location *ast.Node) *ast.Node {
45+
r.checkerMu.Lock()
46+
defer r.checkerMu.Unlock()
47+
return r.checker.getJsxFactoryEntity(location)
48+
}
49+
50+
func (r *emitResolver) GetJsxFragmentFactoryEntity(location *ast.Node) *ast.Node {
51+
r.checkerMu.Lock()
52+
defer r.checkerMu.Unlock()
53+
return r.checker.getJsxFragmentFactoryEntity(location)
54+
}
55+
3856
func (r *emitResolver) IsOptionalParameter(node *ast.Node) bool {
3957
r.checkerMu.Lock()
4058
defer r.checkerMu.Unlock()
@@ -786,13 +804,18 @@ func (r *emitResolver) GetReferencedExportContainer(node *ast.IdentifierNode, pr
786804
return r.getReferenceResolver().GetReferencedExportContainer(node, prefixLocals)
787805
}
788806

789-
func (r *emitResolver) GetReferencedImportDeclaration(node *ast.IdentifierNode) *ast.Declaration {
790-
if !ast.IsParseTreeNode(node) {
791-
return nil
792-
}
807+
func (r *emitResolver) SetReferencedImportDeclaration(node *ast.IdentifierNode, ref *ast.Declaration) {
808+
r.checkerMu.Lock()
809+
defer r.checkerMu.Unlock()
810+
r.jsxLinks.Get(node).importRef = ref
811+
}
793812

813+
func (r *emitResolver) GetReferencedImportDeclaration(node *ast.IdentifierNode) *ast.Declaration {
794814
r.checkerMu.Lock()
795815
defer r.checkerMu.Unlock()
816+
if !ast.IsParseTreeNode(node) {
817+
return r.jsxLinks.Get(node).importRef
818+
}
796819

797820
return r.getReferenceResolver().GetReferencedImportDeclaration(node)
798821
}

internal/checker/grammarchecks.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1195,7 +1195,7 @@ func (c *Checker) checkGrammarJsxName(node *ast.JsxTagNameExpression) bool {
11951195
return c.grammarErrorOnNode(node.Expression(), diagnostics.JSX_property_access_expressions_cannot_include_JSX_namespace_names)
11961196
}
11971197

1198-
if ast.IsJsxNamespacedName(node) && c.compilerOptions.GetJSXTransformEnabled() && !IsIntrinsicJsxName(node.AsJsxNamespacedName().Namespace.Text()) {
1198+
if ast.IsJsxNamespacedName(node) && c.compilerOptions.GetJSXTransformEnabled() && !scanner.IsIntrinsicJsxName(node.AsJsxNamespacedName().Namespace.Text()) {
11991199
return c.grammarErrorOnNode(node, diagnostics.React_components_cannot_include_JSX_namespace_names)
12001200
}
12011201

internal/checker/jsx.go

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ func (c *Checker) getContextualTypeForChildJsxExpression(node *ast.Node, child *
243243
if !(attributesType != nil && !IsTypeAny(attributesType) && jsxChildrenPropertyName != ast.InternalSymbolNameMissing && jsxChildrenPropertyName != "") {
244244
return nil
245245
}
246-
realChildren := getSemanticJsxChildren(node.Children().Nodes)
246+
realChildren := ast.GetSemanticJsxChildren(node.Children().Nodes)
247247
childIndex := slices.Index(realChildren, child)
248248
childFieldType := c.getTypeOfPropertyOfContextualType(attributesType, jsxChildrenPropertyName)
249249
if childFieldType == nil {
@@ -279,7 +279,7 @@ func (c *Checker) discriminateContextualTypeByJSXAttributes(node *ast.Node, cont
279279
return false
280280
}
281281
element := node.Parent.Parent
282-
if s.Name == jsxChildrenPropertyName && ast.IsJsxElement(element) && len(getSemanticJsxChildren(element.Children().Nodes)) != 0 {
282+
if s.Name == jsxChildrenPropertyName && ast.IsJsxElement(element) && len(ast.GetSemanticJsxChildren(element.Children().Nodes)) != 0 {
283283
return false
284284
}
285285
return node.Symbol().Members[s.Name] == nil && c.isDiscriminantProperty(contextualType, s.Name)
@@ -308,7 +308,7 @@ func (c *Checker) elaborateJsxComponents(node *ast.Node, source *Type, target *T
308308
}
309309
childrenNameType := c.getStringLiteralType(childrenPropName)
310310
childrenTargetType := c.getIndexedAccessType(target, childrenNameType)
311-
validChildren := getSemanticJsxChildren(containingElement.Children().Nodes)
311+
validChildren := ast.GetSemanticJsxChildren(containingElement.Children().Nodes)
312312
if len(validChildren) == 0 {
313313
return reportedError
314314
}
@@ -803,7 +803,7 @@ func (c *Checker) createJsxAttributesTypeFromAttributesProperty(openingLikeEleme
803803
children = parent.AsJsxFragment().Children.Nodes
804804
}
805805
}
806-
return len(getSemanticJsxChildren(children)) != 0
806+
return len(ast.GetSemanticJsxChildren(children)) != 0
807807
}
808808
if parentHasSemanticJsxChildren(openingLikeElement) {
809809
var childTypes []*Type = c.checkJsxChildren(openingLikeElement.Parent, checkMode)
@@ -855,19 +855,6 @@ func (c *Checker) createJsxAttributesTypeFromAttributesProperty(openingLikeEleme
855855
return spread
856856
}
857857

858-
func getSemanticJsxChildren(children []*ast.JsxChild) []*ast.JsxChild {
859-
return core.Filter(children, func(i *ast.JsxChild) bool {
860-
switch i.Kind {
861-
case ast.KindJsxExpression:
862-
return i.Expression() != nil
863-
case ast.KindJsxText:
864-
return !i.AsJsxText().ContainsOnlyTriviaWhiteSpaces
865-
default:
866-
return true
867-
}
868-
})
869-
}
870-
871858
func (c *Checker) checkJsxAttribute(node *ast.Node, checkMode CheckMode) *Type {
872859
if node.Initializer() != nil {
873860
return c.checkExpressionForMutableLocation(node.Initializer(), checkMode)

internal/checker/utilities.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,6 @@ func NewDiagnosticChainForNode(chain *ast.Diagnostic, node *ast.Node, message *d
3535
return NewDiagnosticForNode(node, message, args...)
3636
}
3737

38-
func IsIntrinsicJsxName(name string) bool {
39-
return len(name) != 0 && (name[0] >= 'a' && name[0] <= 'z' || strings.ContainsRune(name, '-'))
40-
}
41-
4238
func findInMap[K comparable, V any](m map[K]V, predicate func(V) bool) V {
4339
for _, value := range m {
4440
if predicate(value) {
@@ -1337,7 +1333,7 @@ func isInRightSideOfImportOrExportAssignment(node *ast.EntityName) bool {
13371333
}
13381334

13391335
func isJsxIntrinsicTagName(tagName *ast.Node) bool {
1340-
return ast.IsIdentifier(tagName) && IsIntrinsicJsxName(tagName.Text()) || ast.IsJsxNamespacedName(tagName)
1336+
return ast.IsIdentifier(tagName) && scanner.IsIntrinsicJsxName(tagName.Text()) || ast.IsJsxNamespacedName(tagName)
13411337
}
13421338

13431339
func getContainingObjectLiteral(f *ast.SignatureDeclaration) *ast.Node {

internal/parser/parser.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ func walkTreeForJSXTags(node *ast.Node) *ast.Node {
412412
return true
413413
}
414414
if node.SubtreeFacts()&ast.SubtreeContainsJsx == 0 {
415-
return true
415+
return false
416416
}
417417
if ast.IsJsxOpeningElement(node) || ast.IsJsxFragment(node) {
418418
found = node

internal/printer/emitresolver.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ type EmitResolver interface {
3535
GetEffectiveDeclarationFlags(node *ast.Node, flags ast.ModifierFlags) ast.ModifierFlags
3636
GetResolutionModeOverride(node *ast.Node) core.ResolutionMode
3737

38+
// JSX Emit
39+
GetJsxFactoryEntity(location *ast.Node) *ast.Node
40+
GetJsxFragmentFactoryEntity(location *ast.Node) *ast.Node
41+
SetReferencedImportDeclaration(node *ast.IdentifierNode, ref *ast.Declaration) // for overriding the reference resolver behavior for generated identifiers
42+
3843
// declaration emit checker functionality projections
3944
PrecalculateDeclarationEmitVisibility(file *ast.SourceFile)
4045
IsSymbolAccessible(symbol *ast.Symbol, enclosingDeclaration *ast.Node, meaning ast.SymbolFlags, shouldComputeAliasToMarkVisible bool) SymbolAccessibilityResult

internal/printer/factory.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,21 @@ func (f *NodeFactory) NewDisposeResourcesHelper(envBinding *ast.Expression) *ast
492492

493493
// !!! Class Fields Helpers
494494
// !!! ES2018 Helpers
495+
// Chains a sequence of expressions using the __assign helper or Object.assign if available in the target
496+
func (f *NodeFactory) NewAssignHelper(attributesSegments []*ast.Expression, scriptTarget core.ScriptTarget) *ast.Expression {
497+
if scriptTarget >= core.ScriptTargetES2015 {
498+
return f.NewCallExpression(f.NewPropertyAccessExpression(f.NewIdentifier("Object"), nil, f.NewIdentifier("assign"), ast.NodeFlagsNone), nil, nil, f.NewNodeList(attributesSegments), ast.NodeFlagsNone)
499+
}
500+
f.emitContext.RequestEmitHelper(assignHelper)
501+
return f.NewCallExpression(
502+
f.NewUnscopedHelperName("__assign"),
503+
nil,
504+
nil,
505+
f.NewNodeList(attributesSegments),
506+
ast.NodeFlagsNone,
507+
)
508+
}
509+
495510
// !!! ES2018 Destructuring Helpers
496511
// !!! ES2017 Helpers
497512

internal/printer/helpers.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,24 @@ var disposeResourcesHelper = &EmitHelper{
100100

101101
// !!! Class Fields Helpers
102102
// !!! ES2018 Helpers
103+
var assignHelper = &EmitHelper{
104+
Name: "typescript:assign",
105+
ImportName: "__assign",
106+
Scoped: false,
107+
Priority: &Priority{1},
108+
Text: `var __assign = (this && this.__assign) || function () {
109+
__assign = Object.assign || function(t) {
110+
for (var s, i = 1, n = arguments.length; i < n; i++) {
111+
s = arguments[i];
112+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
113+
t[p] = s[p];
114+
}
115+
return t;
116+
};
117+
return __assign.apply(this, arguments);
118+
};`,
119+
}
120+
103121
// !!! ES2018 Destructuring Helpers
104122
// !!! ES2017 Helpers
105123

internal/scanner/utilities.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package scanner
22

33
import (
4+
"strings"
45
"unicode/utf8"
56

67
"github.com/microsoft/typescript-go/internal/ast"
@@ -60,3 +61,7 @@ func IsIdentifierText(name string, languageVersion core.ScriptTarget, languageVa
6061
}
6162
return true
6263
}
64+
65+
func IsIntrinsicJsxName(name string) bool {
66+
return len(name) != 0 && (name[0] >= 'a' && name[0] <= 'z' || strings.ContainsRune(name, '-'))
67+
}

internal/testutil/tsbaseline/type_symbol_baseline.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,5 +481,5 @@ func isIntrinsicJsxTag(node *ast.Node, sourceFile *ast.SourceFile) bool {
481481
return false
482482
}
483483
text := scanner.GetSourceTextOfNodeFromSourceFile(sourceFile, node, false /*includeTrivia*/)
484-
return checker.IsIntrinsicJsxName(text)
484+
return scanner.IsIntrinsicJsxName(text)
485485
}

0 commit comments

Comments
 (0)