Use bundle info to store info about prologues, emit Helpers, references etc

This commit is contained in:
Sheetal Nandi
2019-01-29 10:51:22 -08:00
parent ff027d41c9
commit 0aaa880197
23 changed files with 3659 additions and 2639 deletions
+51 -40
View File
@@ -45,7 +45,7 @@ namespace ts {
const sourceMapFilePath = jsFilePath && getSourceMapFilePath(jsFilePath, options);
const declarationFilePath = (forceDtsPaths || getEmitDeclarations(options)) ? removeFileExtension(outPath) + Extension.Dts : undefined;
const declarationMapPath = declarationFilePath && getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined;
const bundleInfoPath = options.references && jsFilePath ? (removeFileExtension(jsFilePath) + infoExtension) : undefined;
const bundleInfoPath = options.composite && jsFilePath ? (removeFileExtension(jsFilePath) + infoExtension) : undefined;
return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, bundleInfoPath };
}
@@ -74,13 +74,6 @@ namespace ts {
return (options.sourceMap && !options.inlineSourceMap) ? jsFilePath + ".map" : undefined;
}
function createDefaultBundleInfo(): BundleInfo {
return {
originalOffset: -1,
totalLength: -1
};
}
// JavaScript files are always LanguageVariant.JSX, as JSX syntax is allowed in .js files also.
// So for JavaScript files, '.jsx' is only emitted if the input was '.jsx', and JsxEmit.Preserve.
// For TypeScript, the only time to emit with a '.jsx' extension, is on JSX input, and JsxEmit.Preserve
@@ -114,7 +107,7 @@ namespace ts {
const newLine = getNewLineCharacter(compilerOptions, () => host.getNewLine());
const writer = createTextWriter(newLine);
const { enter, exit } = performance.createTimer("printTime", "beforePrint", "afterPrint");
let bundleInfo: BundleInfo = createDefaultBundleInfo();
let bundleInfo: BundleInfo | undefined;
let emitSkipped = false;
let exportedModulesFromDeclarationEmit: ExportedModulesFromDeclarationEmit | undefined;
@@ -133,8 +126,13 @@ namespace ts {
};
function emitSourceFileOrBundle({ jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, bundleInfoPath }: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) {
emitJsFileOrBundle(sourceFileOrBundle, jsFilePath, sourceMapFilePath, bundleInfoPath);
emitDeclarationFileOrBundle(sourceFileOrBundle, declarationFilePath, declarationMapPath);
if (bundleInfoPath && !emitOnlyDtsFiles) bundleInfo = { js: [], dts: [] };
emitJsFileOrBundle(sourceFileOrBundle, jsFilePath, sourceMapFilePath, bundleInfo && bundleInfo.js);
emitDeclarationFileOrBundle(sourceFileOrBundle, declarationFilePath, declarationMapPath, bundleInfo && bundleInfo.dts);
// Write bundled offset information if applicable
if (!emitOnlyDtsFiles && !emitSkipped && bundleInfoPath) {
writeFile(host, emitterDiagnostics, bundleInfoPath, JSON.stringify(bundleInfo, undefined, 2), /*writeByteOrderMark*/ false);
}
if (!emitSkipped && emittedFilesList) {
if (!emitOnlyDtsFiles) {
@@ -157,7 +155,7 @@ namespace ts {
}
}
function emitJsFileOrBundle(sourceFileOrBundle: SourceFile | Bundle, jsFilePath: string | undefined, sourceMapFilePath: string | undefined, bundleInfoPath: string | undefined) {
function emitJsFileOrBundle(sourceFileOrBundle: SourceFile | Bundle, jsFilePath: string | undefined, sourceMapFilePath: string | undefined, fileBundleInfo: FileBundleInfo | undefined) {
if (emitOnlyDtsFiles || !jsFilePath) {
return;
}
@@ -193,13 +191,13 @@ namespace ts {
});
Debug.assert(transform.transformed.length === 1, "Should only see one output from the transform");
printSourceFileOrBundle(jsFilePath, sourceMapFilePath, transform.transformed[0], bundleInfoPath, printer, compilerOptions);
printSourceFileOrBundle(jsFilePath, sourceMapFilePath, transform.transformed[0], fileBundleInfo, printer, compilerOptions);
// Clean up emit nodes on parse tree
transform.dispose();
}
function emitDeclarationFileOrBundle(sourceFileOrBundle: SourceFile | Bundle, declarationFilePath: string | undefined, declarationMapPath: string | undefined) {
function emitDeclarationFileOrBundle(sourceFileOrBundle: SourceFile | Bundle, declarationFilePath: string | undefined, declarationMapPath: string | undefined, fileBundleInfo: FileBundleInfo | undefined) {
if (!(declarationFilePath && !isInJSFile(sourceFileOrBundle))) {
return;
}
@@ -243,7 +241,7 @@ namespace ts {
emitSkipped = emitSkipped || declBlocked;
if (!declBlocked || emitOnlyDtsFiles) {
Debug.assert(declarationTransform.transformed.length === 1, "Should only see one output from the decl transform");
printSourceFileOrBundle(declarationFilePath, declarationMapPath, declarationTransform.transformed[0], /* bundleInfopath*/ undefined, declarationPrinter, {
printSourceFileOrBundle(declarationFilePath, declarationMapPath, declarationTransform.transformed[0], fileBundleInfo, declarationPrinter, {
sourceMap: compilerOptions.declarationMap,
sourceRoot: compilerOptions.sourceRoot,
mapRoot: compilerOptions.mapRoot,
@@ -272,7 +270,7 @@ namespace ts {
forEachChild(node, collectLinkedAliases);
}
function printSourceFileOrBundle(jsFilePath: string, sourceMapFilePath: string | undefined, sourceFileOrBundle: SourceFile | Bundle, bundleInfoPath: string | undefined, printer: Printer, mapOptions: SourceMapOptions) {
function printSourceFileOrBundle(jsFilePath: string, sourceMapFilePath: string | undefined, sourceFileOrBundle: SourceFile | Bundle, fileBundleInfo: FileBundleInfo | undefined, printer: Printer, mapOptions: SourceMapOptions) {
const bundle = sourceFileOrBundle.kind === SyntaxKind.Bundle ? sourceFileOrBundle : undefined;
const sourceFile = sourceFileOrBundle.kind === SyntaxKind.SourceFile ? sourceFileOrBundle : undefined;
const sourceFiles = bundle ? bundle.sourceFiles : [sourceFile!];
@@ -288,7 +286,7 @@ namespace ts {
}
if (bundle) {
printer.writeBundle(bundle, bundleInfo, writer, sourceMapGenerator);
printer.writeBundle(bundle, fileBundleInfo, writer, sourceMapGenerator);
}
else {
printer.writeFile(sourceFile!, writer, sourceMapGenerator);
@@ -327,16 +325,8 @@ namespace ts {
// Write the output file
writeFile(host, emitterDiagnostics, jsFilePath, writer.getText(), !!compilerOptions.emitBOM, sourceFiles);
// Write bundled offset information if applicable
if (bundleInfoPath) {
bundleInfo.totalLength = writer.getTextPos();
writeFile(host, emitterDiagnostics, bundleInfoPath, JSON.stringify(bundleInfo, undefined, 2), /*writeByteOrderMark*/ false);
}
// Reset state
writer.clear();
bundleInfo = createDefaultBundleInfo();
}
interface SourceMapOptions {
@@ -449,6 +439,7 @@ namespace ts {
let ownWriter: EmitTextWriter; // Reusable `EmitTextWriter` for basic printing.
let write = writeBase;
let isOwnFileEmit: boolean;
let fileBundleInfo: FileBundleInfo | undefined;
// Source Maps
let sourceMapsDisabled = true;
@@ -546,8 +537,13 @@ namespace ts {
writer = previousWriter;
}
function writeBundle(bundle: Bundle, bundleInfo: BundleInfo | undefined, output: EmitTextWriter, sourceMapGenerator: SourceMapGenerator | undefined) {
function getTextPosWithWriteLine() {
return writer.getTextPosWithWriteLine ? writer.getTextPosWithWriteLine() : writer.getTextPos();
}
function writeBundle(bundle: Bundle, bundleInfo: FileBundleInfo | undefined, output: EmitTextWriter, sourceMapGenerator: SourceMapGenerator | undefined) {
isOwnFileEmit = false;
fileBundleInfo = bundleInfo;
const previousWriter = writer;
setWriter(output, sourceMapGenerator);
emitShebangIfNeeded(bundle);
@@ -555,18 +551,17 @@ namespace ts {
emitHelpers(bundle);
emitSyntheticTripleSlashReferencesIfNeeded(bundle);
const pos = getTextPosWithWriteLine();
for (const prepend of bundle.prepends) {
writeLine();
print(EmitHint.Unspecified, prepend, /*sourceFile*/ undefined);
}
if (bundleInfo) {
bundleInfo.originalOffset = writer.getTextPos();
}
for (const sourceFile of bundle.sourceFiles) {
print(EmitHint.SourceFile, sourceFile, sourceFile);
}
if (fileBundleInfo) fileBundleInfo.push({ pos, end: writer.getTextPos(), kind: BundleFileSectionKind.Text });
reset();
writer = previousWriter;
}
@@ -581,6 +576,7 @@ namespace ts {
function writeFile(sourceFile: SourceFile, output: EmitTextWriter, sourceMapGenerator: SourceMapGenerator | undefined) {
isOwnFileEmit = true;
fileBundleInfo = undefined;
const previousWriter = writer;
setWriter(output, sourceMapGenerator);
emitShebangIfNeeded(sourceFile);
@@ -638,6 +634,7 @@ namespace ts {
currentSourceFile = undefined!;
currentLineMap = undefined!;
detachedCommentsInfo = undefined;
fileBundleInfo = undefined;
setWriter(/*output*/ undefined, /*_sourceMapGenerator*/ undefined);
}
@@ -1166,13 +1163,14 @@ namespace ts {
// Skip the helper if it is scoped and we are emitting bundled helpers
continue;
}
const pos = getTextPosWithWriteLine();
if (typeof helper.text === "string") {
writeLines(helper.text);
}
else {
writeLines(helper.text(makeFileLevelOptimisticUniqueName));
}
if (fileBundleInfo) fileBundleInfo.push({ pos, end: writer.getTextPos(), kind: BundleFileSectionKind.EmitHelpers, name: helper.name });
helpersEmitted = true;
}
}
@@ -2307,7 +2305,7 @@ namespace ts {
function emitBlockFunctionBodyWorker(body: Block, emitBlockFunctionBodyOnSingleLine?: boolean) {
// Emit all the prologue directives (like "use strict").
const statementOffset = emitPrologueDirectives(body.statements, /*startWithNewLine*/ true);
const statementOffset = emitPrologueDirectives(body.statements);
const pos = writer.getTextPos();
emitHelpers(body);
if (statementOffset === 0 && pos === writer.getTextPos() && emitBlockFunctionBodyOnSingleLine) {
@@ -2937,7 +2935,9 @@ namespace ts {
function emitTripleSlashDirectives(hasNoDefaultLib: boolean, files: ReadonlyArray<FileReference>, types: ReadonlyArray<FileReference>, libs: ReadonlyArray<FileReference>) {
if (hasNoDefaultLib) {
const pos = writer.getTextPos();
writeComment(`/// <reference no-default-lib="true"/>`);
if (fileBundleInfo) fileBundleInfo.push({ pos, end: writer.getTextPos(), kind: BundleFileSectionKind.NoDefaultLib });
writeLine();
}
if (currentSourceFile && currentSourceFile.moduleName) {
@@ -2956,15 +2956,21 @@ namespace ts {
}
}
for (const directive of files) {
const pos = writer.getTextPos();
writeComment(`/// <reference path="${directive.fileName}" />`);
if (fileBundleInfo) fileBundleInfo.push({ pos, end: writer.getTextPos(), kind: BundleFileSectionKind.Reference, fileName: directive.fileName });
writeLine();
}
for (const directive of types) {
const pos = writer.getTextPos();
writeComment(`/// <reference types="${directive.fileName}" />`);
if (fileBundleInfo) fileBundleInfo.push({ pos, end: writer.getTextPos(), kind: BundleFileSectionKind.Type, fileName: directive.fileName });
writeLine();
}
for (const directive of libs) {
const pos = writer.getTextPos();
writeComment(`/// <reference lib="${directive.fileName}" />`);
if (fileBundleInfo) fileBundleInfo.push({ pos, end: writer.getTextPos(), kind: BundleFileSectionKind.Lib, fileName: directive.fileName });
writeLine();
}
}
@@ -2994,16 +3000,21 @@ namespace ts {
* Emits any prologue directives at the start of a Statement list, returning the
* number of prologue directives written to the output.
*/
function emitPrologueDirectives(statements: ReadonlyArray<Node>, startWithNewLine?: boolean, seenPrologueDirectives?: Map<true>): number {
function emitPrologueDirectives(statements: ReadonlyArray<Node>, sourceFile?: SourceFile, seenPrologueDirectives?: Map<true>): number {
let needsToSetSourceFile = !!sourceFile;
for (let i = 0; i < statements.length; i++) {
const statement = statements[i];
if (isPrologueDirective(statement)) {
const shouldEmitPrologueDirective = seenPrologueDirectives ? !seenPrologueDirectives.has(statement.expression.text) : true;
if (shouldEmitPrologueDirective) {
if (startWithNewLine || i > 0) {
writeLine();
if (needsToSetSourceFile) {
needsToSetSourceFile = false;
setSourceFile(sourceFile!);
}
writeLine();
const pos = writer.getTextPos();
emit(statement);
if (fileBundleInfo) fileBundleInfo.push({ pos, end: writer.getTextPos(), kind: BundleFileSectionKind.Prologue, text: statement.expression.text });
if (seenPrologueDirectives) {
seenPrologueDirectives.set(statement.expression.text, true);
}
@@ -3021,7 +3032,10 @@ namespace ts {
function emitUnparsedPrologues(prologues: ReadonlyArray<UnparsedPrologue>, seenPrologueDirectives: Map<true>) {
for (const prologue of prologues) {
if (!seenPrologueDirectives.has(prologue.text)) {
writeLine();
const pos = writer.getTextPos();
emit(prologue);
if (fileBundleInfo) fileBundleInfo.push({ pos, end: writer.getTextPos(), kind: BundleFileSectionKind.Prologue, text: prologue.text });
if (seenPrologueDirectives) {
seenPrologueDirectives.set(prologue.text, true);
}
@@ -3031,8 +3045,7 @@ namespace ts {
function emitPrologueDirectivesIfNeeded(sourceFileOrBundle: Bundle | SourceFile) {
if (isSourceFile(sourceFileOrBundle)) {
setSourceFile(sourceFileOrBundle);
emitPrologueDirectives(sourceFileOrBundle.statements);
emitPrologueDirectives(sourceFileOrBundle.statements, sourceFileOrBundle);
}
else {
const seenPrologueDirectives = createMap<true>();
@@ -3040,8 +3053,7 @@ namespace ts {
emitUnparsedPrologues((prepend as UnparsedSource).prologues, seenPrologueDirectives);
}
for (const sourceFile of sourceFileOrBundle.sourceFiles) {
setSourceFile(sourceFile);
emitPrologueDirectives(sourceFile.statements, /*startWithNewLine*/ true, seenPrologueDirectives);
emitPrologueDirectives(sourceFile.statements, sourceFile, seenPrologueDirectives);
}
setSourceFile(undefined);
}
@@ -3500,7 +3512,6 @@ namespace ts {
if (line.length) {
writeLine();
write(line);
writer.rawWrite(newLine);
}
}
}
+77 -101
View File
@@ -2629,69 +2629,28 @@ namespace ts {
return node;
}
interface UnscopedEmitHelpersWithLines {
helper: UnscopedEmitHelpers;
lines: ReadonlyArray<string>;
}
let allUnscopedEmitHelpers: ReadonlyArray<UnscopedEmitHelpersWithLines> | undefined;
let allUnscopedEmitHelpers: ReadonlyMap<UnscopedEmitHelpers> | undefined;
function getAllUnscopedEmitHelpers() {
return allUnscopedEmitHelpers ||
(allUnscopedEmitHelpers = [
getUnscopedEmitHelperWithLines(valuesHelper),
getUnscopedEmitHelperWithLines(readHelper),
getUnscopedEmitHelperWithLines(spreadHelper),
getUnscopedEmitHelperWithLines(restHelper),
getUnscopedEmitHelperWithLines(decorateHelper),
getUnscopedEmitHelperWithLines(metadataHelper),
getUnscopedEmitHelperWithLines(paramHelper),
getUnscopedEmitHelperWithLines(awaiterHelper),
getUnscopedEmitHelperWithLines(assignHelper),
getUnscopedEmitHelperWithLines(awaitHelper),
getUnscopedEmitHelperWithLines(asyncGeneratorHelper),
getUnscopedEmitHelperWithLines(asyncDelegator),
getUnscopedEmitHelperWithLines(asyncValues),
getUnscopedEmitHelperWithLines(extendsHelper),
getUnscopedEmitHelperWithLines(templateObjectHelper),
getUnscopedEmitHelperWithLines(generatorHelper),
getUnscopedEmitHelperWithLines(importStarHelper),
getUnscopedEmitHelperWithLines(importDefaultHelper)
]);
}
function getUnscopedEmitHelperWithLines(helper: UnscopedEmitHelpers): UnscopedEmitHelpersWithLines {
const helperLines = helper.text.split(/\r\n?|\n/g);
const indentation = guessIndentation(helperLines);
const lines: string[] = [];
for (const lineText of helperLines) {
const line = indentation ? lineText.slice(indentation) : lineText;
if (line.length) {
lines.push(line);
}
}
return { helper, lines };
}
function tryGetUnscopedEmitHelper(text: string, pos: number) {
const allHelpers = getAllUnscopedEmitHelpers();
if (pos >= text.length) return undefined;
for (const { helper, lines } of allHelpers) {
let newPos = pos;
for (const line of lines) {
const startIndex = text.indexOf(line, newPos);
if (startIndex !== newPos) {
newPos = -1;
break;
}
newPos = skipTrivia(text, newPos + line.length, /*stopAfterLineBreak*/ true);
}
// Found match
if (newPos !== -1) {
return { helper, newPos };
}
}
return undefined;
return allUnscopedEmitHelpers || (allUnscopedEmitHelpers = arrayToMap([
valuesHelper,
readHelper,
spreadHelper,
restHelper,
decorateHelper,
metadataHelper,
paramHelper,
awaiterHelper,
assignHelper,
awaitHelper,
asyncGeneratorHelper,
asyncDelegator,
asyncValues,
extendsHelper,
templateObjectHelper,
generatorHelper,
importStarHelper,
importDefaultHelper
], helper => helper.name));
}
export function createUnparsedSourceFile(text: string): UnparsedSource;
@@ -2699,6 +2658,12 @@ namespace ts {
export function createUnparsedSourceFile(text: string, mapPath: string | undefined, map: string | undefined): UnparsedSource;
export function createUnparsedSourceFile(textOrInputFiles: string | InputFiles, mapPathOrType?: string, map?: string): UnparsedSource {
const node = <UnparsedSource>createNode(SyntaxKind.UnparsedSource);
node.pos = 0;
let prologues: UnparsedPrologue[] | undefined;
let helpers: UnscopedEmitHelpers[] | undefined;
let referencedFiles: FileReference[] | undefined;
let typeReferenceDirectives: string[] | undefined;
let libReferenceDirectives: FileReference[] | undefined;
if (!isString(textOrInputFiles)) {
Debug.assert(mapPathOrType === "js" || mapPathOrType === "dts");
node.fileName = (mapPathOrType === "js" ? textOrInputFiles.javascriptPath : textOrInputFiles.declarationPath) || "";
@@ -2707,6 +2672,41 @@ namespace ts {
text: { get() { return mapPathOrType === "js" ? textOrInputFiles.javascriptText : textOrInputFiles.declarationText; } },
sourceMapText: { get() { return mapPathOrType === "js" ? textOrInputFiles.javascriptMapText : textOrInputFiles.declarationMapText; } },
});
const sections = textOrInputFiles.bundleInfo ? mapPathOrType === "js" ? textOrInputFiles.bundleInfo.js : textOrInputFiles.bundleInfo.dts : undefined;
if (sections) {
for (const section of sections) {
switch (section.kind) {
case BundleFileSectionKind.Prologue:
const unparsedPrologue = <UnparsedPrologue>createNode(SyntaxKind.UnparsedPrologue, section.pos, section.end);
unparsedPrologue.parent = node;
unparsedPrologue.text = section.text;
(prologues || (prologues = [])).push(unparsedPrologue);
break;
case BundleFileSectionKind.EmitHelpers:
(helpers || (helpers = [])).push(getAllUnscopedEmitHelpers().get(section.name)!);
break;
case BundleFileSectionKind.NoDefaultLib:
node.hasNoDefaultLib = true;
break;
case BundleFileSectionKind.Reference:
(referencedFiles || (referencedFiles = [])).push({ pos: -1, end: -1, fileName: section.fileName });
break;
case BundleFileSectionKind.Type:
(typeReferenceDirectives || (typeReferenceDirectives = [])).push(section.fileName);
break;
case BundleFileSectionKind.Lib:
(libReferenceDirectives || (libReferenceDirectives = [])).push({ pos: -1, end: -1, fileName: section.fileName });
break;
case BundleFileSectionKind.Text:
// For now just set node.pos to this
node.pos = section.pos;
break;
default:
Debug.assertNever(section);
}
}
}
}
else {
node.fileName = "";
@@ -2714,47 +2714,16 @@ namespace ts {
node.sourceMapPath = mapPathOrType;
node.sourceMapText = map;
}
const text = node.text;
node.languageVersion = ScriptTarget.Latest;
// Shebang
let pos = isShebangTrivia(text, 0) ? skipTrivia(text, 0, /*stopAfterLineBreak*/ true) : 0;
// Prologue
const scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true, /*languageVariant*/ undefined, text, /*onError*/ undefined, pos);
let prologues: UnparsedPrologue[] | undefined;
while (scanner.scan() === SyntaxKind.StringLiteral) {
const start = pos;
const prologueText = scanner.getTokenValue();
scanner.tryScan(() => scanner.scan() === SyntaxKind.SemicolonToken);
pos = skipTrivia(text, scanner.getTextPos(), /*stopAfterLineBreak*/ true);
const prologue = <UnparsedPrologue>createNode(SyntaxKind.UnparsedPrologue, start, pos);
prologue.parent = node;
prologue.text = prologueText;
(prologues || (prologues = [])).push(prologue);
}
// Helpers
let helpers: UnscopedEmitHelpers[] | undefined;
while (true) {
const helperInfo = tryGetUnscopedEmitHelper(text, pos);
if (!helperInfo) break;
pos = helperInfo.newPos;
(helpers || (helpers = [])).push(helperInfo.helper);
}
// triple slash directives
const newPos = processCommentPragmas(node as {} as PragmaContext, text);
processPragmasIntoFields(node as {} as PragmaContext, noop);
// Rest of the text
node.pos = newPos > pos ? newPos : pos;
node.prologues = prologues || emptyArray;
node.helpers = helpers;
node.referencedFiles = referencedFiles || emptyArray;
node.typeReferenceDirectives = typeReferenceDirectives;
node.libReferenceDirectives = libReferenceDirectives || emptyArray;
node.getLineAndCharacterOfPosition = pos => getLineAndCharacterOfPosition(node, pos);
return node;
}
export function createInputFiles(
javascriptText: string,
declarationText: string
@@ -2765,6 +2734,7 @@ namespace ts {
javascriptMapPath: string | undefined,
declarationPath: string,
declarationMapPath: string | undefined,
bundleInfoPath: string | undefined
): InputFiles;
export function createInputFiles(
javascriptText: string,
@@ -2780,7 +2750,7 @@ namespace ts {
javascriptMapPath?: string,
javascriptMapTextOrDeclarationPath?: string,
declarationMapPath?: string,
declarationMapText?: string
declarationMapTextOrBundleInfoPath?: string
): InputFiles {
const node = <InputFiles>createNode(SyntaxKind.InputFiles);
if (!isString(javascriptTextOrReadFileText)) {
@@ -2798,15 +2768,21 @@ namespace ts {
const result = textGetter(path);
return result !== undefined ? result : `/* Input file ${path} was missing */\r\n`;
};
const jsonGetter = (path: string | undefined) => {
const result = textGetter(path);
return result !== undefined ? JSON.parse(result) as BundleInfo : undefined;
};
node.javascriptPath = declarationTextOrJavascriptPath;
node.javascriptMapPath = javascriptMapPath;
node.declarationPath = Debug.assertDefined(javascriptMapTextOrDeclarationPath);
node.declarationMapPath = declarationMapPath;
node.bundleInfoPath = declarationMapTextOrBundleInfoPath;
Object.defineProperties(node, {
javascriptText: { get() { return definedTextGetter(declarationTextOrJavascriptPath); } },
javascriptMapText: { get() { return textGetter(javascriptMapPath); } }, // TODO:: if there is inline sourceMap in jsFile, use that
declarationText: { get() { return definedTextGetter(Debug.assertDefined(javascriptMapTextOrDeclarationPath)); } },
declarationMapText: { get() { return textGetter(declarationMapPath); } } // TODO:: if there is inline sourceMap in dtsFile, use that
declarationMapText: { get() { return textGetter(declarationMapPath); } }, // TODO:: if there is inline sourceMap in dtsFile, use that
bundleInfo: { get() { return jsonGetter(declarationMapTextOrBundleInfoPath); } }
});
}
else {
@@ -2815,7 +2791,7 @@ namespace ts {
node.javascriptMapText = javascriptMapTextOrDeclarationPath;
node.declarationText = declarationTextOrJavascriptPath;
node.declarationMapPath = declarationMapPath;
node.declarationMapText = declarationMapText;
node.declarationMapText = declarationMapTextOrBundleInfoPath;
}
return node;
}
+1 -2
View File
@@ -7721,7 +7721,7 @@ namespace ts {
}
/*@internal*/
export function processCommentPragmas(context: PragmaContext, sourceText: string) {
export function processCommentPragmas(context: PragmaContext, sourceText: string): void {
const triviaScanner = createScanner(context.languageVersion, /*skipTrivia*/ false, LanguageVariant.Standard, sourceText);
const pragmas: PragmaPseudoMapEntry[] = [];
@@ -7758,7 +7758,6 @@ namespace ts {
}
context.pragmas.set(pragma!.name, pragma!.args);
}
return triviaScanner.getStartPos();
}
type PragmaDiagnosticReporter = (pos: number, length: number, message: DiagnosticMessage) => void;
+2 -2
View File
@@ -1456,12 +1456,12 @@ namespace ts {
// Upstream project didn't have outFile set -- skip (error will have been issued earlier)
if (!out) continue;
const { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath } = getOutputPathsForBundle(resolvedRefOpts.options, /*forceDtsPaths*/ true);
const { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, bundleInfoPath } = getOutputPathsForBundle(resolvedRefOpts.options, /*forceDtsPaths*/ true);
const node = createInputFiles(fileName => {
const path = toPath(fileName);
const sourceFile = getSourceFileByPath(path);
return sourceFile ? sourceFile.text : filesByName.has(path) ? undefined : host.readFile(path);
}, jsFilePath! , sourceMapFilePath, declarationFilePath! , declarationMapPath);
}, jsFilePath! , sourceMapFilePath, declarationFilePath! , declarationMapPath, bundleInfoPath);
nodes.push(node);
}
}
+2 -1
View File
@@ -61,7 +61,7 @@ namespace ts {
const { noResolve, stripInternal } = options;
return transformRoot;
function recordTypeReferenceDirectivesIfNecessary(typeReferenceDirectives: string[] | undefined): void {
function recordTypeReferenceDirectivesIfNecessary(typeReferenceDirectives: ReadonlyArray<string> | undefined): void {
if (!typeReferenceDirectives) {
return;
}
@@ -210,6 +210,7 @@ namespace ts {
const sourceFile = createUnparsedSourceFile(prepend, "dts");
hasNoDefaultLib = hasNoDefaultLib || !!sourceFile.hasNoDefaultLib;
collectReferences(sourceFile, refs);
recordTypeReferenceDirectivesIfNecessary(sourceFile.typeReferenceDirectives);
collectLibs(sourceFile, libs);
return sourceFile;
}
+60 -17
View File
@@ -2770,18 +2770,19 @@ namespace ts {
declarationText: string;
declarationMapPath?: string;
declarationMapText?: string;
bundleInfoPath?: string;
/*@internal*/ bundleInfo?: BundleInfo;
}
export interface UnparsedSource extends Node {
kind: SyntaxKind.UnparsedSource;
fileName: string;
text: string;
languageVersion: ScriptTarget;
prologues: ReadonlyArray<UnparsedPrologue>;
helpers: ReadonlyArray<UnscopedEmitHelpers> | undefined;
referencedFiles: FileReference[];
typeReferenceDirectives: FileReference[];
libReferenceDirectives: FileReference[];
referencedFiles: ReadonlyArray<FileReference>;
typeReferenceDirectives: ReadonlyArray<string> | undefined;
libReferenceDirectives: ReadonlyArray<FileReference>;
hasNoDefaultLib?: boolean;
sourceMapPath?: string;
sourceMapText?: string;
@@ -5425,23 +5426,64 @@ namespace ts {
/*@internal*/ writeNode(hint: EmitHint, node: Node, sourceFile: SourceFile | undefined, writer: EmitTextWriter): void;
/*@internal*/ writeList<T extends Node>(format: ListFormat, list: NodeArray<T> | undefined, sourceFile: SourceFile | undefined, writer: EmitTextWriter): void;
/*@internal*/ writeFile(sourceFile: SourceFile, writer: EmitTextWriter, sourceMapGenerator: SourceMapGenerator | undefined): void;
/*@internal*/ writeBundle(bundle: Bundle, info: BundleInfo | undefined, writer: EmitTextWriter, sourceMapGenerator: SourceMapGenerator | undefined): void;
/*@internal*/ writeBundle(bundle: Bundle, info: FileBundleInfo | undefined, writer: EmitTextWriter, sourceMapGenerator: SourceMapGenerator | undefined): void;
}
/**
* When a bundle contains prepended content, we store a file on disk indicating where the non-prepended
* content of that file starts. On a subsequent build where there are no upstream .d.ts changes, we
* read the bundle info file and the original .js file to quickly re-use portion of the file
* that didn't originate in prepended content.
*/
/*@internal*/
export const enum BundleFileSectionKind {
Prologue = "prologue",
EmitHelpers = "emitHelpers",
NoDefaultLib = "no-default-lib",
Reference = "reference",
Type = "type",
Lib = "lib",
Text = "text",
// internal comments?
}
/*@internal*/
export interface BundleFileSectionBase extends TextRange {
kind: BundleFileSectionKind;
}
/*@internal*/
export interface BundleFilePrologue extends BundleFileSectionBase {
kind: BundleFileSectionKind.Prologue;
text: string;
}
/*@internal*/
export interface BundleFileEmitHelpers extends BundleFileSectionBase {
kind: BundleFileSectionKind.EmitHelpers;
name: string;
}
/*@internal*/
export interface BundleFileHasNoDefaultLib extends BundleFileSectionBase {
kind: BundleFileSectionKind.NoDefaultLib;
}
/*@internal*/
export interface BundleFileReference extends BundleFileSectionBase {
kind: BundleFileSectionKind.Reference | BundleFileSectionKind.Type | BundleFileSectionKind.Lib;
fileName: string;
}
/*@internal*/
export interface BundleFileText extends BundleFileSectionBase {
kind: BundleFileSectionKind.Text;
}
/*@internal*/
export type BundleFileSection = BundleFilePrologue | BundleFileEmitHelpers |
BundleFileHasNoDefaultLib | BundleFileReference | BundleFileText;
/*@internal*/
export type FileBundleInfo = BundleFileSection[];
/* @internal */
export interface BundleInfo {
// The offset (in characters, i.e. suitable for .substr) at which the
// non-prepended portion of the emitted file starts.
originalOffset: number;
// The total length of this bundle. Used to ensure we're pulling from
// the same source as we originally wrote.
totalLength: number;
js?: FileBundleInfo;
dts?: FileBundleInfo;
}
export interface PrintHandlers {
@@ -5597,6 +5639,7 @@ namespace ts {
getColumn(): number;
getIndent(): number;
isAtStartOfLine(): boolean;
getTextPosWithWriteLine?(): number;
}
export interface GetEffectiveTypeRootsHost {
+6 -1
View File
@@ -3200,6 +3200,10 @@ namespace ts {
}
}
function getTextPosWithWriteLine() {
return lineStart ? output.length : (output.length + newLine.length);
}
reset();
return {
@@ -3229,7 +3233,8 @@ namespace ts {
writeStringLiteral: write,
writeSymbol: (s, _) => write(s),
writeTrailingSemicolon: write,
writeComment: write
writeComment: write,
getTextPosWithWriteLine
};
}
+3 -2
View File
@@ -527,16 +527,17 @@ export const b = new A();`);
// Additional source Files
...(additionalSourceFiles || emptyArray),
// outputs
"/src/first/bin/first-output.js",
"/src/first/bin/first-output.js.map",
"/src/first/bin/first-output.d.ts",
"/src/first/bin/first-output.d.ts.map",
"/src/first/bin/first-output.tsbundleinfo",
"/src/2/second-output.js",
"/src/2/second-output.js.map",
"/src/2/second-output.d.ts",
"/src/2/second-output.d.ts.map"
"/src/2/second-output.d.ts.map",
"/src/2/second-output.tsbundleinfo",
];
assert.equal(actualReadFileMap.size, expected.length, `Expected: ${JSON.stringify(expected)} \nActual: ${JSON.stringify(arrayFrom(actualReadFileMap.entries()))}`);