mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Use bundle info to store info about prologues, emit Helpers, references etc
This commit is contained in:
+51
-40
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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()))}`);
|
||||
|
||||
Reference in New Issue
Block a user