package printer import ( "fmt" "strconv" "strings" "efprojects.com/kitten-ipc/kitcom/internal/tsgo/ast" "efprojects.com/kitten-ipc/kitcom/internal/tsgo/core" "efprojects.com/kitten-ipc/kitcom/internal/tsgo/debug" ) type NodeFactory struct { ast.NodeFactory emitContext *EmitContext } func NewNodeFactory(context *EmitContext) *NodeFactory { return &NodeFactory{ NodeFactory: *ast.NewNodeFactory(ast.NodeFactoryHooks{ OnCreate: context.onCreate, OnUpdate: context.onUpdate, OnClone: context.onClone, }), emitContext: context, } } func (f *NodeFactory) newGeneratedIdentifier(kind GeneratedIdentifierFlags, text string, node *ast.Node, options AutoGenerateOptions) *ast.IdentifierNode { id := AutoGenerateId(nextAutoGenerateId.Add(1)) if len(text) == 0 { switch { case node == nil: text = fmt.Sprintf("(auto@%d)", id) case ast.IsMemberName(node): text = node.Text() default: text = fmt.Sprintf("(generated@%v)", ast.GetNodeId(f.emitContext.getNodeForGeneratedNameWorker(node, id))) } text = FormatGeneratedName(false /*privateName*/, options.Prefix, text, options.Suffix) } name := f.NewIdentifier(text) autoGenerate := &AutoGenerateInfo{ Id: id, Flags: kind | (options.Flags & ^GeneratedIdentifierFlagsKindMask), Prefix: options.Prefix, Suffix: options.Suffix, Node: node, } if f.emitContext.autoGenerate == nil { f.emitContext.autoGenerate = make(map[*ast.MemberName]*AutoGenerateInfo) } f.emitContext.autoGenerate[name] = autoGenerate return name } // Allocates a new temp variable name, but does not record it in the environment. It is recommended to pass this to either // `AddVariableDeclaration` or `AddLexicalDeclaration` to ensure it is properly tracked, if you are not otherwise handling // it yourself. func (f *NodeFactory) NewTempVariable() *ast.IdentifierNode { return f.NewTempVariableEx(AutoGenerateOptions{}) } // Allocates a new temp variable name, but does not record it in the environment. It is recommended to pass this to either // `AddVariableDeclaration` or `AddLexicalDeclaration` to ensure it is properly tracked, if you are not otherwise handling // it yourself. func (f *NodeFactory) NewTempVariableEx(options AutoGenerateOptions) *ast.IdentifierNode { return f.newGeneratedIdentifier(GeneratedIdentifierFlagsAuto, "", nil /*node*/, options) } // Allocates a new loop variable name. func (f *NodeFactory) NewLoopVariable() *ast.IdentifierNode { return f.NewLoopVariableEx(AutoGenerateOptions{}) } // Allocates a new loop variable name. func (f *NodeFactory) NewLoopVariableEx(options AutoGenerateOptions) *ast.IdentifierNode { return f.newGeneratedIdentifier(GeneratedIdentifierFlagsLoop, "", nil /*node*/, options) } // Allocates a new unique name based on the provided text. func (f *NodeFactory) NewUniqueName(text string) *ast.IdentifierNode { return f.NewUniqueNameEx(text, AutoGenerateOptions{}) } // Allocates a new unique name based on the provided text. func (f *NodeFactory) NewUniqueNameEx(text string, options AutoGenerateOptions) *ast.IdentifierNode { return f.newGeneratedIdentifier(GeneratedIdentifierFlagsUnique, text, nil /*node*/, options) } // Allocates a new unique name based on the provided node. func (f *NodeFactory) NewGeneratedNameForNode(node *ast.Node) *ast.IdentifierNode { return f.NewGeneratedNameForNodeEx(node, AutoGenerateOptions{}) } // Allocates a new unique name based on the provided node. func (f *NodeFactory) NewGeneratedNameForNodeEx(node *ast.Node, options AutoGenerateOptions) *ast.IdentifierNode { if len(options.Prefix) > 0 || len(options.Suffix) > 0 { options.Flags |= GeneratedIdentifierFlagsOptimistic } return f.newGeneratedIdentifier(GeneratedIdentifierFlagsNode, "", node, options) } func (f *NodeFactory) newGeneratedPrivateIdentifier(kind GeneratedIdentifierFlags, text string, node *ast.Node, options AutoGenerateOptions) *ast.PrivateIdentifierNode { id := AutoGenerateId(nextAutoGenerateId.Add(1)) if len(text) == 0 { switch { case node == nil: text = fmt.Sprintf("(auto@%d)", id) case ast.IsMemberName(node): text = node.Text() default: text = fmt.Sprintf("(generated@%v)", ast.GetNodeId(f.emitContext.getNodeForGeneratedNameWorker(node, id))) } text = FormatGeneratedName(true /*privateName*/, options.Prefix, text, options.Suffix) } else if !strings.HasPrefix(text, "#") { panic("First character of private identifier must be #: " + text) } name := f.NewPrivateIdentifier(text) autoGenerate := &AutoGenerateInfo{ Id: id, Flags: kind | (options.Flags &^ GeneratedIdentifierFlagsKindMask), Prefix: options.Prefix, Suffix: options.Suffix, Node: node, } if f.emitContext.autoGenerate == nil { f.emitContext.autoGenerate = make(map[*ast.MemberName]*AutoGenerateInfo) } f.emitContext.autoGenerate[name] = autoGenerate return name } // Allocates a new unique private name based on the provided text. func (f *NodeFactory) NewUniquePrivateName(text string) *ast.PrivateIdentifierNode { return f.NewUniquePrivateNameEx(text, AutoGenerateOptions{}) } // Allocates a new unique private name based on the provided text. func (f *NodeFactory) NewUniquePrivateNameEx(text string, options AutoGenerateOptions) *ast.PrivateIdentifierNode { return f.newGeneratedPrivateIdentifier(GeneratedIdentifierFlagsUnique, text, nil /*node*/, options) } // Allocates a new unique private name based on the provided node. func (f *NodeFactory) NewGeneratedPrivateNameForNode(node *ast.Node) *ast.PrivateIdentifierNode { return f.NewGeneratedPrivateNameForNodeEx(node, AutoGenerateOptions{}) } // Allocates a new unique private name based on the provided node. func (f *NodeFactory) NewGeneratedPrivateNameForNodeEx(node *ast.Node, options AutoGenerateOptions) *ast.PrivateIdentifierNode { if len(options.Prefix) > 0 || len(options.Suffix) > 0 { options.Flags |= GeneratedIdentifierFlagsOptimistic } return f.newGeneratedPrivateIdentifier(GeneratedIdentifierFlagsNode, "", node, options) } // Allocates a new StringLiteral whose source text is derived from the provided node. This is often used to create a // string representation of an Identifier or NumericLiteral. func (f *NodeFactory) NewStringLiteralFromNode(textSourceNode *ast.Node) *ast.Node { var text string switch textSourceNode.Kind { case ast.KindIdentifier, ast.KindPrivateIdentifier, ast.KindJsxNamespacedName, ast.KindNumericLiteral, ast.KindBigIntLiteral, ast.KindNoSubstitutionTemplateLiteral, ast.KindTemplateHead, ast.KindTemplateMiddle, ast.KindTemplateTail, ast.KindRegularExpressionLiteral: text = textSourceNode.Text() } node := f.NewStringLiteral(text) if f.emitContext.textSource == nil { f.emitContext.textSource = make(map[*ast.StringLiteralNode]*ast.Node) } f.emitContext.textSource[node] = textSourceNode return node } // // Common Tokens // func (f *NodeFactory) NewThisExpression() *ast.Expression { return f.NewKeywordExpression(ast.KindThisKeyword) } func (f *NodeFactory) NewTrueExpression() *ast.Expression { return f.NewKeywordExpression(ast.KindTrueKeyword) } func (f *NodeFactory) NewFalseExpression() *ast.Expression { return f.NewKeywordExpression(ast.KindFalseKeyword) } // // Common Operators // func (f *NodeFactory) NewCommaExpression(left *ast.Expression, right *ast.Expression) *ast.Expression { return f.NewBinaryExpression(nil /*modifiers*/, left, nil /*typeNode*/, f.NewToken(ast.KindCommaToken), right) } func (f *NodeFactory) NewAssignmentExpression(left *ast.Expression, right *ast.Expression) *ast.Expression { return f.NewBinaryExpression(nil /*modifiers*/, left, nil /*typeNode*/, f.NewToken(ast.KindEqualsToken), right) } func (f *NodeFactory) NewLogicalORExpression(left *ast.Expression, right *ast.Expression) *ast.Expression { return f.NewBinaryExpression(nil /*modifiers*/, left, nil /*typeNode*/, f.NewToken(ast.KindBarBarToken), right) } // func (f *NodeFactory) NewLogicalANDExpression(left *ast.Expression, right *ast.Expression) *ast.Expression // func (f *NodeFactory) NewBitwiseORExpression(left *ast.Expression, right *ast.Expression) *ast.Expression // func (f *NodeFactory) NewBitwiseXORExpression(left *ast.Expression, right *ast.Expression) *ast.Expression // func (f *NodeFactory) NewBitwiseANDExpression(left *ast.Expression, right *ast.Expression) *ast.Expression func (f *NodeFactory) NewStrictEqualityExpression(left *ast.Expression, right *ast.Expression) *ast.Expression { return f.NewBinaryExpression(nil /*modifiers*/, left, nil /*typeNode*/, f.NewToken(ast.KindEqualsEqualsEqualsToken), right) } func (f *NodeFactory) NewStrictInequalityExpression(left *ast.Expression, right *ast.Expression) *ast.Expression { return f.NewBinaryExpression(nil /*modifiers*/, left, nil /*typeNode*/, f.NewToken(ast.KindExclamationEqualsEqualsToken), right) } // // Compound Nodes // func (f *NodeFactory) NewVoidZeroExpression() *ast.Expression { return f.NewVoidExpression(f.NewNumericLiteral("0")) } func flattenCommaElement(node *ast.Expression, expressions []*ast.Expression) []*ast.Expression { if ast.IsBinaryExpression(node) && ast.NodeIsSynthesized(node) && node.AsBinaryExpression().OperatorToken.Kind == ast.KindCommaToken { expressions = flattenCommaElement(node.AsBinaryExpression().Left, expressions) expressions = flattenCommaElement(node.AsBinaryExpression().Right, expressions) } else { expressions = append(expressions, node) } return expressions } func flattenCommaElements(expressions []*ast.Expression) []*ast.Expression { var result []*ast.Expression for _, expression := range expressions { result = flattenCommaElement(expression, result) } return result } // Converts a slice of expressions into a single comma-delimited expression. Returns nil if expressions is nil or empty. // NOTE: Unlike Strada, the Corsa implementation does not currently use `ast.KindCommaListExpression`. func (f *NodeFactory) InlineExpressions(expressions []*ast.Expression) *ast.Expression { if len(expressions) == 0 { return nil } if len(expressions) == 1 { return expressions[0] } expressions = flattenCommaElements(expressions) expression := expressions[0] for _, next := range expressions[1:] { expression = f.NewCommaExpression(expression, next) } return expression } // // Utilities // func (f *NodeFactory) NewTypeCheck(value *ast.Node, tag string) *ast.Node { if tag == "null" { return f.NewStrictEqualityExpression(value, f.NewKeywordExpression(ast.KindNullKeyword)) } else if tag == "undefined" { return f.NewStrictEqualityExpression(value, f.NewVoidZeroExpression()) } else { return f.NewStrictEqualityExpression(f.NewTypeOfExpression(value), f.NewStringLiteral(tag)) } } func (f *NodeFactory) NewMethodCall(object *ast.Node, methodName *ast.Node, argumentsList []*ast.Node) *ast.Node { // Preserve the optionality of `object`. if ast.IsCallExpression(object) && (object.Flags&ast.NodeFlagsOptionalChain != 0) { return f.NewCallExpression( f.NewPropertyAccessExpression(object, nil, methodName, ast.NodeFlagsNone), nil, nil, f.NewNodeList(argumentsList), ast.NodeFlagsOptionalChain, ) } return f.NewCallExpression( f.NewPropertyAccessExpression(object, nil, methodName, ast.NodeFlagsNone), nil, nil, f.NewNodeList(argumentsList), ast.NodeFlagsNone, ) } func (f *NodeFactory) NewGlobalMethodCall(globalObjectName string, methodName string, argumentsList []*ast.Node) *ast.Node { return f.NewMethodCall(f.NewIdentifier(globalObjectName), f.NewIdentifier(methodName), argumentsList) } func (f *NodeFactory) NewFunctionCallCall(target *ast.Expression, thisArg *ast.Expression, argumentsList []*ast.Node) *ast.Node { if thisArg == nil { panic("Attempted to construct function call call without this argument expression") } args := append([]*ast.Expression{thisArg}, argumentsList...) return f.NewMethodCall(target, f.NewIdentifier("call"), args) } func (f *NodeFactory) NewArraySliceCall(array *ast.Expression, start int) *ast.Node { var args []*ast.Node if start != 0 { args = append(args, f.NewNumericLiteral(strconv.Itoa(start))) } return f.NewMethodCall(array, f.NewIdentifier("slice"), args) } // Determines whether a node is a parenthesized expression that can be ignored when recreating outer expressions. // // A parenthesized expression can be ignored when all of the following are true: // // - It's `pos` and `end` are not -1 // - It does not have a custom source map range // - It does not have a custom comment range // - It does not have synthetic leading or trailing comments // // If an outermost parenthesized expression is ignored, but the containing expression requires a parentheses around // the expression to maintain precedence, a new parenthesized expression should be created automatically when // the containing expression is created/updated. func (f *NodeFactory) isIgnorableParen(node *ast.Expression) bool { return ast.IsParenthesizedExpression(node) && ast.NodeIsSynthesized(node) && ast.RangeIsSynthesized(f.emitContext.SourceMapRange(node)) && ast.RangeIsSynthesized(f.emitContext.CommentRange(node)) // && // len(emitContext.SyntheticLeadingComments(node)) == 0 && // len(emitContext.SyntheticTrailingComments(node)) == 0 } func (f *NodeFactory) updateOuterExpression(outerExpression *ast.Expression /*OuterExpression*/, expression *ast.Expression) *ast.Expression { switch outerExpression.Kind { case ast.KindParenthesizedExpression: return f.UpdateParenthesizedExpression(outerExpression.AsParenthesizedExpression(), expression) case ast.KindTypeAssertionExpression: return f.UpdateTypeAssertion(outerExpression.AsTypeAssertion(), outerExpression.Type(), expression) case ast.KindAsExpression: return f.UpdateAsExpression(outerExpression.AsAsExpression(), expression, outerExpression.Type()) case ast.KindSatisfiesExpression: return f.UpdateSatisfiesExpression(outerExpression.AsSatisfiesExpression(), expression, outerExpression.Type()) case ast.KindNonNullExpression: return f.UpdateNonNullExpression(outerExpression.AsNonNullExpression(), expression) case ast.KindExpressionWithTypeArguments: return f.UpdateExpressionWithTypeArguments(outerExpression.AsExpressionWithTypeArguments(), expression, outerExpression.TypeArgumentList()) case ast.KindPartiallyEmittedExpression: return f.UpdatePartiallyEmittedExpression(outerExpression.AsPartiallyEmittedExpression(), expression) default: panic(fmt.Sprintf("Unexpected outer expression kind: %s", outerExpression.Kind)) } } func (f *NodeFactory) RestoreOuterExpressions(outerExpression *ast.Expression, innerExpression *ast.Expression, kinds ast.OuterExpressionKinds) *ast.Expression { if outerExpression != nil && ast.IsOuterExpression(outerExpression, kinds) && !f.isIgnorableParen(outerExpression) { return f.updateOuterExpression( outerExpression, f.RestoreOuterExpressions(outerExpression.Expression(), innerExpression, ast.OEKAll), ) } return innerExpression } // Ensures `"use strict"` is the first statement of a slice of statements. func (f *NodeFactory) EnsureUseStrict(statements []*ast.Statement) []*ast.Statement { for _, statement := range statements { if ast.IsPrologueDirective(statement) && statement.AsExpressionStatement().Expression.Text() == "use strict" { return statements } else { break } } useStrictPrologue := f.NewExpressionStatement(f.NewStringLiteral("use strict")) statements = append([]*ast.Statement{useStrictPrologue}, statements...) return statements } // Splits a slice of statements into two parts: standard prologue statements and the rest of the statements func (f *NodeFactory) SplitStandardPrologue(source []*ast.Statement) (prologue []*ast.Statement, rest []*ast.Statement) { for i, statement := range source { if !ast.IsPrologueDirective(statement) { return source[:i], source[i:] } } return nil, source } // Splits a slice of statements into two parts: custom prologue statements (e.g., with `EFCustomPrologue` set) and the rest of the statements func (f *NodeFactory) SplitCustomPrologue(source []*ast.Statement) (prologue []*ast.Statement, rest []*ast.Statement) { for i, statement := range source { if ast.IsPrologueDirective(statement) || f.emitContext.EmitFlags(statement)&EFCustomPrologue == 0 { return source[:i], source[i:] } } return nil, source } // // Declaration Names // type NameOptions struct { AllowComments bool // indicates whether comments may be emitted for the name. AllowSourceMaps bool // indicates whether source maps may be emitted for the name. } type AssignedNameOptions struct { AllowComments bool // indicates whether comments may be emitted for the name. AllowSourceMaps bool // indicates whether source maps may be emitted for the name. IgnoreAssignedName bool // indicates whether the assigned name of a declaration shouldn't be considered. } func (f *NodeFactory) getName(node *ast.Declaration, emitFlags EmitFlags, opts AssignedNameOptions) *ast.IdentifierNode { var nodeName *ast.IdentifierNode if node != nil { if opts.IgnoreAssignedName { nodeName = ast.GetNonAssignedNameOfDeclaration(node) } else { nodeName = ast.GetNameOfDeclaration(node) } } if nodeName != nil { name := nodeName.Clone(f) if !opts.AllowComments { emitFlags |= EFNoComments } if !opts.AllowSourceMaps { emitFlags |= EFNoSourceMap } f.emitContext.AddEmitFlags(name, emitFlags) return name } return f.NewGeneratedNameForNode(node) } // Gets the local name of a declaration. This is primarily used for declarations that can be referred to by name in the // declaration's immediate scope (classes, enums, namespaces). A local name will *never* be prefixed with a module or // namespace export modifier like "exports." when emitted as an expression. func (f *NodeFactory) GetLocalName(node *ast.Declaration) *ast.IdentifierNode { return f.GetLocalNameEx(node, AssignedNameOptions{}) } // Gets the local name of a declaration. This is primarily used for declarations that can be referred to by name in the // declaration's immediate scope (classes, enums, namespaces). A local name will *never* be prefixed with a module or // namespace export modifier like "exports." when emitted as an expression. func (f *NodeFactory) GetLocalNameEx(node *ast.Declaration, opts AssignedNameOptions) *ast.IdentifierNode { return f.getName(node, EFLocalName, opts) } // Gets the export name of a declaration. This is primarily used for declarations that can be // referred to by name in the declaration's immediate scope (classes, enums, namespaces). An // export name will *always* be prefixed with an module or namespace export modifier like // `"exports."` when emitted as an expression if the name points to an exported symbol. func (f *NodeFactory) GetExportName(node *ast.Declaration) *ast.IdentifierNode { return f.GetExportNameEx(node, AssignedNameOptions{}) } // Gets the export name of a declaration. This is primarily used for declarations that can be // referred to by name in the declaration's immediate scope (classes, enums, namespaces). An // export name will *always* be prefixed with an module or namespace export modifier like // `"exports."` when emitted as an expression if the name points to an exported symbol. func (f *NodeFactory) GetExportNameEx(node *ast.Declaration, opts AssignedNameOptions) *ast.IdentifierNode { return f.getName(node, EFExportName, opts) } // Gets the name of a declaration to use during emit. func (f *NodeFactory) GetDeclarationName(node *ast.Declaration) *ast.IdentifierNode { return f.GetDeclarationNameEx(node, NameOptions{}) } // Gets the name of a declaration to use during emit. func (f *NodeFactory) GetDeclarationNameEx(node *ast.Declaration, opts NameOptions) *ast.IdentifierNode { return f.getName(node, EFNone, AssignedNameOptions{AllowComments: opts.AllowComments, AllowSourceMaps: opts.AllowSourceMaps}) } func (f *NodeFactory) GetNamespaceMemberName(ns *ast.IdentifierNode, name *ast.IdentifierNode, opts NameOptions) *ast.IdentifierNode { if !f.emitContext.HasAutoGenerateInfo(name) { name = name.Clone(f) } qualifiedName := f.NewPropertyAccessExpression(ns, nil /*questionDotToken*/, name, ast.NodeFlagsNone) f.emitContext.AssignCommentAndSourceMapRanges(qualifiedName, name) if !opts.AllowComments { f.emitContext.AddEmitFlags(qualifiedName, EFNoComments) } if !opts.AllowSourceMaps { f.emitContext.AddEmitFlags(qualifiedName, EFNoSourceMap) } return qualifiedName } // // Emit Helpers // // Allocates a new Identifier representing a reference to a helper function. func (f *NodeFactory) NewUnscopedHelperName(name string) *ast.IdentifierNode { node := f.NewIdentifier(name) f.emitContext.SetEmitFlags(node, EFHelperName) return node } // !!! TypeScript Helpers // ESNext Helpers func (f *NodeFactory) NewAddDisposableResourceHelper(envBinding *ast.Expression, value *ast.Expression, async bool) *ast.Expression { f.emitContext.RequestEmitHelper(addDisposableResourceHelper) return f.NewCallExpression( f.NewUnscopedHelperName("__addDisposableResource"), nil, /*questionDotToken*/ nil, /*typeArguments*/ f.NewNodeList([]*ast.Expression{envBinding, value, f.NewKeywordExpression(core.IfElse(async, ast.KindTrueKeyword, ast.KindFalseKeyword))}), ast.NodeFlagsNone, ) } func (f *NodeFactory) NewDisposeResourcesHelper(envBinding *ast.Expression) *ast.Expression { f.emitContext.RequestEmitHelper(disposeResourcesHelper) return f.NewCallExpression( f.NewUnscopedHelperName("__disposeResources"), nil, /*questionDotToken*/ nil, /*typeArguments*/ f.NewNodeList([]*ast.Expression{envBinding}), ast.NodeFlagsNone, ) } // !!! Class Fields Helpers // !!! ES2018 Helpers // Chains a sequence of expressions using the __assign helper or Object.assign if available in the target func (f *NodeFactory) NewAssignHelper(attributesSegments []*ast.Expression, scriptTarget core.ScriptTarget) *ast.Expression { if scriptTarget >= core.ScriptTargetES2015 { return f.NewCallExpression(f.NewPropertyAccessExpression(f.NewIdentifier("Object"), nil, f.NewIdentifier("assign"), ast.NodeFlagsNone), nil, nil, f.NewNodeList(attributesSegments), ast.NodeFlagsNone) } f.emitContext.RequestEmitHelper(assignHelper) return f.NewCallExpression( f.NewUnscopedHelperName("__assign"), nil, nil, f.NewNodeList(attributesSegments), ast.NodeFlagsNone, ) } // ES2018 Destructuring Helpers func (f *NodeFactory) NewRestHelper(value *ast.Expression, elements []*ast.Node, computedTempVariables []*ast.Node, location core.TextRange) *ast.Expression { f.emitContext.RequestEmitHelper(restHelper) var propertyNames []*ast.Node computedTempVariableOffset := 0 for i, element := range elements { if i == len(elements)-1 { break } propertyName := ast.TryGetPropertyNameOfBindingOrAssignmentElement(element) if propertyName != nil { if ast.IsComputedPropertyName(propertyName) { debug.AssertIsDefined(computedTempVariables, "Encountered computed property name but 'computedTempVariables' argument was not provided.") temp := computedTempVariables[computedTempVariableOffset] computedTempVariableOffset++ // typeof _tmp === "symbol" ? _tmp : _tmp + "" propertyNames = append(propertyNames, f.NewConditionalExpression( f.NewTypeCheck(temp, "symbol"), f.NewToken(ast.KindQuestionToken), temp, f.NewToken(ast.KindColonToken), f.NewBinaryExpression(nil, temp, nil, f.NewToken(ast.KindPlusToken), f.NewStringLiteral("")), )) } else { propertyNames = append(propertyNames, f.NewStringLiteralFromNode(propertyName)) } } } propNames := f.NewArrayLiteralExpression(f.NewNodeList(propertyNames), false) propNames.Loc = location return f.NewCallExpression( f.NewUnscopedHelperName("__rest"), nil, nil, f.NewNodeList([]*ast.Node{ value, propNames, }), ast.NodeFlagsNone, ) } // !!! ES2017 Helpers // ES2015 Helpers func (f *NodeFactory) NewPropKeyHelper(expr *ast.Expression) *ast.Expression { f.emitContext.RequestEmitHelper(propKeyHelper) return f.NewCallExpression( f.NewUnscopedHelperName("__propKey"), nil, /*questionDotToken*/ nil, /*typeArguments*/ f.NewNodeList([]*ast.Expression{expr}), ast.NodeFlagsNone, ) } func (f *NodeFactory) NewSetFunctionNameHelper(fn *ast.Expression, name *ast.Expression, prefix string) *ast.Expression { f.emitContext.RequestEmitHelper(setFunctionNameHelper) var arguments []*ast.Expression if len(prefix) > 0 { arguments = []*ast.Expression{fn, name, f.NewStringLiteral(prefix)} } else { arguments = []*ast.Expression{fn, name} } return f.NewCallExpression( f.NewUnscopedHelperName("__setFunctionName"), nil, /*questionDotToken*/ nil, /*typeArguments*/ f.NewNodeList(arguments), ast.NodeFlagsNone, ) } // ES Module Helpers // Allocates a new Call expression to the `__importDefault` helper. func (f *NodeFactory) NewImportDefaultHelper(expression *ast.Expression) *ast.Expression { f.emitContext.RequestEmitHelper(importDefaultHelper) return f.NewCallExpression( f.NewUnscopedHelperName("__importDefault"), nil, /*questionDotToken*/ nil, /*typeArguments*/ f.NewNodeList([]*ast.Expression{expression}), ast.NodeFlagsNone, ) } // Allocates a new Call expression to the `__importStar` helper. func (f *NodeFactory) NewImportStarHelper(expression *ast.Expression) *ast.Expression { f.emitContext.RequestEmitHelper(importStarHelper) return f.NewCallExpression( f.NewUnscopedHelperName("__importStar"), nil, /*questionDotToken*/ nil, /*typeArguments*/ f.NewNodeList([]*ast.Expression{expression}), ast.NodeFlagsNone, ) } // Allocates a new Call expression to the `__exportStar` helper. func (f *NodeFactory) NewExportStarHelper(moduleExpression *ast.Expression, exportsExpression *ast.Expression) *ast.Expression { f.emitContext.RequestEmitHelper(exportStarHelper) return f.NewCallExpression( f.NewUnscopedHelperName("__exportStar"), nil, /*questionDotToken*/ nil, /*typeArguments*/ f.NewNodeList([]*ast.Expression{moduleExpression, exportsExpression}), ast.NodeFlagsNone, ) } // Allocates a new Call expression to the `__rewriteRelativeImportExtension` helper. func (f *NodeFactory) NewRewriteRelativeImportExtensionsHelper(firstArgument *ast.Node, preserveJsx bool) *ast.Expression { f.emitContext.RequestEmitHelper(rewriteRelativeImportExtensionsHelper) var arguments []*ast.Expression if preserveJsx { arguments = []*ast.Expression{firstArgument, f.NewToken(ast.KindTrueKeyword)} } else { arguments = []*ast.Expression{firstArgument} } return f.NewCallExpression( f.NewUnscopedHelperName("__rewriteRelativeImportExtension"), nil, /*questionDotToken*/ nil, /*typeArguments*/ f.NewNodeList(arguments), ast.NodeFlagsNone, ) }