vendor tsgo
This commit is contained in:
856
tools/tsgo/internal/transformers/estransforms/forawait.go
Normal file
856
tools/tsgo/internal/transformers/estransforms/forawait.go
Normal file
@@ -0,0 +1,856 @@
|
||||
package estransforms
|
||||
|
||||
import (
|
||||
"github.com/microsoft/typescript-go/internal/ast"
|
||||
"github.com/microsoft/typescript-go/internal/collections"
|
||||
"github.com/microsoft/typescript-go/internal/core"
|
||||
"github.com/microsoft/typescript-go/internal/printer"
|
||||
"github.com/microsoft/typescript-go/internal/transformers"
|
||||
)
|
||||
|
||||
// Facts we track as we traverse the tree
|
||||
type forAwaitHierarchyFacts int
|
||||
|
||||
const forAwaitHierarchyFactsNone forAwaitHierarchyFacts = 0
|
||||
|
||||
const (
|
||||
//
|
||||
// Ancestor facts
|
||||
//
|
||||
|
||||
forAwaitHierarchyFactsHasLexicalThis forAwaitHierarchyFacts = 1 << iota
|
||||
forAwaitHierarchyFactsIterationContainer
|
||||
|
||||
//
|
||||
// Ancestor masks
|
||||
//
|
||||
|
||||
forAwaitHierarchyFactsAncestorFactsMask = 1<<iota - 1
|
||||
|
||||
forAwaitHierarchyFactsSourceFileExcludes = forAwaitHierarchyFactsIterationContainer
|
||||
forAwaitHierarchyFactsStrictModeSourceFileIncludes = forAwaitHierarchyFactsNone
|
||||
|
||||
forAwaitHierarchyFactsClassOrFunctionIncludes = forAwaitHierarchyFactsHasLexicalThis
|
||||
forAwaitHierarchyFactsClassOrFunctionExcludes = forAwaitHierarchyFactsIterationContainer
|
||||
|
||||
forAwaitHierarchyFactsArrowFunctionIncludes = forAwaitHierarchyFactsNone
|
||||
forAwaitHierarchyFactsArrowFunctionExcludes = forAwaitHierarchyFactsClassOrFunctionExcludes
|
||||
|
||||
forAwaitHierarchyFactsIterationStatementIncludes = forAwaitHierarchyFactsIterationContainer
|
||||
forAwaitHierarchyFactsIterationStatementExcludes = forAwaitHierarchyFactsNone
|
||||
)
|
||||
|
||||
type forawaitTransformer struct {
|
||||
transformers.Transformer
|
||||
superAccessState
|
||||
compilerOptions *core.CompilerOptions
|
||||
|
||||
enclosingFunctionFlags ast.FunctionFlags
|
||||
forAwaitHierarchyFacts forAwaitHierarchyFacts
|
||||
exportedVariableStatement bool
|
||||
|
||||
fallbackNodeVisitor *ast.NodeVisitor
|
||||
noAsyncModifierVisitor *ast.NodeVisitor
|
||||
}
|
||||
|
||||
func newforawaitTransformer(opts *transformers.TransformOptions) *transformers.Transformer {
|
||||
tx := &forawaitTransformer{
|
||||
compilerOptions: opts.CompilerOptions,
|
||||
}
|
||||
result := tx.NewTransformer(tx.visit, opts.Context)
|
||||
tx.initSuperAccessVisitor(tx.EmitContext(), tx.Factory())
|
||||
tx.fallbackNodeVisitor = tx.EmitContext().NewNodeVisitor(tx.visitFallback)
|
||||
tx.noAsyncModifierVisitor = tx.EmitContext().NewNodeVisitor(func(node *ast.Node) *ast.Node {
|
||||
if node.Kind == ast.KindAsyncKeyword {
|
||||
return nil
|
||||
}
|
||||
return node
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
func (tx *forawaitTransformer) affectsSubtree(excludeFacts forAwaitHierarchyFacts, includeFacts forAwaitHierarchyFacts) bool {
|
||||
return tx.forAwaitHierarchyFacts != (tx.forAwaitHierarchyFacts&^excludeFacts | includeFacts)
|
||||
}
|
||||
|
||||
// enterSubtree sets the HierarchyFacts for this node prior to visiting this node's subtree,
|
||||
// returning the facts set prior to modification.
|
||||
func (tx *forawaitTransformer) enterSubtree(excludeFacts forAwaitHierarchyFacts, includeFacts forAwaitHierarchyFacts) forAwaitHierarchyFacts {
|
||||
ancestorFacts := tx.forAwaitHierarchyFacts
|
||||
tx.forAwaitHierarchyFacts = (tx.forAwaitHierarchyFacts&^excludeFacts | includeFacts) & forAwaitHierarchyFactsAncestorFactsMask
|
||||
return ancestorFacts
|
||||
}
|
||||
|
||||
// exitSubtree restores the HierarchyFacts for this node's ancestor after visiting this node's
|
||||
// subtree.
|
||||
func (tx *forawaitTransformer) exitSubtree(ancestorFacts forAwaitHierarchyFacts) {
|
||||
tx.forAwaitHierarchyFacts = ancestorFacts
|
||||
}
|
||||
|
||||
func (tx *forawaitTransformer) visitModifiersNoAsync(modifiers *ast.ModifierList) *ast.ModifierList {
|
||||
return tx.noAsyncModifierVisitor.VisitModifiers(modifiers)
|
||||
}
|
||||
|
||||
func (tx *forawaitTransformer) doWithHierarchyFacts(cb func(*forawaitTransformer, *ast.Node) *ast.Node, node *ast.Node, excludeFacts forAwaitHierarchyFacts, includeFacts forAwaitHierarchyFacts) *ast.Node {
|
||||
if tx.affectsSubtree(excludeFacts, includeFacts) {
|
||||
ancestorFacts := tx.enterSubtree(excludeFacts, includeFacts)
|
||||
result := cb(tx, node)
|
||||
tx.exitSubtree(ancestorFacts)
|
||||
return result
|
||||
}
|
||||
return cb(tx, node)
|
||||
}
|
||||
|
||||
func (tx *forawaitTransformer) visitDefault(node *ast.Node) *ast.Node {
|
||||
return tx.Visitor().VisitEachChild(node)
|
||||
}
|
||||
|
||||
func (tx *forawaitTransformer) fallbackVisitor(node *ast.Node) *ast.Node {
|
||||
if tx.capturedSuperProperties == nil {
|
||||
return node
|
||||
}
|
||||
switch node.Kind {
|
||||
case ast.KindFunctionExpression, ast.KindFunctionDeclaration,
|
||||
ast.KindMethodDeclaration, ast.KindGetAccessor, ast.KindSetAccessor,
|
||||
ast.KindConstructor:
|
||||
return node
|
||||
}
|
||||
tx.trackSuperAccess(node)
|
||||
return tx.fallbackNodeVisitor.VisitEachChild(node)
|
||||
}
|
||||
|
||||
func (tx *forawaitTransformer) visitFallback(node *ast.Node) *ast.Node {
|
||||
return tx.fallbackVisitor(node)
|
||||
}
|
||||
|
||||
func (tx *forawaitTransformer) visit(node *ast.Node) *ast.Node {
|
||||
if node.SubtreeFacts()&ast.SubtreeContainsForAwaitOrAsyncGenerator == 0 {
|
||||
return tx.fallbackVisitor(node)
|
||||
}
|
||||
tx.trackSuperAccess(node)
|
||||
switch node.Kind {
|
||||
case ast.KindSourceFile:
|
||||
return tx.visitSourceFile(node.AsSourceFile())
|
||||
case ast.KindAwaitExpression:
|
||||
return tx.visitAwaitExpression(node.AsAwaitExpression())
|
||||
case ast.KindYieldExpression:
|
||||
return tx.visitYieldExpression(node.AsYieldExpression())
|
||||
case ast.KindReturnStatement:
|
||||
return tx.visitReturnStatement(node.AsReturnStatement())
|
||||
case ast.KindLabeledStatement:
|
||||
return tx.visitLabeledStatement(node.AsLabeledStatement())
|
||||
case ast.KindDoStatement, ast.KindWhileStatement, ast.KindForInStatement:
|
||||
return tx.doWithHierarchyFacts(
|
||||
(*forawaitTransformer).visitDefault,
|
||||
node,
|
||||
forAwaitHierarchyFactsIterationStatementExcludes,
|
||||
forAwaitHierarchyFactsIterationStatementIncludes,
|
||||
)
|
||||
case ast.KindForOfStatement:
|
||||
return tx.visitForOfStatement(node.AsForInOrOfStatement(), nil)
|
||||
case ast.KindForStatement:
|
||||
return tx.doWithHierarchyFacts(
|
||||
(*forawaitTransformer).visitDefault,
|
||||
node,
|
||||
forAwaitHierarchyFactsIterationStatementExcludes,
|
||||
forAwaitHierarchyFactsIterationStatementIncludes,
|
||||
)
|
||||
case ast.KindConstructor:
|
||||
return tx.doWithHierarchyFacts(
|
||||
(*forawaitTransformer).visitConstructorDeclaration,
|
||||
node,
|
||||
forAwaitHierarchyFactsClassOrFunctionExcludes,
|
||||
forAwaitHierarchyFactsClassOrFunctionIncludes,
|
||||
)
|
||||
case ast.KindMethodDeclaration:
|
||||
return tx.doWithHierarchyFacts(
|
||||
(*forawaitTransformer).visitMethodDeclaration,
|
||||
node,
|
||||
forAwaitHierarchyFactsClassOrFunctionExcludes,
|
||||
forAwaitHierarchyFactsClassOrFunctionIncludes,
|
||||
)
|
||||
case ast.KindGetAccessor:
|
||||
return tx.doWithHierarchyFacts(
|
||||
(*forawaitTransformer).visitGetAccessorDeclaration,
|
||||
node,
|
||||
forAwaitHierarchyFactsClassOrFunctionExcludes,
|
||||
forAwaitHierarchyFactsClassOrFunctionIncludes,
|
||||
)
|
||||
case ast.KindSetAccessor:
|
||||
return tx.doWithHierarchyFacts(
|
||||
(*forawaitTransformer).visitSetAccessorDeclaration,
|
||||
node,
|
||||
forAwaitHierarchyFactsClassOrFunctionExcludes,
|
||||
forAwaitHierarchyFactsClassOrFunctionIncludes,
|
||||
)
|
||||
case ast.KindFunctionDeclaration:
|
||||
return tx.doWithHierarchyFacts(
|
||||
(*forawaitTransformer).visitFunctionDeclaration,
|
||||
node,
|
||||
forAwaitHierarchyFactsClassOrFunctionExcludes,
|
||||
forAwaitHierarchyFactsClassOrFunctionIncludes,
|
||||
)
|
||||
case ast.KindFunctionExpression:
|
||||
return tx.doWithHierarchyFacts(
|
||||
(*forawaitTransformer).visitFunctionExpression,
|
||||
node,
|
||||
forAwaitHierarchyFactsClassOrFunctionExcludes,
|
||||
forAwaitHierarchyFactsClassOrFunctionIncludes,
|
||||
)
|
||||
case ast.KindArrowFunction:
|
||||
return tx.doWithHierarchyFacts(
|
||||
(*forawaitTransformer).visitArrowFunction,
|
||||
node,
|
||||
forAwaitHierarchyFactsArrowFunctionExcludes,
|
||||
forAwaitHierarchyFactsArrowFunctionIncludes,
|
||||
)
|
||||
case ast.KindClassDeclaration, ast.KindClassExpression:
|
||||
return tx.doWithHierarchyFacts(
|
||||
(*forawaitTransformer).visitDefault,
|
||||
node,
|
||||
forAwaitHierarchyFactsClassOrFunctionExcludes,
|
||||
forAwaitHierarchyFactsClassOrFunctionIncludes,
|
||||
)
|
||||
default:
|
||||
return tx.Visitor().VisitEachChild(node)
|
||||
}
|
||||
}
|
||||
|
||||
func (tx *forawaitTransformer) visitAwaitExpression(node *ast.AwaitExpression) *ast.Node {
|
||||
if tx.enclosingFunctionFlags&ast.FunctionFlagsAsync != 0 && tx.enclosingFunctionFlags&ast.FunctionFlagsGenerator != 0 {
|
||||
result := tx.Factory().NewYieldExpression(
|
||||
nil, /*asteriskToken*/
|
||||
tx.Factory().NewAwaitHelper(tx.Visitor().VisitNode(node.Expression)),
|
||||
)
|
||||
result.Loc = node.Loc
|
||||
tx.EmitContext().SetOriginal(result, node.AsNode())
|
||||
return result
|
||||
}
|
||||
return tx.Visitor().VisitEachChild(node.AsNode())
|
||||
}
|
||||
|
||||
func (tx *forawaitTransformer) visitYieldExpression(node *ast.YieldExpression) *ast.Node {
|
||||
if tx.enclosingFunctionFlags&ast.FunctionFlagsAsync != 0 && tx.enclosingFunctionFlags&ast.FunctionFlagsGenerator != 0 {
|
||||
if node.AsteriskToken != nil {
|
||||
expression := tx.Visitor().VisitNode(node.Expression)
|
||||
|
||||
asyncValuesResult := tx.Factory().NewAsyncValuesHelper(expression)
|
||||
asyncValuesResult.Loc = expression.Loc
|
||||
|
||||
asyncDelegatorResult := tx.Factory().NewAsyncDelegatorHelper(asyncValuesResult)
|
||||
asyncDelegatorResult.Loc = expression.Loc
|
||||
|
||||
innerYield := tx.Factory().UpdateYieldExpression(
|
||||
node,
|
||||
node.AsteriskToken,
|
||||
asyncDelegatorResult,
|
||||
)
|
||||
|
||||
awaitedYield := tx.Factory().NewAwaitHelper(innerYield)
|
||||
|
||||
result := tx.Factory().NewYieldExpression(
|
||||
nil, /*asteriskToken*/
|
||||
awaitedYield,
|
||||
)
|
||||
result.Loc = node.Loc
|
||||
tx.EmitContext().SetOriginal(result, node.AsNode())
|
||||
return result
|
||||
}
|
||||
|
||||
var innerExpression *ast.Node
|
||||
if node.Expression != nil {
|
||||
innerExpression = tx.Visitor().VisitNode(node.Expression)
|
||||
} else {
|
||||
innerExpression = tx.Factory().NewVoidZeroExpression()
|
||||
}
|
||||
|
||||
result := tx.Factory().NewYieldExpression(
|
||||
nil, /*asteriskToken*/
|
||||
tx.createDownlevelAwait(innerExpression),
|
||||
)
|
||||
result.Loc = node.Loc
|
||||
tx.EmitContext().SetOriginal(result, node.AsNode())
|
||||
return result
|
||||
}
|
||||
|
||||
return tx.Visitor().VisitEachChild(node.AsNode())
|
||||
}
|
||||
|
||||
func (tx *forawaitTransformer) visitReturnStatement(node *ast.ReturnStatement) *ast.Node {
|
||||
if tx.enclosingFunctionFlags&ast.FunctionFlagsAsync != 0 && tx.enclosingFunctionFlags&ast.FunctionFlagsGenerator != 0 {
|
||||
var expression *ast.Node
|
||||
if node.Expression != nil {
|
||||
expression = tx.Visitor().VisitNode(node.Expression)
|
||||
} else {
|
||||
expression = tx.Factory().NewVoidZeroExpression()
|
||||
}
|
||||
return tx.Factory().UpdateReturnStatement(
|
||||
node,
|
||||
tx.createDownlevelAwait(expression),
|
||||
)
|
||||
}
|
||||
|
||||
return tx.Visitor().VisitEachChild(node.AsNode())
|
||||
}
|
||||
|
||||
func (tx *forawaitTransformer) visitLabeledStatement(node *ast.LabeledStatement) *ast.Node {
|
||||
if tx.enclosingFunctionFlags&ast.FunctionFlagsAsync != 0 {
|
||||
statement := unwrapInnermostStatementOfLabel(node)
|
||||
if statement.Kind == ast.KindForOfStatement && statement.AsForInOrOfStatement().AwaitModifier != nil {
|
||||
return tx.visitForOfStatement(statement.AsForInOrOfStatement(), node)
|
||||
}
|
||||
return tx.Factory().RestoreEnclosingLabel(tx.Visitor().VisitNode(statement), node)
|
||||
}
|
||||
return tx.Visitor().VisitEachChild(node.AsNode())
|
||||
}
|
||||
|
||||
// unwrapInnermostStatementOfLabel follows LabeledStatement chains to find the innermost statement.
|
||||
func unwrapInnermostStatementOfLabel(node *ast.LabeledStatement) *ast.Node {
|
||||
for {
|
||||
if node.Statement.Kind != ast.KindLabeledStatement {
|
||||
return node.Statement
|
||||
}
|
||||
node = node.Statement.AsLabeledStatement()
|
||||
}
|
||||
}
|
||||
|
||||
func (tx *forawaitTransformer) visitSourceFile(node *ast.SourceFile) *ast.Node {
|
||||
ancestorFacts := tx.enterSubtree(
|
||||
forAwaitHierarchyFactsSourceFileExcludes,
|
||||
forAwaitHierarchyFactsStrictModeSourceFileIncludes,
|
||||
)
|
||||
tx.exportedVariableStatement = false
|
||||
visited := tx.Visitor().VisitEachChild(node.AsNode())
|
||||
tx.EmitContext().AddEmitHelper(visited, tx.EmitContext().ReadEmitHelpers()...)
|
||||
tx.exitSubtree(ancestorFacts)
|
||||
return visited
|
||||
}
|
||||
|
||||
// visitForOfStatement visits a ForOfStatement and converts it into a ES2015-compatible ForOfStatement.
|
||||
func (tx *forawaitTransformer) visitForOfStatement(node *ast.ForInOrOfStatement, outermostLabeledStatement *ast.LabeledStatement) *ast.Node {
|
||||
ancestorFacts := tx.enterSubtree(forAwaitHierarchyFactsIterationStatementExcludes, forAwaitHierarchyFactsIterationStatementIncludes)
|
||||
var result *ast.Node
|
||||
if node.AwaitModifier != nil {
|
||||
result = tx.transformForAwaitOfStatement(node, outermostLabeledStatement, ancestorFacts)
|
||||
} else {
|
||||
result = tx.Factory().RestoreEnclosingLabel(tx.Visitor().VisitEachChild(node.AsNode()), outermostLabeledStatement)
|
||||
}
|
||||
tx.exitSubtree(ancestorFacts)
|
||||
return result
|
||||
}
|
||||
|
||||
func (tx *forawaitTransformer) convertForOfStatementHead(node *ast.ForInOrOfStatement, boundValue *ast.Node, nonUserCode *ast.Node) *ast.Node {
|
||||
f := tx.Factory()
|
||||
value := f.NewTempVariable()
|
||||
tx.EmitContext().AddVariableDeclaration(value)
|
||||
iteratorValueExpression := f.NewAssignmentExpression(value, boundValue)
|
||||
iteratorValueStatement := f.NewExpressionStatement(iteratorValueExpression)
|
||||
tx.EmitContext().SetSourceMapRange(iteratorValueStatement, node.Expression.Loc)
|
||||
|
||||
exitNonUserCodeExpression := f.NewAssignmentExpression(nonUserCode, f.NewKeywordExpression(ast.KindFalseKeyword))
|
||||
exitNonUserCodeStatement := f.NewExpressionStatement(exitNonUserCodeExpression)
|
||||
tx.EmitContext().SetSourceMapRange(exitNonUserCodeStatement, node.Expression.Loc)
|
||||
|
||||
statements := []*ast.Node{iteratorValueStatement, exitNonUserCodeStatement}
|
||||
binding := tx.Factory().CreateForOfBindingStatement(node.Initializer, value)
|
||||
statements = append(statements, tx.Visitor().VisitNode(binding))
|
||||
|
||||
var bodyLocation core.TextRange
|
||||
var statementsLocation core.TextRange
|
||||
statement := tx.Visitor().VisitEmbeddedStatement(node.Statement)
|
||||
if ast.IsBlock(statement) {
|
||||
statements = append(statements, statement.Statements()...)
|
||||
bodyLocation = statement.Loc
|
||||
statementsLocation = statement.StatementList().Loc
|
||||
} else {
|
||||
statements = append(statements, statement)
|
||||
}
|
||||
|
||||
stmtList := f.NewNodeList(statements)
|
||||
stmtList.Loc = statementsLocation
|
||||
block := f.NewBlock(stmtList, true)
|
||||
block.Loc = bodyLocation
|
||||
return block
|
||||
}
|
||||
|
||||
func (tx *forawaitTransformer) createDownlevelAwait(expression *ast.Node) *ast.Node {
|
||||
if tx.enclosingFunctionFlags&ast.FunctionFlagsGenerator != 0 {
|
||||
return tx.Factory().NewYieldExpression(
|
||||
nil, /*asteriskToken*/
|
||||
tx.Factory().NewAwaitHelper(expression),
|
||||
)
|
||||
}
|
||||
return tx.Factory().NewAwaitExpression(expression)
|
||||
}
|
||||
|
||||
func (tx *forawaitTransformer) transformForAwaitOfStatement(node *ast.ForInOrOfStatement, outermostLabeledStatement *ast.LabeledStatement, ancestorFacts forAwaitHierarchyFacts) *ast.Node {
|
||||
f := tx.Factory()
|
||||
expression := tx.Visitor().VisitNode(node.Expression)
|
||||
|
||||
var iterator *ast.Node
|
||||
if ast.IsIdentifier(expression) {
|
||||
iterator = f.NewGeneratedNameForNode(expression)
|
||||
} else {
|
||||
iterator = f.NewTempVariable()
|
||||
}
|
||||
|
||||
var result *ast.Node
|
||||
if ast.IsIdentifier(expression) {
|
||||
result = f.NewGeneratedNameForNode(iterator)
|
||||
} else {
|
||||
result = f.NewTempVariable()
|
||||
}
|
||||
|
||||
nonUserCode := f.NewTempVariable()
|
||||
done := f.NewTempVariable()
|
||||
tx.EmitContext().AddVariableDeclaration(done)
|
||||
errorRecord := f.NewUniqueName("e")
|
||||
catchVariable := f.NewGeneratedNameForNode(errorRecord)
|
||||
returnMethod := f.NewTempVariable()
|
||||
callValues := f.NewAsyncValuesHelper(expression)
|
||||
callValues.Loc = node.Expression.Loc
|
||||
callNext := f.NewCallExpression(
|
||||
f.NewPropertyAccessExpression(iterator, nil, f.NewIdentifier("next"), ast.NodeFlagsNone),
|
||||
nil, nil,
|
||||
f.NewNodeList([]*ast.Node{}),
|
||||
ast.NodeFlagsNone,
|
||||
)
|
||||
getDone := f.NewPropertyAccessExpression(result, nil, f.NewIdentifier("done"), ast.NodeFlagsNone)
|
||||
getValue := f.NewPropertyAccessExpression(result, nil, f.NewIdentifier("value"), ast.NodeFlagsNone)
|
||||
callReturn := f.NewFunctionCallCall(returnMethod, iterator, []*ast.Node{})
|
||||
|
||||
tx.EmitContext().AddVariableDeclaration(errorRecord)
|
||||
tx.EmitContext().AddVariableDeclaration(returnMethod)
|
||||
|
||||
// if we are enclosed in an outer loop ensure we reset 'errorRecord' per each iteration
|
||||
var initializer *ast.Node
|
||||
if ancestorFacts&forAwaitHierarchyFactsIterationContainer != 0 {
|
||||
initializer = f.InlineExpressions([]*ast.Node{
|
||||
f.NewAssignmentExpression(errorRecord, f.NewVoidZeroExpression()),
|
||||
callValues,
|
||||
})
|
||||
} else {
|
||||
initializer = callValues
|
||||
}
|
||||
|
||||
// Build the for statement
|
||||
iteratorDecl := f.NewVariableDeclaration(iterator, nil, nil, initializer)
|
||||
iteratorDecl.Loc = node.Expression.Loc
|
||||
varDeclList := f.NewVariableDeclarationList(f.NewNodeList([]*ast.Node{
|
||||
f.NewVariableDeclaration(nonUserCode, nil, nil, f.NewKeywordExpression(ast.KindTrueKeyword)),
|
||||
iteratorDecl,
|
||||
f.NewVariableDeclaration(result, nil, nil, nil),
|
||||
}), ast.NodeFlagsNone)
|
||||
varDeclList.Loc = node.Expression.Loc
|
||||
|
||||
condition := f.InlineExpressions([]*ast.Node{
|
||||
f.NewAssignmentExpression(result, tx.createDownlevelAwait(callNext)),
|
||||
f.NewAssignmentExpression(done, getDone),
|
||||
f.NewPrefixUnaryExpression(ast.KindExclamationToken, done),
|
||||
})
|
||||
|
||||
incrementor := f.NewAssignmentExpression(nonUserCode, f.NewKeywordExpression(ast.KindTrueKeyword))
|
||||
|
||||
forStatement := f.NewForStatement(
|
||||
varDeclList,
|
||||
condition,
|
||||
incrementor,
|
||||
tx.convertForOfStatementHead(node, getValue, nonUserCode),
|
||||
)
|
||||
forStatement.Loc = node.Loc
|
||||
tx.EmitContext().AddEmitFlags(forStatement, printer.EFNoTokenTrailingSourceMaps)
|
||||
tx.EmitContext().SetOriginal(forStatement, node.AsNode())
|
||||
|
||||
// Build the try/catch/finally
|
||||
tryBlock := f.NewBlock(f.NewNodeList([]*ast.Node{
|
||||
f.RestoreEnclosingLabel(forStatement, outermostLabeledStatement),
|
||||
}), true)
|
||||
|
||||
// catch clause: { e_1 = { error: e_2 }; }
|
||||
catchBody := f.NewBlock(f.NewNodeList([]*ast.Node{
|
||||
f.NewExpressionStatement(
|
||||
f.NewAssignmentExpression(
|
||||
errorRecord,
|
||||
f.NewObjectLiteralExpression(f.NewNodeList([]*ast.Node{
|
||||
f.NewPropertyAssignment(nil, f.NewIdentifier("error"), nil, nil, catchVariable),
|
||||
}), false),
|
||||
),
|
||||
),
|
||||
}), false)
|
||||
tx.EmitContext().AddEmitFlags(catchBody, printer.EFSingleLine)
|
||||
catchClause := f.NewCatchClause(
|
||||
f.NewVariableDeclaration(catchVariable, nil, nil, nil),
|
||||
catchBody,
|
||||
)
|
||||
|
||||
// finally block
|
||||
// inner try: if (!nonUserCode && !done && (returnMethod = iterator.return)) await returnMethod.call(iterator);
|
||||
innerIfCondition := f.NewBinaryExpression(
|
||||
nil,
|
||||
f.NewBinaryExpression(
|
||||
nil,
|
||||
f.NewPrefixUnaryExpression(ast.KindExclamationToken, nonUserCode),
|
||||
nil,
|
||||
f.NewToken(ast.KindAmpersandAmpersandToken),
|
||||
f.NewPrefixUnaryExpression(ast.KindExclamationToken, done),
|
||||
),
|
||||
nil,
|
||||
f.NewToken(ast.KindAmpersandAmpersandToken),
|
||||
f.NewAssignmentExpression(
|
||||
returnMethod,
|
||||
f.NewPropertyAccessExpression(iterator, nil, f.NewIdentifier("return"), ast.NodeFlagsNone),
|
||||
),
|
||||
)
|
||||
innerIfStatement := f.NewIfStatement(
|
||||
innerIfCondition,
|
||||
f.NewExpressionStatement(tx.createDownlevelAwait(callReturn)),
|
||||
nil,
|
||||
)
|
||||
tx.EmitContext().AddEmitFlags(innerIfStatement, printer.EFSingleLine)
|
||||
|
||||
innerTryBlock := f.NewBlock(f.NewNodeList([]*ast.Node{innerIfStatement}), false)
|
||||
|
||||
// inner finally: if (errorRecord) throw errorRecord.error;
|
||||
innerFinallyIf := f.NewIfStatement(
|
||||
errorRecord,
|
||||
f.NewThrowStatement(
|
||||
f.NewPropertyAccessExpression(errorRecord, nil, f.NewIdentifier("error"), ast.NodeFlagsNone),
|
||||
),
|
||||
nil,
|
||||
)
|
||||
tx.EmitContext().AddEmitFlags(innerFinallyIf, printer.EFSingleLine)
|
||||
innerFinallyBlock := f.NewBlock(f.NewNodeList([]*ast.Node{innerFinallyIf}), false)
|
||||
tx.EmitContext().AddEmitFlags(innerFinallyBlock, printer.EFSingleLine)
|
||||
|
||||
innerTryStatement := f.NewTryStatement(innerTryBlock, nil, innerFinallyBlock)
|
||||
finallyBlock := f.NewBlock(f.NewNodeList([]*ast.Node{innerTryStatement}), true)
|
||||
|
||||
return f.NewTryStatement(tryBlock, catchClause, finallyBlock)
|
||||
}
|
||||
|
||||
func (tx *forawaitTransformer) visitConstructorDeclaration(node *ast.Node) *ast.Node {
|
||||
decl := node.AsConstructorDeclaration()
|
||||
savedEnclosingFunctionFlags := tx.enclosingFunctionFlags
|
||||
tx.enclosingFunctionFlags = ast.GetFunctionFlags(node)
|
||||
updated := tx.Factory().UpdateConstructorDeclaration(
|
||||
decl,
|
||||
decl.Modifiers(),
|
||||
nil, /*typeParameters*/
|
||||
tx.EmitContext().VisitParameters(decl.Parameters, tx.Visitor()),
|
||||
nil, /*returnType*/
|
||||
nil, /*fullSignature*/
|
||||
tx.EmitContext().VisitFunctionBody(node.Body(), tx.Visitor()),
|
||||
)
|
||||
tx.enclosingFunctionFlags = savedEnclosingFunctionFlags
|
||||
return updated
|
||||
}
|
||||
|
||||
func (tx *forawaitTransformer) visitGetAccessorDeclaration(node *ast.Node) *ast.Node {
|
||||
decl := node.AsGetAccessorDeclaration()
|
||||
savedEnclosingFunctionFlags := tx.enclosingFunctionFlags
|
||||
tx.enclosingFunctionFlags = ast.GetFunctionFlags(node)
|
||||
updated := tx.Factory().UpdateGetAccessorDeclaration(
|
||||
decl,
|
||||
decl.Modifiers(),
|
||||
tx.Visitor().VisitNode(decl.Name()),
|
||||
nil, /*typeParameters*/
|
||||
tx.EmitContext().VisitParameters(decl.Parameters, tx.Visitor()),
|
||||
nil, /*returnType*/
|
||||
nil, /*fullSignature*/
|
||||
tx.EmitContext().VisitFunctionBody(node.Body(), tx.Visitor()),
|
||||
)
|
||||
tx.enclosingFunctionFlags = savedEnclosingFunctionFlags
|
||||
return updated
|
||||
}
|
||||
|
||||
func (tx *forawaitTransformer) visitSetAccessorDeclaration(node *ast.Node) *ast.Node {
|
||||
decl := node.AsSetAccessorDeclaration()
|
||||
savedEnclosingFunctionFlags := tx.enclosingFunctionFlags
|
||||
tx.enclosingFunctionFlags = ast.GetFunctionFlags(node)
|
||||
updated := tx.Factory().UpdateSetAccessorDeclaration(
|
||||
decl,
|
||||
decl.Modifiers(),
|
||||
tx.Visitor().VisitNode(decl.Name()),
|
||||
nil, /*typeParameters*/
|
||||
tx.EmitContext().VisitParameters(decl.Parameters, tx.Visitor()),
|
||||
nil, /*returnType*/
|
||||
nil, /*fullSignature*/
|
||||
tx.EmitContext().VisitFunctionBody(node.Body(), tx.Visitor()),
|
||||
)
|
||||
tx.enclosingFunctionFlags = savedEnclosingFunctionFlags
|
||||
return updated
|
||||
}
|
||||
|
||||
func (tx *forawaitTransformer) visitMethodDeclaration(node *ast.Node) *ast.Node {
|
||||
decl := node.AsMethodDeclaration()
|
||||
savedEnclosingFunctionFlags := tx.enclosingFunctionFlags
|
||||
tx.enclosingFunctionFlags = ast.GetFunctionFlags(node)
|
||||
|
||||
var modifiers *ast.ModifierList
|
||||
if tx.enclosingFunctionFlags&ast.FunctionFlagsGenerator != 0 {
|
||||
modifiers = tx.visitModifiersNoAsync(decl.Modifiers())
|
||||
} else {
|
||||
modifiers = decl.Modifiers()
|
||||
}
|
||||
|
||||
var asteriskToken *ast.TokenNode
|
||||
if tx.enclosingFunctionFlags&ast.FunctionFlagsAsync != 0 {
|
||||
asteriskToken = nil
|
||||
} else {
|
||||
asteriskToken = decl.AsteriskToken
|
||||
}
|
||||
|
||||
var parameters *ast.NodeList
|
||||
var body *ast.Node
|
||||
if tx.enclosingFunctionFlags&ast.FunctionFlagsAsync != 0 && tx.enclosingFunctionFlags&ast.FunctionFlagsGenerator != 0 {
|
||||
parameters = tx.transformAsyncGeneratorFunctionParameterList(node)
|
||||
body = tx.transformAsyncGeneratorFunctionBody(node)
|
||||
} else {
|
||||
parameters = tx.EmitContext().VisitParameters(decl.Parameters, tx.Visitor())
|
||||
body = tx.EmitContext().VisitFunctionBody(node.Body(), tx.Visitor())
|
||||
}
|
||||
|
||||
updated := tx.Factory().UpdateMethodDeclaration(
|
||||
decl,
|
||||
modifiers,
|
||||
asteriskToken,
|
||||
tx.Visitor().VisitNode(decl.Name()),
|
||||
nil, /*postfixToken*/
|
||||
nil, /*typeParameters*/
|
||||
parameters,
|
||||
nil, /*returnType*/
|
||||
nil, /*fullSignature*/
|
||||
body,
|
||||
)
|
||||
tx.enclosingFunctionFlags = savedEnclosingFunctionFlags
|
||||
return updated
|
||||
}
|
||||
|
||||
func (tx *forawaitTransformer) visitFunctionDeclaration(node *ast.Node) *ast.Node {
|
||||
decl := node.AsFunctionDeclaration()
|
||||
savedEnclosingFunctionFlags := tx.enclosingFunctionFlags
|
||||
tx.enclosingFunctionFlags = ast.GetFunctionFlags(node)
|
||||
|
||||
var modifiers *ast.ModifierList
|
||||
if tx.enclosingFunctionFlags&ast.FunctionFlagsGenerator != 0 {
|
||||
modifiers = tx.visitModifiersNoAsync(decl.Modifiers())
|
||||
} else {
|
||||
modifiers = decl.Modifiers()
|
||||
}
|
||||
|
||||
var asteriskToken *ast.TokenNode
|
||||
if tx.enclosingFunctionFlags&ast.FunctionFlagsAsync != 0 {
|
||||
asteriskToken = nil
|
||||
} else {
|
||||
asteriskToken = decl.AsteriskToken
|
||||
}
|
||||
|
||||
var parameters *ast.NodeList
|
||||
var body *ast.Node
|
||||
if tx.enclosingFunctionFlags&ast.FunctionFlagsAsync != 0 && tx.enclosingFunctionFlags&ast.FunctionFlagsGenerator != 0 {
|
||||
parameters = tx.transformAsyncGeneratorFunctionParameterList(node)
|
||||
body = tx.transformAsyncGeneratorFunctionBody(node)
|
||||
} else {
|
||||
parameters = tx.EmitContext().VisitParameters(decl.Parameters, tx.Visitor())
|
||||
body = tx.EmitContext().VisitFunctionBody(node.Body(), tx.Visitor())
|
||||
}
|
||||
|
||||
updated := tx.Factory().UpdateFunctionDeclaration(
|
||||
decl,
|
||||
modifiers,
|
||||
asteriskToken,
|
||||
decl.Name(),
|
||||
nil, /*typeParameters*/
|
||||
parameters,
|
||||
nil, /*returnType*/
|
||||
nil, /*fullSignature*/
|
||||
body,
|
||||
)
|
||||
tx.enclosingFunctionFlags = savedEnclosingFunctionFlags
|
||||
return updated
|
||||
}
|
||||
|
||||
func (tx *forawaitTransformer) visitArrowFunction(node *ast.Node) *ast.Node {
|
||||
decl := node.AsArrowFunction()
|
||||
savedEnclosingFunctionFlags := tx.enclosingFunctionFlags
|
||||
tx.enclosingFunctionFlags = ast.GetFunctionFlags(node)
|
||||
updated := tx.Factory().UpdateArrowFunction(
|
||||
decl,
|
||||
decl.Modifiers(),
|
||||
nil, /*typeParameters*/
|
||||
tx.EmitContext().VisitParameters(decl.Parameters, tx.Visitor()),
|
||||
nil, /*returnType*/
|
||||
nil, /*fullSignature*/
|
||||
decl.EqualsGreaterThanToken,
|
||||
tx.EmitContext().VisitFunctionBody(node.Body(), tx.Visitor()),
|
||||
)
|
||||
tx.enclosingFunctionFlags = savedEnclosingFunctionFlags
|
||||
return updated
|
||||
}
|
||||
|
||||
func (tx *forawaitTransformer) visitFunctionExpression(node *ast.Node) *ast.Node {
|
||||
decl := node.AsFunctionExpression()
|
||||
savedEnclosingFunctionFlags := tx.enclosingFunctionFlags
|
||||
tx.enclosingFunctionFlags = ast.GetFunctionFlags(node)
|
||||
|
||||
var modifiers *ast.ModifierList
|
||||
if tx.enclosingFunctionFlags&ast.FunctionFlagsGenerator != 0 {
|
||||
modifiers = tx.visitModifiersNoAsync(decl.Modifiers())
|
||||
} else {
|
||||
modifiers = decl.Modifiers()
|
||||
}
|
||||
|
||||
var asteriskToken *ast.TokenNode
|
||||
if tx.enclosingFunctionFlags&ast.FunctionFlagsAsync != 0 {
|
||||
asteriskToken = nil
|
||||
} else {
|
||||
asteriskToken = decl.AsteriskToken
|
||||
}
|
||||
|
||||
var parameters *ast.NodeList
|
||||
var body *ast.Node
|
||||
if tx.enclosingFunctionFlags&ast.FunctionFlagsAsync != 0 && tx.enclosingFunctionFlags&ast.FunctionFlagsGenerator != 0 {
|
||||
parameters = tx.transformAsyncGeneratorFunctionParameterList(node)
|
||||
body = tx.transformAsyncGeneratorFunctionBody(node)
|
||||
} else {
|
||||
parameters = tx.EmitContext().VisitParameters(decl.Parameters, tx.Visitor())
|
||||
body = tx.EmitContext().VisitFunctionBody(node.Body(), tx.Visitor())
|
||||
}
|
||||
|
||||
updated := tx.Factory().UpdateFunctionExpression(
|
||||
decl,
|
||||
modifiers,
|
||||
asteriskToken,
|
||||
decl.Name(),
|
||||
nil, /*typeParameters*/
|
||||
parameters,
|
||||
nil, /*returnType*/
|
||||
nil, /*fullSignature*/
|
||||
body,
|
||||
)
|
||||
tx.enclosingFunctionFlags = savedEnclosingFunctionFlags
|
||||
return updated
|
||||
}
|
||||
|
||||
func (tx *forawaitTransformer) transformAsyncGeneratorFunctionParameterList(node *ast.Node) *ast.NodeList {
|
||||
if isSimpleParameterList(node.Parameters()) {
|
||||
return tx.EmitContext().VisitParameters(node.ParameterList(), tx.Visitor())
|
||||
}
|
||||
// Add fixed parameters to preserve the function's `length` property.
|
||||
var newParameters []*ast.Node
|
||||
for _, parameter := range node.Parameters() {
|
||||
param := parameter.AsParameterDeclaration()
|
||||
if param.Initializer != nil || param.DotDotDotToken != nil {
|
||||
break
|
||||
}
|
||||
newParameter := tx.Factory().NewParameterDeclaration(
|
||||
nil,
|
||||
nil,
|
||||
tx.Factory().NewGeneratedNameForNodeEx(param.Name(), printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsReservedInNestedScopes}),
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
newParameters = append(newParameters, newParameter)
|
||||
}
|
||||
newParametersArray := tx.Factory().NewNodeList(newParameters)
|
||||
newParametersArray.Loc = node.ParameterList().Loc
|
||||
return newParametersArray
|
||||
}
|
||||
|
||||
func (tx *forawaitTransformer) transformAsyncGeneratorFunctionBody(node *ast.Node) *ast.Node {
|
||||
f := tx.Factory()
|
||||
var innerParameters *ast.NodeList
|
||||
if !isSimpleParameterList(node.Parameters()) {
|
||||
innerParameters = tx.EmitContext().VisitParameters(node.ParameterList(), tx.Visitor())
|
||||
}
|
||||
|
||||
savedCapturedSuperProperties := tx.capturedSuperProperties
|
||||
savedHasSuperElementAccess := tx.hasSuperElementAccess
|
||||
savedHasSuperPropertyAssignment := tx.hasSuperPropertyAssignment
|
||||
savedSuperBinding := tx.superBinding
|
||||
savedSuperIndexBinding := tx.superIndexBinding
|
||||
tx.capturedSuperProperties = &collections.OrderedSet[string]{}
|
||||
tx.hasSuperElementAccess = false
|
||||
tx.hasSuperPropertyAssignment = false
|
||||
tx.superBinding = f.NewUniqueNameEx("_super", printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsOptimistic | printer.GeneratedIdentifierFlagsFileLevel})
|
||||
tx.superIndexBinding = f.NewUniqueNameEx("_superIndex", printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsOptimistic | printer.GeneratedIdentifierFlagsFileLevel})
|
||||
|
||||
asyncBody := f.UpdateBlock(
|
||||
node.Body().AsBlock(),
|
||||
tx.Visitor().VisitNodes(node.Body().StatementList()),
|
||||
node.Body().AsBlock().MultiLine,
|
||||
)
|
||||
asyncBody = f.UpdateBlock(
|
||||
asyncBody.AsBlock(),
|
||||
tx.EmitContext().EndAndMergeVariableEnvironmentList(asyncBody.StatementList()),
|
||||
asyncBody.AsBlock().MultiLine,
|
||||
)
|
||||
|
||||
// Substitute super property accesses with _super/_superIndex helpers
|
||||
emitSuperHelpers := tx.capturedSuperProperties.Size() > 0 || tx.hasSuperElementAccess
|
||||
if emitSuperHelpers {
|
||||
asyncBody = tx.substituteSuperAccessesInBody(asyncBody)
|
||||
}
|
||||
|
||||
var innerParams *ast.NodeList
|
||||
if innerParameters != nil {
|
||||
innerParams = innerParameters
|
||||
} else {
|
||||
innerParams = f.NewNodeList([]*ast.Node{})
|
||||
}
|
||||
|
||||
var name *ast.Node
|
||||
if node.Name() != nil {
|
||||
name = f.NewGeneratedNameForNode(node.Name())
|
||||
}
|
||||
|
||||
generatorFunc := f.NewFunctionExpression(
|
||||
nil, /*modifiers*/
|
||||
f.NewToken(ast.KindAsteriskToken),
|
||||
name,
|
||||
nil, /*typeParameters*/
|
||||
innerParams,
|
||||
nil, /*returnType*/
|
||||
nil, /*fullSignature*/
|
||||
asyncBody,
|
||||
)
|
||||
|
||||
returnStatement := f.NewReturnStatement(
|
||||
f.NewAsyncGeneratorHelper(
|
||||
generatorFunc,
|
||||
tx.forAwaitHierarchyFacts&forAwaitHierarchyFactsHasLexicalThis != 0,
|
||||
),
|
||||
)
|
||||
|
||||
tx.EmitContext().StartVariableEnvironment()
|
||||
if emitSuperHelpers {
|
||||
if tx.capturedSuperProperties.Size() > 0 {
|
||||
tx.EmitContext().AddInitializationStatement(tx.createSuperAccessVariableStatement())
|
||||
}
|
||||
}
|
||||
|
||||
outerStatements := []*ast.Node{returnStatement}
|
||||
|
||||
block := f.UpdateBlock(
|
||||
node.Body().AsBlock(),
|
||||
tx.EmitContext().EndAndMergeVariableEnvironmentList(f.NewNodeList(outerStatements)),
|
||||
node.Body().AsBlock().MultiLine,
|
||||
)
|
||||
|
||||
if emitSuperHelpers && tx.hasSuperElementAccess {
|
||||
if tx.hasSuperPropertyAssignment {
|
||||
tx.EmitContext().AddEmitHelper(block, printer.AdvancedAsyncSuperHelper)
|
||||
} else {
|
||||
tx.EmitContext().AddEmitHelper(block, printer.AsyncSuperHelper)
|
||||
}
|
||||
}
|
||||
|
||||
tx.capturedSuperProperties = savedCapturedSuperProperties
|
||||
tx.hasSuperElementAccess = savedHasSuperElementAccess
|
||||
tx.hasSuperPropertyAssignment = savedHasSuperPropertyAssignment
|
||||
tx.superBinding = savedSuperBinding
|
||||
tx.superIndexBinding = savedSuperIndexBinding
|
||||
|
||||
return block
|
||||
}
|
||||
Reference in New Issue
Block a user