Skip to content

Transform API: TypeError in getOrCreateEmitNode #24709

@agentcooper

Description

@agentcooper

TypeScript Version: 3.0.0-dev.20180605

Same in 2.9.1 and earlier.

Search Terms: getOrCreateEmitNode, annotatedNodes

Code

Quick summary: we create TS file, apply a transform which changes a method name, and compile the final AST.

import * as ts from "typescript";
import { readFileSync } from "fs";
import { join } from "path";

const options: ts.CompilerOptions = {
  target: ts.ScriptTarget.ES3,
  module: ts.ModuleKind.None,
  noLib: true,
};

const sourceFile = transform(
  ts.createSourceFile(
    "input.ts",
    "class X { hello(userName: string) { return `Hello, ${userName}!`; } }",
    ts.ScriptTarget.ES2017,
    true,
    ts.ScriptKind.TS,
  ),
);

// console.log(ts.createPrinter().printFile(sourceFile));

const host: ts.CompilerHost = {
  getSourceFile(
    fileName: string,
    languageVersion: ts.ScriptTarget,
  ): ts.SourceFile {
    if (fileName === sourceFile.fileName) {
      return sourceFile;
    }

    throw new Error(`File not found: ${fileName}`);
  },
  getDefaultLibFileName: () => "lib.d.ts",
  writeFile: (_fileName, _content) => {
    throw new Error("Unsupported!");
  },
  getCurrentDirectory: () => ts.sys.getCurrentDirectory(),
  getCanonicalFileName: fileName =>
    ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(),
  getNewLine: () => ts.sys.newLine,
  useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,
  fileExists: (fileName: string) => fileName === sourceFile.fileName,
  readFile(fileName: string): string {
    if (fileName === sourceFile.fileName) {
      return sourceFile.getText();
    }
    return "";
  },
  resolveModuleNames(
    _moduleNames: string[],
    _containingFile: string,
  ): ts.ResolvedModule[] {
    throw new Error("Unsupported!");
  },
  getDirectories(_path: string): string[] {
    throw new Error("Unsupported!");
  },
};

const program = ts.createProgram(["input.ts"], options, host);

function transformSourceFile(
  context: ts.TransformationContext,
): ts.Transformer<ts.SourceFile> {
  return (sourceFile: ts.SourceFile) => {
    function visit(node: ts.Node) {
      if (ts.isMethodDeclaration(node)) {
        return ts.updateMethod(
          node,
          node.decorators,
          node.modifiers,
          node.asteriskToken,
          ts.createIdentifier("foobar"),
          node.questionToken,
          node.typeParameters,
          node.parameters,
          node.type,
          node.body,
        );
      }

      return ts.visitEachChild(node, visit, context);
    }

    return ts.visitEachChild(sourceFile, visit, context);
  };
}

function transform(source: ts.SourceFile): ts.SourceFile {
  const result = ts.transform(source, [transformSourceFile]);
  const transformedSource = result.transformed[0];
  result.dispose();
  return transformedSource;
}

program.emit(sourceFile, (fileName, source) => {
  console.log(source);
});

Expected behavior:

No exceptions.

Actual behavior:

/Users/test/transform-test/node_modules/typescript/lib/typescript.js:55251
                getOrCreateEmitNode(sourceFile).annotatedNodes.push(node);
                                                              ^
TypeError: Cannot read property 'push' of undefined
    at getOrCreateEmitNode (/Users/test/transform-test/node_modules/typescript/lib/typescript.js:55251:63)
    at Object.setEmitFlags (/Users/test/transform-test/node_modules/typescript/lib/typescript.js:55270:9)
    at visitParameter (/Users/test/transform-test/node_modules/typescript/lib/typescript.js:60754:16)
    at visitTypeScript (/Users/test/transform-test/node_modules/typescript/lib/typescript.js:59155:28)
    at visitorWorker (/Users/test/transform-test/node_modules/typescript/lib/typescript.js:58892:24)
    at saveStateAndInvoke (/Users/test/transform-test/node_modules/typescript/lib/typescript.js:58836:27)
    at visitor (/Users/test/transform-test/node_modules/typescript/lib/typescript.js:58882:20)
    at visitNodes (/Users/test/transform-test/node_modules/typescript/lib/typescript.js:57074:48)
    at visitParameterList (/Users/test/transform-test/node_modules/typescript/lib/typescript.js:57122:23)
    at Object.visitEachChild (/Users/test/transform-test/node_modules/typescript/lib/typescript.js:57172:395)

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScriptDomain: APIRelates to the public API for TypeScriptHelp WantedYou can do this

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions