Skip to content

Commit 07a8400

Browse files
committed
Use bundle info to store info about prologues, emit Helpers, references etc
1 parent ff027d4 commit 07a8400

23 files changed

+3659
-2638
lines changed

src/compiler/emitter.ts

+51-39
Large diffs are not rendered by default.

src/compiler/factory.ts

+77-101
Original file line numberDiff line numberDiff line change
@@ -2629,76 +2629,41 @@ namespace ts {
26292629
return node;
26302630
}
26312631

2632-
interface UnscopedEmitHelpersWithLines {
2633-
helper: UnscopedEmitHelpers;
2634-
lines: ReadonlyArray<string>;
2635-
}
2636-
2637-
let allUnscopedEmitHelpers: ReadonlyArray<UnscopedEmitHelpersWithLines> | undefined;
2632+
let allUnscopedEmitHelpers: ReadonlyMap<UnscopedEmitHelpers> | undefined;
26382633
function getAllUnscopedEmitHelpers() {
2639-
return allUnscopedEmitHelpers ||
2640-
(allUnscopedEmitHelpers = [
2641-
getUnscopedEmitHelperWithLines(valuesHelper),
2642-
getUnscopedEmitHelperWithLines(readHelper),
2643-
getUnscopedEmitHelperWithLines(spreadHelper),
2644-
getUnscopedEmitHelperWithLines(restHelper),
2645-
getUnscopedEmitHelperWithLines(decorateHelper),
2646-
getUnscopedEmitHelperWithLines(metadataHelper),
2647-
getUnscopedEmitHelperWithLines(paramHelper),
2648-
getUnscopedEmitHelperWithLines(awaiterHelper),
2649-
getUnscopedEmitHelperWithLines(assignHelper),
2650-
getUnscopedEmitHelperWithLines(awaitHelper),
2651-
getUnscopedEmitHelperWithLines(asyncGeneratorHelper),
2652-
getUnscopedEmitHelperWithLines(asyncDelegator),
2653-
getUnscopedEmitHelperWithLines(asyncValues),
2654-
getUnscopedEmitHelperWithLines(extendsHelper),
2655-
getUnscopedEmitHelperWithLines(templateObjectHelper),
2656-
getUnscopedEmitHelperWithLines(generatorHelper),
2657-
getUnscopedEmitHelperWithLines(importStarHelper),
2658-
getUnscopedEmitHelperWithLines(importDefaultHelper)
2659-
]);
2660-
}
2661-
2662-
function getUnscopedEmitHelperWithLines(helper: UnscopedEmitHelpers): UnscopedEmitHelpersWithLines {
2663-
const helperLines = helper.text.split(/\r\n?|\n/g);
2664-
const indentation = guessIndentation(helperLines);
2665-
const lines: string[] = [];
2666-
for (const lineText of helperLines) {
2667-
const line = indentation ? lineText.slice(indentation) : lineText;
2668-
if (line.length) {
2669-
lines.push(line);
2670-
}
2671-
}
2672-
return { helper, lines };
2673-
}
2674-
2675-
function tryGetUnscopedEmitHelper(text: string, pos: number) {
2676-
const allHelpers = getAllUnscopedEmitHelpers();
2677-
if (pos >= text.length) return undefined;
2678-
for (const { helper, lines } of allHelpers) {
2679-
let newPos = pos;
2680-
for (const line of lines) {
2681-
const startIndex = text.indexOf(line, newPos);
2682-
if (startIndex !== newPos) {
2683-
newPos = -1;
2684-
break;
2685-
}
2686-
newPos = skipTrivia(text, newPos + line.length, /*stopAfterLineBreak*/ true);
2687-
}
2688-
2689-
// Found match
2690-
if (newPos !== -1) {
2691-
return { helper, newPos };
2692-
}
2693-
}
2694-
return undefined;
2634+
return allUnscopedEmitHelpers || (allUnscopedEmitHelpers = arrayToMap([
2635+
valuesHelper,
2636+
readHelper,
2637+
spreadHelper,
2638+
restHelper,
2639+
decorateHelper,
2640+
metadataHelper,
2641+
paramHelper,
2642+
awaiterHelper,
2643+
assignHelper,
2644+
awaitHelper,
2645+
asyncGeneratorHelper,
2646+
asyncDelegator,
2647+
asyncValues,
2648+
extendsHelper,
2649+
templateObjectHelper,
2650+
generatorHelper,
2651+
importStarHelper,
2652+
importDefaultHelper
2653+
], helper => helper.name));
26952654
}
26962655

26972656
export function createUnparsedSourceFile(text: string): UnparsedSource;
26982657
export function createUnparsedSourceFile(inputFile: InputFiles, type: "js" | "dts"): UnparsedSource;
26992658
export function createUnparsedSourceFile(text: string, mapPath: string | undefined, map: string | undefined): UnparsedSource;
27002659
export function createUnparsedSourceFile(textOrInputFiles: string | InputFiles, mapPathOrType?: string, map?: string): UnparsedSource {
27012660
const node = <UnparsedSource>createNode(SyntaxKind.UnparsedSource);
2661+
node.pos = 0;
2662+
let prologues: UnparsedPrologue[] | undefined;
2663+
let helpers: UnscopedEmitHelpers[] | undefined;
2664+
let referencedFiles: FileReference[] | undefined;
2665+
let typeReferenceDirectives: string[] | undefined;
2666+
let libReferenceDirectives: FileReference[] | undefined;
27022667
if (!isString(textOrInputFiles)) {
27032668
Debug.assert(mapPathOrType === "js" || mapPathOrType === "dts");
27042669
node.fileName = (mapPathOrType === "js" ? textOrInputFiles.javascriptPath : textOrInputFiles.declarationPath) || "";
@@ -2707,54 +2672,58 @@ namespace ts {
27072672
text: { get() { return mapPathOrType === "js" ? textOrInputFiles.javascriptText : textOrInputFiles.declarationText; } },
27082673
sourceMapText: { get() { return mapPathOrType === "js" ? textOrInputFiles.javascriptMapText : textOrInputFiles.declarationMapText; } },
27092674
});
2675+
2676+
const sections = textOrInputFiles.bundleInfo ? mapPathOrType === "js" ? textOrInputFiles.bundleInfo.js : textOrInputFiles.bundleInfo.dts : undefined;
2677+
if (sections) {
2678+
for (const section of sections) {
2679+
switch (section.kind) {
2680+
case BundleFileSectionKind.Prologue:
2681+
const unparsedPrologue = <UnparsedPrologue>createNode(SyntaxKind.UnparsedPrologue, section.pos, section.end);
2682+
unparsedPrologue.parent = node;
2683+
unparsedPrologue.text = section.text;
2684+
(prologues || (prologues = [])).push(unparsedPrologue);
2685+
break;
2686+
case BundleFileSectionKind.EmitHelpers:
2687+
(helpers || (helpers = [])).push(getAllUnscopedEmitHelpers().get(section.name)!);
2688+
break;
2689+
case BundleFileSectionKind.NoDefaultLib:
2690+
node.hasNoDefaultLib = true;
2691+
break;
2692+
case BundleFileSectionKind.Reference:
2693+
(referencedFiles || (referencedFiles = [])).push({ pos: -1, end: -1, fileName: section.fileName });
2694+
break;
2695+
case BundleFileSectionKind.Type:
2696+
(typeReferenceDirectives || (typeReferenceDirectives = [])).push(section.fileName);
2697+
break;
2698+
case BundleFileSectionKind.Lib:
2699+
(libReferenceDirectives || (libReferenceDirectives = [])).push({ pos: -1, end: -1, fileName: section.fileName });
2700+
break;
2701+
case BundleFileSectionKind.Text:
2702+
// For now just set node.pos to this
2703+
node.pos = section.pos;
2704+
break;
2705+
default:
2706+
Debug.assertNever(section);
2707+
}
2708+
}
2709+
}
27102710
}
27112711
else {
27122712
node.fileName = "";
27132713
node.text = textOrInputFiles;
27142714
node.sourceMapPath = mapPathOrType;
27152715
node.sourceMapText = map;
27162716
}
2717-
const text = node.text;
2718-
node.languageVersion = ScriptTarget.Latest;
2719-
2720-
// Shebang
2721-
let pos = isShebangTrivia(text, 0) ? skipTrivia(text, 0, /*stopAfterLineBreak*/ true) : 0;
2722-
2723-
// Prologue
2724-
const scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true, /*languageVariant*/ undefined, text, /*onError*/ undefined, pos);
2725-
let prologues: UnparsedPrologue[] | undefined;
2726-
while (scanner.scan() === SyntaxKind.StringLiteral) {
2727-
const start = pos;
2728-
const prologueText = scanner.getTokenValue();
2729-
scanner.tryScan(() => scanner.scan() === SyntaxKind.SemicolonToken);
2730-
pos = skipTrivia(text, scanner.getTextPos(), /*stopAfterLineBreak*/ true);
2731-
2732-
const prologue = <UnparsedPrologue>createNode(SyntaxKind.UnparsedPrologue, start, pos);
2733-
prologue.parent = node;
2734-
prologue.text = prologueText;
2735-
(prologues || (prologues = [])).push(prologue);
2736-
}
2737-
2738-
// Helpers
2739-
let helpers: UnscopedEmitHelpers[] | undefined;
2740-
while (true) {
2741-
const helperInfo = tryGetUnscopedEmitHelper(text, pos);
2742-
if (!helperInfo) break;
2743-
pos = helperInfo.newPos;
2744-
(helpers || (helpers = [])).push(helperInfo.helper);
2745-
}
2746-
2747-
// triple slash directives
2748-
const newPos = processCommentPragmas(node as {} as PragmaContext, text);
2749-
processPragmasIntoFields(node as {} as PragmaContext, noop);
2750-
2751-
// Rest of the text
2752-
node.pos = newPos > pos ? newPos : pos;
27532717
node.prologues = prologues || emptyArray;
27542718
node.helpers = helpers;
2719+
node.referencedFiles = referencedFiles || emptyArray;
2720+
node.typeReferenceDirectives = typeReferenceDirectives;
2721+
node.libReferenceDirectives = libReferenceDirectives || emptyArray;
2722+
27552723
node.getLineAndCharacterOfPosition = pos => getLineAndCharacterOfPosition(node, pos);
27562724
return node;
27572725
}
2726+
27582727
export function createInputFiles(
27592728
javascriptText: string,
27602729
declarationText: string
@@ -2765,6 +2734,7 @@ namespace ts {
27652734
javascriptMapPath: string | undefined,
27662735
declarationPath: string,
27672736
declarationMapPath: string | undefined,
2737+
bundleInfoPath: string | undefined
27682738
): InputFiles;
27692739
export function createInputFiles(
27702740
javascriptText: string,
@@ -2780,7 +2750,7 @@ namespace ts {
27802750
javascriptMapPath?: string,
27812751
javascriptMapTextOrDeclarationPath?: string,
27822752
declarationMapPath?: string,
2783-
declarationMapText?: string
2753+
declarationMapTextOrBundleInfoPath?: string
27842754
): InputFiles {
27852755
const node = <InputFiles>createNode(SyntaxKind.InputFiles);
27862756
if (!isString(javascriptTextOrReadFileText)) {
@@ -2798,15 +2768,21 @@ namespace ts {
27982768
const result = textGetter(path);
27992769
return result !== undefined ? result : `/* Input file ${path} was missing */\r\n`;
28002770
};
2771+
const jsonGetter = (path: string | undefined) => {
2772+
const result = textGetter(path);
2773+
return result !== undefined ? JSON.parse(result) as BundleInfo : undefined;
2774+
};
28012775
node.javascriptPath = declarationTextOrJavascriptPath;
28022776
node.javascriptMapPath = javascriptMapPath;
28032777
node.declarationPath = Debug.assertDefined(javascriptMapTextOrDeclarationPath);
28042778
node.declarationMapPath = declarationMapPath;
2779+
node.bundleInfoPath = declarationMapTextOrBundleInfoPath;
28052780
Object.defineProperties(node, {
28062781
javascriptText: { get() { return definedTextGetter(declarationTextOrJavascriptPath); } },
28072782
javascriptMapText: { get() { return textGetter(javascriptMapPath); } }, // TODO:: if there is inline sourceMap in jsFile, use that
28082783
declarationText: { get() { return definedTextGetter(Debug.assertDefined(javascriptMapTextOrDeclarationPath)); } },
2809-
declarationMapText: { get() { return textGetter(declarationMapPath); } } // TODO:: if there is inline sourceMap in dtsFile, use that
2784+
declarationMapText: { get() { return textGetter(declarationMapPath); } }, // TODO:: if there is inline sourceMap in dtsFile, use that
2785+
bundleInfo: { get() { return jsonGetter(declarationMapTextOrBundleInfoPath); } }
28102786
});
28112787
}
28122788
else {
@@ -2815,7 +2791,7 @@ namespace ts {
28152791
node.javascriptMapText = javascriptMapTextOrDeclarationPath;
28162792
node.declarationText = declarationTextOrJavascriptPath;
28172793
node.declarationMapPath = declarationMapPath;
2818-
node.declarationMapText = declarationMapText;
2794+
node.declarationMapText = declarationMapTextOrBundleInfoPath;
28192795
}
28202796
return node;
28212797
}

src/compiler/parser.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -7721,7 +7721,7 @@ namespace ts {
77217721
}
77227722

77237723
/*@internal*/
7724-
export function processCommentPragmas(context: PragmaContext, sourceText: string) {
7724+
export function processCommentPragmas(context: PragmaContext, sourceText: string): void {
77257725
const triviaScanner = createScanner(context.languageVersion, /*skipTrivia*/ false, LanguageVariant.Standard, sourceText);
77267726
const pragmas: PragmaPseudoMapEntry[] = [];
77277727

@@ -7758,7 +7758,6 @@ namespace ts {
77587758
}
77597759
context.pragmas.set(pragma!.name, pragma!.args);
77607760
}
7761-
return triviaScanner.getStartPos();
77627761
}
77637762

77647763
type PragmaDiagnosticReporter = (pos: number, length: number, message: DiagnosticMessage) => void;

src/compiler/program.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1456,12 +1456,12 @@ namespace ts {
14561456
// Upstream project didn't have outFile set -- skip (error will have been issued earlier)
14571457
if (!out) continue;
14581458

1459-
const { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath } = getOutputPathsForBundle(resolvedRefOpts.options, /*forceDtsPaths*/ true);
1459+
const { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, bundleInfoPath } = getOutputPathsForBundle(resolvedRefOpts.options, /*forceDtsPaths*/ true);
14601460
const node = createInputFiles(fileName => {
14611461
const path = toPath(fileName);
14621462
const sourceFile = getSourceFileByPath(path);
14631463
return sourceFile ? sourceFile.text : filesByName.has(path) ? undefined : host.readFile(path);
1464-
}, jsFilePath! , sourceMapFilePath, declarationFilePath! , declarationMapPath);
1464+
}, jsFilePath! , sourceMapFilePath, declarationFilePath! , declarationMapPath, bundleInfoPath);
14651465
nodes.push(node);
14661466
}
14671467
}

src/compiler/transformers/declarations.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ namespace ts {
6161
const { noResolve, stripInternal } = options;
6262
return transformRoot;
6363

64-
function recordTypeReferenceDirectivesIfNecessary(typeReferenceDirectives: string[] | undefined): void {
64+
function recordTypeReferenceDirectivesIfNecessary(typeReferenceDirectives: ReadonlyArray<string> | undefined): void {
6565
if (!typeReferenceDirectives) {
6666
return;
6767
}
@@ -210,6 +210,7 @@ namespace ts {
210210
const sourceFile = createUnparsedSourceFile(prepend, "dts");
211211
hasNoDefaultLib = hasNoDefaultLib || !!sourceFile.hasNoDefaultLib;
212212
collectReferences(sourceFile, refs);
213+
recordTypeReferenceDirectivesIfNecessary(sourceFile.typeReferenceDirectives);
213214
collectLibs(sourceFile, libs);
214215
return sourceFile;
215216
}

0 commit comments

Comments
 (0)