Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

After Transformer called with a Bundle, not a Source file #24459

Closed
LucasSloan opened this issue May 29, 2018 · 4 comments
Closed

After Transformer called with a Bundle, not a Source file #24459

LucasSloan opened this issue May 29, 2018 · 4 comments
Labels
API Relates to the public API for TypeScript Bug A bug in TypeScript Help Wanted You can do this
Milestone

Comments

@LucasSloan
Copy link

TypeScript Version: 2.9.0-rc

Search Terms: bundle transformer

Code

import * as ts from 'typescript';
import * as path from 'path';

const {cachedLibPath, cachedLib} = (() => {
  const host = ts.createCompilerHost({});
  const fn = host.getDefaultLibFileName({});
  const p = ts.getDefaultLibFilePath({});
  return {
    // Normalize path to fix mixed/wrong directory separators on Windows.
    cachedLibPath: path.normalize(p),
    cachedLib: host.getSourceFile(fn, ts.ScriptTarget.Latest),
  };
})();

const reproTransformer: (context: ts.TransformationContext) => ts.Transformer<ts.SourceFile> =
  (context: ts.TransformationContext): ts.Transformer<ts.SourceFile> => {
    return (sf: ts.SourceFile): ts.SourceFile => {
      console.error(ts.SyntaxKind[sf.kind]);
      return sf;
    }
  }

function createSourceCachingHost(
  sources: Map<string, string>, options: ts.CompilerOptions): ts.CompilerHost {
const host = ts.createCompilerHost({});

host.getSourceFile = (fileName: string, languageVersion: ts.ScriptTarget,
                      onError?: (msg: string) => void): ts.SourceFile|undefined => {
  // Normalize path to fix wrong directory separators on Windows which
  // would break the equality check.
  fileName = path.normalize(fileName);
  if (fileName === cachedLibPath) return cachedLib;
  if (path.isAbsolute(fileName)) fileName = path.relative(process.cwd(), fileName);
  const contents = sources.get(fileName);
  if (contents !== undefined) {
    return ts.createSourceFile(fileName, contents, ts.ScriptTarget.Latest, true);
  }
  throw new Error(
      'unexpected file read of ' + fileName + ' not in ' + Array.from(sources.keys()));
};
const originalFileExists = host.fileExists;
host.fileExists = (fileName: string): boolean => {
  if (path.isAbsolute(fileName)) fileName = path.relative(process.cwd(), fileName);
  if (sources.has(fileName)) {
    return true;
  }
  // Typescript occasionally needs to look on disk for files we don't pass into
  // the program as a source (eg to resolve a module that's in node_modules),
  // but only .ts files explicitly passed in should be findable
  if (/\.ts$/.test(fileName)) {
    return false;
  }
  return originalFileExists.call(host, fileName);
};

return host;
}


function emit(sources: Map<string, string>, options: ts.CompilerOptions) {
  const fileNames = Array.from(sources.keys());
  const tsHost = createSourceCachingHost(sources, options);
  const program = ts.createProgram(fileNames, options, tsHost);

  const tsTransformers: ts.CustomTransformers = {
    after: [reproTransformer],
  }

  program.emit(undefined, undefined, undefined, undefined, tsTransformers);
}

const one_source_file = new Map([['a.ts', 'const x = 1']]);
const two_source_files = new Map([['a.ts', 'const x = 1'], ['b.ts', 'const y = ""']]);

emit(one_source_file, {});
emit(two_source_files, {outFile: 'c.js'});

Expected behavior:
reproTransformer is a scheduled as an after transformer, and the type for ts.CustomTransformers says that it will only ever be called with a SourceFile, so the two emit calls should print out:
SourceFile
SourceFile
SourceFile
Actual behavior:
SourceFile
Bundle

I tested without the outFile flag, and I got the expected behavior, so the issue is to do with the outfile.

@mhegazy
Copy link
Contributor

mhegazy commented Jul 16, 2018

This seems right to me. with --outFile sourceFiles are "bundled" into a new node. a transformer can perform some transformations on the new file generated by the bundle if it needs to.

@mhegazy mhegazy added the Working as Intended The behavior described is the intended behavior; this is not a bug label Jul 16, 2018
@LucasSloan
Copy link
Author

Right, my problem is not that the transformer was fed a Bundle, it's that the type of an after transformer doesn't allow for the transformer to be called with a Bundle.

@mhegazy mhegazy added Bug A bug in TypeScript Help Wanted You can do this API Relates to the public API for TypeScript and removed Working as Intended The behavior described is the intended behavior; this is not a bug labels Jul 17, 2018
@mhegazy
Copy link
Contributor

mhegazy commented Jul 17, 2018

ah. sorry about that. we would be happy to take a PR to fix the declarations.

@jakebailey
Copy link
Member

#31301 was supposed to close this, but the "Fixes" line was incorrectly written so GitHub didn't do it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API Relates to the public API for TypeScript Bug A bug in TypeScript Help Wanted You can do this
Projects
None yet
Development

No branches or pull requests

4 participants