diff --git a/scripts/processTypes.ts b/scripts/processTypes.ts index e1c676d8ee9..6b8d313a539 100644 --- a/scripts/processTypes.ts +++ b/scripts/processTypes.ts @@ -537,6 +537,7 @@ function generateFactory(outputFile: string) { writer.writeLine(); writer.increaseIndent(); writeCreateAndUpdateFunctions(); + writeCloneFunction(); writer.decreaseIndent(); writer.write(`}`); writer.writeLine(); @@ -726,6 +727,63 @@ function generateFactory(outputFile: string) { writer.writeLine(); } + function writeCloneFunction() { + writer.write(`export function cloneNode(node: TNode): TNode;`); + writer.writeLine(); + + writer.write(`export function cloneNode(node: Node): Node {`); + writer.writeLine(); + writer.increaseIndent(); + + writer.write(`if (!node) {`); + writer.writeLine(); + writer.increaseIndent(); + + writer.write(`return node;`); + writer.writeLine(); + + writer.decreaseIndent(); + writer.write(`}`); + writer.writeLine(); + + writer.write(`switch (node.kind) {`); + writer.writeLine(); + writer.increaseIndent(); + + for (let syntaxNode of syntax) { + if (!syntaxNode.options.create) { + continue; + } + + writer.write(`case SyntaxKind.${syntaxNode.kindName}:`); + writer.writeLine(); + writer.increaseIndent(); + + writer.write(`return factory.create${syntaxNode.kindName}(`); + for (let i = 0; i < syntaxNode.members.length; ++i) { + if (i > 0) { + writer.write(`, `); + } + + let member = syntaxNode.members[i]; + writer.write(`(<${syntaxNode.typeName}>node).${member.propertyName}`); + } + + writer.write(`);`); + writer.writeLine(); + + writer.decreaseIndent(); + } + + writer.decreaseIndent(); + writer.write(`}`); + writer.writeLine(); + + writer.decreaseIndent(); + writer.write(`}`); + writer.writeLine(); + } + function writeUpdateFunction(syntaxNode: SyntaxNode) { if (!syntaxNode.options.update || !hasChildNodes(syntaxNode)) { return; diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index eba8bde4767..31a994fab07 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -330,8 +330,6 @@ namespace ts { return writeTextOfNode(currentSourceFile, type); case SyntaxKind.ExpressionWithTypeArguments: return emitExpressionWithTypeArguments(type); - case SyntaxKind.TypePredicate: - return emitTypePredicate(type); case SyntaxKind.TypeReference: return emitTypeReference(type); case SyntaxKind.TypeQuery: @@ -393,12 +391,6 @@ namespace ts { } } - function emitTypePredicate(type: TypePredicateNode) { - writeTextOfNode(currentSourceFile, type.parameterName); - write(" is "); - emitType(type.type); - } - function emitTypeReference(type: TypeReferenceNode) { emitEntityName(type.typeName); if (type.typeArguments) { diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 1435061cfb5..fce95c59ae8 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -3045,31 +3045,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi return expr; } - function createDefaultValueCheck(value: Expression, defaultValue: Expression): Expression { - // The value expression will be evaluated twice, so for anything but a simple identifier - // we need to generate a temporary variable - value = ensureIdentifier(value); - // Return the expression 'value === void 0 ? defaultValue : value' - return factory.createConditionalExpression2( - factory.createBinaryExpression2( - value, - SyntaxKind.EqualsEqualsEqualsToken, - factory.createVoidZeroExpression() - ), - defaultValue, - value - ); - } - - function createPropertyAccessForDestructuringProperty(object: Expression, propName: Identifier | LiteralExpression): Expression { - // We create a synthetic copy of the identifier in order to avoid the rewriting that might - // otherwise occur when the identifier is emitted. - return factory.createPropertyOrElementAccessExpression( - factory.parenthesizeForAccess(object), - factory.cloneIdentifierOrLiteralExpression(propName) - ); - } - function emitObjectLiteralAssignment(target: ObjectLiteralExpression, value: Expression) { let properties = target.properties; if (properties.length !== 1) { @@ -3108,7 +3083,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitDestructuringAssignment(target: Expression, value: Expression) { if (target.kind === SyntaxKind.BinaryExpression && (target).operatorToken.kind === SyntaxKind.EqualsToken) { - value = createDefaultValueCheck(value, (target).right); + value = factory.createDefaultValueCheck(value, (target).right, ensureIdentifier); target = (target).left; } if (target.kind === SyntaxKind.ObjectLiteralExpression) { @@ -3145,7 +3120,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitBindingElement(target: BindingElement, value: Expression) { if (target.initializer) { // Combine value and initializer - value = value ? createDefaultValueCheck(value, target.initializer) : target.initializer; + value = value ? factory.createDefaultValueCheck(value, target.initializer, ensureIdentifier) : target.initializer; } else if (!value) { // Use 'void 0' in absence of value and initializer @@ -6601,4 +6576,4 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } } } -} +} diff --git a/src/compiler/factory.generated.ts b/src/compiler/factory.generated.ts index 980b8a0c395..bb72f0daeeb 100644 --- a/src/compiler/factory.generated.ts +++ b/src/compiler/factory.generated.ts @@ -2077,6 +2077,363 @@ namespace ts { } return node; } + export function cloneNode(node: TNode): TNode; + export function cloneNode(node: Node): Node { + if (!node) { + return node; + } + switch (node.kind) { + case SyntaxKind.NumericLiteral: + return factory.createNumericLiteral((node).text); + case SyntaxKind.StringLiteral: + return factory.createStringLiteral((node).text); + case SyntaxKind.RegularExpressionLiteral: + return factory.createRegularExpressionLiteral((node).text); + case SyntaxKind.NoSubstitutionTemplateLiteral: + return factory.createNoSubstitutionTemplateLiteral((node).text); + case SyntaxKind.TemplateHead: + return factory.createTemplateHead((node).text); + case SyntaxKind.TemplateMiddle: + return factory.createTemplateMiddle((node).text); + case SyntaxKind.TemplateTail: + return factory.createTemplateTail((node).text); + case SyntaxKind.Identifier: + return factory.createIdentifier((node).text, (node).originalKeywordKind); + case SyntaxKind.QualifiedName: + return factory.createQualifiedName((node).left, (node).right); + case SyntaxKind.ComputedPropertyName: + return factory.createComputedPropertyName((node).expression); + case SyntaxKind.TypeParameter: + return factory.createTypeParameter((node).name, (node).constraint, + (node).expression); + case SyntaxKind.Parameter: + return factory.createParameter((node).decorators, (node).modifiers, + (node).dotDotDotToken, (node).name, (node).questionToken, + (node).type, (node).initializer); + case SyntaxKind.Decorator: + return factory.createDecorator((node).expression); + case SyntaxKind.PropertySignature: + return factory.createPropertySignature((node).decorators, (node).modifiers, + (node).name, (node).questionToken, (node).type); + case SyntaxKind.PropertyDeclaration: + return factory.createPropertyDeclaration((node).decorators, (node).modifiers, + (node).name, (node).questionToken, (node).type, + (node).initializer); + case SyntaxKind.MethodSignature: + return factory.createMethodSignature((node).decorators, (node).modifiers, + (node).name, (node).questionToken, (node).typeParameters, + (node).parameters, (node).type); + case SyntaxKind.MethodDeclaration: + return factory.createMethodDeclaration((node).decorators, (node).modifiers, + (node).name, (node).typeParameters, (node).parameters, + (node).type, (node).body); + case SyntaxKind.Constructor: + return factory.createConstructor((node).decorators, (node).modifiers, + (node).parameters, (node).type, (node).body); + case SyntaxKind.GetAccessor: + return factory.createGetAccessor((node).decorators, (node).modifiers, + (node).name, (node).parameters, (node).type, + (node).body); + case SyntaxKind.SetAccessor: + return factory.createSetAccessor((node).decorators, (node).modifiers, + (node).name, (node).parameters, (node).type, + (node).body); + case SyntaxKind.CallSignature: + return factory.createCallSignature((node).typeParameters, (node).parameters, + (node).type); + case SyntaxKind.ConstructSignature: + return factory.createConstructSignature((node).typeParameters, + (node).parameters, (node).type); + case SyntaxKind.IndexSignature: + return factory.createIndexSignature((node).decorators, (node).modifiers, + (node).parameters, (node).type); + case SyntaxKind.TypePredicate: + return factory.createTypePredicate((node).parameterName, (node).type); + case SyntaxKind.TypeReference: + return factory.createTypeReference((node).typeName, (node).typeArguments); + case SyntaxKind.FunctionType: + return factory.createFunctionType((node).typeParameters, (node).parameters, + (node).type); + case SyntaxKind.ConstructorType: + return factory.createConstructorType((node).typeParameters, (node).parameters, + (node).type); + case SyntaxKind.TypeQuery: + return factory.createTypeQuery((node).exprName); + case SyntaxKind.TypeLiteral: + return factory.createTypeLiteral((node).members); + case SyntaxKind.ArrayType: + return factory.createArrayType((node).elementType); + case SyntaxKind.TupleType: + return factory.createTupleType((node).elementTypes); + case SyntaxKind.UnionType: + return factory.createUnionType((node).types); + case SyntaxKind.IntersectionType: + return factory.createIntersectionType((node).types); + case SyntaxKind.ParenthesizedType: + return factory.createParenthesizedType((node).type); + case SyntaxKind.ObjectBindingPattern: + return factory.createObjectBindingPattern((node).elements); + case SyntaxKind.ArrayBindingPattern: + return factory.createArrayBindingPattern((node).elements); + case SyntaxKind.BindingElement: + return factory.createBindingElement((node).decorators, (node).modifiers, + (node).propertyName, (node).dotDotDotToken, (node).name, + (node).initializer); + case SyntaxKind.ArrayLiteralExpression: + return factory.createArrayLiteralExpression((node).elements); + case SyntaxKind.ObjectLiteralExpression: + return factory.createObjectLiteralExpression((node).decorators, + (node).modifiers, (node).properties); + case SyntaxKind.PropertyAccessExpression: + return factory.createPropertyAccessExpression((node).expression, + (node).dotToken, (node).name); + case SyntaxKind.ElementAccessExpression: + return factory.createElementAccessExpression((node).expression, + (node).argumentExpression); + case SyntaxKind.CallExpression: + return factory.createCallExpression((node).expression, (node).typeArguments, + (node).arguments); + case SyntaxKind.NewExpression: + return factory.createNewExpression((node).expression, (node).typeArguments, + (node).arguments); + case SyntaxKind.TaggedTemplateExpression: + return factory.createTaggedTemplateExpression((node).tag, (node).template); + case SyntaxKind.TypeAssertionExpression: + return factory.createTypeAssertionExpression((node).type, (node).expression); + case SyntaxKind.ParenthesizedExpression: + return factory.createParenthesizedExpression((node).expression); + case SyntaxKind.FunctionExpression: + return factory.createFunctionExpression((node).decorators, (node).modifiers, + (node).asteriskToken, (node).name, (node).typeParameters, + (node).parameters, (node).type, (node).body); + case SyntaxKind.ArrowFunction: + return factory.createArrowFunction((node).decorators, (node).modifiers, + (node).typeParameters, (node).parameters, (node).type, + (node).equalsGreaterThanToken, (node).body); + case SyntaxKind.DeleteExpression: + return factory.createDeleteExpression((node).expression); + case SyntaxKind.TypeOfExpression: + return factory.createTypeOfExpression((node).expression); + case SyntaxKind.VoidExpression: + return factory.createVoidExpression((node).expression); + case SyntaxKind.AwaitExpression: + return factory.createAwaitExpression((node).expression); + case SyntaxKind.PrefixUnaryExpression: + return factory.createPrefixUnaryExpression((node).operator, (node).operand); + case SyntaxKind.PostfixUnaryExpression: + return factory.createPostfixUnaryExpression((node).operand, (node).operator); + case SyntaxKind.BinaryExpression: + return factory.createBinaryExpression((node).left, (node).operatorToken, + (node).right); + case SyntaxKind.ConditionalExpression: + return factory.createConditionalExpression((node).condition, (node).questionToken, + (node).whenTrue, (node).colonToken, (node).whenFalse); + case SyntaxKind.TemplateExpression: + return factory.createTemplateExpression((node).head, (node).templateSpans); + case SyntaxKind.YieldExpression: + return factory.createYieldExpression((node).asteriskToken, (node).expression); + case SyntaxKind.SpreadElementExpression: + return factory.createSpreadElementExpression((node).expression); + case SyntaxKind.ClassExpression: + return factory.createClassExpression((node).decorators, (node).modifiers, + (node).name, (node).typeParameters, (node).heritageClauses, + (node).members); + case SyntaxKind.OmittedExpression: + return factory.createOmittedExpression(); + case SyntaxKind.ExpressionWithTypeArguments: + return factory.createExpressionWithTypeArguments((node).expression, + (node).typeArguments); + case SyntaxKind.AsExpression: + return factory.createAsExpression((node).expression, (node).type); + case SyntaxKind.TemplateSpan: + return factory.createTemplateSpan((node).expression, (node).literal); + case SyntaxKind.SemicolonClassElement: + return factory.createSemicolonClassElement(); + case SyntaxKind.Block: + return factory.createBlock((node).statements); + case SyntaxKind.VariableStatement: + return factory.createVariableStatement((node).declarationList); + case SyntaxKind.EmptyStatement: + return factory.createEmptyStatement(); + case SyntaxKind.ExpressionStatement: + return factory.createExpressionStatement((node).expression); + case SyntaxKind.IfStatement: + return factory.createIfStatement((node).expression, (node).thenStatement, + (node).elseStatement); + case SyntaxKind.DoStatement: + return factory.createDoStatement((node).statement, (node).expression); + case SyntaxKind.WhileStatement: + return factory.createWhileStatement((node).expression, (node).statement); + case SyntaxKind.ForStatement: + return factory.createForStatement((node).initializer, (node).condition, + (node).incrementor, (node).statement); + case SyntaxKind.ForInStatement: + return factory.createForInStatement((node).initializer, (node).expression, + (node).statement); + case SyntaxKind.ForOfStatement: + return factory.createForOfStatement((node).initializer, (node).expression, + (node).statement); + case SyntaxKind.ContinueStatement: + return factory.createContinueStatement((node).label); + case SyntaxKind.BreakStatement: + return factory.createBreakStatement((node).label); + case SyntaxKind.ReturnStatement: + return factory.createReturnStatement((node).expression); + case SyntaxKind.WithStatement: + return factory.createWithStatement((node).expression, (node).statement); + case SyntaxKind.SwitchStatement: + return factory.createSwitchStatement((node).expression, (node).caseBlock); + case SyntaxKind.LabeledStatement: + return factory.createLabeledStatement((node).label, (node).statement); + case SyntaxKind.ThrowStatement: + return factory.createThrowStatement((node).expression); + case SyntaxKind.TryStatement: + return factory.createTryStatement((node).tryBlock, (node).catchClause, + (node).finallyBlock); + case SyntaxKind.DebuggerStatement: + return factory.createDebuggerStatement(); + case SyntaxKind.VariableDeclaration: + return factory.createVariableDeclaration((node).decorators, (node).modifiers, + (node).name, (node).type, (node).initializer); + case SyntaxKind.VariableDeclarationList: + return factory.createVariableDeclarationList((node).declarations); + case SyntaxKind.FunctionDeclaration: + return factory.createFunctionDeclaration((node).decorators, (node).modifiers, + (node).asteriskToken, (node).name, (node).typeParameters, + (node).parameters, (node).type, (node).body); + case SyntaxKind.ClassDeclaration: + return factory.createClassDeclaration((node).decorators, (node).modifiers, + (node).name, (node).typeParameters, (node).heritageClauses, + (node).members); + case SyntaxKind.InterfaceDeclaration: + return factory.createInterfaceDeclaration((node).decorators, (node).modifiers, + (node).name, (node).typeParameters, (node).heritageClauses, + (node).members); + case SyntaxKind.TypeAliasDeclaration: + return factory.createTypeAliasDeclaration((node).decorators, (node).modifiers, + (node).name, (node).typeParameters, (node).type); + case SyntaxKind.EnumDeclaration: + return factory.createEnumDeclaration((node).decorators, (node).modifiers, + (node).name, (node).members); + case SyntaxKind.ModuleDeclaration: + return factory.createModuleDeclaration((node).decorators, (node).modifiers, + (node).name, (node).body); + case SyntaxKind.ModuleBlock: + return factory.createModuleBlock((node).statements); + case SyntaxKind.CaseBlock: + return factory.createCaseBlock((node).clauses); + case SyntaxKind.ImportEqualsDeclaration: + return factory.createImportEqualsDeclaration((node).decorators, + (node).modifiers, (node).name, + (node).moduleReference); + case SyntaxKind.ImportDeclaration: + return factory.createImportDeclaration((node).decorators, (node).modifiers, + (node).importClause, (node).moduleSpecifier); + case SyntaxKind.ImportClause: + return factory.createImportClause((node).name, (node).namedBindings); + case SyntaxKind.NamespaceImport: + return factory.createNamespaceImport((node).name); + case SyntaxKind.NamedImports: + return factory.createNamedImports((node).elements); + case SyntaxKind.ImportSpecifier: + return factory.createImportSpecifier((node).propertyName, (node).name); + case SyntaxKind.ExportAssignment: + return factory.createExportAssignment((node).decorators, (node).modifiers, + (node).expression); + case SyntaxKind.ExportDeclaration: + return factory.createExportDeclaration((node).decorators, (node).modifiers, + (node).exportClause, (node).moduleSpecifier); + case SyntaxKind.NamedExports: + return factory.createNamedExports((node).elements); + case SyntaxKind.ExportSpecifier: + return factory.createExportSpecifier((node).propertyName, (node).name); + case SyntaxKind.MissingDeclaration: + return factory.createMissingDeclaration((node).decorators, (node).modifiers); + case SyntaxKind.ExternalModuleReference: + return factory.createExternalModuleReference((node).expression); + case SyntaxKind.JsxElement: + return factory.createJsxElement((node).openingElement, (node).children, (node).closingElement + ); + case SyntaxKind.JsxSelfClosingElement: + return factory.createJsxSelfClosingElement((node).tagName, (node).attributes); + case SyntaxKind.JsxOpeningElement: + return factory.createJsxOpeningElement((node).tagName, (node).attributes); + case SyntaxKind.JsxText: + return factory.createJsxText(); + case SyntaxKind.JsxClosingElement: + return factory.createJsxClosingElement((node).tagName); + case SyntaxKind.JsxAttribute: + return factory.createJsxAttribute((node).name, (node).initializer); + case SyntaxKind.JsxSpreadAttribute: + return factory.createJsxSpreadAttribute((node).expression); + case SyntaxKind.JsxExpression: + return factory.createJsxExpression((node).expression); + case SyntaxKind.CaseClause: + return factory.createCaseClause((node).expression, (node).statements); + case SyntaxKind.DefaultClause: + return factory.createDefaultClause((node).statements); + case SyntaxKind.HeritageClause: + return factory.createHeritageClause((node).types); + case SyntaxKind.CatchClause: + return factory.createCatchClause((node).variableDeclaration, (node).block); + case SyntaxKind.PropertyAssignment: + return factory.createPropertyAssignment((node).name, (node).questionToken, + (node).initializer); + case SyntaxKind.ShorthandPropertyAssignment: + return factory.createShorthandPropertyAssignment((node).name, + (node).questionToken); + case SyntaxKind.EnumMember: + return factory.createEnumMember((node).name, (node).initializer); + case SyntaxKind.JSDocTypeExpression: + return factory.createJSDocTypeExpression((node).type); + case SyntaxKind.JSDocAllType: + return factory.createJSDocAllType(); + case SyntaxKind.JSDocUnknownType: + return factory.createJSDocUnknownType(); + case SyntaxKind.JSDocArrayType: + return factory.createJSDocArrayType((node).elementType); + case SyntaxKind.JSDocUnionType: + return factory.createJSDocUnionType((node).types); + case SyntaxKind.JSDocTupleType: + return factory.createJSDocTupleType((node).types); + case SyntaxKind.JSDocNullableType: + return factory.createJSDocNullableType((node).type); + case SyntaxKind.JSDocNonNullableType: + return factory.createJSDocNonNullableType((node).type); + case SyntaxKind.JSDocRecordType: + return factory.createJSDocRecordType((node).members); + case SyntaxKind.JSDocRecordMember: + return factory.createJSDocRecordMember((node).name, (node).type); + case SyntaxKind.JSDocTypeReference: + return factory.createJSDocTypeReference((node).name, (node).typeArguments); + case SyntaxKind.JSDocOptionalType: + return factory.createJSDocOptionalType((node).type); + case SyntaxKind.JSDocFunctionType: + return factory.createJSDocFunctionType((node).parameters, (node).type); + case SyntaxKind.JSDocVariadicType: + return factory.createJSDocVariadicType((node).type); + case SyntaxKind.JSDocConstructorType: + return factory.createJSDocConstructorType((node).type); + case SyntaxKind.JSDocThisType: + return factory.createJSDocThisType((node).type); + case SyntaxKind.JSDocComment: + return factory.createJSDocComment((node).tags); + case SyntaxKind.JSDocTag: + return factory.createJSDocTag((node).atToken, (node).tagName); + case SyntaxKind.JSDocParameterTag: + return factory.createJSDocParameterTag((node).preParameterName, (node).typeExpression, + (node).postParameterName, (node).atToken, (node).tagName); + case SyntaxKind.JSDocReturnTag: + return factory.createJSDocReturnTag((node).typeExpression, (node).atToken, + (node).tagName); + case SyntaxKind.JSDocTypeTag: + return factory.createJSDocTypeTag((node).typeExpression, (node).atToken, (node).tagName + ); + case SyntaxKind.JSDocTemplateTag: + return factory.createJSDocTemplateTag((node).typeParameters, (node).atToken, + (node).tagName); + } + } } export function isNumericLiteral(node: Node): node is LiteralExpression { return node && node.kind === SyntaxKind.NumericLiteral; diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 0abdefebe9b..872478326d2 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -148,21 +148,10 @@ namespace ts { export function createVoidZeroExpression(): VoidExpression { return factory.createVoidExpression(factory.createNumericLiteral2(0)); } - - export function cloneIdentifier(node: Identifier) { - return factory.createIdentifier( - node.text); - } - - export function cloneIdentifierOrLiteralExpression(node: Identifier | LiteralExpression) { - let newNode = factory.createNode(node.kind); - newNode.text = node.text; - return newNode; - } - + export function createPropertyOrElementAccessExpression(expression: Expression, propName: Identifier | LiteralExpression): LeftHandSideExpression { if (!nodeIsSynthesized(propName)) { - propName = cloneIdentifierOrLiteralExpression(propName); + propName = cloneNode(propName); } if (propName.kind !== SyntaxKind.Identifier) { @@ -197,5 +186,22 @@ namespace ts { ] ); } + + export function createDefaultValueCheck(value: Expression, defaultValue: Expression, ensureIdentifier: (value: Expression) => Expression): Expression { + // The value expression will be evaluated twice, so for anything but a simple identifier + // we need to generate a temporary variable + value = ensureIdentifier(value); + + // === void 0 ? : + return factory.createConditionalExpression2( + factory.createBinaryExpression2( + value, + SyntaxKind.EqualsEqualsEqualsToken, + factory.createVoidZeroExpression() + ), + defaultValue, + value + ); + } } } \ No newline at end of file