From 57546393ff0a3d1e643870bf835119f37d07bdb3 Mon Sep 17 00:00:00 2001 From: ispedals Date: Sun, 28 Oct 2018 12:38:16 -0400 Subject: [PATCH] Support synthesized SourceFile parent in getOrCreateEmitNode (#24709) getOrCreateEmitNode() assumes that the SourceFile of node that is part of a parse tree will also be a parse tree node. This assumption is not valid for a transformed SourceFile. disposeEmitNodes() already handles this case by getting the original SourceFile node if the provided node is synthesized, so do the same in getOrCreateEmitNode(). This results in the test case in #24709 to run without error. --- src/compiler/factory.ts | 2 +- src/testRunner/unittests/transform.ts | 40 +++++++++++++++++++ .../transformsCorrectly.issue24709.js | 6 +++ 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/transformApi/transformsCorrectly.issue24709.js diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 01de5850471..a5e38943072 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -2819,7 +2819,7 @@ namespace ts { return node.emitNode = { annotatedNodes: [node] } as EmitNode; } - const sourceFile = getSourceFileOfNode(node); + const sourceFile = getSourceFileOfNode(getParseTreeNode(getSourceFileOfNode(node))); getOrCreateEmitNode(sourceFile).annotatedNodes!.push(node); } diff --git a/src/testRunner/unittests/transform.ts b/src/testRunner/unittests/transform.ts index f219fb6c683..2fc4d117e99 100644 --- a/src/testRunner/unittests/transform.ts +++ b/src/testRunner/unittests/transform.ts @@ -400,6 +400,46 @@ namespace Foo { } }).outputText; }); + + // https://github.com/Microsoft/TypeScript/issues/24709 + testBaseline("issue24709", () => { + const fs = vfs.createFromFileSystem(Harness.IO, /*caseSensitive*/ true); + const transformed = transform(createSourceFile("source.ts", "class X { echo(x: string) { return x; } }", ScriptTarget.ES3), [transformSourceFile]); + const transformedSourceFile = transformed.transformed[0]; + transformed.dispose(); + const host = new fakes.CompilerHost(fs); + host.getSourceFile = () => transformedSourceFile; + const program = createProgram(["source.ts"], { + target: ScriptTarget.ES3, + module: ModuleKind.None, + noLib: true + }, host); + program.emit(transformedSourceFile, (_p, s, b) => host.writeFile("source.js", s, b)); + return host.readFile("source.js")!.toString(); + + function transformSourceFile(context: TransformationContext) { + const visitor: Visitor = (node) => { + if (isMethodDeclaration(node)) { + return updateMethod( + node, + node.decorators, + node.modifiers, + node.asteriskToken, + createIdentifier("foobar"), + node.questionToken, + node.typeParameters, + node.parameters, + node.type, + node.body, + ); + } + return visitEachChild(node, visitor, context); + }; + return (node: SourceFile) => visitNode(node, visitor); + } + + }); + }); } diff --git a/tests/baselines/reference/transformApi/transformsCorrectly.issue24709.js b/tests/baselines/reference/transformApi/transformsCorrectly.issue24709.js new file mode 100644 index 00000000000..9d1d48ca96d --- /dev/null +++ b/tests/baselines/reference/transformApi/transformsCorrectly.issue24709.js @@ -0,0 +1,6 @@ +var X = /** @class */ (function () { + function X() { + } + X.prototype.foobar = function (x) { return x; }; + return X; +}());