Fix off-by-one error with sourcemaps

This commit is contained in:
Ron Buckton 2018-06-14 22:54:31 -07:00
parent 374cbd6e5f
commit e62a5edc94
7 changed files with 119 additions and 231 deletions

View File

@ -64,10 +64,10 @@ namespace ts {
// Used for initialize lastEncodedSourceMapSpan and reset lastEncodedSourceMapSpan when updateLastEncodedAndRecordedSpans
const defaultLastEncodedSourceMapSpan: SourceMapSpan = {
emittedLine: 1,
emittedColumn: 1,
sourceLine: 1,
sourceColumn: 1,
emittedLine: 0,
emittedColumn: 0,
sourceLine: 0,
sourceColumn: 0,
sourceIndex: 0
};
@ -258,6 +258,11 @@ namespace ts {
return;
}
Debug.assert(lastRecordedSourceMapSpan.emittedColumn >= 0, "lastEncodedSourceMapSpan.emittedColumn was negative");
Debug.assert(lastRecordedSourceMapSpan.sourceIndex >= 0, "lastEncodedSourceMapSpan.sourceIndex was negative");
Debug.assert(lastRecordedSourceMapSpan.sourceLine >= 0, "lastEncodedSourceMapSpan.sourceLine was negative");
Debug.assert(lastRecordedSourceMapSpan.sourceColumn >= 0, "lastEncodedSourceMapSpan.sourceColumn was negative");
let prevEncodedEmittedColumn = lastEncodedSourceMapSpan!.emittedColumn;
// Line/Comma delimiters
if (lastEncodedSourceMapSpan!.emittedLine === lastRecordedSourceMapSpan.emittedLine) {
@ -271,7 +276,7 @@ namespace ts {
for (let encodedLine = lastEncodedSourceMapSpan!.emittedLine; encodedLine < lastRecordedSourceMapSpan.emittedLine; encodedLine++) {
sourceMapData.sourceMapMappings += ";";
}
prevEncodedEmittedColumn = 1;
prevEncodedEmittedColumn = 0;
}
// 1. Relative Column 0 based
@ -316,10 +321,6 @@ namespace ts {
const sourceLinePos = getLineAndCharacterOfPosition(currentSource, pos);
// Convert the location to be one-based.
sourceLinePos.line++;
sourceLinePos.character++;
const emittedLine = writer.getLine();
const emittedColumn = writer.getColumn();
@ -410,8 +411,8 @@ namespace ts {
encodeLastRecordedSourceMapSpan();
lastRecordedSourceMapSpan = {
...raw,
emittedLine: raw.emittedLine + offsetLine - 1,
emittedColumn: raw.emittedLine === 0 ? (raw.emittedColumn + firstLineColumnOffset - 1) : raw.emittedColumn,
emittedLine: raw.emittedLine + offsetLine,
emittedColumn: raw.emittedLine === 0 ? (raw.emittedColumn + firstLineColumnOffset) : raw.emittedColumn,
sourceIndex: newIndex,
};
});

View File

@ -148,8 +148,16 @@ namespace ts.sourcemaps {
}
}
export function calculateDecodedMappings<T>(map: SourceMapData, processPosition: (position: RawSourceMapPosition) => T, host?: { log?(s: string): void }): T[] {
const state: DecoderState<T> = {
/*@internal*/
export interface MappingsDecoder extends Iterator<SourceMapSpan> {
readonly decodingIndex: number;
readonly error: string | undefined;
readonly lastSpan: SourceMapSpan;
}
/*@internal*/
export function decodeMappings(map: SourceMapData): MappingsDecoder {
const state: DecoderState = {
encodedText: map.mappings,
currentNameIndex: undefined,
sourceMapNamesLength: map.names ? map.names.length : undefined,
@ -158,20 +166,40 @@ namespace ts.sourcemaps {
currentSourceColumn: 0,
currentSourceLine: 0,
currentSourceIndex: 0,
positions: [],
decodingIndex: 0,
processPosition,
decodingIndex: 0
};
while (!hasCompletedDecoding(state)) {
decodeSinglePosition(state);
if (state.error) {
if (host && host.log) {
host.log(`Encountered error while decoding sourcemap: ${state.error}`);
}
return [];
}
function captureSpan(): SourceMapSpan {
return {
emittedColumn: state.currentEmittedColumn,
emittedLine: state.currentEmittedLine,
sourceColumn: state.currentSourceColumn,
sourceIndex: state.currentSourceIndex,
sourceLine: state.currentSourceLine,
nameIndex: state.currentNameIndex
};
}
return state.positions;
return {
get decodingIndex() { return state.decodingIndex; },
get error() { return state.error; },
get lastSpan() { return captureSpan(); },
next() {
if (hasCompletedDecoding(state) || state.error) return { done: true, value: undefined as never };
if (!decodeSinglePosition(state)) return { done: true, value: undefined as never };
return { done: false, value: captureSpan() };
}
};
}
export function calculateDecodedMappings<T>(map: SourceMapData, processPosition: (position: RawSourceMapPosition) => T, host?: { log?(s: string): void }): T[] {
const decoder = decodeMappings(map);
const positions = arrayFrom(decoder, processPosition);
if (decoder.error) {
if (host && host.log) {
host.log(`Encountered error while decoding sourcemap: ${decoder.error}`);
}
return [];
}
return positions;
}
interface ProcessedSourceMapPosition {
@ -189,7 +217,7 @@ namespace ts.sourcemaps {
nameIndex?: number;
}
interface DecoderState<T> {
interface DecoderState {
decodingIndex: number;
currentEmittedLine: number;
currentEmittedColumn: number;
@ -200,15 +228,13 @@ namespace ts.sourcemaps {
encodedText: string;
sourceMapNamesLength?: number;
error?: string;
positions: T[];
processPosition: (position: RawSourceMapPosition) => T;
}
function hasCompletedDecoding(state: DecoderState<any>) {
function hasCompletedDecoding(state: DecoderState) {
return state.decodingIndex === state.encodedText.length;
}
function decodeSinglePosition<T>(state: DecoderState<T>): void {
function decodeSinglePosition(state: DecoderState): boolean {
while (state.decodingIndex < state.encodedText.length) {
const char = state.encodedText.charCodeAt(state.decodingIndex);
if (char === CharacterCodes.semicolon) {
@ -230,40 +256,40 @@ namespace ts.sourcemaps {
state.currentEmittedColumn += base64VLQFormatDecode();
// Incorrect emittedColumn dont support this map
if (createErrorIfCondition(state.currentEmittedColumn < 0, "Invalid emittedColumn found")) {
return;
return false;
}
// Dont support reading mappings that dont have information about original source and its line numbers
if (createErrorIfCondition(isSourceMappingSegmentEnd(state.encodedText, state.decodingIndex), "Unsupported Error Format: No entries after emitted column")) {
return;
return false;
}
// 2. Relative sourceIndex
state.currentSourceIndex += base64VLQFormatDecode();
// Incorrect sourceIndex dont support this map
if (createErrorIfCondition(state.currentSourceIndex < 0, "Invalid sourceIndex found")) {
return;
return false;
}
// Dont support reading mappings that dont have information about original source position
if (createErrorIfCondition(isSourceMappingSegmentEnd(state.encodedText, state.decodingIndex), "Unsupported Error Format: No entries after sourceIndex")) {
return;
return false;
}
// 3. Relative sourceLine 0 based
state.currentSourceLine += base64VLQFormatDecode();
// Incorrect sourceLine dont support this map
if (createErrorIfCondition(state.currentSourceLine < 0, "Invalid sourceLine found")) {
return;
return false;
}
// Dont support reading mappings that dont have information about original source and its line numbers
if (createErrorIfCondition(isSourceMappingSegmentEnd(state.encodedText, state.decodingIndex), "Unsupported Error Format: No entries after emitted Line")) {
return;
return false;
}
// 4. Relative sourceColumn 0 based
state.currentSourceColumn += base64VLQFormatDecode();
// Incorrect sourceColumn dont support this map
if (createErrorIfCondition(state.currentSourceColumn < 0, "Invalid sourceLine found")) {
return;
return false;
}
// 5. Check if there is name:
if (!isSourceMappingSegmentEnd(state.encodedText, state.decodingIndex)) {
@ -279,27 +305,15 @@ namespace ts.sourcemaps {
}
// Dont support reading mappings that dont have information about original source and its line numbers
if (createErrorIfCondition(!isSourceMappingSegmentEnd(state.encodedText, state.decodingIndex), "Unsupported Error Format: There are more entries after " + (state.currentNameIndex === undefined ? "sourceColumn" : "nameIndex"))) {
return;
return false;
}
// Entry should be complete
capturePosition();
return;
return true;
}
createErrorIfCondition(/*condition*/ true, "No encoded entry found");
return;
function capturePosition() {
state.positions.push(state.processPosition({
emittedColumn: state.currentEmittedColumn,
emittedLine: state.currentEmittedLine,
sourceColumn: state.currentSourceColumn,
sourceIndex: state.currentSourceIndex,
sourceLine: state.currentSourceLine,
nameIndex: state.currentNameIndex
}));
}
return false;
function createErrorIfCondition(condition: boolean, errormsg: string) {
if (state.error) {

View File

@ -7,177 +7,38 @@ namespace Harness.SourceMapRecorder {
namespace SourceMapDecoder {
let sourceMapMappings: string;
let sourceMapNames: string[] | undefined;
let decodingIndex: number;
let prevNameIndex: number;
let decodeOfEncodedMapping: ts.SourceMapSpan;
let errorDecodeOfEncodedMapping: string | undefined;
let mappings: ts.sourcemaps.MappingsDecoder | undefined;
export interface DecodedMapping {
sourceMapSpan: ts.SourceMapSpan;
error?: string;
}
export function initializeSourceMapDecoding(sourceMapData: ts.SourceMapData) {
sourceMapMappings = sourceMapData.sourceMapMappings;
sourceMapNames = sourceMapData.sourceMapNames;
decodingIndex = 0;
prevNameIndex = 0;
decodeOfEncodedMapping = {
emittedLine: 1,
emittedColumn: 1,
sourceLine: 1,
sourceColumn: 1,
sourceIndex: 0,
};
errorDecodeOfEncodedMapping = undefined;
sourceMapMappings = sourceMapData.sourceMapMappings;
mappings = ts.sourcemaps.decodeMappings({
version: 3,
file: sourceMapData.sourceMapFile,
sources: sourceMapData.sourceMapSources,
sourceRoot: sourceMapData.sourceMapSourceRoot,
sourcesContent: sourceMapData.sourceMapSourcesContent,
mappings: sourceMapData.sourceMapMappings,
names: sourceMapData.sourceMapNames
});
}
function isSourceMappingSegmentEnd() {
if (decodingIndex === sourceMapMappings.length) {
return true;
}
if (sourceMapMappings.charAt(decodingIndex) === ",") {
return true;
}
if (sourceMapMappings.charAt(decodingIndex) === ";") {
return true;
}
return false;
}
export function decodeNextEncodedSourceMapSpan() {
errorDecodeOfEncodedMapping = undefined;
function createErrorIfCondition(condition: boolean, errormsg: string) {
if (errorDecodeOfEncodedMapping) {
// there was existing error:
return true;
}
if (condition) {
errorDecodeOfEncodedMapping = errormsg;
}
return condition;
}
function base64VLQFormatDecode() {
function base64FormatDecode() {
return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".indexOf(sourceMapMappings.charAt(decodingIndex));
}
let moreDigits = true;
let shiftCount = 0;
let value = 0;
for (; moreDigits; decodingIndex++) {
if (createErrorIfCondition(decodingIndex >= sourceMapMappings.length, "Error in decoding base64VLQFormatDecode, past the mapping string")) {
return undefined!; // TODO: GH#18217
}
// 6 digit number
const currentByte = base64FormatDecode();
// If msb is set, we still have more bits to continue
moreDigits = (currentByte & 32) !== 0;
// least significant 5 bits are the next msbs in the final value.
value = value | ((currentByte & 31) << shiftCount);
shiftCount += 5;
}
// Least significant bit if 1 represents negative and rest of the msb is actual absolute value
if ((value & 1) === 0) {
// + number
value = value >> 1;
}
else {
// - number
value = value >> 1;
value = -value;
}
return value;
}
while (decodingIndex < sourceMapMappings.length) {
if (sourceMapMappings.charAt(decodingIndex) === ";") {
// New line
decodeOfEncodedMapping.emittedLine++;
decodeOfEncodedMapping.emittedColumn = 1;
decodingIndex++;
continue;
}
if (sourceMapMappings.charAt(decodingIndex) === ",") {
// Next entry is on same line - no action needed
decodingIndex++;
continue;
}
// Read the current span
// 1. Column offset from prev read jsColumn
decodeOfEncodedMapping.emittedColumn += base64VLQFormatDecode();
// Incorrect emittedColumn dont support this map
if (createErrorIfCondition(decodeOfEncodedMapping.emittedColumn < 1, "Invalid emittedColumn found")) {
return { error: errorDecodeOfEncodedMapping, sourceMapSpan: decodeOfEncodedMapping };
}
// Dont support reading mappings that dont have information about original source and its line numbers
if (createErrorIfCondition(isSourceMappingSegmentEnd(), "Unsupported Error Format: No entries after emitted column")) {
return { error: errorDecodeOfEncodedMapping, sourceMapSpan: decodeOfEncodedMapping };
}
// 2. Relative sourceIndex
decodeOfEncodedMapping.sourceIndex += base64VLQFormatDecode();
// Incorrect sourceIndex dont support this map
if (createErrorIfCondition(decodeOfEncodedMapping.sourceIndex < 0, "Invalid sourceIndex found")) {
return { error: errorDecodeOfEncodedMapping, sourceMapSpan: decodeOfEncodedMapping };
}
// Dont support reading mappings that dont have information about original source span
if (createErrorIfCondition(isSourceMappingSegmentEnd(), "Unsupported Error Format: No entries after sourceIndex")) {
return { error: errorDecodeOfEncodedMapping, sourceMapSpan: decodeOfEncodedMapping };
}
// 3. Relative sourceLine 0 based
decodeOfEncodedMapping.sourceLine += base64VLQFormatDecode();
// Incorrect sourceLine dont support this map
if (createErrorIfCondition(decodeOfEncodedMapping.sourceLine < 1, "Invalid sourceLine found")) {
return { error: errorDecodeOfEncodedMapping, sourceMapSpan: decodeOfEncodedMapping };
}
// Dont support reading mappings that dont have information about original source and its line numbers
if (createErrorIfCondition(isSourceMappingSegmentEnd(), "Unsupported Error Format: No entries after emitted Line")) {
return { error: errorDecodeOfEncodedMapping, sourceMapSpan: decodeOfEncodedMapping };
}
// 4. Relative sourceColumn 0 based
decodeOfEncodedMapping.sourceColumn += base64VLQFormatDecode();
// Incorrect sourceColumn dont support this map
if (createErrorIfCondition(decodeOfEncodedMapping.sourceColumn < 1, "Invalid sourceLine found")) {
return { error: errorDecodeOfEncodedMapping, sourceMapSpan: decodeOfEncodedMapping };
}
// 5. Check if there is name:
if (!isSourceMappingSegmentEnd()) {
prevNameIndex += base64VLQFormatDecode();
decodeOfEncodedMapping.nameIndex = prevNameIndex;
// Incorrect nameIndex dont support this map
if (createErrorIfCondition(decodeOfEncodedMapping.nameIndex < 0 || decodeOfEncodedMapping.nameIndex >= sourceMapNames!.length, "Invalid name index for the source map entry")) {
return { error: errorDecodeOfEncodedMapping, sourceMapSpan: decodeOfEncodedMapping };
}
}
// Dont support reading mappings that dont have information about original source and its line numbers
if (createErrorIfCondition(!isSourceMappingSegmentEnd(), "Unsupported Error Format: There are more entries after " + (decodeOfEncodedMapping.nameIndex === -1 ? "sourceColumn" : "nameIndex"))) {
return { error: errorDecodeOfEncodedMapping, sourceMapSpan: decodeOfEncodedMapping };
}
// Populated the entry
return { error: errorDecodeOfEncodedMapping, sourceMapSpan: decodeOfEncodedMapping };
}
createErrorIfCondition(/*condition*/ true, "No encoded entry found");
return undefined!; // TODO: GH#18217
export function decodeNextEncodedSourceMapSpan(): DecodedMapping {
if (!mappings) return ts.Debug.fail("not initialized");
const result = mappings.next();
if (result.done) return { error: mappings.error || "No encoded entry found", sourceMapSpan: mappings.lastSpan };
return { sourceMapSpan: result.value };
}
export function hasCompletedDecoding() {
return decodingIndex === sourceMapMappings.length;
if (!mappings) return ts.Debug.fail("not initialized");
return mappings.decodingIndex === sourceMapMappings.length;
}
export function getRemainingDecodeString() {
@ -197,7 +58,7 @@ namespace Harness.SourceMapRecorder {
let spansOnSingleLine: SourceMapSpanWithDecodeErrors[];
let prevWrittenSourcePos: number;
let prevWrittenJsLine: number;
let nextJsLineToWrite: number;
let spanMarkerContinues: boolean;
export function initializeSourceMapSpanWriter(sourceMapRecordWriter: Compiler.WriterAggregator, sourceMapData: ts.SourceMapData, currentJsFile: documents.TextDocument) {
@ -210,7 +71,7 @@ namespace Harness.SourceMapRecorder {
spansOnSingleLine = [];
prevWrittenSourcePos = 0;
prevWrittenJsLine = 0;
nextJsLineToWrite = 0;
spanMarkerContinues = false;
SourceMapDecoder.initializeSourceMapDecoding(sourceMapData);
@ -227,7 +88,7 @@ namespace Harness.SourceMapRecorder {
}
function getSourceMapSpanString(mapEntry: ts.SourceMapSpan, getAbsentNameIndex?: boolean) {
let mapString = "Emitted(" + mapEntry.emittedLine + ", " + mapEntry.emittedColumn + ") Source(" + mapEntry.sourceLine + ", " + mapEntry.sourceColumn + ") + SourceIndex(" + mapEntry.sourceIndex + ")";
let mapString = "Emitted(" + (mapEntry.emittedLine + 1) + ", " + (mapEntry.emittedColumn + 1) + ") Source(" + (mapEntry.sourceLine + 1) + ", " + (mapEntry.sourceColumn + 1) + ") + SourceIndex(" + mapEntry.sourceIndex + ")";
if (mapEntry.nameIndex! >= 0 && mapEntry.nameIndex! < sourceMapNames!.length) {
mapString += " name (" + sourceMapNames![mapEntry.nameIndex!] + ")";
}
@ -244,7 +105,7 @@ namespace Harness.SourceMapRecorder {
// verify the decoded span is same as the new span
const decodeResult = SourceMapDecoder.decodeNextEncodedSourceMapSpan();
let decodeErrors: string[] | undefined;
if (decodeResult.error
if (typeof decodeResult.error === "string"
|| decodeResult.sourceMapSpan.emittedLine !== sourceMapSpan.emittedLine
|| decodeResult.sourceMapSpan.emittedColumn !== sourceMapSpan.emittedColumn
|| decodeResult.sourceMapSpan.sourceLine !== sourceMapSpan.sourceLine
@ -305,8 +166,8 @@ namespace Harness.SourceMapRecorder {
}
function writeJsFileLines(endJsLine: number) {
for (; prevWrittenJsLine < endJsLine; prevWrittenJsLine++) {
sourceMapRecorder.Write(">>>" + getTextOfLine(prevWrittenJsLine, jsLineMap, jsFile.text));
for (; nextJsLineToWrite < endJsLine; nextJsLineToWrite++) {
sourceMapRecorder.Write(">>>" + getTextOfLine(nextJsLineToWrite, jsLineMap, jsFile.text));
}
}
@ -331,7 +192,7 @@ namespace Harness.SourceMapRecorder {
let prevEmittedCol!: number;
function iterateSpans(fn: (currentSpan: SourceMapSpanWithDecodeErrors, index: number) => void) {
prevEmittedCol = 1;
prevEmittedCol = 0;
for (let i = 0; i < spansOnSingleLine.length; i++) {
fn(spansOnSingleLine[i], i);
prevEmittedCol = spansOnSingleLine[i].sourceMapSpan.emittedColumn;
@ -340,7 +201,7 @@ namespace Harness.SourceMapRecorder {
function writeSourceMapIndent(indentLength: number, indentPrefix: string) {
sourceMapRecorder.Write(indentPrefix);
for (let i = 1; i < indentLength; i++) {
for (let i = 0; i < indentLength; i++) {
sourceMapRecorder.Write(" ");
}
}
@ -362,7 +223,7 @@ namespace Harness.SourceMapRecorder {
}
function writeSourceMapSourceText(currentSpan: SourceMapSpanWithDecodeErrors, index: number) {
const sourcePos = tsLineMap[currentSpan.sourceMapSpan.sourceLine - 1] + (currentSpan.sourceMapSpan.sourceColumn - 1);
const sourcePos = tsLineMap[currentSpan.sourceMapSpan.sourceLine] + (currentSpan.sourceMapSpan.sourceColumn);
let sourceText = "";
if (prevWrittenSourcePos < sourcePos) {
// Position that goes forward, get text
@ -397,15 +258,15 @@ namespace Harness.SourceMapRecorder {
const currentJsLine = spansOnSingleLine[0].sourceMapSpan.emittedLine;
// Write js line
writeJsFileLines(currentJsLine);
writeJsFileLines(currentJsLine + 1);
// Emit markers
iterateSpans(writeSourceMapMarker);
const jsFileText = getTextOfLine(currentJsLine, jsLineMap, jsFile.text);
if (prevEmittedCol < jsFileText.length) {
const jsFileText = getTextOfLine(currentJsLine + 1, jsLineMap, jsFile.text);
if (prevEmittedCol < jsFileText.length - 1) {
// There is remaining text on this line that will be part of next source span so write marker that continues
writeSourceMapMarker(/*currentSpan*/ undefined!, spansOnSingleLine.length, /*endColumn*/ jsFileText.length, /*endContinues*/ true); // TODO: GH#18217
writeSourceMapMarker(/*currentSpan*/ undefined!, spansOnSingleLine.length, /*endColumn*/ jsFileText.length - 1, /*endContinues*/ true); // TODO: GH#18217
}
// Emit Source text

View File

@ -3091,8 +3091,8 @@ namespace ts {
decreaseIndent: () => { indent--; },
getIndent: () => indent,
getTextPos: () => output.length,
getLine: () => lineCount + 1,
getColumn: () => lineStart ? indent * getIndentSize() + 1 : output.length - linePos + 1,
getLine: () => lineCount,
getColumn: () => lineStart ? indent * getIndentSize() : output.length - linePos,
getText: () => output,
isAtStartOfLine: () => lineStart,
clear: reset,

View File

@ -8546,6 +8546,12 @@ declare namespace ts.sourcemaps {
log(text: string): void;
}
function decode(host: SourceMapDecodeHost, mapPath: string, map: SourceMapData, program?: Program, fallbackCache?: SourceFileLikeCache): SourceMapper;
interface MappingsDecoder extends Iterator<SourceMapSpan> {
readonly decodingIndex: number;
readonly error: string | undefined;
readonly lastSpan: SourceMapSpan;
}
function decodeMappings(map: SourceMapData): MappingsDecoder;
function calculateDecodedMappings<T>(map: SourceMapData, processPosition: (position: RawSourceMapPosition) => T, host?: {
log?(s: string): void;
}): T[];

View File

@ -8546,6 +8546,12 @@ declare namespace ts.sourcemaps {
log(text: string): void;
}
function decode(host: SourceMapDecodeHost, mapPath: string, map: SourceMapData, program?: Program, fallbackCache?: SourceFileLikeCache): SourceMapper;
interface MappingsDecoder extends Iterator<SourceMapSpan> {
readonly decodingIndex: number;
readonly error: string | undefined;
readonly lastSpan: SourceMapSpan;
}
function decodeMappings(map: SourceMapData): MappingsDecoder;
function calculateDecodedMappings<T>(map: SourceMapData, processPosition: (position: RawSourceMapPosition) => T, host?: {
log?(s: string): void;
}): T[];

View File

@ -80,7 +80,7 @@ declare var c: C;
//# sourceMappingURL=third-output.d.ts.map
//// [/src/third/thirdjs/output/third-output.d.ts.map]
{"version":3,"file":"third-output.d.ts","sourceRoot":"","sources":["../../third_part1.ts","../../../first/first_part1.ts","../../../first/first_part3.ts","../../../second/second_part1.ts","../../../second/second_part2.ts"],"names":[],"mappings":"DCDD,UAAU,QAAQ;GACd,IAAI,EAAE,GAAG,CAAC;AACb;DAED,QAAA,MAAM,CAAC,iBAAiB,CAAC;DAEzB,UAAU,iBAAiB;GACvB,IAAI,EAAE,GAAG,CAAC;AACb;DCRD,6BAEC;;DCFD,kBAAU,CAAC,CAAC;AAEX;DAED,kBAAU,CAAC,CAAC;AAMX;DCVD;GACI,WAAW;AAGd;;;AJHA,QAAA,IAAI,CAAC,GAAU,CAAC"}
{"version":3,"file":"third-output.d.ts","sourceRoot":"","sources":["../../third_part1.ts","../../../first/first_part1.ts","../../../first/first_part3.ts","../../../second/second_part1.ts","../../../second/second_part2.ts"],"names":[],"mappings":"ACAA,UAAU,QAAQ;IACd,IAAI,EAAE,GAAG,CAAC;CACb;AAED,QAAA,MAAM,CAAC,iBAAiB,CAAC;AAEzB,UAAU,iBAAiB;IACvB,IAAI,EAAE,GAAG,CAAC;CACb;ACRD,6BAEC;;ACFD,kBAAU,CAAC,CAAC;CAEX;AAED,kBAAU,CAAC,CAAC;CAMX;ACVD;IACI,WAAW;CAGd;;AJJD,QAAA,IAAI,CAAC,GAAU,CAAC"}
//// [/src/third/thirdjs/output/third-output.js]
var s = "Hello, world";
@ -111,5 +111,5 @@ c.doSomething();
//# sourceMappingURL=third-output.js.map
//// [/src/third/thirdjs/output/third-output.js.map]
{"version":3,"file":"third-output.js","sourceRoot":"","sources":["../../third_part1.ts","../../../first/first_part1.ts","../../../first/first_part2.ts","../../../first/first_part3.ts","../../../second/second_part1.ts","../../../second/second_part2.ts"],"names":[],"mappings":"DCGD,IAAM,CAAC,GAAG,cAAc,CAAC;DAMzB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;DCVf,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;DCAjB;GACI,OAAO,gBAAgB,CAAC;DAC5B,CAAC;;DCED,IAAU,CAAC,CAMV;DAND,WAAU,CAAC;GACP;OACI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;GAC3B,CAAC;GAED,CAAC,EAAE,CAAC;DACR,CAAC,EANS,CAAC,KAAD,CAAC,QAMV;DCVD;GAAA;GAIA,CAAC;GAHG,uBAAW,GAAX;OACI,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;GACtC,CAAC;GACL,QAAC;DAAD,CAAC,AAJD,IAIC;;;ALHA,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC;AAChB,CAAC,CAAC,WAAW,EAAE,CAAC"}
{"version":3,"file":"third-output.js","sourceRoot":"","sources":["../../third_part1.ts","../../../first/first_part1.ts","../../../first/first_part2.ts","../../../first/first_part3.ts","../../../second/second_part1.ts","../../../second/second_part2.ts"],"names":[],"mappings":"ACIA,IAAM,CAAC,GAAG,cAAc,CAAC;AAMzB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;ACVf,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;ACAjB;IACI,OAAO,gBAAgB,CAAC;AAC5B,CAAC;;ACED,IAAU,CAAC,CAMV;AAND,WAAU,CAAC;IACP;QACI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC3B,CAAC;IAED,CAAC,EAAE,CAAC;AACR,CAAC,EANS,CAAC,KAAD,CAAC,QAMV;ACVD;IAAA;IAIA,CAAC;IAHG,uBAAW,GAAX;QACI,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IACtC,CAAC;IACL,QAAC;AAAD,CAAC,AAJD,IAIC;;ALJD,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC;AAChB,CAAC,CAAC,WAAW,EAAE,CAAC"}