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

    APIRelates to the public API for TypeScriptBugA bug in TypeScriptHelp WantedYou can do this

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions