Skip to content

Commit a4a8a8b

Browse files
committed
Make handling of input sourcemaps less flaky
Signed-off-by: Karthik Ganeshram <[email protected]>
1 parent 242d361 commit a4a8a8b

File tree

2 files changed

+37
-3
lines changed

2 files changed

+37
-3
lines changed

packages/build-tools/src/index.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
calculateChecksum,
88
chainSourceMaps,
99
fileExists,
10+
getSourceMapFromFile,
1011
saveBuildData,
1112
} from './utils.js';
1213
import { getCliArgs } from './cli.js';
@@ -17,6 +18,7 @@ import { mergeWit } from '../lib/wit_tools.js';
1718
import { precompile } from "./precompile.js"
1819
import path from 'node:path'
1920
import { SourceMapInput } from '@ampproject/remapping';
21+
import { get } from 'node:http';
2022

2123
async function main() {
2224
try {
@@ -70,9 +72,8 @@ async function main() {
7072
const source = await readFile(src, 'utf8');
7173
let { content: precompiledSource, sourceMap: precompiledSourceMap } = precompile(source, src, true, 'precompiled-source.js') as { content: string; sourceMap: SourceMapInput };
7274
// Check if input file has a source map because if we does, we need to chain it with the precompiled source map
73-
// TODO: check using the sourcemap comment instead of the file existence and also deal with base64 encoded source maps
74-
if (await fileExists(src + '.map')) {
75-
const inputSourceMap = JSON.parse(await readFile(src + '.map', 'utf8')) as SourceMapInput;
75+
let inputSourceMap = await getSourceMapFromFile(src);
76+
if (inputSourceMap) {
7677
precompiledSourceMap = chainSourceMaps(precompiledSourceMap, { [src]: inputSourceMap }) as SourceMapInput;
7778
}
7879

packages/build-tools/src/utils.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { readFile } from 'fs/promises';
22
import { createHash } from 'node:crypto';
33
import { access, writeFile } from 'node:fs/promises';
44
import remapping, { SourceMapInput } from '@ampproject/remapping';
5+
import path from 'path';
56

67
type FileName = string;
78
type SourceMapLookup = Record<FileName, SourceMapInput>;
@@ -73,3 +74,35 @@ export async function saveBuildData(
7374
throw error;
7475
}
7576
}
77+
78+
export async function getSourceMapFromFile(filePath: string): Promise<SourceMapInput | null> {
79+
try {
80+
const content = await readFile(filePath, 'utf8');
81+
82+
// Look for the sourceMappingURL comment
83+
const sourceMapRegex = /\/\/[#@]\s*sourceMappingURL=(.+)$/m;
84+
const match = content.match(sourceMapRegex);
85+
86+
if (!match) return null;
87+
88+
const sourceMapUrl = match[1].trim();
89+
90+
if (sourceMapUrl.startsWith('data:application/json;base64,')) {
91+
// Inline base64-encoded source map
92+
const base64 = sourceMapUrl.slice('data:application/json;base64,'.length);
93+
const rawMap = Buffer.from(base64, 'base64').toString('utf8');
94+
return JSON.parse(rawMap);
95+
} else {
96+
// External .map file
97+
const mapPath = path.resolve(path.dirname(filePath), sourceMapUrl);
98+
try {
99+
const rawMap = await readFile(mapPath, 'utf8');
100+
return JSON.parse(rawMap);
101+
} catch (e) {
102+
return null; // map file not found or invalid
103+
}
104+
}
105+
} catch (err) {
106+
return null; // file doesn't exist or can't be read
107+
}
108+
}

0 commit comments

Comments
 (0)