@atlaspack/core 2.16.2-canary.430 → 2.16.2-canary.431
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/requests/WriteBundleRequest.js +168 -17
- package/lib/requests/WriteBundleRequest.js +181 -13
- package/lib/types/requests/WriteBundleRequest.d.ts +33 -0
- package/package.json +18 -18
- package/src/requests/WriteBundleRequest.ts +202 -22
- package/test/requests/WriteBundleRequest.test.ts +363 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -36,8 +36,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.SourceMapHashRefRewriteStream = void 0;
|
|
39
40
|
exports.default = createWriteBundleRequest;
|
|
40
41
|
exports.applyReplacementsToSourceMap = applyReplacementsToSourceMap;
|
|
42
|
+
exports.applyReplacementsToVLQMappings = applyReplacementsToVLQMappings;
|
|
41
43
|
exports.computeSourceMapRoot = computeSourceMapRoot;
|
|
42
44
|
const constants_1 = require("../constants");
|
|
43
45
|
const nullthrows_1 = __importDefault(require("nullthrows"));
|
|
@@ -56,10 +58,12 @@ const profiler_1 = require("@atlaspack/profiler");
|
|
|
56
58
|
const RequestTracker_1 = require("../RequestTracker");
|
|
57
59
|
const feature_flags_1 = require("@atlaspack/feature-flags");
|
|
58
60
|
const EnvironmentManager_1 = require("../EnvironmentManager");
|
|
59
|
-
const source_map_1 =
|
|
61
|
+
const source_map_1 = require("@atlaspack/source-map");
|
|
60
62
|
const HASH_REF_PREFIX_LEN = constants_1.HASH_REF_PREFIX.length;
|
|
61
63
|
const BOUNDARY_LENGTH = constants_1.HASH_REF_PREFIX.length + 32 - 1;
|
|
62
64
|
const HASH_REF_PLACEHOLDER_LEN = HASH_REF_PREFIX_LEN + constants_1.HASH_REF_HASH_LEN;
|
|
65
|
+
// The JSON key prefix we scan for in the source map stream.
|
|
66
|
+
const MAPPINGS_KEY_BUF = Buffer.from('"mappings":"');
|
|
63
67
|
/**
|
|
64
68
|
* Writes a bundle to the dist directory, replacing hash references with the final content hashes.
|
|
65
69
|
*/
|
|
@@ -136,28 +140,14 @@ async function run({ input, options, api }) {
|
|
|
136
140
|
await writeFiles(contentStream, info, hashRefToNameHash, options, config, outputFS, filePath, writeOptions, devDeps, api, bundleReplacements);
|
|
137
141
|
const hasSourceMap = await options.cache.has(mapKey);
|
|
138
142
|
if (mapKey && env.sourceMap && !env.sourceMap.inline && hasSourceMap) {
|
|
143
|
+
const mapEntry = await options.cache.getBlob(mapKey);
|
|
139
144
|
let mapStream;
|
|
140
145
|
if ((0, feature_flags_1.getFeatureFlag)('fixSourceMapHashRefs') &&
|
|
141
146
|
bundleReplacements &&
|
|
142
147
|
bundleReplacements.length > 0) {
|
|
143
|
-
|
|
144
|
-
const mapBuffer = Buffer.isBuffer(mapEntry)
|
|
145
|
-
? mapEntry
|
|
146
|
-
: Buffer.from(mapEntry);
|
|
147
|
-
const projectRoot = typeof options.projectRoot === 'string'
|
|
148
|
-
? options.projectRoot
|
|
149
|
-
: String(options.projectRoot);
|
|
150
|
-
const sourceMap = new source_map_1.default(projectRoot, mapBuffer);
|
|
151
|
-
applyReplacementsToSourceMap(sourceMap, bundleReplacements);
|
|
152
|
-
const mapJson = await sourceMap.stringify({
|
|
153
|
-
format: 'string',
|
|
154
|
-
file: name,
|
|
155
|
-
sourceRoot: computeSourceMapRoot(bundle, options),
|
|
156
|
-
});
|
|
157
|
-
mapStream = (0, utils_1.blobToStream)(Buffer.from(typeof mapJson === 'string' ? mapJson : JSON.stringify(mapJson), 'utf8'));
|
|
148
|
+
mapStream = (0, utils_1.blobToStream)(mapEntry).pipe(new SourceMapHashRefRewriteStream(bundleReplacements));
|
|
158
149
|
}
|
|
159
150
|
else {
|
|
160
|
-
const mapEntry = await options.cache.getBlob(mapKey);
|
|
161
151
|
mapStream = (0, utils_1.blobToStream)(mapEntry);
|
|
162
152
|
}
|
|
163
153
|
await writeFiles(mapStream, info, hashRefToNameHash, options, config, outputFS, (0, projectPath_1.toProjectPathUnsafe)((0, projectPath_1.fromProjectPathRelative)(filePath) + '.map'), writeOptions, devDeps, api);
|
|
@@ -192,6 +182,167 @@ function applyReplacementsToSourceMap(sourceMap, replacements) {
|
|
|
192
182
|
}
|
|
193
183
|
}
|
|
194
184
|
}
|
|
185
|
+
/**
|
|
186
|
+
* Applies hash-ref replacement column offsets directly to a VLQ mappings
|
|
187
|
+
* string without deserializing the full source map into a native struct.
|
|
188
|
+
*
|
|
189
|
+
* Each replacement r describes a hash-ref that was substituted in the output
|
|
190
|
+
* file. r.column is in the progressively-shifted post-replacement coordinate
|
|
191
|
+
* space (matching the already-shifted source map state after all previous
|
|
192
|
+
* offsetColumns calls), so thresholds are applied sequentially against the
|
|
193
|
+
* running absCol values exactly as the native offsetColumns implementation does.
|
|
194
|
+
*/
|
|
195
|
+
function applyReplacementsToVLQMappings(mappings, replacements) {
|
|
196
|
+
if (replacements.length === 0)
|
|
197
|
+
return mappings;
|
|
198
|
+
// Group replacements by line (0-indexed), sorted by column ascending.
|
|
199
|
+
const byLine = new Map();
|
|
200
|
+
for (const r of replacements) {
|
|
201
|
+
let arr = byLine.get(r.line);
|
|
202
|
+
if (!arr) {
|
|
203
|
+
arr = [];
|
|
204
|
+
byLine.set(r.line, arr);
|
|
205
|
+
}
|
|
206
|
+
arr.push(r);
|
|
207
|
+
}
|
|
208
|
+
for (const arr of byLine.values()) {
|
|
209
|
+
arr.sort((a, b) => a.column - b.column);
|
|
210
|
+
}
|
|
211
|
+
const lines = mappings.split(';');
|
|
212
|
+
const resultLines = [];
|
|
213
|
+
for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
|
|
214
|
+
const lineReps = byLine.get(lineIdx);
|
|
215
|
+
if (!lineReps || lineReps.length === 0) {
|
|
216
|
+
resultLines.push(lines[lineIdx]);
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
const line = lines[lineIdx];
|
|
220
|
+
if (!line) {
|
|
221
|
+
resultLines.push('');
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
// Decode segment column deltas to absolute columns.
|
|
225
|
+
const segments = line.split(',');
|
|
226
|
+
const colVlqEnds = [];
|
|
227
|
+
const absCols = [];
|
|
228
|
+
let absCol = 0;
|
|
229
|
+
for (const seg of segments) {
|
|
230
|
+
const { value: colDelta, nextPos } = (0, source_map_1.decodeVLQ)(seg, 0);
|
|
231
|
+
absCol += colDelta;
|
|
232
|
+
colVlqEnds.push(nextPos);
|
|
233
|
+
absCols.push(absCol);
|
|
234
|
+
}
|
|
235
|
+
// Apply each replacement's column shift sequentially against the
|
|
236
|
+
// current absCol values (which have already been adjusted by previous
|
|
237
|
+
// replacements on this line), mirroring the sequential offsetColumns calls.
|
|
238
|
+
for (const r of lineReps) {
|
|
239
|
+
const delta = r.newLength - r.originalLength;
|
|
240
|
+
if (delta === 0)
|
|
241
|
+
continue;
|
|
242
|
+
const threshold = r.column + r.originalLength;
|
|
243
|
+
for (let i = 0; i < absCols.length; i++) {
|
|
244
|
+
if (absCols[i] >= threshold) {
|
|
245
|
+
absCols[i] += delta;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
// Re-encode with updated absolute columns; only the leading column VLQ
|
|
250
|
+
// field of each segment changes – the tail bytes are sliced unchanged.
|
|
251
|
+
const resultSegments = [];
|
|
252
|
+
let prevAbsCol = 0;
|
|
253
|
+
for (let i = 0; i < segments.length; i++) {
|
|
254
|
+
const newDelta = absCols[i] - prevAbsCol;
|
|
255
|
+
prevAbsCol = absCols[i];
|
|
256
|
+
resultSegments.push((0, source_map_1.encodeVLQ)(newDelta) + segments[i].slice(colVlqEnds[i]));
|
|
257
|
+
}
|
|
258
|
+
resultLines.push(resultSegments.join(','));
|
|
259
|
+
}
|
|
260
|
+
return resultLines.join(';');
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* A Transform stream that rewrites the "mappings" VLQ field of a source map
|
|
264
|
+
* JSON to account for hash-ref replacements, without ever loading the full
|
|
265
|
+
* JSON object or the native Rust SourceMapInner into memory.
|
|
266
|
+
*
|
|
267
|
+
* Field order in cached source maps (from partialVlqMapToSourceMap / toVLQ):
|
|
268
|
+
* mappings → sources → sourcesContent → names → version → file → sourceRoot
|
|
269
|
+
*
|
|
270
|
+
* "mappings" is the very first field, so we scan only a tiny header before
|
|
271
|
+
* switching to zero-copy passthrough for the bulk sourcesContent bytes.
|
|
272
|
+
*/
|
|
273
|
+
class SourceMapHashRefRewriteStream extends stream_1.Transform {
|
|
274
|
+
constructor(replacements) {
|
|
275
|
+
super();
|
|
276
|
+
this.replacements = replacements;
|
|
277
|
+
this.state = 'scanning';
|
|
278
|
+
this.scanBuf = Buffer.alloc(0);
|
|
279
|
+
this.mappingsBufs = [];
|
|
280
|
+
}
|
|
281
|
+
// @ts-expect-error TS7006
|
|
282
|
+
_transform(chunk, _encoding, cb) {
|
|
283
|
+
if (this.state === 'passthrough') {
|
|
284
|
+
this.push(chunk);
|
|
285
|
+
cb();
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
if (this.state === 'scanning') {
|
|
289
|
+
const combined = Buffer.concat([this.scanBuf, chunk]);
|
|
290
|
+
const idx = combined.indexOf(MAPPINGS_KEY_BUF);
|
|
291
|
+
if (idx === -1) {
|
|
292
|
+
// Key not yet found – hold back enough bytes to handle a split key.
|
|
293
|
+
const keepLen = Math.min(combined.length, MAPPINGS_KEY_BUF.length - 1);
|
|
294
|
+
if (combined.length > keepLen) {
|
|
295
|
+
this.push(combined.slice(0, combined.length - keepLen));
|
|
296
|
+
}
|
|
297
|
+
this.scanBuf = combined.slice(combined.length - keepLen);
|
|
298
|
+
cb();
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
// Emit everything up to and including the key.
|
|
302
|
+
const keyEnd = idx + MAPPINGS_KEY_BUF.length;
|
|
303
|
+
this.push(combined.slice(0, keyEnd));
|
|
304
|
+
this.scanBuf = Buffer.alloc(0);
|
|
305
|
+
this.state = 'buffering';
|
|
306
|
+
this._bufferingTransform(combined.slice(keyEnd), cb);
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
// state === 'buffering'
|
|
310
|
+
this._bufferingTransform(chunk, cb);
|
|
311
|
+
}
|
|
312
|
+
// @ts-expect-error TS7006
|
|
313
|
+
_bufferingTransform(chunk, cb) {
|
|
314
|
+
// Mappings values contain only base64 chars, ';', and ',' – no escaping –
|
|
315
|
+
// so scanning for the closing '"' (0x22) is safe.
|
|
316
|
+
const closeIdx = chunk.indexOf(0x22);
|
|
317
|
+
if (closeIdx === -1) {
|
|
318
|
+
this.mappingsBufs.push(chunk);
|
|
319
|
+
cb();
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
this.mappingsBufs.push(chunk.slice(0, closeIdx));
|
|
323
|
+
// VLQ chars are all ASCII (<128), so latin1 round-trips without loss.
|
|
324
|
+
const mappingsStr = Buffer.concat(this.mappingsBufs).toString('latin1');
|
|
325
|
+
const rewritten = applyReplacementsToVLQMappings(mappingsStr, this.replacements);
|
|
326
|
+
this.push(Buffer.from(rewritten, 'latin1'));
|
|
327
|
+
// Emit the closing '"' and everything remaining in one push.
|
|
328
|
+
this.push(chunk.slice(closeIdx));
|
|
329
|
+
this.state = 'passthrough';
|
|
330
|
+
this.mappingsBufs = [];
|
|
331
|
+
cb();
|
|
332
|
+
}
|
|
333
|
+
// @ts-expect-error TS7006
|
|
334
|
+
_flush(cb) {
|
|
335
|
+
if (this.state === 'scanning' && this.scanBuf.length > 0) {
|
|
336
|
+
this.push(this.scanBuf);
|
|
337
|
+
}
|
|
338
|
+
else if (this.state === 'buffering') {
|
|
339
|
+
// Malformed JSON – flush whatever we buffered as-is.
|
|
340
|
+
this.push(Buffer.concat(this.mappingsBufs));
|
|
341
|
+
}
|
|
342
|
+
cb();
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
exports.SourceMapHashRefRewriteStream = SourceMapHashRefRewriteStream;
|
|
195
346
|
/**
|
|
196
347
|
* Computes the sourceRoot for a source map file. This is the relative path from
|
|
197
348
|
* the output directory back to the project root, so that source paths (stored
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
exports.SourceMapHashRefRewriteStream = void 0;
|
|
6
7
|
exports.applyReplacementsToSourceMap = applyReplacementsToSourceMap;
|
|
8
|
+
exports.applyReplacementsToVLQMappings = applyReplacementsToVLQMappings;
|
|
7
9
|
exports.computeSourceMapRoot = computeSourceMapRoot;
|
|
8
10
|
exports.default = createWriteBundleRequest;
|
|
9
11
|
var _constants = require("../constants");
|
|
@@ -78,7 +80,7 @@ function _featureFlags() {
|
|
|
78
80
|
}
|
|
79
81
|
var _EnvironmentManager = require("../EnvironmentManager");
|
|
80
82
|
function _sourceMap() {
|
|
81
|
-
const data =
|
|
83
|
+
const data = require("@atlaspack/source-map");
|
|
82
84
|
_sourceMap = function () {
|
|
83
85
|
return data;
|
|
84
86
|
};
|
|
@@ -90,6 +92,9 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
90
92
|
const HASH_REF_PREFIX_LEN = _constants.HASH_REF_PREFIX.length;
|
|
91
93
|
const BOUNDARY_LENGTH = _constants.HASH_REF_PREFIX.length + 32 - 1;
|
|
92
94
|
const HASH_REF_PLACEHOLDER_LEN = HASH_REF_PREFIX_LEN + _constants.HASH_REF_HASH_LEN;
|
|
95
|
+
|
|
96
|
+
// The JSON key prefix we scan for in the source map stream.
|
|
97
|
+
const MAPPINGS_KEY_BUF = Buffer.from('"mappings":"');
|
|
93
98
|
/**
|
|
94
99
|
* Writes a bundle to the dist directory, replacing hash references with the final content hashes.
|
|
95
100
|
*/
|
|
@@ -179,21 +184,11 @@ async function run({
|
|
|
179
184
|
await writeFiles(contentStream, info, hashRefToNameHash, options, config, outputFS, filePath, writeOptions, devDeps, api, bundleReplacements);
|
|
180
185
|
const hasSourceMap = await options.cache.has(mapKey);
|
|
181
186
|
if (mapKey && env.sourceMap && !env.sourceMap.inline && hasSourceMap) {
|
|
187
|
+
const mapEntry = await options.cache.getBlob(mapKey);
|
|
182
188
|
let mapStream;
|
|
183
189
|
if ((0, _featureFlags().getFeatureFlag)('fixSourceMapHashRefs') && bundleReplacements && bundleReplacements.length > 0) {
|
|
184
|
-
|
|
185
|
-
const mapBuffer = Buffer.isBuffer(mapEntry) ? mapEntry : Buffer.from(mapEntry);
|
|
186
|
-
const projectRoot = typeof options.projectRoot === 'string' ? options.projectRoot : String(options.projectRoot);
|
|
187
|
-
const sourceMap = new (_sourceMap().default)(projectRoot, mapBuffer);
|
|
188
|
-
applyReplacementsToSourceMap(sourceMap, bundleReplacements);
|
|
189
|
-
const mapJson = await sourceMap.stringify({
|
|
190
|
-
format: 'string',
|
|
191
|
-
file: name,
|
|
192
|
-
sourceRoot: computeSourceMapRoot(bundle, options)
|
|
193
|
-
});
|
|
194
|
-
mapStream = (0, _utils().blobToStream)(Buffer.from(typeof mapJson === 'string' ? mapJson : JSON.stringify(mapJson), 'utf8'));
|
|
190
|
+
mapStream = (0, _utils().blobToStream)(mapEntry).pipe(new SourceMapHashRefRewriteStream(bundleReplacements));
|
|
195
191
|
} else {
|
|
196
|
-
const mapEntry = await options.cache.getBlob(mapKey);
|
|
197
192
|
mapStream = (0, _utils().blobToStream)(mapEntry);
|
|
198
193
|
}
|
|
199
194
|
await writeFiles(mapStream, info, hashRefToNameHash, options, config, outputFS, (0, _projectPath.toProjectPathUnsafe)((0, _projectPath.fromProjectPathRelative)(filePath) + '.map'), writeOptions, devDeps, api);
|
|
@@ -228,6 +223,178 @@ function applyReplacementsToSourceMap(sourceMap, replacements) {
|
|
|
228
223
|
}
|
|
229
224
|
}
|
|
230
225
|
|
|
226
|
+
/**
|
|
227
|
+
* Applies hash-ref replacement column offsets directly to a VLQ mappings
|
|
228
|
+
* string without deserializing the full source map into a native struct.
|
|
229
|
+
*
|
|
230
|
+
* Each replacement r describes a hash-ref that was substituted in the output
|
|
231
|
+
* file. r.column is in the progressively-shifted post-replacement coordinate
|
|
232
|
+
* space (matching the already-shifted source map state after all previous
|
|
233
|
+
* offsetColumns calls), so thresholds are applied sequentially against the
|
|
234
|
+
* running absCol values exactly as the native offsetColumns implementation does.
|
|
235
|
+
*/
|
|
236
|
+
function applyReplacementsToVLQMappings(mappings, replacements) {
|
|
237
|
+
if (replacements.length === 0) return mappings;
|
|
238
|
+
|
|
239
|
+
// Group replacements by line (0-indexed), sorted by column ascending.
|
|
240
|
+
const byLine = new Map();
|
|
241
|
+
for (const r of replacements) {
|
|
242
|
+
let arr = byLine.get(r.line);
|
|
243
|
+
if (!arr) {
|
|
244
|
+
arr = [];
|
|
245
|
+
byLine.set(r.line, arr);
|
|
246
|
+
}
|
|
247
|
+
arr.push(r);
|
|
248
|
+
}
|
|
249
|
+
for (const arr of byLine.values()) {
|
|
250
|
+
arr.sort((a, b) => a.column - b.column);
|
|
251
|
+
}
|
|
252
|
+
const lines = mappings.split(';');
|
|
253
|
+
const resultLines = [];
|
|
254
|
+
for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
|
|
255
|
+
const lineReps = byLine.get(lineIdx);
|
|
256
|
+
if (!lineReps || lineReps.length === 0) {
|
|
257
|
+
resultLines.push(lines[lineIdx]);
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
const line = lines[lineIdx];
|
|
261
|
+
if (!line) {
|
|
262
|
+
resultLines.push('');
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Decode segment column deltas to absolute columns.
|
|
267
|
+
const segments = line.split(',');
|
|
268
|
+
const colVlqEnds = [];
|
|
269
|
+
const absCols = [];
|
|
270
|
+
let absCol = 0;
|
|
271
|
+
for (const seg of segments) {
|
|
272
|
+
const {
|
|
273
|
+
value: colDelta,
|
|
274
|
+
nextPos
|
|
275
|
+
} = (0, _sourceMap().decodeVLQ)(seg, 0);
|
|
276
|
+
absCol += colDelta;
|
|
277
|
+
colVlqEnds.push(nextPos);
|
|
278
|
+
absCols.push(absCol);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Apply each replacement's column shift sequentially against the
|
|
282
|
+
// current absCol values (which have already been adjusted by previous
|
|
283
|
+
// replacements on this line), mirroring the sequential offsetColumns calls.
|
|
284
|
+
for (const r of lineReps) {
|
|
285
|
+
const delta = r.newLength - r.originalLength;
|
|
286
|
+
if (delta === 0) continue;
|
|
287
|
+
const threshold = r.column + r.originalLength;
|
|
288
|
+
for (let i = 0; i < absCols.length; i++) {
|
|
289
|
+
if (absCols[i] >= threshold) {
|
|
290
|
+
absCols[i] += delta;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Re-encode with updated absolute columns; only the leading column VLQ
|
|
296
|
+
// field of each segment changes – the tail bytes are sliced unchanged.
|
|
297
|
+
const resultSegments = [];
|
|
298
|
+
let prevAbsCol = 0;
|
|
299
|
+
for (let i = 0; i < segments.length; i++) {
|
|
300
|
+
const newDelta = absCols[i] - prevAbsCol;
|
|
301
|
+
prevAbsCol = absCols[i];
|
|
302
|
+
resultSegments.push((0, _sourceMap().encodeVLQ)(newDelta) + segments[i].slice(colVlqEnds[i]));
|
|
303
|
+
}
|
|
304
|
+
resultLines.push(resultSegments.join(','));
|
|
305
|
+
}
|
|
306
|
+
return resultLines.join(';');
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* A Transform stream that rewrites the "mappings" VLQ field of a source map
|
|
310
|
+
* JSON to account for hash-ref replacements, without ever loading the full
|
|
311
|
+
* JSON object or the native Rust SourceMapInner into memory.
|
|
312
|
+
*
|
|
313
|
+
* Field order in cached source maps (from partialVlqMapToSourceMap / toVLQ):
|
|
314
|
+
* mappings → sources → sourcesContent → names → version → file → sourceRoot
|
|
315
|
+
*
|
|
316
|
+
* "mappings" is the very first field, so we scan only a tiny header before
|
|
317
|
+
* switching to zero-copy passthrough for the bulk sourcesContent bytes.
|
|
318
|
+
*/
|
|
319
|
+
class SourceMapHashRefRewriteStream extends _stream().Transform {
|
|
320
|
+
constructor(replacements) {
|
|
321
|
+
super();
|
|
322
|
+
this.replacements = replacements;
|
|
323
|
+
this.state = 'scanning';
|
|
324
|
+
this.scanBuf = Buffer.alloc(0);
|
|
325
|
+
this.mappingsBufs = [];
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// @ts-expect-error TS7006
|
|
329
|
+
_transform(chunk, _encoding, cb) {
|
|
330
|
+
if (this.state === 'passthrough') {
|
|
331
|
+
this.push(chunk);
|
|
332
|
+
cb();
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
if (this.state === 'scanning') {
|
|
336
|
+
const combined = Buffer.concat([this.scanBuf, chunk]);
|
|
337
|
+
const idx = combined.indexOf(MAPPINGS_KEY_BUF);
|
|
338
|
+
if (idx === -1) {
|
|
339
|
+
// Key not yet found – hold back enough bytes to handle a split key.
|
|
340
|
+
const keepLen = Math.min(combined.length, MAPPINGS_KEY_BUF.length - 1);
|
|
341
|
+
if (combined.length > keepLen) {
|
|
342
|
+
this.push(combined.slice(0, combined.length - keepLen));
|
|
343
|
+
}
|
|
344
|
+
this.scanBuf = combined.slice(combined.length - keepLen);
|
|
345
|
+
cb();
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Emit everything up to and including the key.
|
|
350
|
+
const keyEnd = idx + MAPPINGS_KEY_BUF.length;
|
|
351
|
+
this.push(combined.slice(0, keyEnd));
|
|
352
|
+
this.scanBuf = Buffer.alloc(0);
|
|
353
|
+
this.state = 'buffering';
|
|
354
|
+
this._bufferingTransform(combined.slice(keyEnd), cb);
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// state === 'buffering'
|
|
359
|
+
this._bufferingTransform(chunk, cb);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// @ts-expect-error TS7006
|
|
363
|
+
_bufferingTransform(chunk, cb) {
|
|
364
|
+
// Mappings values contain only base64 chars, ';', and ',' – no escaping –
|
|
365
|
+
// so scanning for the closing '"' (0x22) is safe.
|
|
366
|
+
const closeIdx = chunk.indexOf(0x22);
|
|
367
|
+
if (closeIdx === -1) {
|
|
368
|
+
this.mappingsBufs.push(chunk);
|
|
369
|
+
cb();
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
this.mappingsBufs.push(chunk.slice(0, closeIdx));
|
|
373
|
+
|
|
374
|
+
// VLQ chars are all ASCII (<128), so latin1 round-trips without loss.
|
|
375
|
+
const mappingsStr = Buffer.concat(this.mappingsBufs).toString('latin1');
|
|
376
|
+
const rewritten = applyReplacementsToVLQMappings(mappingsStr, this.replacements);
|
|
377
|
+
this.push(Buffer.from(rewritten, 'latin1'));
|
|
378
|
+
|
|
379
|
+
// Emit the closing '"' and everything remaining in one push.
|
|
380
|
+
this.push(chunk.slice(closeIdx));
|
|
381
|
+
this.state = 'passthrough';
|
|
382
|
+
this.mappingsBufs = [];
|
|
383
|
+
cb();
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// @ts-expect-error TS7006
|
|
387
|
+
_flush(cb) {
|
|
388
|
+
if (this.state === 'scanning' && this.scanBuf.length > 0) {
|
|
389
|
+
this.push(this.scanBuf);
|
|
390
|
+
} else if (this.state === 'buffering') {
|
|
391
|
+
// Malformed JSON – flush whatever we buffered as-is.
|
|
392
|
+
this.push(Buffer.concat(this.mappingsBufs));
|
|
393
|
+
}
|
|
394
|
+
cb();
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
231
398
|
/**
|
|
232
399
|
* Computes the sourceRoot for a source map file. This is the relative path from
|
|
233
400
|
* the output directory back to the project root, so that source paths (stored
|
|
@@ -238,6 +405,7 @@ function applyReplacementsToSourceMap(sourceMap, replacements) {
|
|
|
238
405
|
*
|
|
239
406
|
* This logic must stay in sync with PackagerRunner.generateSourceMap.
|
|
240
407
|
*/
|
|
408
|
+
exports.SourceMapHashRefRewriteStream = SourceMapHashRefRewriteStream;
|
|
241
409
|
function computeSourceMapRoot(bundle, options) {
|
|
242
410
|
let name = (0, _nullthrows().default)(bundle.name);
|
|
243
411
|
let filePath = (0, _projectPath.joinProjectPath)(bundle.target.distDir, name);
|
|
@@ -4,6 +4,7 @@ import type { StaticRunOpts } from '../RequestTracker';
|
|
|
4
4
|
import type { Bundle, PackagedBundleInfo, AtlaspackOptions } from '../types';
|
|
5
5
|
import type BundleGraph from '../BundleGraph';
|
|
6
6
|
import type { BundleInfo } from '../PackagerRunner';
|
|
7
|
+
import { Transform } from 'stream';
|
|
7
8
|
import { requestTypes } from '../RequestTracker';
|
|
8
9
|
import SourceMap from '@atlaspack/source-map';
|
|
9
10
|
export type HashRefReplacement = {
|
|
@@ -33,6 +34,38 @@ export type WriteBundleRequest = {
|
|
|
33
34
|
*/
|
|
34
35
|
export default function createWriteBundleRequest(input: WriteBundleRequestInput): WriteBundleRequest;
|
|
35
36
|
export declare function applyReplacementsToSourceMap(sourceMap: SourceMap, replacements: HashRefReplacement[]): void;
|
|
37
|
+
/**
|
|
38
|
+
* Applies hash-ref replacement column offsets directly to a VLQ mappings
|
|
39
|
+
* string without deserializing the full source map into a native struct.
|
|
40
|
+
*
|
|
41
|
+
* Each replacement r describes a hash-ref that was substituted in the output
|
|
42
|
+
* file. r.column is in the progressively-shifted post-replacement coordinate
|
|
43
|
+
* space (matching the already-shifted source map state after all previous
|
|
44
|
+
* offsetColumns calls), so thresholds are applied sequentially against the
|
|
45
|
+
* running absCol values exactly as the native offsetColumns implementation does.
|
|
46
|
+
*/
|
|
47
|
+
export declare function applyReplacementsToVLQMappings(mappings: string, replacements: HashRefReplacement[]): string;
|
|
48
|
+
/**
|
|
49
|
+
* A Transform stream that rewrites the "mappings" VLQ field of a source map
|
|
50
|
+
* JSON to account for hash-ref replacements, without ever loading the full
|
|
51
|
+
* JSON object or the native Rust SourceMapInner into memory.
|
|
52
|
+
*
|
|
53
|
+
* Field order in cached source maps (from partialVlqMapToSourceMap / toVLQ):
|
|
54
|
+
* mappings → sources → sourcesContent → names → version → file → sourceRoot
|
|
55
|
+
*
|
|
56
|
+
* "mappings" is the very first field, so we scan only a tiny header before
|
|
57
|
+
* switching to zero-copy passthrough for the bulk sourcesContent bytes.
|
|
58
|
+
*/
|
|
59
|
+
export declare class SourceMapHashRefRewriteStream extends Transform {
|
|
60
|
+
private replacements;
|
|
61
|
+
private state;
|
|
62
|
+
private scanBuf;
|
|
63
|
+
private mappingsBufs;
|
|
64
|
+
constructor(replacements: HashRefReplacement[]);
|
|
65
|
+
_transform(chunk: Buffer, _encoding: string, cb: any): void;
|
|
66
|
+
private _bufferingTransform;
|
|
67
|
+
_flush(cb: any): void;
|
|
68
|
+
}
|
|
36
69
|
/**
|
|
37
70
|
* Computes the sourceRoot for a source map file. This is the relative path from
|
|
38
71
|
* the output directory back to the project root, so that source paths (stored
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaspack/core",
|
|
3
|
-
"version": "2.16.2-canary.
|
|
3
|
+
"version": "2.16.2-canary.431+de388ff76",
|
|
4
4
|
"license": "(MIT OR Apache-2.0)",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -22,22 +22,22 @@
|
|
|
22
22
|
"build:lib": "gulp build --gulpfile ../../../gulpfile.js --cwd ."
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@atlaspack/build-cache": "2.13.3-canary.
|
|
26
|
-
"@atlaspack/cache": "3.1.1-canary.
|
|
27
|
-
"@atlaspack/diagnostic": "2.14.1-canary.
|
|
28
|
-
"@atlaspack/events": "2.14.1-canary.
|
|
29
|
-
"@atlaspack/feature-flags": "2.14.1-canary.
|
|
30
|
-
"@atlaspack/fs": "2.14.5-canary.
|
|
31
|
-
"@atlaspack/graph": "3.4.1-canary.
|
|
32
|
-
"@atlaspack/logger": "2.14.5-canary.
|
|
33
|
-
"@atlaspack/package-manager": "2.14.5-canary.
|
|
34
|
-
"@atlaspack/plugin": "2.14.5-canary.
|
|
35
|
-
"@atlaspack/profiler": "2.14.1-canary.
|
|
36
|
-
"@atlaspack/rust": "3.2.1-canary.
|
|
37
|
-
"@atlaspack/source-map": "3.2.11-canary.
|
|
38
|
-
"@atlaspack/types": "2.14.5-canary.
|
|
39
|
-
"@atlaspack/utils": "2.14.5-canary.
|
|
40
|
-
"@atlaspack/workers": "2.14.5-canary.
|
|
25
|
+
"@atlaspack/build-cache": "2.13.3-canary.499+de388ff76",
|
|
26
|
+
"@atlaspack/cache": "3.1.1-canary.431+de388ff76",
|
|
27
|
+
"@atlaspack/diagnostic": "2.14.1-canary.499+de388ff76",
|
|
28
|
+
"@atlaspack/events": "2.14.1-canary.499+de388ff76",
|
|
29
|
+
"@atlaspack/feature-flags": "2.14.1-canary.499+de388ff76",
|
|
30
|
+
"@atlaspack/fs": "2.14.5-canary.431+de388ff76",
|
|
31
|
+
"@atlaspack/graph": "3.4.1-canary.499+de388ff76",
|
|
32
|
+
"@atlaspack/logger": "2.14.5-canary.431+de388ff76",
|
|
33
|
+
"@atlaspack/package-manager": "2.14.5-canary.431+de388ff76",
|
|
34
|
+
"@atlaspack/plugin": "2.14.5-canary.431+de388ff76",
|
|
35
|
+
"@atlaspack/profiler": "2.14.1-canary.499+de388ff76",
|
|
36
|
+
"@atlaspack/rust": "3.2.1-canary.431+de388ff76",
|
|
37
|
+
"@atlaspack/source-map": "3.2.11-canary.4210+de388ff76",
|
|
38
|
+
"@atlaspack/types": "2.14.5-canary.431+de388ff76",
|
|
39
|
+
"@atlaspack/utils": "2.14.5-canary.431+de388ff76",
|
|
40
|
+
"@atlaspack/workers": "2.14.5-canary.431+de388ff76",
|
|
41
41
|
"@mischnic/json-sourcemap": "^0.1.0",
|
|
42
42
|
"base-x": "^3.0.8",
|
|
43
43
|
"browserslist": "^4.6.6",
|
|
@@ -61,5 +61,5 @@
|
|
|
61
61
|
"./src/serializerCore.js": "./src/serializerCore.browser.js"
|
|
62
62
|
},
|
|
63
63
|
"type": "commonjs",
|
|
64
|
-
"gitHead": "
|
|
64
|
+
"gitHead": "de388ff76d39dece97ad475fcccdb6efb6283bfc"
|
|
65
65
|
}
|