vendor tsgo
This commit is contained in:
537
tools/tsgo/internal/transformers/estransforms/namedevaluation.go
Normal file
537
tools/tsgo/internal/transformers/estransforms/namedevaluation.go
Normal file
@@ -0,0 +1,537 @@
|
||||
package estransforms
|
||||
|
||||
import (
|
||||
"slices"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/ast"
|
||||
"github.com/microsoft/typescript-go/internal/debug"
|
||||
"github.com/microsoft/typescript-go/internal/printer"
|
||||
)
|
||||
|
||||
/**
|
||||
* Gets whether a node is a `static {}` block containing only a single call to the `__setFunctionName` helper where that
|
||||
* call's second argument is the value stored in the `assignedName` property of the block's `EmitNode`.
|
||||
* @internal
|
||||
*/
|
||||
func isClassNamedEvaluationHelperBlock(emitContext *printer.EmitContext, node *ast.Node) bool {
|
||||
if !ast.IsClassStaticBlockDeclaration(node) || len(node.AsClassStaticBlockDeclaration().Body.Statements()) != 1 {
|
||||
return false
|
||||
}
|
||||
|
||||
statement := node.AsClassStaticBlockDeclaration().Body.Statements()[0]
|
||||
if ast.IsExpressionStatement(statement) {
|
||||
expression := statement.Expression()
|
||||
if emitContext.IsCallToHelper(expression, "__setFunctionName") {
|
||||
arguments := expression.AsCallExpression().Arguments
|
||||
return len(arguments.Nodes) >= 2 &&
|
||||
arguments.Nodes[1] == emitContext.AssignedName(node.AsNode())
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether a `ClassLikeDeclaration` has a `static {}` block containing only a single call to the
|
||||
* `__setFunctionName` helper.
|
||||
* @internal
|
||||
*/
|
||||
func classHasExplicitlyAssignedName(emitContext *printer.EmitContext, node *ast.ClassLikeDeclaration) bool {
|
||||
if assignedName := emitContext.AssignedName(node); assignedName != nil {
|
||||
for _, member := range node.Members() {
|
||||
if isClassNamedEvaluationHelperBlock(emitContext, member) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether a `ClassLikeDeclaration` has a declared name or contains a `static {}` block containing only a single
|
||||
* call to the `__setFunctionName` helper.
|
||||
* @internal
|
||||
*/
|
||||
func classHasDeclaredOrExplicitlyAssignedName(emitContext *printer.EmitContext, node *ast.ClassLikeDeclaration) bool {
|
||||
return node.Name() != nil || classHasExplicitlyAssignedName(emitContext, node)
|
||||
}
|
||||
|
||||
type anonymousFunctionDefinition = ast.Node // ClassExpression | FunctionExpression | ArrowFunction
|
||||
|
||||
// Indicates whether an expression is an anonymous function definition.
|
||||
//
|
||||
// See https://tc39.es/ecma262/#sec-isanonymousfunctiondefinition
|
||||
func isAnonymousFunctionDefinition(emitContext *printer.EmitContext, node *ast.Expression, cb func(*anonymousFunctionDefinition) bool) bool {
|
||||
node = ast.SkipOuterExpressions(node, ast.OEKAll)
|
||||
switch node.Kind {
|
||||
case ast.KindClassExpression:
|
||||
if classHasDeclaredOrExplicitlyAssignedName(emitContext, node) {
|
||||
return false
|
||||
}
|
||||
break
|
||||
case ast.KindFunctionExpression:
|
||||
if node.AsFunctionExpression().Name() != nil {
|
||||
return false
|
||||
}
|
||||
break
|
||||
case ast.KindArrowFunction:
|
||||
break
|
||||
default:
|
||||
return false
|
||||
}
|
||||
if cb != nil {
|
||||
return cb(node)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func isNamedEvaluation(emitContext *printer.EmitContext, node *ast.Node) bool {
|
||||
return isNamedEvaluationAnd(emitContext, node, nil)
|
||||
}
|
||||
|
||||
func isNamedEvaluationAnd(emitContext *printer.EmitContext, node *ast.Node, cb func(*anonymousFunctionDefinition) bool) bool {
|
||||
if !ast.IsNamedEvaluationSource(node) {
|
||||
return false
|
||||
}
|
||||
switch node.Kind {
|
||||
case ast.KindShorthandPropertyAssignment:
|
||||
return isAnonymousFunctionDefinition(emitContext, node.AsShorthandPropertyAssignment().ObjectAssignmentInitializer, cb)
|
||||
case ast.KindPropertyAssignment, ast.KindVariableDeclaration, ast.KindParameter, ast.KindBindingElement, ast.KindPropertyDeclaration:
|
||||
return isAnonymousFunctionDefinition(emitContext, node.Initializer(), cb)
|
||||
case ast.KindBinaryExpression:
|
||||
return isAnonymousFunctionDefinition(emitContext, node.AsBinaryExpression().Right, cb)
|
||||
case ast.KindExportAssignment:
|
||||
return isAnonymousFunctionDefinition(emitContext, node.Expression(), cb)
|
||||
default:
|
||||
debug.Fail("Unhandled case in isNamedEvaluation")
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Gets a string literal to use as the assigned name of an anonymous class or function declaration.
|
||||
func getAssignedNameOfIdentifier(emitContext *printer.EmitContext, name *ast.IdentifierNode, expression *ast.Node /*WrappedExpression<AnonymousFunctionDefinition>*/) *ast.StringLiteralNode {
|
||||
original := emitContext.MostOriginal(ast.SkipOuterExpressions(expression, ast.OEKAll))
|
||||
if (ast.IsClassDeclaration(original) || ast.IsFunctionDeclaration(original)) &&
|
||||
original.Name() == nil && ast.HasSyntacticModifier(original, ast.ModifierFlagsDefault) {
|
||||
return emitContext.Factory.NewStringLiteral("default", ast.TokenFlagsNone)
|
||||
}
|
||||
return emitContext.Factory.NewStringLiteralFromNode(name)
|
||||
}
|
||||
|
||||
func getAssignedNameOfPropertyName(emitContext *printer.EmitContext, name *ast.PropertyName, assignedNameText string) (assignedName *ast.Expression, updatedName *ast.PropertyName) {
|
||||
factory := emitContext.Factory
|
||||
if len(assignedNameText) > 0 {
|
||||
assignedName := factory.NewStringLiteral(assignedNameText, ast.TokenFlagsNone)
|
||||
return assignedName, name
|
||||
}
|
||||
|
||||
if ast.IsPropertyNameLiteral(name) || ast.IsPrivateIdentifier(name) {
|
||||
assignedName := factory.NewStringLiteralFromNode(name)
|
||||
return assignedName, name
|
||||
}
|
||||
|
||||
expression := name.Expression()
|
||||
if ast.IsPropertyNameLiteral(expression) && !ast.IsIdentifier(expression) {
|
||||
assignedName := factory.NewStringLiteralFromNode(expression)
|
||||
return assignedName, name
|
||||
}
|
||||
|
||||
debug.Assert(ast.IsComputedPropertyName(name), "Expected computed property name")
|
||||
|
||||
assignedName = factory.NewGeneratedNameForNode(name)
|
||||
emitContext.AddVariableDeclaration(assignedName)
|
||||
|
||||
key := factory.NewPropKeyHelper(expression)
|
||||
assignment := factory.NewAssignmentExpression(assignedName, key)
|
||||
updatedName = factory.UpdateComputedPropertyName(name.AsComputedPropertyName(), assignment)
|
||||
return assignedName, updatedName
|
||||
}
|
||||
|
||||
// Creates a class `static {}` block used to dynamically set the name of a class.
|
||||
//
|
||||
// The assignedName parameter is the expression used to resolve the assigned name at runtime. This expression should not produce
|
||||
// side effects.
|
||||
// The thisExpression parameter overrides the expression to use for the actual `this` reference. This can be used to provide an
|
||||
// expression that has already had its `EmitFlags` set or may have been tracked to prevent substitution.
|
||||
func createClassNamedEvaluationHelperBlock(emitContext *printer.EmitContext, assignedName *ast.Expression, thisExpression *ast.Expression) *ast.Node {
|
||||
// produces:
|
||||
//
|
||||
// static { __setFunctionName(this, "C"); }
|
||||
//
|
||||
|
||||
if thisExpression == nil {
|
||||
thisExpression = emitContext.Factory.NewThisExpression()
|
||||
}
|
||||
|
||||
factory := emitContext.Factory
|
||||
expression := factory.NewSetFunctionNameHelper(thisExpression, assignedName, "" /*prefix*/)
|
||||
statement := factory.NewExpressionStatement(expression)
|
||||
body := factory.NewBlock(factory.NewNodeList([]*ast.Statement{statement}), false /*multiLine*/)
|
||||
block := factory.NewClassStaticBlockDeclaration(nil /*modifiers*/, body)
|
||||
|
||||
// We use `emitNode.assignedName` to indicate this is a NamedEvaluation helper block
|
||||
// and to stash the expression used to resolve the assigned name.
|
||||
emitContext.SetAssignedName(block, assignedName)
|
||||
return block.AsNode()
|
||||
}
|
||||
|
||||
// Injects a class `static {}` block used to dynamically set the name of a class, if one does not already exist.
|
||||
func injectClassNamedEvaluationHelperBlockIfMissing(
|
||||
emitContext *printer.EmitContext,
|
||||
node *ast.ClassLikeDeclaration,
|
||||
assignedName *ast.Expression,
|
||||
thisExpression *ast.Expression,
|
||||
) *ast.ClassLikeDeclaration {
|
||||
// given:
|
||||
//
|
||||
// let C = class {
|
||||
// };
|
||||
//
|
||||
// produces:
|
||||
//
|
||||
// let C = class {
|
||||
// static { __setFunctionName(this, "C"); }
|
||||
// };
|
||||
|
||||
// NOTE: If the class has a `_classThis` assignment block, this helper will be injected after that block.
|
||||
|
||||
if classHasExplicitlyAssignedName(emitContext, node) {
|
||||
return node
|
||||
}
|
||||
|
||||
factory := emitContext.Factory
|
||||
namedEvaluationBlock := createClassNamedEvaluationHelperBlock(emitContext, assignedName, thisExpression)
|
||||
if node.Name() != nil {
|
||||
emitContext.SetSourceMapRange(namedEvaluationBlock.Body().Statements()[0], node.Name().Loc)
|
||||
}
|
||||
|
||||
insertionIndex := slices.IndexFunc(node.Members(), func(n *ast.Node) bool {
|
||||
return isClassThisAssignmentBlock(emitContext, n)
|
||||
}) + 1
|
||||
leading := slices.Clone(node.Members()[:insertionIndex])
|
||||
trailing := slices.Clone(node.Members()[insertionIndex:])
|
||||
|
||||
var members []*ast.ClassElement
|
||||
members = append(members, leading...)
|
||||
members = append(members, namedEvaluationBlock)
|
||||
members = append(members, trailing...)
|
||||
membersList := factory.NewNodeList(members)
|
||||
membersList.Loc = node.MemberList().Loc
|
||||
|
||||
oldNode := node
|
||||
if ast.IsClassDeclaration(node) {
|
||||
node = factory.UpdateClassDeclaration(
|
||||
node.AsClassDeclaration(),
|
||||
node.Modifiers(),
|
||||
node.Name(),
|
||||
node.TypeParameterList(),
|
||||
node.AsClassDeclaration().HeritageClauses,
|
||||
membersList,
|
||||
)
|
||||
} else {
|
||||
node = factory.UpdateClassExpression(
|
||||
node.AsClassExpression(),
|
||||
node.Modifiers(),
|
||||
node.Name(),
|
||||
node.TypeParameterList(),
|
||||
node.AsClassExpression().HeritageClauses,
|
||||
membersList,
|
||||
)
|
||||
}
|
||||
|
||||
emitContext.SetAssignedName(node, assignedName)
|
||||
|
||||
// Transfer ClassThis from old to new node, since UpdateClassExpression creates
|
||||
// a new node that won't have ClassThis set on it.
|
||||
if ct := emitContext.ClassThis(oldNode); ct != nil {
|
||||
emitContext.SetClassThis(node, ct)
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
func finishTransformNamedEvaluation(
|
||||
emitContext *printer.EmitContext,
|
||||
expression *ast.Node, // WrappedExpression<AnonymousFunctionDefinition>,
|
||||
assignedName *ast.Expression,
|
||||
ignoreEmptyStringLiteral bool,
|
||||
) *ast.Expression {
|
||||
if ignoreEmptyStringLiteral && ast.IsStringLiteral(assignedName) && len(assignedName.Text()) == 0 {
|
||||
return expression
|
||||
}
|
||||
|
||||
factory := emitContext.Factory
|
||||
innerExpression := ast.SkipOuterExpressions(expression, ast.OEKAll)
|
||||
|
||||
var updatedExpression *ast.Expression
|
||||
if ast.IsClassExpression(innerExpression) {
|
||||
updatedExpression = injectClassNamedEvaluationHelperBlockIfMissing(emitContext, innerExpression, assignedName, nil /*thisExpression*/)
|
||||
} else {
|
||||
updatedExpression = factory.NewSetFunctionNameHelper(innerExpression, assignedName, "" /*prefix*/)
|
||||
}
|
||||
|
||||
return factory.RestoreOuterExpressions(expression, updatedExpression, ast.OEKAll)
|
||||
}
|
||||
|
||||
func transformNamedEvaluationOfPropertyAssignment(context *printer.EmitContext, node *ast.PropertyAssignment /*NamedEvaluation & PropertyAssignment*/, ignoreEmptyStringLiteral bool, assignedNameText string) *ast.Expression {
|
||||
// 13.2.5.5 RS: PropertyDefinitionEvaluation
|
||||
// PropertyAssignment : PropertyName `:` AssignmentExpression
|
||||
// ...
|
||||
// 5. If IsAnonymousFunctionDefinition(|AssignmentExpression|) is *true* and _isProtoSetter_ is *false*, then
|
||||
// a. Let _popValue_ be ? NamedEvaluation of |AssignmentExpression| with argument _propKey_.
|
||||
// ...
|
||||
|
||||
factory := context.Factory
|
||||
assignedName, name := getAssignedNameOfPropertyName(context, node.Name(), assignedNameText)
|
||||
initializer := finishTransformNamedEvaluation(context, node.Initializer, assignedName, ignoreEmptyStringLiteral)
|
||||
return factory.UpdatePropertyAssignment(node, nil /*modifiers*/, name, nil /*postfixToken*/, nil /*typeNode*/, initializer)
|
||||
}
|
||||
|
||||
func transformNamedEvaluationOfShorthandAssignmentProperty(emitContext *printer.EmitContext, node *ast.ShorthandPropertyAssignment /*NamedEvaluation & ShorthandPropertyAssignment*/, ignoreEmptyStringLiteral bool, assignedNameText string) *ast.Expression {
|
||||
// 13.15.5.3 RS: PropertyDestructuringAssignmentEvaluation
|
||||
// AssignmentProperty : IdentifierReference Initializer?
|
||||
// ...
|
||||
// 4. If |Initializer?| is present and _v_ is *undefined*, then
|
||||
// a. If IsAnonymousFunctionDefinition(|Initializer|) is *true*, then
|
||||
// i. Set _v_ to ? NamedEvaluation of |Initializer| with argument _P_.
|
||||
// ...
|
||||
|
||||
factory := emitContext.Factory
|
||||
var assignedName *ast.Expression
|
||||
if len(assignedNameText) > 0 {
|
||||
assignedName = factory.NewStringLiteral(assignedNameText, ast.TokenFlagsNone)
|
||||
} else {
|
||||
assignedName = getAssignedNameOfIdentifier(emitContext, node.Name(), node.ObjectAssignmentInitializer)
|
||||
}
|
||||
objectAssignmentInitializer := finishTransformNamedEvaluation(emitContext, node.ObjectAssignmentInitializer, assignedName, ignoreEmptyStringLiteral)
|
||||
return factory.UpdateShorthandPropertyAssignment(
|
||||
node,
|
||||
nil, /*modifiers*/
|
||||
node.Name(),
|
||||
nil, /*postfixToken*/
|
||||
nil, /*typeNode*/
|
||||
node.EqualsToken,
|
||||
objectAssignmentInitializer,
|
||||
)
|
||||
}
|
||||
|
||||
func transformNamedEvaluationOfVariableDeclaration(emitContext *printer.EmitContext, node *ast.VariableDeclaration /*NamedEvaluation & VariableDeclaration*/, ignoreEmptyStringLiteral bool, assignedNameText string) *ast.Expression {
|
||||
// 14.3.1.2 RS: Evaluation
|
||||
// LexicalBinding : BindingIdentifier Initializer
|
||||
// ...
|
||||
// 3. If IsAnonymousFunctionDefinition(|Initializer|) is *true*, then
|
||||
// a. Let _value_ be ? NamedEvaluation of |Initializer| with argument _bindingId_.
|
||||
// ...
|
||||
//
|
||||
// 14.3.2.1 RS: Evaluation
|
||||
// VariableDeclaration : BindingIdentifier Initializer
|
||||
// ...
|
||||
// 3. If IsAnonymousFunctionDefinition(|Initializer|) is *true*, then
|
||||
// a. Let _value_ be ? NamedEvaluation of |Initializer| with argument _bindingId_.
|
||||
// ...
|
||||
|
||||
factory := emitContext.Factory
|
||||
var assignedName *ast.Expression
|
||||
if len(assignedNameText) > 0 {
|
||||
assignedName = factory.NewStringLiteral(assignedNameText, ast.TokenFlagsNone)
|
||||
} else {
|
||||
assignedName = getAssignedNameOfIdentifier(emitContext, node.Name(), node.Initializer)
|
||||
}
|
||||
initializer := finishTransformNamedEvaluation(emitContext, node.Initializer, assignedName, ignoreEmptyStringLiteral)
|
||||
return factory.UpdateVariableDeclaration(
|
||||
node,
|
||||
node.Name(),
|
||||
nil, /*exclamationToken*/
|
||||
nil, /*typeNode*/
|
||||
initializer,
|
||||
)
|
||||
}
|
||||
|
||||
func transformNamedEvaluationOfParameterDeclaration(emitContext *printer.EmitContext, node *ast.ParameterDeclaration /*NamedEvaluation & ParameterDeclaration*/, ignoreEmptyStringLiteral bool, assignedNameText string) *ast.Expression {
|
||||
// 8.6.3 RS: IteratorBindingInitialization
|
||||
// SingleNameBinding : BindingIdentifier Initializer?
|
||||
// ...
|
||||
// 5. If |Initializer| is present and _v_ is *undefined*, then
|
||||
// a. If IsAnonymousFunctionDefinition(|Initializer|) is *true*, then
|
||||
// i. Set _v_ to ? NamedEvaluation of |Initializer| with argument _bindingId_.
|
||||
// ...
|
||||
//
|
||||
// 14.3.3.3 RS: KeyedBindingInitialization
|
||||
// SingleNameBinding : BindingIdentifier Initializer?
|
||||
// ...
|
||||
// 4. If |Initializer| is present and _v_ is *undefined*, then
|
||||
// a. If IsAnonymousFunctionDefinition(|Initializer|) is *true*, then
|
||||
// i. Set _v_ to ? NamedEvaluation of |Initializer| with argument _bindingId_.
|
||||
// ...
|
||||
|
||||
factory := emitContext.Factory
|
||||
var assignedName *ast.Expression
|
||||
if len(assignedNameText) > 0 {
|
||||
assignedName = factory.NewStringLiteral(assignedNameText, ast.TokenFlagsNone)
|
||||
} else {
|
||||
assignedName = getAssignedNameOfIdentifier(emitContext, node.Name(), node.Initializer)
|
||||
}
|
||||
initializer := finishTransformNamedEvaluation(emitContext, node.Initializer, assignedName, ignoreEmptyStringLiteral)
|
||||
return factory.UpdateParameterDeclaration(
|
||||
node,
|
||||
nil, /*modifiers*/
|
||||
node.DotDotDotToken,
|
||||
node.Name(),
|
||||
nil, /*questionToken*/
|
||||
nil, /*typeNode*/
|
||||
initializer,
|
||||
)
|
||||
}
|
||||
|
||||
func transformNamedEvaluationOfBindingElement(emitContext *printer.EmitContext, node *ast.BindingElement /*NamedEvaluation & BindingElement*/, ignoreEmptyStringLiteral bool, assignedNameText string) *ast.Expression {
|
||||
// 8.6.3 RS: IteratorBindingInitialization
|
||||
// SingleNameBinding : BindingIdentifier Initializer?
|
||||
// ...
|
||||
// 5. If |Initializer| is present and _v_ is *undefined*, then
|
||||
// a. If IsAnonymousFunctionDefinition(|Initializer|) is *true*, then
|
||||
// i. Set _v_ to ? NamedEvaluation of |Initializer| with argument _bindingId_.
|
||||
// ...
|
||||
//
|
||||
// 14.3.3.3 RS: KeyedBindingInitialization
|
||||
// SingleNameBinding : BindingIdentifier Initializer?
|
||||
// ...
|
||||
// 4. If |Initializer| is present and _v_ is *undefined*, then
|
||||
// a. If IsAnonymousFunctionDefinition(|Initializer|) is *true*, then
|
||||
// i. Set _v_ to ? NamedEvaluation of |Initializer| with argument _bindingId_.
|
||||
// ...
|
||||
|
||||
factory := emitContext.Factory
|
||||
var assignedName *ast.Expression
|
||||
if len(assignedNameText) > 0 {
|
||||
assignedName = factory.NewStringLiteral(assignedNameText, ast.TokenFlagsNone)
|
||||
} else {
|
||||
assignedName = getAssignedNameOfIdentifier(emitContext, node.Name(), node.Initializer)
|
||||
}
|
||||
initializer := finishTransformNamedEvaluation(emitContext, node.Initializer, assignedName, ignoreEmptyStringLiteral)
|
||||
return factory.UpdateBindingElement(
|
||||
node,
|
||||
node.DotDotDotToken,
|
||||
node.PropertyName,
|
||||
node.Name(),
|
||||
initializer,
|
||||
)
|
||||
}
|
||||
|
||||
func transformNamedEvaluationOfPropertyDeclaration(emitContext *printer.EmitContext, node *ast.PropertyDeclaration /*NamedEvaluation & PropertyDeclaration*/, ignoreEmptyStringLiteral bool, assignedNameText string) *ast.Expression {
|
||||
// 10.2.1.3 RS: EvaluateBody
|
||||
// Initializer : `=` AssignmentExpression
|
||||
// ...
|
||||
// 3. If IsAnonymousFunctionDefinition(|AssignmentExpression|) is *true*, then
|
||||
// a. Let _value_ be ? NamedEvaluation of |Initializer| with argument _functionObject_.[[ClassFieldInitializerName]].
|
||||
// ...
|
||||
|
||||
factory := emitContext.Factory
|
||||
assignedName, name := getAssignedNameOfPropertyName(emitContext, node.Name(), assignedNameText)
|
||||
initializer := finishTransformNamedEvaluation(emitContext, node.Initializer, assignedName, ignoreEmptyStringLiteral)
|
||||
return factory.UpdatePropertyDeclaration(
|
||||
node,
|
||||
node.Modifiers(),
|
||||
name,
|
||||
nil, /*postfixToken*/
|
||||
nil, /*typeNode*/
|
||||
initializer,
|
||||
)
|
||||
}
|
||||
|
||||
func transformNamedEvaluationOfAssignmentExpression(emitContext *printer.EmitContext, node *ast.BinaryExpression /*NamedEvaluation & BinaryExpression*/, ignoreEmptyStringLiteral bool, assignedNameText string) *ast.Expression {
|
||||
// 13.15.2 RS: Evaluation
|
||||
// AssignmentExpression : LeftHandSideExpression `=` AssignmentExpression
|
||||
// 1. If |LeftHandSideExpression| is neither an |ObjectLiteral| nor an |ArrayLiteral|, then
|
||||
// a. Let _lref_ be ? Evaluation of |LeftHandSideExpression|.
|
||||
// b. If IsAnonymousFunctionDefinition(|AssignmentExpression|) and IsIdentifierRef of |LeftHandSideExpression| are both *true*, then
|
||||
// i. Let _rval_ be ? NamedEvaluation of |AssignmentExpression| with argument _lref_.[[ReferencedName]].
|
||||
// ...
|
||||
//
|
||||
// AssignmentExpression : LeftHandSideExpression `&&=` AssignmentExpression
|
||||
// ...
|
||||
// 5. If IsAnonymousFunctionDefinition(|AssignmentExpression|) is *true* and IsIdentifierRef of |LeftHandSideExpression| is *true*, then
|
||||
// a. Let _rval_ be ? NamedEvaluation of |AssignmentExpression| with argument _lref_.[[ReferencedName]].
|
||||
// ...
|
||||
//
|
||||
// AssignmentExpression : LeftHandSideExpression `||=` AssignmentExpression
|
||||
// ...
|
||||
// 5. If IsAnonymousFunctionDefinition(|AssignmentExpression|) is *true* and IsIdentifierRef of |LeftHandSideExpression| is *true*, then
|
||||
// a. Let _rval_ be ? NamedEvaluation of |AssignmentExpression| with argument _lref_.[[ReferencedName]].
|
||||
// ...
|
||||
//
|
||||
// AssignmentExpression : LeftHandSideExpression `??=` AssignmentExpression
|
||||
// ...
|
||||
// 4. If IsAnonymousFunctionDefinition(|AssignmentExpression|) is *true* and IsIdentifierRef of |LeftHandSideExpression| is *true*, then
|
||||
// a. Let _rval_ be ? NamedEvaluation of |AssignmentExpression| with argument _lref_.[[ReferencedName]].
|
||||
// ...
|
||||
|
||||
factory := emitContext.Factory
|
||||
var assignedName *ast.Expression
|
||||
if len(assignedNameText) > 0 {
|
||||
assignedName = factory.NewStringLiteral(assignedNameText, ast.TokenFlagsNone)
|
||||
} else {
|
||||
assignedName = getAssignedNameOfIdentifier(emitContext, node.Left, node.Right)
|
||||
}
|
||||
right := finishTransformNamedEvaluation(emitContext, node.Right, assignedName, ignoreEmptyStringLiteral)
|
||||
return factory.UpdateBinaryExpression(
|
||||
node,
|
||||
nil, /*modifiers*/
|
||||
node.Left,
|
||||
nil, /*typeNode*/
|
||||
node.OperatorToken,
|
||||
right,
|
||||
)
|
||||
}
|
||||
|
||||
func transformNamedEvaluationOfExportAssignment(emitContext *printer.EmitContext, node *ast.ExportAssignment /*NamedEvaluation & ExportAssignment*/, ignoreEmptyStringLiteral bool, assignedNameText string) *ast.Expression {
|
||||
// 16.2.3.7 RS: Evaluation
|
||||
// ExportDeclaration : `export` `default` AssignmentExpression `;`
|
||||
// 1. If IsAnonymousFunctionDefinition(|AssignmentExpression|) is *true*, then
|
||||
// a. Let _value_ be ? NamedEvaluation of |AssignmentExpression| with argument `"default"`.
|
||||
// ...
|
||||
|
||||
// NOTE: Since emit for `export =` translates to `module.exports = ...`, the assigned name of the class or function
|
||||
// is `""`.
|
||||
|
||||
factory := emitContext.Factory
|
||||
var assignedName *ast.Expression
|
||||
if len(assignedNameText) > 0 {
|
||||
assignedName = factory.NewStringLiteral(assignedNameText, ast.TokenFlagsNone)
|
||||
} else if node.IsExportEquals {
|
||||
assignedName = factory.NewStringLiteral("", ast.TokenFlagsNone)
|
||||
} else {
|
||||
assignedName = factory.NewStringLiteral("default", ast.TokenFlagsNone)
|
||||
}
|
||||
expression := finishTransformNamedEvaluation(emitContext, node.Expression, assignedName, ignoreEmptyStringLiteral)
|
||||
return factory.UpdateExportAssignment(
|
||||
node,
|
||||
nil, /*modifiers*/
|
||||
node.IsExportEquals,
|
||||
nil, /*typeNode*/
|
||||
expression,
|
||||
)
|
||||
}
|
||||
|
||||
// Performs a shallow transformation of a `NamedEvaluation` node, such that a valid name will be assigned.
|
||||
func transformNamedEvaluation(context *printer.EmitContext, node *ast.Node /*NamedEvaluation*/, ignoreEmptyStringLiteral bool, assignedName string) *ast.Expression {
|
||||
switch node.Kind {
|
||||
case ast.KindPropertyAssignment:
|
||||
return transformNamedEvaluationOfPropertyAssignment(context, node.AsPropertyAssignment(), ignoreEmptyStringLiteral, assignedName)
|
||||
case ast.KindShorthandPropertyAssignment:
|
||||
return transformNamedEvaluationOfShorthandAssignmentProperty(context, node.AsShorthandPropertyAssignment(), ignoreEmptyStringLiteral, assignedName)
|
||||
case ast.KindVariableDeclaration:
|
||||
return transformNamedEvaluationOfVariableDeclaration(context, node.AsVariableDeclaration(), ignoreEmptyStringLiteral, assignedName)
|
||||
case ast.KindParameter:
|
||||
return transformNamedEvaluationOfParameterDeclaration(context, node.AsParameterDeclaration(), ignoreEmptyStringLiteral, assignedName)
|
||||
case ast.KindBindingElement:
|
||||
return transformNamedEvaluationOfBindingElement(context, node.AsBindingElement(), ignoreEmptyStringLiteral, assignedName)
|
||||
case ast.KindPropertyDeclaration:
|
||||
return transformNamedEvaluationOfPropertyDeclaration(context, node.AsPropertyDeclaration(), ignoreEmptyStringLiteral, assignedName)
|
||||
case ast.KindBinaryExpression:
|
||||
return transformNamedEvaluationOfAssignmentExpression(context, node.AsBinaryExpression(), ignoreEmptyStringLiteral, assignedName)
|
||||
case ast.KindExportAssignment:
|
||||
return transformNamedEvaluationOfExportAssignment(context, node.AsExportAssignment(), ignoreEmptyStringLiteral, assignedName)
|
||||
default:
|
||||
debug.Fail("Unhandled case in transformNamedEvaluation")
|
||||
return node
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user