From 6f766c2872c1c43e96b2692ac3bf07a38b32e877 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 8 Apr 2016 12:50:07 -0700 Subject: [PATCH 01/10] Correct destructuring assignment to empty object Previously, chained destructuring object assignments would fail when the leftmost target was empty because the shortcut code would forget to check whether the right-hand side was also a destructuring assignment. --- src/compiler/transformers/destructuring.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/compiler/transformers/destructuring.ts b/src/compiler/transformers/destructuring.ts index 7cd37bade6c..06e8a354d85 100644 --- a/src/compiler/transformers/destructuring.ts +++ b/src/compiler/transformers/destructuring.ts @@ -17,10 +17,16 @@ namespace ts { node: BinaryExpression, needsValue: boolean, recordTempVariable: (node: Identifier) => void, - visitor?: (node: Node) => VisitResult) { + visitor?: (node: Node) => VisitResult): Expression { if (isEmptyObjectLiteralOrArrayLiteral(node.left)) { - return node.right; + const right = node.right; + if (isDestructuringAssignment(right)) { + return flattenDestructuringAssignment(context, right, needsValue, recordTempVariable, visitor); + } + else { + return node.right; + } } let location: TextRange = node; @@ -401,4 +407,4 @@ namespace ts { return emitTempVariableAssignment(value, location); } } -} \ No newline at end of file +} From 8b506c7b052a6da791ec9d3b6c5130f7af88b201 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Fri, 8 Apr 2016 15:31:31 -0700 Subject: [PATCH 02/10] Cleans up a few things and fixes #7868. --- Jakefile.js | 40 ++++--- src/compiler/checker.ts | 126 ++++++++++++++------- src/compiler/transformers/es6.ts | 24 ++-- src/compiler/transformers/module/module.ts | 70 ++++++------ src/compiler/transformers/module/system.ts | 6 +- src/compiler/transformers/ts.ts | 81 +++++++------ src/compiler/types.ts | 7 +- src/compiler/utilities.ts | 34 +++++- 8 files changed, 236 insertions(+), 152 deletions(-) diff --git a/Jakefile.js b/Jakefile.js index c88d6933d55..6ed276c73c0 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -309,7 +309,7 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts options += " --stripInternal" } - if (useBuiltCompiler && !/^(no?|f(alse)?|0|-)$/i.test(process.env.USE_TRANSFORMS)) { + if (useBuiltCompiler && !environmentVariableIsDisabled("USE_TRANSFORMS")) { console.warn("\u001b[93mwarning: 'USE_TRANSFORMS' environment variable is not set to 'false'. Experimental transforms will be enabled by default.\u001b[0m"); } @@ -658,19 +658,21 @@ function exec(cmd, completeHandler, errorHandler) { } function cleanTestDirs() { - // Clean the local baselines directory - if (fs.existsSync(localBaseline)) { - jake.rmRf(localBaseline); - } + if (!environmentVariableIsDisabled("CLEAN_TESTS")) { + // Clean the local baselines directory + if (fs.existsSync(localBaseline)) { + jake.rmRf(localBaseline); + } - // Clean the local Rwc baselines directory - if (fs.existsSync(localRwcBaseline)) { - jake.rmRf(localRwcBaseline); - } + // Clean the local Rwc baselines directory + if (fs.existsSync(localRwcBaseline)) { + jake.rmRf(localRwcBaseline); + } - jake.mkdirP(localRwcBaseline); - jake.mkdirP(localTest262Baseline); - jake.mkdirP(localBaseline); + jake.mkdirP(localRwcBaseline); + jake.mkdirP(localTest262Baseline); + jake.mkdirP(localBaseline); + } } // used to pass data from jake command line directly to run.js @@ -833,7 +835,7 @@ function runConsoleTests(defaultReporter, defaultSubsets) { var light = process.env.light || false; var stackTraceLimit = process.env.stackTraceLimit || 1; var testConfigFile = 'test.config'; - if(fs.existsSync(testConfigFile)) { + if (fs.existsSync(testConfigFile)) { fs.unlinkSync(testConfigFile); } @@ -866,7 +868,7 @@ function runConsoleTests(defaultReporter, defaultSubsets) { console.log(cmd); exec(cmd, function () { deleteTemporaryProjectOutput(); - if (i === 0) { + if (i === 0 && !environmentVariableIsDisabled("lint")) { var lint = jake.Task['lint']; lint.addListener('complete', function () { complete(); @@ -1258,4 +1260,12 @@ ProgressBar.prototype = { this._lastProgress = progress; this.visible = true; } -}; \ No newline at end of file +}; + +function environmentVariableIsEnabled(name) { + return /^(y(es)?|t(rue)?|on|enabled?|1|\+)$/.test(process.env[name]); +} + +function environmentVariableIsDisabled(name) { + return /^(no?|f(alse)?|off|disabled?|0|-)$/.test(process.env[name]); +} \ No newline at end of file diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index aeaad03267b..10e3c19497d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1118,7 +1118,7 @@ namespace ts { } // Resolves a qualified name and any involved aliases - function resolveEntityName(name: EntityName | Expression, meaning: SymbolFlags, ignoreErrors?: boolean): Symbol { + function resolveEntityName(name: EntityName | Expression, meaning: SymbolFlags, ignoreErrors?: boolean, location?: Node): Symbol { if (nodeIsMissing(name)) { return undefined; } @@ -1127,7 +1127,7 @@ namespace ts { if (name.kind === SyntaxKind.Identifier) { const message = meaning === SymbolFlags.Namespace ? Diagnostics.Cannot_find_namespace_0 : Diagnostics.Cannot_find_name_0; - symbol = resolveName(name, (name).text, meaning, ignoreErrors ? undefined : message, name); + symbol = resolveName(location || name, (name).text, meaning, ignoreErrors ? undefined : message, name); if (!symbol) { return undefined; } @@ -1136,7 +1136,7 @@ namespace ts { const left = name.kind === SyntaxKind.QualifiedName ? (name).left : (name).expression; const right = name.kind === SyntaxKind.QualifiedName ? (name).right : (name).name; - const namespace = resolveEntityName(left, SymbolFlags.Namespace, ignoreErrors); + const namespace = resolveEntityName(left, SymbolFlags.Namespace, ignoreErrors, location); if (!namespace || namespace === unknownSymbol || nodeIsMissing(right)) { return undefined; } @@ -16042,7 +16042,14 @@ namespace ts { // Emitter support function isArgumentsLocalBinding(node: Identifier): boolean { - return getReferencedValueSymbol(node) === argumentsSymbol; + if (!isGeneratedIdentifier(node)) { + node = getSourceTreeNodeOfType(node, isIdentifier); + if (node) { + return getReferencedValueSymbol(node) === argumentsSymbol; + } + } + + return false; } function moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean { @@ -16077,37 +16084,49 @@ namespace ts { // When resolved as an expression identifier, if the given node references an exported entity, return the declaration // node of the exported entity's container. Otherwise, return undefined. function getReferencedExportContainer(node: Identifier, prefixLocals?: boolean): SourceFile | ModuleDeclaration | EnumDeclaration { - let symbol = getReferencedValueSymbol(node); - if (symbol) { - if (symbol.flags & SymbolFlags.ExportValue) { - // If we reference an exported entity within the same module declaration, then whether - // we prefix depends on the kind of entity. SymbolFlags.ExportHasLocal encompasses all the - // kinds that we do NOT prefix. - const exportSymbol = getMergedSymbol(symbol.exportSymbol); - if (exportSymbol.flags & SymbolFlags.ExportHasLocal && !prefixLocals) { - return undefined; + node = getSourceTreeNodeOfType(node, isIdentifier); + if (node) { + let symbol = getReferencedValueSymbol(node); + if (symbol) { + if (symbol.flags & SymbolFlags.ExportValue) { + // If we reference an exported entity within the same module declaration, then whether + // we prefix depends on the kind of entity. SymbolFlags.ExportHasLocal encompasses all the + // kinds that we do NOT prefix. + const exportSymbol = getMergedSymbol(symbol.exportSymbol); + if (exportSymbol.flags & SymbolFlags.ExportHasLocal && !prefixLocals) { + return undefined; + } + symbol = exportSymbol; } - symbol = exportSymbol; - } - const parentSymbol = getParentOfSymbol(symbol); - if (parentSymbol) { - if (parentSymbol.flags & SymbolFlags.ValueModule && parentSymbol.valueDeclaration.kind === SyntaxKind.SourceFile) { - return parentSymbol.valueDeclaration; - } - for (let n = node.parent; n; n = n.parent) { - if ((n.kind === SyntaxKind.ModuleDeclaration || n.kind === SyntaxKind.EnumDeclaration) && getSymbolOfNode(n) === parentSymbol) { - return n; + const parentSymbol = getParentOfSymbol(symbol); + if (parentSymbol) { + if (parentSymbol.flags & SymbolFlags.ValueModule && parentSymbol.valueDeclaration.kind === SyntaxKind.SourceFile) { + return parentSymbol.valueDeclaration; + } + for (let n = node.parent; n; n = n.parent) { + if ((n.kind === SyntaxKind.ModuleDeclaration || n.kind === SyntaxKind.EnumDeclaration) && getSymbolOfNode(n) === parentSymbol) { + return n; + } } } } } + + return undefined; } // When resolved as an expression identifier, if the given node references an import, return the declaration of // that import. Otherwise, return undefined. function getReferencedImportDeclaration(node: Identifier): Declaration { - const symbol = getReferencedValueSymbol(node); - return symbol && symbol.flags & SymbolFlags.Alias ? getDeclarationOfAliasSymbol(symbol) : undefined; + node = getSourceTreeNodeOfType(node, isIdentifier); + if (node) { + const symbol = getReferencedValueSymbol(node); + if (symbol && symbol.flags & SymbolFlags.Alias) { + return getDeclarationOfAliasSymbol(symbol); + } + } + + return undefined; } function isSymbolOfDeclarationWithCollidingName(symbol: Symbol): boolean { @@ -16157,35 +16176,54 @@ namespace ts { // a name that either hides an existing name or might hide it when compiled downlevel, // return the declaration of that entity. Otherwise, return undefined. function getReferencedDeclarationWithCollidingName(node: Identifier): Declaration { - const symbol = getReferencedValueSymbol(node); - return symbol && isSymbolOfDeclarationWithCollidingName(symbol) ? symbol.valueDeclaration : undefined; + if (!isGeneratedIdentifier(node)) { + node = getSourceTreeNodeOfType(node, isIdentifier); + if (node) { + const symbol = getReferencedValueSymbol(node); + if (symbol && isSymbolOfDeclarationWithCollidingName(symbol)) { + return symbol.valueDeclaration; + } + } + } + + return undefined; } // Return true if the given node is a declaration of a nested block scoped entity with a name that either hides an // existing name or might hide a name when compiled downlevel function isDeclarationWithCollidingName(node: Declaration): boolean { - return isSymbolOfDeclarationWithCollidingName(getSymbolOfNode(node)); + node = getSourceTreeNodeOfType(node, isDeclaration); + if (node) { + const symbol = getSymbolOfNode(node); + if (symbol) { + return isSymbolOfDeclarationWithCollidingName(symbol); + } + } + + return false; } function isValueAliasDeclaration(node: Node): boolean { + node = getSourceTreeNode(node); switch (node.kind) { case SyntaxKind.ImportEqualsDeclaration: case SyntaxKind.ImportClause: case SyntaxKind.NamespaceImport: case SyntaxKind.ImportSpecifier: case SyntaxKind.ExportSpecifier: - return isAliasResolvedToValue(getSymbolOfNode(node)); + return isAliasResolvedToValue(getSymbolOfNode(node) || unknownSymbol); case SyntaxKind.ExportDeclaration: const exportClause = (node).exportClause; return exportClause && forEach(exportClause.elements, isValueAliasDeclaration); case SyntaxKind.ExportAssignment: - return (node).expression && (node).expression.kind === SyntaxKind.Identifier ? isAliasResolvedToValue(getSymbolOfNode(node)) : true; + return (node).expression && (node).expression.kind === SyntaxKind.Identifier ? isAliasResolvedToValue(getSymbolOfNode(node) || unknownSymbol) : true; } return false; } function isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean { - if (node.parent.kind !== SyntaxKind.SourceFile || !isInternalModuleImportEqualsDeclaration(node)) { + node = getSourceTreeNodeOfType(node, isImportEqualsDeclaration); + if (node === undefined || node.parent.kind !== SyntaxKind.SourceFile || !isInternalModuleImportEqualsDeclaration(node)) { // parent is not source file or it is not reference to internal module return false; } @@ -16212,9 +16250,10 @@ namespace ts { } function isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean { + node = getSourceTreeNode(node); if (isAliasSymbolDeclaration(node)) { const symbol = getSymbolOfNode(node); - if (getSymbolLinks(symbol).referenced) { + if (symbol && getSymbolLinks(symbol).referenced) { return true; } } @@ -16247,7 +16286,8 @@ namespace ts { } function getNodeCheckFlags(node: Node): NodeCheckFlags { - return getNodeLinks(node).flags; + node = getSourceTreeNode(node); + return node ? getNodeLinks(node).flags : undefined; } function getEnumMemberValue(node: EnumMember): number { @@ -16275,16 +16315,16 @@ namespace ts { return type.flags & TypeFlags.ObjectType && getSignaturesOfType(type, SignatureKind.Call).length > 0; } - function getTypeReferenceSerializationKind(typeName: EntityName): TypeReferenceSerializationKind { + function getTypeReferenceSerializationKind(typeName: EntityName, location?: Node): TypeReferenceSerializationKind { // Resolve the symbol as a value to ensure the type can be reached at runtime during emit. - const valueSymbol = resolveEntityName(typeName, SymbolFlags.Value, /*ignoreErrors*/ true); + const valueSymbol = resolveEntityName(typeName, SymbolFlags.Value, /*ignoreErrors*/ true, location); const constructorType = valueSymbol ? getTypeOfSymbol(valueSymbol) : undefined; if (constructorType && isConstructorType(constructorType)) { return TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue; } // Resolve the symbol as a type so that we can provide a more useful hint for the type serializer. - const typeSymbol = resolveEntityName(typeName, SymbolFlags.Type, /*ignoreErrors*/ true); + const typeSymbol = resolveEntityName(typeName, SymbolFlags.Type, /*ignoreErrors*/ true, location); // We might not be able to resolve type symbol so use unknown type in that case (eg error case) if (!typeSymbol) { return TypeReferenceSerializationKind.ObjectType; @@ -16363,9 +16403,17 @@ namespace ts { } function getReferencedValueDeclaration(reference: Identifier): Declaration { - Debug.assert(!nodeIsSynthesized(reference)); - const symbol = getReferencedValueSymbol(reference); - return symbol && getExportSymbolOfValueSymbolIfExported(symbol).valueDeclaration; + if (!isGeneratedIdentifier(reference)) { + reference = getSourceTreeNodeOfType(reference, isIdentifier); + if (reference) { + const symbol = getReferencedValueSymbol(reference); + if (symbol) { + return getExportSymbolOfValueSymbolIfExported(symbol).valueDeclaration; + } + } + } + + return undefined; } function createResolver(): EmitResolver { diff --git a/src/compiler/transformers/es6.ts b/src/compiler/transformers/es6.ts index 82b60cf8a08..5f6c953cbc8 100644 --- a/src/compiler/transformers/es6.ts +++ b/src/compiler/transformers/es6.ts @@ -467,7 +467,7 @@ namespace ts { if (isGeneratedIdentifier(node)) { return node; } - if (node.text !== "arguments" && !resolver.isArgumentsLocalBinding(getOriginalNode(node))) { + if (node.text !== "arguments" && !resolver.isArgumentsLocalBinding(node)) { return node; } return convertedLoopState.argumentsName || (convertedLoopState.argumentsName = createUniqueName("arguments")); @@ -1426,10 +1426,7 @@ namespace ts { // * Why loop initializer is excluded? // - Since we've introduced a fresh name it already will be undefined. - const original = getOriginalNode(node); - Debug.assert(isVariableDeclaration(original)); - - const flags = resolver.getNodeCheckFlags(original); + const flags = resolver.getNodeCheckFlags(node); const isCapturedInFunction = flags & NodeCheckFlags.CapturedBlockScopedBinding; const isDeclaredInLoop = flags & NodeCheckFlags.BlockScopedBindingInLoop; const emittedAsTopLevel = @@ -1443,7 +1440,7 @@ namespace ts { !emittedAsTopLevel && enclosingBlockScopeContainer.kind !== SyntaxKind.ForInStatement && enclosingBlockScopeContainer.kind !== SyntaxKind.ForOfStatement - && (!resolver.isDeclarationWithCollidingName(original) + && (!resolver.isDeclarationWithCollidingName(node) || (isDeclaredInLoop && !isCapturedInFunction && !isIterationStatement(enclosingBlockScopeContainer, /*lookInLabeledStatements*/ false))); @@ -1721,7 +1718,7 @@ namespace ts { } function shouldConvertIterationStatementBody(node: IterationStatement): boolean { - return (resolver.getNodeCheckFlags(getOriginalNode(node)) & NodeCheckFlags.LoopWithCapturedBlockScopedBinding) !== 0; + return (resolver.getNodeCheckFlags(node) & NodeCheckFlags.LoopWithCapturedBlockScopedBinding) !== 0; } /** @@ -2614,8 +2611,8 @@ namespace ts { // Only substitute the identifier if we have enabled substitutions for block-scoped // bindings. if (enabledSubstitutions & ES6SubstitutionFlags.BlockScopedBindings) { - const original = getOriginalNode(node); - if (isIdentifier(original) && !nodeIsSynthesized(original) && original.parent && isNameOfDeclarationWithCollidingName(original)) { + const original = getSourceTreeNodeOfType(node, isIdentifier); + if (original && isNameOfDeclarationWithCollidingName(original)) { return getGeneratedNameForNode(original); } } @@ -2668,12 +2665,9 @@ namespace ts { */ function substituteExpressionIdentifier(node: Identifier): Identifier { if (enabledSubstitutions & ES6SubstitutionFlags.BlockScopedBindings) { - const original = getOriginalNode(node); - if (isIdentifier(original)) { - const declaration = resolver.getReferencedDeclarationWithCollidingName(original); - if (declaration) { - return getGeneratedNameForNode(declaration.name); - } + const declaration = resolver.getReferencedDeclarationWithCollidingName(node); + if (declaration) { + return getGeneratedNameForNode(declaration.name); } } diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index ad6fd2000fb..196ddb059b7 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -460,8 +460,7 @@ namespace ts { function visitExportAssignment(node: ExportAssignment): VisitResult { if (!node.isExportEquals) { - const original = getOriginalNode(node); - if (nodeIsSynthesized(original) || resolver.isValueAliasDeclaration(original)) { + if (nodeIsSynthesized(node) || resolver.isValueAliasDeclaration(node)) { const statements: Statement[] = []; addExportDefault(statements, node.expression, /*location*/ node); return statements; @@ -713,46 +712,43 @@ namespace ts { } function substituteExpressionIdentifier(node: Identifier): Expression { - const original = getOriginalNode(node); - if (isIdentifier(original)) { - const container = resolver.getReferencedExportContainer(original, (getNodeEmitFlags(node) & NodeEmitFlags.PrefixExportedLocal) !== 0); - if (container) { - if (container.kind === SyntaxKind.SourceFile) { - return createPropertyAccess( - createIdentifier("exports"), - getSynthesizedClone(node), - /*location*/ node - ); - } + const container = resolver.getReferencedExportContainer(node, (getNodeEmitFlags(node) & NodeEmitFlags.ExportName) !== 0); + if (container) { + if (container.kind === SyntaxKind.SourceFile) { + return createPropertyAccess( + createIdentifier("exports"), + getSynthesizedClone(node), + /*location*/ node + ); } - else { - const declaration = resolver.getReferencedImportDeclaration(node.parent ? node : original); - if (declaration) { - if (declaration.kind === SyntaxKind.ImportClause) { - if (languageVersion >= ScriptTarget.ES5) { - return createPropertyAccess( - getGeneratedNameForNode(declaration.parent), - createIdentifier("default"), - /*location*/ node - ); - } - else { - return createElementAccess( - getGeneratedNameForNode(declaration.parent), - createLiteral("default"), - /*location*/ node - ); - } - } - else if (declaration.kind === SyntaxKind.ImportSpecifier) { - const name = (declaration).propertyName - || (declaration).name; + } + else { + const declaration = resolver.getReferencedImportDeclaration(node); + if (declaration) { + if (declaration.kind === SyntaxKind.ImportClause) { + if (languageVersion >= ScriptTarget.ES5) { return createPropertyAccess( - getGeneratedNameForNode(declaration.parent.parent.parent), - getSynthesizedClone(name), + getGeneratedNameForNode(declaration.parent), + createIdentifier("default"), /*location*/ node ); } + else { + return createElementAccess( + getGeneratedNameForNode(declaration.parent), + createLiteral("default"), + /*location*/ node + ); + } + } + else if (declaration.kind === SyntaxKind.ImportSpecifier) { + const name = (declaration).propertyName + || (declaration).name; + return createPropertyAccess( + getGeneratedNameForNode(declaration.parent.parent.parent), + getSynthesizedClone(name), + /*location*/ node + ); } } } diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index 81c657b158c..3bda78830e7 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -570,8 +570,7 @@ namespace ts { function visitExportAssignment(node: ExportAssignment): Statement { if (!node.isExportEquals) { - const original = getOriginalNode(node); - if (nodeIsSynthesized(original) || resolver.isValueAliasDeclaration(original)) { + if (nodeIsSynthesized(node) || resolver.isValueAliasDeclaration(node)) { return createExportStatement( createLiteral("default"), node.expression @@ -1012,8 +1011,7 @@ namespace ts { const left = node.left; switch (left.kind) { case SyntaxKind.Identifier: - const originalNode = getOriginalNode(left); - const exportDeclaration = resolver.getReferencedExportContainer(originalNode); + const exportDeclaration = resolver.getReferencedExportContainer(left); if (exportDeclaration) { return createExportExpression(left, node); } diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 0b8c11a66e2..78536f56697 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -596,7 +596,7 @@ namespace ts { // Record an alias to avoid class double-binding. let decoratedClassAlias: Identifier; - if (resolver.getNodeCheckFlags(getOriginalNode(node)) & NodeCheckFlags.DecoratedClassWithSelfReference) { + if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.DecoratedClassWithSelfReference) { enableExpressionSubstitutionForDecoratedClasses(); decoratedClassAlias = createUniqueName(node.name && !isGeneratedIdentifier(node.name) ? node.name.text : "default"); decoratedClassAliases[getOriginalNodeId(node)] = decoratedClassAlias; @@ -1380,7 +1380,6 @@ namespace ts { function addOldTypeMetadata(node: Declaration, decoratorExpressions: Expression[]) { if (compilerOptions.emitDecoratorMetadata) { - let properties: ObjectLiteralElement[]; if (shouldAddTypeMetadata(node)) { decoratorExpressions.push(createMetadataHelper("design:type", serializeTypeOfNode(node))); } @@ -1614,11 +1613,9 @@ namespace ts { * @param node The type reference node. */ function serializeTypeReferenceNode(node: TypeReferenceNode) { - // Clone the type name and parent it to a location outside of the current declaration. - const typeName = cloneEntityName(node.typeName, currentScope); - switch (resolver.getTypeReferenceSerializationKind(typeName)) { + switch (resolver.getTypeReferenceSerializationKind(node.typeName, currentScope)) { case TypeReferenceSerializationKind.Unknown: - const serialized = serializeEntityNameAsExpression(typeName, /*useFallback*/ true); + const serialized = serializeEntityNameAsExpression(node.typeName, /*useFallback*/ true); const temp = createTempVariable(hoistVariableDeclaration); return createLogicalOr( createLogicalAnd( @@ -1634,7 +1631,7 @@ namespace ts { ); case TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue: - return serializeEntityNameAsExpression(typeName, /*useFallback*/ false); + return serializeEntityNameAsExpression(node.typeName, /*useFallback*/ false); case TypeReferenceSerializationKind.VoidType: return createVoidZero(); @@ -1675,17 +1672,20 @@ namespace ts { function serializeEntityNameAsExpression(node: EntityName, useFallback: boolean): Expression { switch (node.kind) { case SyntaxKind.Identifier: + const name = getMutableClone(node); + name.original = undefined; + name.parent = currentScope; if (useFallback) { return createLogicalAnd( createStrictInequality( - createTypeOf(node), + createTypeOf(name), createLiteral("undefined") ), - node + name ); } - return node; + return name; case SyntaxKind.QualifiedName: return serializeQualifiedNameAsExpression(node, useFallback); @@ -2646,7 +2646,7 @@ namespace ts { else { // We set the "PrefixExportedLocal" flag to indicate to any module transformer // downstream that any `exports.` prefix should be added. - setNodeEmitFlags(name, getNodeEmitFlags(name) | NodeEmitFlags.PrefixExportedLocal); + setNodeEmitFlags(name, getNodeEmitFlags(name) | NodeEmitFlags.ExportName); return name; } } @@ -2738,41 +2738,52 @@ namespace ts { } function substituteExpressionIdentifier(node: Identifier): Expression { + return trySubstituteDecoratedClassName(node) + || trySubstituteNamespaceExportedName(node) + || node; + } + + function trySubstituteDecoratedClassName(node: Identifier): Expression { if (enabledSubstitutions & TypeScriptSubstitutionFlags.DecoratedClasses) { - const original = getOriginalNode(node); - if (isIdentifier(original)) { - if (resolver.getNodeCheckFlags(original) & NodeCheckFlags.SelfReferenceInDecoratedClass) { - // Due to the emit for class decorators, any reference to the class from inside of the class body - // must instead be rewritten to point to a temporary variable to avoid issues with the double-bind - // behavior of class names in ES6. - const declaration = resolver.getReferencedValueDeclaration(original); - if (declaration) { - const classAlias = currentDecoratedClassAliases[getNodeId(declaration)]; - if (classAlias) { - return getRelocatedClone(classAlias, /*location*/ node); - } + if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.SelfReferenceInDecoratedClass) { + // Due to the emit for class decorators, any reference to the class from inside of the class body + // must instead be rewritten to point to a temporary variable to avoid issues with the double-bind + // behavior of class names in ES6. + const declaration = resolver.getReferencedValueDeclaration(node); + if (declaration) { + const classAlias = currentDecoratedClassAliases[getNodeId(declaration)]; + if (classAlias) { + return getRelocatedClone(classAlias, /*location*/ node); } } } } + return undefined; + } + + function trySubstituteNamespaceExportedName(node: Identifier): Expression { if (enabledSubstitutions & applicableSubstitutions) { + // If this is explicitly a local name, do not substitute. + if (getNodeEmitFlags(node) & NodeEmitFlags.LocalName) { + return node; + } + // If we are nested within a namespace declaration, we may need to qualifiy // an identifier that is exported from a merged namespace. - const original = getOriginalNode(node); - if (isIdentifier(original) && original.parent) { - const container = resolver.getReferencedExportContainer(original); - if (container) { - const substitute = - (applicableSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports && container.kind === SyntaxKind.ModuleDeclaration) || - (applicableSubstitutions & TypeScriptSubstitutionFlags.NonQualifiedEnumMembers && container.kind === SyntaxKind.EnumDeclaration); - if (substitute) { - return createPropertyAccess(getGeneratedNameForNode(container), node, /*location*/ node); - } + const original = getSourceTreeNodeOfType(node, isIdentifier); + const container = resolver.getReferencedExportContainer(original, /*prefixLocals*/ false); + if (container && original !== container.name) { + const substitute = + (applicableSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports && container.kind === SyntaxKind.ModuleDeclaration) || + (applicableSubstitutions & TypeScriptSubstitutionFlags.NonQualifiedEnumMembers && container.kind === SyntaxKind.EnumDeclaration); + if (substitute) { + return createPropertyAccess(getGeneratedNameForNode(container), node, /*location*/ node); } } } - return node; + + return undefined; } function substituteCallExpression(node: CallExpression): Expression { @@ -2900,7 +2911,7 @@ namespace ts { function getSuperContainerAsyncMethodFlags() { return currentSuperContainer !== undefined - && resolver.getNodeCheckFlags(getOriginalNode(currentSuperContainer)) & (NodeCheckFlags.AsyncMethodWithSuper | NodeCheckFlags.AsyncMethodWithSuperBinding); + && resolver.getNodeCheckFlags(currentSuperContainer) & (NodeCheckFlags.AsyncMethodWithSuper | NodeCheckFlags.AsyncMethodWithSuperBinding); } } } \ No newline at end of file diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 7723abfe270..ab63484a812 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1963,7 +1963,7 @@ namespace ts { // Returns the constant value this property access resolves to, or 'undefined' for a non-constant getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number; getReferencedValueDeclaration(reference: Identifier): Declaration; - getTypeReferenceSerializationKind(typeName: EntityName): TypeReferenceSerializationKind; + getTypeReferenceSerializationKind(typeName: EntityName, location?: Node): TypeReferenceSerializationKind; isOptionalParameter(node: ParameterDeclaration): boolean; moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean; isArgumentsLocalBinding(node: Identifier): boolean; @@ -2875,8 +2875,9 @@ namespace ts { NoSourceMap = 1 << 10, // Do not emit a source map location for this node. NoNestedSourceMaps = 1 << 11, // Do not emit source map locations for children of this node. NoComments = 1 << 12, // Do not emit comments for this node. - PrefixExportedLocal = 1 << 13, // Ensure an export prefix is added for an identifier that points to an exported declaration with a local name (see SymbolFlags.ExportHasLocal). - Indented = 1 << 14, // Adds an explicit extra indentation level for class and function bodies when printing (used to match old emitter). + ExportName = 1 << 13, // Ensure an export prefix is added for an identifier that points to an exported declaration with a local name (see SymbolFlags.ExportHasLocal). + LocalName = 1 << 14, // Ensure an export prefix is not added for an identifier that points to an exported declaration. + Indented = 1 << 15, // Adds an explicit extra indentation level for class and function bodies when printing (used to match old emitter). } /** Additional context provided to `visitEachChild` */ diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index aaaf699834d..fd1ad48a74f 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1713,16 +1713,20 @@ namespace ts { /** * Creates a deep clone of an EntityName, with new parent pointers. + * NOTE: The new entity name will *not* have "original" pointers. + * * @param node The EntityName to clone. * @param parent The parent for the cloned node. */ export function cloneEntityName(node: EntityName, parent?: Node): EntityName { const clone = getMutableClone(node); + clone.original = undefined; clone.parent = parent; if (isQualifiedName(clone)) { const { left, right } = clone; clone.left = cloneEntityName(left, clone); clone.right = getMutableClone(right); + clone.right.original = undefined; clone.right.parent = clone; } @@ -1741,13 +1745,31 @@ namespace ts { } export function getOriginalNode(node: Node): Node { - while (node.original !== undefined) { - node = node.original; + if (node) { + while (node.original !== undefined) { + node = node.original; + } } return node; } + export function getSourceTreeNode(node: Node): Node { + node = getOriginalNode(node); + if (node) { + if (node.parent || node.kind === SyntaxKind.SourceFile) { + return node; + } + } + + return undefined; + } + + export function getSourceTreeNodeOfType(node: T, nodeTest: (node: Node) => node is T): T { + const source = getSourceTreeNode(node); + return source && nodeTest(source) ? source : undefined; + } + export function getOriginalNodeId(node: Node) { node = getOriginalNode(node); return node ? getNodeId(node) : 0; @@ -2999,7 +3021,7 @@ namespace ts { break; case SyntaxKind.ImportEqualsDeclaration: - if ((node).moduleReference.kind === SyntaxKind.ExternalModuleReference && resolver.isReferencedAliasDeclaration(getOriginalNode(node))) { + if ((node).moduleReference.kind === SyntaxKind.ExternalModuleReference && resolver.isReferencedAliasDeclaration(node)) { // import x = require("mod") where x is referenced externalImports.push(node); } @@ -3012,7 +3034,7 @@ namespace ts { externalImports.push(node); hasExportStars = true; } - else if (resolver.isValueAliasDeclaration(getOriginalNode(node))) { + else if (resolver.isValueAliasDeclaration(node)) { // export { x, y } from "mod" where at least one export is a value symbol externalImports.push(node); } @@ -3414,6 +3436,10 @@ namespace ts { || kind === SyntaxKind.ModuleDeclaration; } + export function isImportEqualsDeclaration(node: Node): node is ImportEqualsDeclaration { + return node.kind === SyntaxKind.ImportEqualsDeclaration; + } + export function isImportClause(node: Node): node is ImportClause { return node.kind === SyntaxKind.ImportClause; } From 2cb7401a56d89bb80ed58c9d0ede7dfbf63c933b Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 11 Apr 2016 14:27:18 -0700 Subject: [PATCH 03/10] Do not emit ES6 import/export inside namespaces ES6 imports and exports are illegal inside namespaces. In order to emit syntactically legal code, skip emit for these incorrect statements. --- src/compiler/transformers/ts.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 0b8c11a66e2..90bac017d5a 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -157,7 +157,15 @@ namespace ts { * @param node The node to visit. */ function namespaceElementVisitorWorker(node: Node): VisitResult { - if (node.transformFlags & TransformFlags.TypeScript || hasModifier(node, ModifierFlags.Export)) { + if (node.kind === SyntaxKind.ExportDeclaration || + node.kind === SyntaxKind.ImportDeclaration || + node.kind === SyntaxKind.ImportClause || + (node.kind === SyntaxKind.ImportEqualsDeclaration && + (node).moduleReference.kind === SyntaxKind.ExternalModuleReference)) { + // do not emit ES6 imports and exports since they are illegal inside a namespace + return createNotEmittedStatement(node); + } + else if (node.transformFlags & TransformFlags.TypeScript || hasModifier(node, ModifierFlags.Export)) { // This node is explicitly marked as TypeScript, or is exported at the namespace // level, so we should transform the node. return visitTypeScript(node); @@ -2903,4 +2911,4 @@ namespace ts { && resolver.getNodeCheckFlags(getOriginalNode(currentSuperContainer)) & (NodeCheckFlags.AsyncMethodWithSuper | NodeCheckFlags.AsyncMethodWithSuperBinding); } } -} \ No newline at end of file +} From 221c0f36564729313900558c89a13342a43c12a6 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 12 Apr 2016 09:56:51 -0700 Subject: [PATCH 04/10] Update es5 module internal imports test and related baselines --- .../es5ModuleInternalNamedImports.errors.txt | 18 +++++++++++++++++- .../reference/es5ModuleInternalNamedImports.js | 5 ++++- .../reference/es6ModuleInternalNamedImports.js | 7 ------- .../es6ModuleInternalNamedImports2.js | 7 ------- .../exportDeclarationInInternalModule.js | 1 - .../compiler/es5ModuleInternalNamedImports.ts | 4 ++++ 6 files changed, 25 insertions(+), 17 deletions(-) diff --git a/tests/baselines/reference/es5ModuleInternalNamedImports.errors.txt b/tests/baselines/reference/es5ModuleInternalNamedImports.errors.txt index f51ff27a412..936f381628d 100644 --- a/tests/baselines/reference/es5ModuleInternalNamedImports.errors.txt +++ b/tests/baselines/reference/es5ModuleInternalNamedImports.errors.txt @@ -6,9 +6,13 @@ tests/cases/compiler/es5ModuleInternalNamedImports.ts(27,5): error TS1194: Expor tests/cases/compiler/es5ModuleInternalNamedImports.ts(28,5): error TS1194: Export declarations are not permitted in a namespace. tests/cases/compiler/es5ModuleInternalNamedImports.ts(29,5): error TS1194: Export declarations are not permitted in a namespace. tests/cases/compiler/es5ModuleInternalNamedImports.ts(30,5): error TS1194: Export declarations are not permitted in a namespace. +tests/cases/compiler/es5ModuleInternalNamedImports.ts(31,25): error TS1147: Import declarations in a namespace cannot reference a module. +tests/cases/compiler/es5ModuleInternalNamedImports.ts(32,20): error TS1147: Import declarations in a namespace cannot reference a module. +tests/cases/compiler/es5ModuleInternalNamedImports.ts(33,32): error TS1147: Import declarations in a namespace cannot reference a module. +tests/cases/compiler/es5ModuleInternalNamedImports.ts(35,16): error TS2307: Cannot find module 'M3'. -==== tests/cases/compiler/es5ModuleInternalNamedImports.ts (8 errors) ==== +==== tests/cases/compiler/es5ModuleInternalNamedImports.ts (12 errors) ==== export module M { // variable @@ -55,5 +59,17 @@ tests/cases/compiler/es5ModuleInternalNamedImports.ts(30,5): error TS1194: Expor export {M_A as a}; ~~~~~~~~~~~~~~~~~~ !!! error TS1194: Export declarations are not permitted in a namespace. + import * as M2 from "M2"; + ~~~~ +!!! error TS1147: Import declarations in a namespace cannot reference a module. + import M4 from "M4"; + ~~~~ +!!! error TS1147: Import declarations in a namespace cannot reference a module. + export import M5 = require("M5"); + ~~~~ +!!! error TS1147: Import declarations in a namespace cannot reference a module. } + import M3 from "M3"; + ~~~~ +!!! error TS2307: Cannot find module 'M3'. \ No newline at end of file diff --git a/tests/baselines/reference/es5ModuleInternalNamedImports.js b/tests/baselines/reference/es5ModuleInternalNamedImports.js index e8963b7db40..2fcbd5a53d8 100644 --- a/tests/baselines/reference/es5ModuleInternalNamedImports.js +++ b/tests/baselines/reference/es5ModuleInternalNamedImports.js @@ -29,7 +29,11 @@ export module M { export {M_F as f}; export {M_E as e}; export {M_A as a}; + import * as M2 from "M2"; + import M4 from "M4"; + export import M5 = require("M5"); } +import M3 from "M3"; //// [es5ModuleInternalNamedImports.js] @@ -60,6 +64,5 @@ define(["require", "exports"], function (require, exports) { var M_E = M.M_E; // alias M.M_A = M_M; - // Reexports })(M = exports.M || (exports.M = {})); }); diff --git a/tests/baselines/reference/es6ModuleInternalNamedImports.js b/tests/baselines/reference/es6ModuleInternalNamedImports.js index 98504601d02..22d15b9fd61 100644 --- a/tests/baselines/reference/es6ModuleInternalNamedImports.js +++ b/tests/baselines/reference/es6ModuleInternalNamedImports.js @@ -55,11 +55,4 @@ export var M; var M_E = M.M_E; // alias M.M_A = M_M; - // Reexports - export { M_V as v }; - export { M_C as c }; - export { M_M as m }; - export { M_F as f }; - export { M_E as e }; - export { M_A as a }; })(M || (M = {})); diff --git a/tests/baselines/reference/es6ModuleInternalNamedImports2.js b/tests/baselines/reference/es6ModuleInternalNamedImports2.js index 98226a1e52b..35eabc9a65e 100644 --- a/tests/baselines/reference/es6ModuleInternalNamedImports2.js +++ b/tests/baselines/reference/es6ModuleInternalNamedImports2.js @@ -59,11 +59,4 @@ export var M; M.M_A = M_M; })(M || (M = {})); (function (M) { - // Reexports - export { M_V as v }; - export { M_C as c }; - export { M_M as m }; - export { M_F as f }; - export { M_E as e }; - export { M_A as a }; })(M || (M = {})); diff --git a/tests/baselines/reference/exportDeclarationInInternalModule.js b/tests/baselines/reference/exportDeclarationInInternalModule.js index ecd9d5adf4d..a9ea4bf5eda 100644 --- a/tests/baselines/reference/exportDeclarationInInternalModule.js +++ b/tests/baselines/reference/exportDeclarationInInternalModule.js @@ -53,7 +53,6 @@ var Bbb; return SomeType; }()); Bbb.SomeType = SomeType; - // this line causes the nullref })(Bbb || (Bbb = {})); var a; diff --git a/tests/cases/compiler/es5ModuleInternalNamedImports.ts b/tests/cases/compiler/es5ModuleInternalNamedImports.ts index 05943d1c67e..62b976a7df7 100644 --- a/tests/cases/compiler/es5ModuleInternalNamedImports.ts +++ b/tests/cases/compiler/es5ModuleInternalNamedImports.ts @@ -30,4 +30,8 @@ export module M { export {M_F as f}; export {M_E as e}; export {M_A as a}; + import * as M2 from "M2"; + import M4 from "M4"; + export import M5 = require("M5"); } +import M3 from "M3"; From e6670811b0b762b953ea3f7fe3bd53b00aa688ad Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 12 Apr 2016 10:46:27 -0700 Subject: [PATCH 05/10] Remove parentheses and accept baselines --- tests/baselines/reference/emptyAssignmentPatterns02_ES5.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/emptyAssignmentPatterns02_ES5.js b/tests/baselines/reference/emptyAssignmentPatterns02_ES5.js index 27a0b5f9b61..370e019104f 100644 --- a/tests/baselines/reference/emptyAssignmentPatterns02_ES5.js +++ b/tests/baselines/reference/emptyAssignmentPatterns02_ES5.js @@ -9,8 +9,8 @@ let x, y, z, a1, a2, a3; //// [emptyAssignmentPatterns02_ES5.js] var a; var x, y, z, a1, a2, a3; -((x = a.x, y = a.y, z = a.z, a)); -((a1 = a[0], a2 = a[1], a3 = a[2], a)); +(x = a.x, y = a.y, z = a.z, a); +(a1 = a[0], a2 = a[1], a3 = a[2], a); //// [emptyAssignmentPatterns02_ES5.d.ts] From 349ced2d402b43df21b63cfff22bc39f42788a45 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 12 Apr 2016 14:39:50 -0700 Subject: [PATCH 06/10] Do not emit "from" if import clause is missing in import declaration --- src/compiler/printer.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/compiler/printer.ts b/src/compiler/printer.ts index f39793a80af..512951a65e7 100644 --- a/src/compiler/printer.ts +++ b/src/compiler/printer.ts @@ -1643,8 +1643,10 @@ const _super = (function (geti, seti) { function emitImportDeclaration(node: ImportDeclaration) { emitModifiers(node, node.modifiers); write("import "); - emit(node.importClause); - write(" from "); + if (node.importClause) { + emit(node.importClause); + write(" from "); + } emitExpression(node.moduleSpecifier); write(";"); } From 446494060d2b4e66b423b2a98e014e7d5ecd82a5 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 12 Apr 2016 18:40:39 -0700 Subject: [PATCH 07/10] PR feedback --- Jakefile.js | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/Jakefile.js b/Jakefile.js index 6ed276c73c0..dd0d7643fb3 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -658,21 +658,19 @@ function exec(cmd, completeHandler, errorHandler) { } function cleanTestDirs() { - if (!environmentVariableIsDisabled("CLEAN_TESTS")) { - // Clean the local baselines directory - if (fs.existsSync(localBaseline)) { - jake.rmRf(localBaseline); - } - - // Clean the local Rwc baselines directory - if (fs.existsSync(localRwcBaseline)) { - jake.rmRf(localRwcBaseline); - } - - jake.mkdirP(localRwcBaseline); - jake.mkdirP(localTest262Baseline); - jake.mkdirP(localBaseline); + // Clean the local baselines directory + if (fs.existsSync(localBaseline)) { + jake.rmRf(localBaseline); } + + // Clean the local Rwc baselines directory + if (fs.existsSync(localRwcBaseline)) { + jake.rmRf(localRwcBaseline); + } + + jake.mkdirP(localRwcBaseline); + jake.mkdirP(localTest262Baseline); + jake.mkdirP(localBaseline); } // used to pass data from jake command line directly to run.js @@ -828,8 +826,11 @@ function runTestsAndWriteOutput(file) { }); } -function runConsoleTests(defaultReporter, defaultSubsets) { - cleanTestDirs(); +function runConsoleTests(defaultReporter, defaultSubsets, dirty) { + if (!dirty) { + cleanTestDirs(); + } + var debug = process.env.debug || process.env.d; tests = process.env.test || process.env.tests || process.env.t; var light = process.env.light || false; @@ -868,7 +869,7 @@ function runConsoleTests(defaultReporter, defaultSubsets) { console.log(cmd); exec(cmd, function () { deleteTemporaryProjectOutput(); - if (i === 0 && !environmentVariableIsDisabled("lint")) { + if (i === 0 && !dirty) { var lint = jake.Task['lint']; lint.addListener('complete', function () { complete(); @@ -896,6 +897,9 @@ task("runtests", ["build-rules", "tests", builtLocalDirectory], function() { task("runtests-file", ["build-rules", "tests", builtLocalDirectory], function () { runTestsAndWriteOutput("tests/baselines/local/testresults.tap"); }, { async: true }); +task("runtests-dirty", ["build-rules", "tests", builtLocalDirectory], function () { + runConsoleTests("mocha-fivemat-progress-reporter", [], /*dirty*/ true); +}, { async: true }); desc("Generates code coverage data via instanbul"); task("generate-code-coverage", ["tests", builtLocalDirectory], function () { From 9899cda6d3eaefd685443e791d73135a31d2d613 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 13 Apr 2016 10:43:01 -0700 Subject: [PATCH 08/10] PR Feedback, also removes cloneEntityName. --- src/compiler/checker.ts | 5 ++++- src/compiler/emitter.ts | 31 +++++++++++++++++++------------ src/compiler/transformers/ts.ts | 2 +- src/compiler/utilities.ts | 22 ---------------------- 4 files changed, 24 insertions(+), 36 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 10e3c19497d..e339cd390f5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16216,7 +16216,10 @@ namespace ts { const exportClause = (node).exportClause; return exportClause && forEach(exportClause.elements, isValueAliasDeclaration); case SyntaxKind.ExportAssignment: - return (node).expression && (node).expression.kind === SyntaxKind.Identifier ? isAliasResolvedToValue(getSymbolOfNode(node) || unknownSymbol) : true; + return (node).expression + && (node).expression.kind === SyntaxKind.Identifier + ? isAliasResolvedToValue(getSymbolOfNode(node) || unknownSymbol) + : true; } return false; } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index bb4d179704c..e3f9838cf26 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2240,41 +2240,49 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge emit(node.right); } - function emitQualifiedNameAsExpression(node: QualifiedName, useFallback: boolean) { + function emitQualifiedNameAsExpression(node: QualifiedName, useFallback: boolean, location?: Node) { if (node.left.kind === SyntaxKind.Identifier) { - emitEntityNameAsExpression(node.left, useFallback); + emitEntityNameAsExpression(node.left, useFallback, location); } else if (useFallback) { const temp = createAndRecordTempVariable(TempFlags.Auto); write("("); emitNodeWithoutSourceMap(temp); write(" = "); - emitEntityNameAsExpression(node.left, /*useFallback*/ true); + emitEntityNameAsExpression(node.left, /*useFallback*/ true, location); write(") && "); emitNodeWithoutSourceMap(temp); } else { - emitEntityNameAsExpression(node.left, /*useFallback*/ false); + emitEntityNameAsExpression(node.left, /*useFallback*/ false, location); } write("."); emit(node.right); } - function emitEntityNameAsExpression(node: EntityName | Expression, useFallback: boolean) { + function emitEntityNameAsExpression(node: EntityName | Expression, useFallback: boolean, location?: Node) { switch (node.kind) { case SyntaxKind.Identifier: + let name = node; + if (location) { + // to resolve the expression to the correct container, create a shallow + // clone of `node` with a new parent. + name = clone(name); + name.parent = location; + } + if (useFallback) { write("typeof "); - emitExpressionIdentifier(node); + emitExpressionIdentifier(name); write(" !== 'undefined' && "); } - emitExpressionIdentifier(node); + emitExpressionIdentifier(name); break; case SyntaxKind.QualifiedName: - emitQualifiedNameAsExpression(node, useFallback); + emitQualifiedNameAsExpression(node, useFallback, location); break; default: @@ -5943,22 +5951,21 @@ const _super = (function (geti, seti) { } // Clone the type name and parent it to a location outside of the current declaration. - const typeName = cloneEntityName(node.typeName, location); - const result = resolver.getTypeReferenceSerializationKind(typeName); + const result = resolver.getTypeReferenceSerializationKind(node.typeName, location); switch (result) { case TypeReferenceSerializationKind.Unknown: let temp = createAndRecordTempVariable(TempFlags.Auto); write("(typeof ("); emitNodeWithoutSourceMap(temp); write(" = "); - emitEntityNameAsExpression(typeName, /*useFallback*/ true); + emitEntityNameAsExpression(node.typeName, /*useFallback*/ true, location); write(") === 'function' && "); emitNodeWithoutSourceMap(temp); write(") || Object"); break; case TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue: - emitEntityNameAsExpression(typeName, /*useFallback*/ false); + emitEntityNameAsExpression(node.typeName, /*useFallback*/ false, location); break; case TypeReferenceSerializationKind.VoidType: diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 78536f56697..710edd77504 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -2644,7 +2644,7 @@ namespace ts { return getNamespaceMemberName(name); } else { - // We set the "PrefixExportedLocal" flag to indicate to any module transformer + // We set the "ExportName" flag to indicate to any module transformer // downstream that any `exports.` prefix should be added. setNodeEmitFlags(name, getNodeEmitFlags(name) | NodeEmitFlags.ExportName); return name; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index fd1ad48a74f..83038f1e3df 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1711,28 +1711,6 @@ namespace ts { || kind === SyntaxKind.SourceFile; } - /** - * Creates a deep clone of an EntityName, with new parent pointers. - * NOTE: The new entity name will *not* have "original" pointers. - * - * @param node The EntityName to clone. - * @param parent The parent for the cloned node. - */ - export function cloneEntityName(node: EntityName, parent?: Node): EntityName { - const clone = getMutableClone(node); - clone.original = undefined; - clone.parent = parent; - if (isQualifiedName(clone)) { - const { left, right } = clone; - clone.left = cloneEntityName(left, clone); - clone.right = getMutableClone(right); - clone.right.original = undefined; - clone.right.parent = clone; - } - - return clone; - } - export function nodeIsSynthesized(node: TextRange): boolean { return positionIsSynthesized(node.pos) || positionIsSynthesized(node.end); From bdb76400f316813e290865941ff8bb2449354003 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 13 Apr 2016 11:38:21 -0700 Subject: [PATCH 09/10] Return undefined instead of createNotEmittedStatement --- src/compiler/transformers/ts.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 90bac017d5a..1cf93f050c9 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -163,7 +163,7 @@ namespace ts { (node.kind === SyntaxKind.ImportEqualsDeclaration && (node).moduleReference.kind === SyntaxKind.ExternalModuleReference)) { // do not emit ES6 imports and exports since they are illegal inside a namespace - return createNotEmittedStatement(node); + return undefined; } else if (node.transformFlags & TransformFlags.TypeScript || hasModifier(node, ModifierFlags.Export)) { // This node is explicitly marked as TypeScript, or is exported at the namespace From 47e9ee57c825c94b6700c5c6b549dcc19124a544 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 13 Apr 2016 12:45:05 -0700 Subject: [PATCH 10/10] Remove commas from nodeEdgeTraversalMap manually for now --- src/compiler/visitor.ts | 178 ++++++++++++++++++++-------------------- 1 file changed, 89 insertions(+), 89 deletions(-) diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 81f36399b62..d55357bed8d 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -46,27 +46,27 @@ namespace ts { const nodeEdgeTraversalMap: Map = { [SyntaxKind.QualifiedName]: [ { name: "left", test: isEntityName }, - { name: "right", test: isIdentifier }, + { name: "right", test: isIdentifier } ], [SyntaxKind.ComputedPropertyName]: [ - { name: "expression", test: isExpression }, + { name: "expression", test: isExpression } ], [SyntaxKind.Parameter]: [ { name: "decorators", test: isDecorator }, { name: "modifiers", test: isModifier }, { name: "name", test: isBindingName }, { name: "type", test: isTypeNode, optional: true }, - { name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList }, + { name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList } ], [SyntaxKind.Decorator]: [ - { name: "expression", test: isLeftHandSideExpression }, + { name: "expression", test: isLeftHandSideExpression } ], [SyntaxKind.PropertyDeclaration]: [ { name: "decorators", test: isDecorator }, { name: "modifiers", test: isModifier }, { name: "name", test: isPropertyName }, { name: "type", test: isTypeNode, optional: true }, - { name: "initializer", test: isExpression, optional: true }, + { name: "initializer", test: isExpression, optional: true } ], [SyntaxKind.MethodDeclaration]: [ { name: "decorators", test: isDecorator }, @@ -75,7 +75,7 @@ namespace ts { { name: "typeParameters", test: isTypeParameter }, { name: "parameters", test: isParameter }, { name: "type", test: isTypeNode, optional: true }, - { name: "body", test: isBlock, optional: true }, + { name: "body", test: isBlock, optional: true } ], [SyntaxKind.Constructor]: [ { name: "decorators", test: isDecorator }, @@ -83,7 +83,7 @@ namespace ts { { name: "typeParameters", test: isTypeParameter }, { name: "parameters", test: isParameter }, { name: "type", test: isTypeNode, optional: true }, - { name: "body", test: isBlock, optional: true }, + { name: "body", test: isBlock, optional: true } ], [SyntaxKind.GetAccessor]: [ { name: "decorators", test: isDecorator }, @@ -92,7 +92,7 @@ namespace ts { { name: "typeParameters", test: isTypeParameter }, { name: "parameters", test: isParameter }, { name: "type", test: isTypeNode, optional: true }, - { name: "body", test: isBlock, optional: true }, + { name: "body", test: isBlock, optional: true } ], [SyntaxKind.SetAccessor]: [ { name: "decorators", test: isDecorator }, @@ -101,53 +101,53 @@ namespace ts { { name: "typeParameters", test: isTypeParameter }, { name: "parameters", test: isParameter }, { name: "type", test: isTypeNode, optional: true }, - { name: "body", test: isBlock, optional: true }, + { name: "body", test: isBlock, optional: true } ], [SyntaxKind.ObjectBindingPattern]: [ - { name: "elements", test: isBindingElement }, + { name: "elements", test: isBindingElement } ], [SyntaxKind.ArrayBindingPattern]: [ - { name: "elements", test: isBindingElement }, + { name: "elements", test: isBindingElement } ], [SyntaxKind.BindingElement]: [ { name: "propertyName", test: isPropertyName, optional: true }, { name: "name", test: isBindingName }, - { name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList }, + { name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList } ], [SyntaxKind.ArrayLiteralExpression]: [ - { name: "elements", test: isExpression, parenthesize: parenthesizeExpressionForList }, + { name: "elements", test: isExpression, parenthesize: parenthesizeExpressionForList } ], [SyntaxKind.ObjectLiteralExpression]: [ - { name: "properties", test: isObjectLiteralElement }, + { name: "properties", test: isObjectLiteralElement } ], [SyntaxKind.PropertyAccessExpression]: [ { name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess }, - { name: "name", test: isIdentifier }, + { name: "name", test: isIdentifier } ], [SyntaxKind.ElementAccessExpression]: [ { name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess }, - { name: "argumentExpression", test: isExpression }, + { name: "argumentExpression", test: isExpression } ], [SyntaxKind.CallExpression]: [ { name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess }, { name: "typeArguments", test: isTypeNode }, - { name: "arguments", test: isExpression, parenthesize: parenthesizeExpressionForList }, + { name: "arguments", test: isExpression, parenthesize: parenthesizeExpressionForList } ], [SyntaxKind.NewExpression]: [ { name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForNew }, { name: "typeArguments", test: isTypeNode }, - { name: "arguments", test: isExpression, parenthesize: parenthesizeExpressionForList }, + { name: "arguments", test: isExpression, parenthesize: parenthesizeExpressionForList } ], [SyntaxKind.TaggedTemplateExpression]: [ { name: "tag", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess }, - { name: "template", test: isTemplate }, + { name: "template", test: isTemplate } ], [SyntaxKind.TypeAssertionExpression]: [ { name: "type", test: isTypeNode }, - { name: "expression", test: isUnaryExpression }, + { name: "expression", test: isUnaryExpression } ], [SyntaxKind.ParenthesizedExpression]: [ - { name: "expression", test: isExpression }, + { name: "expression", test: isExpression } ], [SyntaxKind.FunctionExpression]: [ { name: "decorators", test: isDecorator }, @@ -156,7 +156,7 @@ namespace ts { { name: "typeParameters", test: isTypeParameter }, { name: "parameters", test: isParameter }, { name: "type", test: isTypeNode, optional: true }, - { name: "body", test: isBlock, optional: true }, + { name: "body", test: isBlock, optional: true } ], [SyntaxKind.ArrowFunction]: [ { name: "decorators", test: isDecorator }, @@ -164,44 +164,44 @@ namespace ts { { name: "typeParameters", test: isTypeParameter }, { name: "parameters", test: isParameter }, { name: "type", test: isTypeNode, optional: true }, - { name: "body", test: isConciseBody, lift: liftToBlock, parenthesize: parenthesizeConciseBody }, + { name: "body", test: isConciseBody, lift: liftToBlock, parenthesize: parenthesizeConciseBody } ], [SyntaxKind.DeleteExpression]: [ - { name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand }, + { name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand } ], [SyntaxKind.TypeOfExpression]: [ - { name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand }, + { name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand } ], [SyntaxKind.VoidExpression]: [ - { name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand }, + { name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand } ], [SyntaxKind.AwaitExpression]: [ - { name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand }, + { name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand } ], [SyntaxKind.PrefixUnaryExpression]: [ - { name: "operand", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand }, + { name: "operand", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand } ], [SyntaxKind.PostfixUnaryExpression]: [ - { name: "operand", test: isLeftHandSideExpression, parenthesize: parenthesizePostfixOperand }, + { name: "operand", test: isLeftHandSideExpression, parenthesize: parenthesizePostfixOperand } ], [SyntaxKind.BinaryExpression]: [ { name: "left", test: isExpression, parenthesize: (node: Expression, parent: BinaryExpression) => parenthesizeBinaryOperand(getOperator(parent), node, true, /*leftOperand*/ undefined) }, - { name: "right", test: isExpression, parenthesize: (node: Expression, parent: BinaryExpression) => parenthesizeBinaryOperand(getOperator(parent), node, false, parent.left) }, + { name: "right", test: isExpression, parenthesize: (node: Expression, parent: BinaryExpression) => parenthesizeBinaryOperand(getOperator(parent), node, false, parent.left) } ], [SyntaxKind.ConditionalExpression]: [ { name: "condition", test: isExpression }, { name: "whenTrue", test: isExpression }, - { name: "whenFalse", test: isExpression }, + { name: "whenFalse", test: isExpression } ], [SyntaxKind.TemplateExpression]: [ { name: "head", test: isTemplateLiteralFragment }, - { name: "templateSpans", test: isTemplateSpan }, + { name: "templateSpans", test: isTemplateSpan } ], [SyntaxKind.YieldExpression]: [ - { name: "expression", test: isExpression, optional: true }, + { name: "expression", test: isExpression, optional: true } ], [SyntaxKind.SpreadElementExpression]: [ - { name: "expression", test: isExpression, parenthesize: parenthesizeExpressionForList }, + { name: "expression", test: isExpression, parenthesize: parenthesizeExpressionForList } ], [SyntaxKind.ClassExpression]: [ { name: "decorators", test: isDecorator }, @@ -209,96 +209,96 @@ namespace ts { { name: "name", test: isIdentifier, optional: true }, { name: "typeParameters", test: isTypeParameter }, { name: "heritageClauses", test: isHeritageClause }, - { name: "members", test: isClassElement }, + { name: "members", test: isClassElement } ], [SyntaxKind.ExpressionWithTypeArguments]: [ { name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess }, - { name: "typeArguments", test: isTypeNode }, + { name: "typeArguments", test: isTypeNode } ], [SyntaxKind.AsExpression]: [ { name: "expression", test: isExpression }, - { name: "type", test: isTypeNode }, + { name: "type", test: isTypeNode } ], [SyntaxKind.TemplateSpan]: [ { name: "expression", test: isExpression }, - { name: "literal", test: isTemplateLiteralFragment }, + { name: "literal", test: isTemplateLiteralFragment } ], [SyntaxKind.Block]: [ - { name: "statements", test: isStatement }, + { name: "statements", test: isStatement } ], [SyntaxKind.VariableStatement]: [ { name: "decorators", test: isDecorator }, { name: "modifiers", test: isModifier }, - { name: "declarationList", test: isVariableDeclarationList }, + { name: "declarationList", test: isVariableDeclarationList } ], [SyntaxKind.ExpressionStatement]: [ - { name: "expression", test: isExpression, parenthesize: parenthesizeExpressionForExpressionStatement }, + { name: "expression", test: isExpression, parenthesize: parenthesizeExpressionForExpressionStatement } ], [SyntaxKind.IfStatement]: [ { name: "expression", test: isExpression }, { name: "thenStatement", test: isStatement, lift: liftToBlock }, - { name: "elseStatement", test: isStatement, lift: liftToBlock, optional: true }, + { name: "elseStatement", test: isStatement, lift: liftToBlock, optional: true } ], [SyntaxKind.DoStatement]: [ { name: "statement", test: isStatement, lift: liftToBlock }, - { name: "expression", test: isExpression }, + { name: "expression", test: isExpression } ], [SyntaxKind.WhileStatement]: [ { name: "expression", test: isExpression }, - { name: "statement", test: isStatement, lift: liftToBlock }, + { name: "statement", test: isStatement, lift: liftToBlock } ], [SyntaxKind.ForStatement]: [ { name: "initializer", test: isForInitializer, optional: true }, { name: "condition", test: isExpression, optional: true }, { name: "incrementor", test: isExpression, optional: true }, - { name: "statement", test: isStatement, lift: liftToBlock }, + { name: "statement", test: isStatement, lift: liftToBlock } ], [SyntaxKind.ForInStatement]: [ { name: "initializer", test: isForInitializer }, { name: "expression", test: isExpression }, - { name: "statement", test: isStatement, lift: liftToBlock }, + { name: "statement", test: isStatement, lift: liftToBlock } ], [SyntaxKind.ForOfStatement]: [ { name: "initializer", test: isForInitializer }, { name: "expression", test: isExpression }, - { name: "statement", test: isStatement, lift: liftToBlock }, + { name: "statement", test: isStatement, lift: liftToBlock } ], [SyntaxKind.ContinueStatement]: [ - { name: "label", test: isIdentifier, optional: true }, + { name: "label", test: isIdentifier, optional: true } ], [SyntaxKind.BreakStatement]: [ - { name: "label", test: isIdentifier, optional: true }, + { name: "label", test: isIdentifier, optional: true } ], [SyntaxKind.ReturnStatement]: [ - { name: "expression", test: isExpression, optional: true }, + { name: "expression", test: isExpression, optional: true } ], [SyntaxKind.WithStatement]: [ { name: "expression", test: isExpression }, - { name: "statement", test: isStatement, lift: liftToBlock }, + { name: "statement", test: isStatement, lift: liftToBlock } ], [SyntaxKind.SwitchStatement]: [ { name: "expression", test: isExpression }, - { name: "caseBlock", test: isCaseBlock }, + { name: "caseBlock", test: isCaseBlock } ], [SyntaxKind.LabeledStatement]: [ { name: "label", test: isIdentifier }, - { name: "statement", test: isStatement, lift: liftToBlock }, + { name: "statement", test: isStatement, lift: liftToBlock } ], [SyntaxKind.ThrowStatement]: [ - { name: "expression", test: isExpression }, + { name: "expression", test: isExpression } ], [SyntaxKind.TryStatement]: [ { name: "tryBlock", test: isBlock }, { name: "catchClause", test: isCatchClause, optional: true }, - { name: "finallyBlock", test: isBlock, optional: true }, + { name: "finallyBlock", test: isBlock, optional: true } ], [SyntaxKind.VariableDeclaration]: [ { name: "name", test: isBindingName }, { name: "type", test: isTypeNode, optional: true }, - { name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList }, + { name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList } ], [SyntaxKind.VariableDeclarationList]: [ - { name: "declarations", test: isVariableDeclaration }, + { name: "declarations", test: isVariableDeclaration } ], [SyntaxKind.FunctionDeclaration]: [ { name: "decorators", test: isDecorator }, @@ -307,7 +307,7 @@ namespace ts { { name: "typeParameters", test: isTypeParameter }, { name: "parameters", test: isParameter }, { name: "type", test: isTypeNode, optional: true }, - { name: "body", test: isBlock, optional: true }, + { name: "body", test: isBlock, optional: true } ], [SyntaxKind.ClassDeclaration]: [ { name: "decorators", test: isDecorator }, @@ -315,127 +315,127 @@ namespace ts { { name: "name", test: isIdentifier, optional: true }, { name: "typeParameters", test: isTypeParameter }, { name: "heritageClauses", test: isHeritageClause }, - { name: "members", test: isClassElement }, + { name: "members", test: isClassElement } ], [SyntaxKind.EnumDeclaration]: [ { name: "decorators", test: isDecorator }, { name: "modifiers", test: isModifier }, { name: "name", test: isIdentifier }, - { name: "members", test: isEnumMember }, + { name: "members", test: isEnumMember } ], [SyntaxKind.ModuleDeclaration]: [ { name: "decorators", test: isDecorator }, { name: "modifiers", test: isModifier }, { name: "name", test: isModuleName }, - { name: "body", test: isModuleBody }, + { name: "body", test: isModuleBody } ], [SyntaxKind.ModuleBlock]: [ - { name: "statements", test: isStatement }, + { name: "statements", test: isStatement } ], [SyntaxKind.CaseBlock]: [ - { name: "clauses", test: isCaseOrDefaultClause }, + { name: "clauses", test: isCaseOrDefaultClause } ], [SyntaxKind.ImportEqualsDeclaration]: [ { name: "decorators", test: isDecorator }, { name: "modifiers", test: isModifier }, { name: "name", test: isIdentifier }, - { name: "moduleReference", test: isModuleReference }, + { name: "moduleReference", test: isModuleReference } ], [SyntaxKind.ImportDeclaration]: [ { name: "decorators", test: isDecorator }, { name: "modifiers", test: isModifier }, { name: "importClause", test: isImportClause, optional: true }, - { name: "moduleSpecifier", test: isExpression }, + { name: "moduleSpecifier", test: isExpression } ], [SyntaxKind.ImportClause]: [ { name: "name", test: isIdentifier, optional: true }, - { name: "namedBindings", test: isNamedImportBindings, optional: true }, + { name: "namedBindings", test: isNamedImportBindings, optional: true } ], [SyntaxKind.NamespaceImport]: [ - { name: "name", test: isIdentifier }, + { name: "name", test: isIdentifier } ], [SyntaxKind.NamedImports]: [ - { name: "elements", test: isImportSpecifier }, + { name: "elements", test: isImportSpecifier } ], [SyntaxKind.ImportSpecifier]: [ { name: "propertyName", test: isIdentifier, optional: true }, - { name: "name", test: isIdentifier }, + { name: "name", test: isIdentifier } ], [SyntaxKind.ExportAssignment]: [ { name: "decorators", test: isDecorator }, { name: "modifiers", test: isModifier }, - { name: "expression", test: isExpression }, + { name: "expression", test: isExpression } ], [SyntaxKind.ExportDeclaration]: [ { name: "decorators", test: isDecorator }, { name: "modifiers", test: isModifier }, { name: "exportClause", test: isNamedExports, optional: true }, - { name: "moduleSpecifier", test: isExpression, optional: true }, + { name: "moduleSpecifier", test: isExpression, optional: true } ], [SyntaxKind.NamedExports]: [ - { name: "elements", test: isExportSpecifier }, + { name: "elements", test: isExportSpecifier } ], [SyntaxKind.ExportSpecifier]: [ { name: "propertyName", test: isIdentifier, optional: true }, - { name: "name", test: isIdentifier }, + { name: "name", test: isIdentifier } ], [SyntaxKind.ExternalModuleReference]: [ - { name: "expression", test: isExpression, optional: true }, + { name: "expression", test: isExpression, optional: true } ], [SyntaxKind.JsxElement]: [ { name: "openingElement", test: isJsxOpeningElement }, { name: "children", test: isJsxChild }, - { name: "closingElement", test: isJsxClosingElement }, + { name: "closingElement", test: isJsxClosingElement } ], [SyntaxKind.JsxSelfClosingElement]: [ { name: "tagName", test: isEntityName }, - { name: "attributes", test: isJsxAttributeLike }, + { name: "attributes", test: isJsxAttributeLike } ], [SyntaxKind.JsxOpeningElement]: [ { name: "tagName", test: isEntityName }, - { name: "attributes", test: isJsxAttributeLike }, + { name: "attributes", test: isJsxAttributeLike } ], [SyntaxKind.JsxClosingElement]: [ - { name: "tagName", test: isEntityName }, + { name: "tagName", test: isEntityName } ], [SyntaxKind.JsxAttribute]: [ { name: "name", test: isIdentifier }, - { name: "initializer", test: isStringLiteralOrJsxExpression, optional: true }, + { name: "initializer", test: isStringLiteralOrJsxExpression, optional: true } ], [SyntaxKind.JsxSpreadAttribute]: [ - { name: "expression", test: isExpression }, + { name: "expression", test: isExpression } ], [SyntaxKind.JsxExpression]: [ - { name: "expression", test: isExpression, optional: true }, + { name: "expression", test: isExpression, optional: true } ], [SyntaxKind.CaseClause]: [ { name: "expression", test: isExpression, parenthesize: parenthesizeExpressionForList }, - { name: "statements", test: isStatement }, + { name: "statements", test: isStatement } ], [SyntaxKind.DefaultClause]: [ - { name: "statements", test: isStatement }, + { name: "statements", test: isStatement } ], [SyntaxKind.HeritageClause]: [ - { name: "types", test: isExpressionWithTypeArguments }, + { name: "types", test: isExpressionWithTypeArguments } ], [SyntaxKind.CatchClause]: [ { name: "variableDeclaration", test: isVariableDeclaration }, - { name: "block", test: isBlock }, + { name: "block", test: isBlock } ], [SyntaxKind.PropertyAssignment]: [ { name: "name", test: isPropertyName }, - { name: "initializer", test: isExpression, parenthesize: parenthesizeExpressionForList }, + { name: "initializer", test: isExpression, parenthesize: parenthesizeExpressionForList } ], [SyntaxKind.ShorthandPropertyAssignment]: [ { name: "name", test: isIdentifier }, - { name: "objectAssignmentInitializer", test: isExpression, optional: true }, + { name: "objectAssignmentInitializer", test: isExpression, optional: true } ], [SyntaxKind.EnumMember]: [ { name: "name", test: isPropertyName }, - { name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList }, + { name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList } ], [SyntaxKind.SourceFile]: [ - { name: "statements", test: isStatement }, + { name: "statements", test: isStatement } ], [SyntaxKind.NotEmittedStatement]: [], [SyntaxKind.PartiallyEmittedExpression]: [