webpack 5.110.0 → 5.110.2
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/README.md +10 -17
- package/lib/ExportsInfo.js +10 -0
- package/lib/FileSystemInfo.js +17 -2
- package/lib/Generator.js +17 -0
- package/lib/NormalModule.js +3 -3
- package/lib/RuntimeTemplate.js +423 -430
- package/lib/asset/AssetBytesGenerator.js +1 -3
- package/lib/asset/AssetGenerator.js +1 -3
- package/lib/asset/AssetSourceGenerator.js +1 -3
- package/lib/config/defaults.js +6 -0
- package/lib/css/CssGenerator.js +1 -3
- package/lib/css/CssLoadingRuntimeModule.js +32 -13
- package/lib/css/CssModulesPlugin.js +9 -17
- package/lib/css/data.js +13 -3
- package/lib/css/syntax.js +78 -10
- package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +10 -4
- package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +2 -0
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +48 -3
- package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +83 -14
- package/lib/dependencies/HarmonyImportSideEffectDependency.js +114 -0
- package/lib/dependencies/WorkerAndWorkletPlugin.js +1 -0
- package/lib/dependencies/WorkerDependency.js +6 -12
- package/lib/dependencies/WorkletDependency.js +7 -11
- package/lib/esm/ModuleChunkLoadingPlugin.js +6 -9
- package/lib/esm/ModuleChunkLoadingRuntimeModule.js +7 -1
- package/lib/html/HtmlGenerator.js +1 -1
- package/lib/html/HtmlModulesPlugin.js +55 -16
- package/lib/html/syntax.js +113 -26
- package/lib/javascript/JavascriptGenerator.js +1 -1
- package/lib/javascript/JavascriptModulesPlugin.js +3 -10
- package/lib/json/JsonGenerator.js +1 -1
- package/lib/loaders/LoaderRunner.js +33 -5
- package/lib/node/ReadFileCompileAsyncWasmPlugin.js +8 -15
- package/lib/optimize/ConcatenatedModule.js +8 -0
- package/lib/optimize/ConstExportsPlugin.js +5 -0
- package/lib/optimize/InlineExports.js +121 -0
- package/lib/optimize/RealContentHashPlugin.js +111 -35
- package/lib/prefetch/ResourceHintPlugin.js +6 -12
- package/lib/serialization/ObjectMiddleware.js +128 -108
- package/lib/typescript/TypeScriptPlugin.js +8 -10
- package/lib/util/SourceProcessor.js +24 -8
- package/lib/util/createMappings.js +25 -3
- package/lib/util/removeBOM.js +82 -1
- package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +5 -3
- package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +5 -3
- package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +3 -1
- package/lib/wasm-async/UniversalCompileAsyncWasmPlugin.js +7 -12
- package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +3 -1
- package/lib/web/FetchCompileAsyncWasmPlugin.js +10 -6
- package/lib/web/FetchCompileWasmPlugin.js +4 -2
- package/package.json +1 -1
- package/types.d.ts +77 -10
|
@@ -345,47 +345,68 @@ ${referencingAssets
|
|
|
345
345
|
}
|
|
346
346
|
return hashes;
|
|
347
347
|
};
|
|
348
|
+
// Tarjan: hashes naming each other come out as one group where a chain
|
|
349
|
+
// walk would never end, and groups arrive dependencies-first as needed.
|
|
350
|
+
/** @type {string[][]} */
|
|
351
|
+
const groupsInOrder = [];
|
|
352
|
+
/** @type {Map<string, number>} */
|
|
353
|
+
const indexOf = new Map();
|
|
354
|
+
/** @type {Map<string, number>} */
|
|
355
|
+
const lowOf = new Map();
|
|
356
|
+
/** @type {Set<string>} */
|
|
357
|
+
const onStack = new Set();
|
|
358
|
+
/** @type {string[]} */
|
|
359
|
+
const stack = [];
|
|
348
360
|
/**
|
|
349
|
-
*
|
|
361
|
+
* Visits one hash and everything its assets reference.
|
|
350
362
|
* @param {string} hash the hash
|
|
351
|
-
* @returns {
|
|
363
|
+
* @returns {void}
|
|
352
364
|
*/
|
|
353
|
-
const
|
|
354
|
-
const
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
)
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
for (const hash of hashToAssets.keys()) {
|
|
363
|
-
/**
|
|
364
|
-
* Processes the provided hash.
|
|
365
|
-
* @param {string} hash the hash
|
|
366
|
-
* @param {Set<string>} stack stack of hashes
|
|
367
|
-
*/
|
|
368
|
-
const add = (hash, stack) => {
|
|
369
|
-
const deps = getDependencies(hash);
|
|
370
|
-
if (!deps) return;
|
|
371
|
-
stack.add(hash);
|
|
365
|
+
const strongConnect = (hash) => {
|
|
366
|
+
const index = indexOf.size;
|
|
367
|
+
indexOf.set(hash, index);
|
|
368
|
+
lowOf.set(hash, index);
|
|
369
|
+
stack.push(hash);
|
|
370
|
+
onStack.add(hash);
|
|
371
|
+
// An unowned reference reports the caching problem and stays a leaf.
|
|
372
|
+
const deps = getDependencies(hash);
|
|
373
|
+
if (deps) {
|
|
372
374
|
for (const dep of deps) {
|
|
373
|
-
if (
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
375
|
+
if (!indexOf.has(dep)) {
|
|
376
|
+
strongConnect(dep);
|
|
377
|
+
lowOf.set(
|
|
378
|
+
hash,
|
|
379
|
+
Math.min(
|
|
380
|
+
/** @type {number} */ (lowOf.get(hash)),
|
|
381
|
+
/** @type {number} */ (lowOf.get(dep))
|
|
382
|
+
)
|
|
383
|
+
);
|
|
384
|
+
} else if (onStack.has(dep)) {
|
|
385
|
+
lowOf.set(
|
|
386
|
+
hash,
|
|
387
|
+
Math.min(
|
|
388
|
+
/** @type {number} */ (lowOf.get(hash)),
|
|
389
|
+
/** @type {number} */ (indexOf.get(dep))
|
|
390
|
+
)
|
|
380
391
|
);
|
|
381
392
|
}
|
|
382
|
-
add(dep, stack);
|
|
383
393
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
394
|
+
}
|
|
395
|
+
if (lowOf.get(hash) === indexOf.get(hash)) {
|
|
396
|
+
/** @type {string[]} */
|
|
397
|
+
const group = [];
|
|
398
|
+
/** @type {string} */
|
|
399
|
+
let member;
|
|
400
|
+
do {
|
|
401
|
+
member = /** @type {string} */ (stack.pop());
|
|
402
|
+
onStack.delete(member);
|
|
403
|
+
if (hashToAssets.has(member)) group.push(member);
|
|
404
|
+
} while (member !== hash);
|
|
405
|
+
if (group.length > 0) groupsInOrder.push(group);
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
for (const hash of hashToAssets.keys()) {
|
|
409
|
+
if (!indexOf.has(hash)) strongConnect(hash);
|
|
389
410
|
}
|
|
390
411
|
/** @type {Map<string, string>} */
|
|
391
412
|
const hashToNewHash = new Map();
|
|
@@ -474,7 +495,62 @@ ${referencingAssets
|
|
|
474
495
|
};
|
|
475
496
|
/** @type {Comparator<AssetInfoForRealContentHash>} */
|
|
476
497
|
const comparator = compareSelect((a) => a.name, compareStrings);
|
|
477
|
-
for (const
|
|
498
|
+
for (const group of groupsInOrder) {
|
|
499
|
+
// A cycle is assigned as one group: members are told apart by stable
|
|
500
|
+
// markers, so the group hashes to a fixed point instead of chasing one.
|
|
501
|
+
if (group.length > 1) {
|
|
502
|
+
const members = group.sort();
|
|
503
|
+
/** @type {Map<string, string>} */
|
|
504
|
+
const markerOf = new Map(
|
|
505
|
+
members.map((hash, i) => [hash, `|webpack/scc/${i}|`])
|
|
506
|
+
);
|
|
507
|
+
for (let i = 0; i < members.length; i++) {
|
|
508
|
+
const oldHash = members[i];
|
|
509
|
+
const memberAssets =
|
|
510
|
+
/** @type {AssetInfoForRealContentHash[]} */
|
|
511
|
+
(hashToAssets.get(oldHash));
|
|
512
|
+
memberAssets.sort(comparator);
|
|
513
|
+
const hash = createHash(this._hashFunction);
|
|
514
|
+
if (compilation.outputOptions.hashSalt) {
|
|
515
|
+
hash.update(compilation.outputOptions.hashSalt);
|
|
516
|
+
}
|
|
517
|
+
// Two members can normalize to the same text; the position keeps
|
|
518
|
+
// their hashes apart, and sorting keeps the position stable.
|
|
519
|
+
hash.update(`${i}`);
|
|
520
|
+
for (const asset of memberAssets) {
|
|
521
|
+
if (Buffer.isBuffer(asset.content)) {
|
|
522
|
+
hash.update(asset.content);
|
|
523
|
+
continue;
|
|
524
|
+
}
|
|
525
|
+
const withoutOwn =
|
|
526
|
+
/** @type {Hashes} */
|
|
527
|
+
(asset.ownHashes).has(oldHash);
|
|
528
|
+
hash.update(
|
|
529
|
+
asset.content.replace(hashRegExp, (matched) => {
|
|
530
|
+
// Its own occurrences vanish, exactly as a lone hash's do.
|
|
531
|
+
if (
|
|
532
|
+
withoutOwn &&
|
|
533
|
+
/** @type {Hashes} */ (asset.ownHashes).has(matched)
|
|
534
|
+
) {
|
|
535
|
+
return "";
|
|
536
|
+
}
|
|
537
|
+
const marker = markerOf.get(matched);
|
|
538
|
+
if (marker !== undefined) return marker;
|
|
539
|
+
const mapped = hashToNewHash.get(matched);
|
|
540
|
+
return mapped === undefined ? matched : mapped;
|
|
541
|
+
})
|
|
542
|
+
);
|
|
543
|
+
}
|
|
544
|
+
const digest = hash.digest(
|
|
545
|
+
/** @type {HashDigest} */ (
|
|
546
|
+
hashToDigest.get(oldHash) || this._hashDigest
|
|
547
|
+
)
|
|
548
|
+
);
|
|
549
|
+
hashToNewHash.set(oldHash, digest.slice(0, oldHash.length));
|
|
550
|
+
}
|
|
551
|
+
continue;
|
|
552
|
+
}
|
|
553
|
+
const oldHash = group[0];
|
|
478
554
|
const assets =
|
|
479
555
|
/** @type {AssetInfoForRealContentHash[]} */
|
|
480
556
|
(hashToAssets.get(oldHash));
|
|
@@ -481,19 +481,13 @@ const collectStartupAssetHintLines = (
|
|
|
481
481
|
seenWorkerChunks.add(workerChunk.id);
|
|
482
482
|
// The same specifier the `new Worker(...)` call site bakes, asked of the
|
|
483
483
|
// same module, so the two agree on whether a literal is spellable.
|
|
484
|
-
const specifier = runtimeTemplate.
|
|
485
|
-
|
|
484
|
+
const specifier = runtimeTemplate.getAnalyzableWorkerUrl(
|
|
485
|
+
dep.options.publicPath,
|
|
486
|
+
workerChunk,
|
|
487
|
+
module,
|
|
486
488
|
chunkGraph,
|
|
487
|
-
|
|
488
|
-
)
|
|
489
|
-
? runtimeTemplate._getAnalyzableChunkSpecifier(
|
|
490
|
-
dep.options.publicPath,
|
|
491
|
-
workerChunk,
|
|
492
|
-
module,
|
|
493
|
-
chunkGraph,
|
|
494
|
-
set
|
|
495
|
-
)
|
|
496
|
-
: null;
|
|
489
|
+
set
|
|
490
|
+
);
|
|
497
491
|
// Without one the call site keeps the runtime form, where it wraps its own
|
|
498
492
|
// href — firing the `<link>` here too would emit the call twice.
|
|
499
493
|
if (specifier === null) continue;
|
|
@@ -461,7 +461,7 @@ class ObjectMiddleware extends SerializerMiddleware {
|
|
|
461
461
|
return buf;
|
|
462
462
|
};
|
|
463
463
|
let currentPosTypeLookup = 0;
|
|
464
|
-
/** @type {Map<
|
|
464
|
+
/** @type {Map<SerializerConfigWithSerializer, number>} */
|
|
465
465
|
let objectTypeLookup = new Map();
|
|
466
466
|
/** @type {Set<ComplexSerializableType>} */
|
|
467
467
|
const cycleStack = new Set();
|
|
@@ -573,140 +573,160 @@ class ObjectMiddleware extends SerializerMiddleware {
|
|
|
573
573
|
...context
|
|
574
574
|
};
|
|
575
575
|
this.extendContext(ctx);
|
|
576
|
+
// Dispatched on `typeof` first: two thirds of the items are numbers,
|
|
577
|
+
// booleans and `undefined`, and only 3% are buffers.
|
|
576
578
|
/**
|
|
577
579
|
* Processes the provided item.
|
|
578
580
|
* @param {ComplexSerializableType} item item to serialize
|
|
579
581
|
*/
|
|
580
582
|
const process = (item) => {
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
result.push(ESCAPE, ref - currentPos);
|
|
583
|
+
switch (typeof item) {
|
|
584
|
+
case "number":
|
|
585
|
+
case "boolean":
|
|
586
|
+
result.push(item);
|
|
586
587
|
return;
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
588
|
+
case "string": {
|
|
589
|
+
if (item.length > 1) {
|
|
590
|
+
// short strings are shorter when not emitting a reference (this saves 1 byte per empty string)
|
|
591
|
+
// check if we can emit a reference
|
|
592
|
+
const ref = referenceable.get(item);
|
|
593
|
+
if (ref !== undefined) {
|
|
594
|
+
const offset = ref - currentPos;
|
|
595
|
+
if (
|
|
596
|
+
// One far ref → 5 bytes (`null` + offset), one near ref -> 2/3 bytes
|
|
597
|
+
offset >= -32768 ||
|
|
598
|
+
// long enough that the ref wins, keep it
|
|
599
|
+
item.length >= 4 ||
|
|
600
|
+
// multibyte → inline would be even bigger, keep it
|
|
601
|
+
Buffer.byteLength(item) !== item.length
|
|
602
|
+
) {
|
|
603
|
+
// A back-reference is `null` + the offset.
|
|
604
|
+
result.push(ESCAPE, offset);
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
addReferenceable(item);
|
|
595
609
|
}
|
|
596
|
-
item = alreadyUsedBuffer;
|
|
597
|
-
}
|
|
598
|
-
addReferenceable(item);
|
|
599
610
|
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
if (ref !== undefined) {
|
|
610
|
-
result.push(ESCAPE, ref - currentPos);
|
|
611
|
+
if (item.length > 102400 && context.logger) {
|
|
612
|
+
context.logger.warn(
|
|
613
|
+
`Serializing big strings (${Math.round(
|
|
614
|
+
item.length / 1024
|
|
615
|
+
)}kiB) impacts deserialization performance (consider using Buffer instead and decode when needed)`
|
|
616
|
+
);
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
result.push(item);
|
|
611
620
|
return;
|
|
612
621
|
}
|
|
622
|
+
case "undefined":
|
|
623
|
+
result.push(ESCAPE, ESCAPE_UNDEFINED);
|
|
624
|
+
return;
|
|
625
|
+
case "object": {
|
|
626
|
+
// ESCAPE is null, so this covers null too
|
|
627
|
+
if (item === ESCAPE) {
|
|
628
|
+
result.push(ESCAPE, ESCAPE_ESCAPE_VALUE);
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
613
631
|
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
632
|
+
if (Buffer.isBuffer(item)) {
|
|
633
|
+
// check if we can emit a reference
|
|
634
|
+
const ref = referenceable.get(item);
|
|
635
|
+
if (ref !== undefined) {
|
|
636
|
+
result.push(ESCAPE, ref - currentPos);
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
const alreadyUsedBuffer = dedupeBuffer(item);
|
|
640
|
+
if (alreadyUsedBuffer !== item) {
|
|
641
|
+
const ref = referenceable.get(alreadyUsedBuffer);
|
|
642
|
+
if (ref !== undefined) {
|
|
643
|
+
referenceable.set(item, ref);
|
|
644
|
+
result.push(ESCAPE, ref - currentPos);
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
item = alreadyUsedBuffer;
|
|
648
|
+
}
|
|
649
|
+
addReferenceable(item);
|
|
619
650
|
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
);
|
|
624
|
-
const key = `${request}/${name}`;
|
|
625
|
-
const lastIndex = objectTypeLookup.get(key);
|
|
651
|
+
result.push(/** @type {Buffer} */ (item));
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
626
654
|
|
|
627
|
-
|
|
628
|
-
|
|
655
|
+
// check if we can emit a reference
|
|
656
|
+
const ref = referenceable.get(item);
|
|
657
|
+
if (ref !== undefined) {
|
|
658
|
+
result.push(ESCAPE, ref - currentPos);
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
629
661
|
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
662
|
+
if (cycleStack.has(item)) {
|
|
663
|
+
throw new Error(
|
|
664
|
+
"This is a circular references. To serialize circular references use 'setCircularReference' somewhere in the circle during serialize and deserialize."
|
|
665
|
+
);
|
|
666
|
+
}
|
|
634
667
|
|
|
635
|
-
|
|
668
|
+
// Keyed by the registration itself: one per class, so it stands in for
|
|
669
|
+
// `${request}/${name}` without building that string per object.
|
|
670
|
+
const config = ObjectMiddleware.getSerializerFor(
|
|
671
|
+
/** @type {Constructor} */
|
|
672
|
+
(item)
|
|
673
|
+
);
|
|
674
|
+
const { request, name, serializer } = config;
|
|
675
|
+
const lastIndex = objectTypeLookup.get(config);
|
|
636
676
|
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
} finally {
|
|
640
|
-
cycleStack.delete(item);
|
|
641
|
-
}
|
|
677
|
+
if (lastIndex === undefined) {
|
|
678
|
+
objectTypeLookup.set(config, currentPosTypeLookup++);
|
|
642
679
|
|
|
643
|
-
|
|
680
|
+
result.push(ESCAPE, request, name);
|
|
681
|
+
} else {
|
|
682
|
+
result.push(ESCAPE, currentPosTypeLookup - lastIndex);
|
|
683
|
+
}
|
|
644
684
|
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
if (ref !== undefined) {
|
|
652
|
-
const offset = ref - currentPos;
|
|
653
|
-
if (
|
|
654
|
-
// One far ref → 5 bytes (`null` + offset), one near ref -> 2/3 bytes
|
|
655
|
-
offset >= -32768 ||
|
|
656
|
-
// long enough that the ref wins, keep it
|
|
657
|
-
item.length >= 4 ||
|
|
658
|
-
// multibyte → inline would be even bigger, keep it
|
|
659
|
-
Buffer.byteLength(item) !== item.length
|
|
660
|
-
) {
|
|
661
|
-
// A back-reference is `null` + the offset.
|
|
662
|
-
result.push(ESCAPE, offset);
|
|
663
|
-
return;
|
|
664
|
-
}
|
|
685
|
+
cycleStack.add(item);
|
|
686
|
+
|
|
687
|
+
try {
|
|
688
|
+
serializer.serialize(item, ctx);
|
|
689
|
+
} finally {
|
|
690
|
+
cycleStack.delete(item);
|
|
665
691
|
}
|
|
666
|
-
addReferenceable(item);
|
|
667
|
-
}
|
|
668
692
|
|
|
669
|
-
|
|
670
|
-
context.logger.warn(
|
|
671
|
-
`Serializing big strings (${Math.round(
|
|
672
|
-
item.length / 1024
|
|
673
|
-
)}kiB) impacts deserialization performance (consider using Buffer instead and decode when needed)`
|
|
674
|
-
);
|
|
675
|
-
}
|
|
693
|
+
result.push(ESCAPE, ESCAPE_END_OBJECT);
|
|
676
694
|
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
if (!SerializerMiddleware.isLazy(item)) {
|
|
680
|
-
throw new Error(`Unexpected function ${item}`);
|
|
695
|
+
addReferenceable(item);
|
|
696
|
+
return;
|
|
681
697
|
}
|
|
698
|
+
case "function": {
|
|
699
|
+
if (!SerializerMiddleware.isLazy(item)) {
|
|
700
|
+
throw new Error(`Unexpected function ${item}`);
|
|
701
|
+
}
|
|
682
702
|
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
703
|
+
/** @type {SerializedType | undefined} */
|
|
704
|
+
const serializedData =
|
|
705
|
+
SerializerMiddleware.getLazySerializedValue(item);
|
|
686
706
|
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
707
|
+
if (serializedData !== undefined) {
|
|
708
|
+
if (typeof serializedData === "function") {
|
|
709
|
+
result.push(serializedData);
|
|
710
|
+
} else {
|
|
711
|
+
throw new Error("Not implemented");
|
|
712
|
+
}
|
|
713
|
+
} else if (SerializerMiddleware.isLazy(item, this)) {
|
|
691
714
|
throw new Error("Not implemented");
|
|
715
|
+
} else {
|
|
716
|
+
const data =
|
|
717
|
+
/** @type {() => PrimitiveSerializableType[] | Promise<PrimitiveSerializableType[]>} */
|
|
718
|
+
(
|
|
719
|
+
SerializerMiddleware.serializeLazy(item, (data) =>
|
|
720
|
+
this.serialize([data], context)
|
|
721
|
+
)
|
|
722
|
+
);
|
|
723
|
+
SerializerMiddleware.setLazySerializedValue(item, data);
|
|
724
|
+
result.push(data);
|
|
692
725
|
}
|
|
693
|
-
|
|
694
|
-
throw new Error("Not implemented");
|
|
695
|
-
} else {
|
|
696
|
-
const data =
|
|
697
|
-
/** @type {() => PrimitiveSerializableType[] | Promise<PrimitiveSerializableType[]>} */
|
|
698
|
-
(
|
|
699
|
-
SerializerMiddleware.serializeLazy(item, (data) =>
|
|
700
|
-
this.serialize([data], context)
|
|
701
|
-
)
|
|
702
|
-
);
|
|
703
|
-
SerializerMiddleware.setLazySerializedValue(item, data);
|
|
704
|
-
result.push(data);
|
|
726
|
+
return;
|
|
705
727
|
}
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
} else {
|
|
709
|
-
result.push(item);
|
|
728
|
+
default:
|
|
729
|
+
result.push(item);
|
|
710
730
|
}
|
|
711
731
|
};
|
|
712
732
|
|
|
@@ -14,7 +14,7 @@ const {
|
|
|
14
14
|
} = require("../ModuleTypeConstants");
|
|
15
15
|
const NormalModule = require("../NormalModule");
|
|
16
16
|
const memoize = require("../util/memoize");
|
|
17
|
-
const
|
|
17
|
+
const { removeBOMFromResult } = require("../util/removeBOM");
|
|
18
18
|
|
|
19
19
|
const getModuleBuildError = memoize(() =>
|
|
20
20
|
require("../errors/ModuleBuildError")
|
|
@@ -133,15 +133,11 @@ const stripTypes = (input) => {
|
|
|
133
133
|
};
|
|
134
134
|
|
|
135
135
|
/**
|
|
136
|
-
* Coerce a Buffer-or-string source to a UTF-8 string, dropping any BOM.
|
|
137
136
|
* @param {string | Buffer} source raw source from the loader pipeline
|
|
138
|
-
* @returns {string} UTF-8 string
|
|
137
|
+
* @returns {string} UTF-8 string
|
|
139
138
|
*/
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
const stripped = removeBOM(text);
|
|
143
|
-
return typeof stripped === "string" ? stripped : stripped.toString("utf8");
|
|
144
|
-
};
|
|
139
|
+
const asString = (source) =>
|
|
140
|
+
Buffer.isBuffer(source) ? source.toString("utf8") : source;
|
|
145
141
|
|
|
146
142
|
class TypeScriptPlugin {
|
|
147
143
|
/**
|
|
@@ -181,8 +177,10 @@ class TypeScriptPlugin {
|
|
|
181
177
|
throw new (getModuleBuildError())(new Error(NODE_API_MISSING));
|
|
182
178
|
}
|
|
183
179
|
|
|
184
|
-
|
|
185
|
-
|
|
180
|
+
// A BOM must be off the source before it is stripped of types, and its
|
|
181
|
+
// map moved with it.
|
|
182
|
+
const [rawSource, loaderSourceMap, ...rest] = removeBOMFromResult(result);
|
|
183
|
+
const preStripSource = asString(rawSource);
|
|
186
184
|
const strippedSource = stripTypes(preStripSource);
|
|
187
185
|
|
|
188
186
|
const needSourceMap = module.useSourceMap || module.useSimpleSourceMap;
|
|
@@ -99,6 +99,23 @@ const expandDeferredWrites = (text, resolve, infix) => {
|
|
|
99
99
|
return out + text.slice(from);
|
|
100
100
|
};
|
|
101
101
|
|
|
102
|
+
/**
|
|
103
|
+
* The text this print spells with every deferred write declined: each marker
|
|
104
|
+
* replaced by what would stand there had no renderer answered. What a print
|
|
105
|
+
* verifying itself by re-parsing has to read, since a marker otherwise parses
|
|
106
|
+
* as text where its node stood. `build` rather than `source` so a write inside
|
|
107
|
+
* an attribute comes back escaped for where it sits.
|
|
108
|
+
* @param {string} text the printed output, holding this print's markers
|
|
109
|
+
* @param {DeferredWrite[]} writes what the print deferred, indexed by id
|
|
110
|
+
* @returns {string} the text with every marker put back
|
|
111
|
+
*/
|
|
112
|
+
const declineDeferredWrites = (text, writes) =>
|
|
113
|
+
expandDeferredWrites(
|
|
114
|
+
text,
|
|
115
|
+
(id) => (id < writes.length ? writes[id].build(undefined) : undefined),
|
|
116
|
+
deferredInfix
|
|
117
|
+
);
|
|
118
|
+
|
|
102
119
|
/**
|
|
103
120
|
* Babel-style visitor map keyed by a numeric node-type discriminator; a bucket
|
|
104
121
|
* is a function (enter-only) or `{ enter?, exit? }`.
|
|
@@ -389,16 +406,14 @@ class PrintContext {
|
|
|
389
406
|
_growStore(need) {
|
|
390
407
|
// From empty: a context that prints one inline `style=""` must not pay for
|
|
391
408
|
// a stylesheet's worth of columns.
|
|
392
|
-
const
|
|
393
|
-
|
|
394
|
-
//
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
for (let i =
|
|
398
|
-
for (let i = held.length; i < size; i++) text.push("");
|
|
409
|
+
const text = this._storeText;
|
|
410
|
+
const size = Math.max(need, text.length * 2, 16);
|
|
411
|
+
// Appended in place: `push` keeps the column packed for the read every
|
|
412
|
+
// composed child makes, and what it already holds never moves — where
|
|
413
|
+
// filling a second array would copy every slot again at each growth.
|
|
414
|
+
for (let i = text.length; i < size; i++) text.push("");
|
|
399
415
|
const gen = new Int32Array(size);
|
|
400
416
|
gen.set(this._storeGen);
|
|
401
|
-
this._storeText = text;
|
|
402
417
|
this._storeGen = gen;
|
|
403
418
|
}
|
|
404
419
|
|
|
@@ -1142,4 +1157,5 @@ class SourceProcessor {
|
|
|
1142
1157
|
SourceProcessor.PrintContext = PrintContext;
|
|
1143
1158
|
|
|
1144
1159
|
module.exports = SourceProcessor;
|
|
1160
|
+
module.exports.declineDeferredWrites = declineDeferredWrites;
|
|
1145
1161
|
module.exports.deferredWrite = deferredWrite;
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
* while richer call sites can pass arrays of segments.
|
|
14
14
|
*
|
|
15
15
|
* TODO move this encoder into `webpack-sources` and replace the body of this
|
|
16
|
-
* file with re-exports. The public shape (`encodeVLQ`, `
|
|
17
|
-
* `MappingSegment`, `LineMappings`) is intended to
|
|
18
|
-
* upstream so call sites don't have to change.
|
|
16
|
+
* file with re-exports. The public shape (`encodeVLQ`, `decodeVLQ`,
|
|
17
|
+
* `encodeMappings(lines)`, `MappingSegment`, `LineMappings`) is intended to
|
|
18
|
+
* match what would land upstream so call sites don't have to change.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
const VLQ_BASE64 =
|
|
@@ -38,6 +38,27 @@ const encodeVLQ = (value) => {
|
|
|
38
38
|
return result;
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Decode one base64 VLQ value per the source-map V3 spec.
|
|
43
|
+
* @param {string} mappings a VLQ encoded `mappings` string
|
|
44
|
+
* @param {number} start index of the value's first character
|
|
45
|
+
* @returns {{ value: number, end: number }} the decoded value and the index just past it; `end` equals `start` when there is no valid value at `start`
|
|
46
|
+
*/
|
|
47
|
+
const decodeVLQ = (mappings, start) => {
|
|
48
|
+
let value = 0;
|
|
49
|
+
let shift = 0;
|
|
50
|
+
let index = start;
|
|
51
|
+
let digit;
|
|
52
|
+
do {
|
|
53
|
+
digit = index < mappings.length ? VLQ_BASE64.indexOf(mappings[index]) : -1;
|
|
54
|
+
if (digit < 0) return { value: 0, end: start };
|
|
55
|
+
value += (digit & 0x1f) << shift;
|
|
56
|
+
shift += 5;
|
|
57
|
+
index++;
|
|
58
|
+
} while (digit & 0x20);
|
|
59
|
+
return { value: value & 1 ? -(value >>> 1) : value >>> 1, end: index };
|
|
60
|
+
};
|
|
61
|
+
|
|
41
62
|
/**
|
|
42
63
|
* @typedef {object} MappingSegment
|
|
43
64
|
* @property {number=} generatedColumn 0-based generated column (defaults to 0)
|
|
@@ -114,5 +135,6 @@ const encodeMappings = (lines) => {
|
|
|
114
135
|
return encodedLines.join(";");
|
|
115
136
|
};
|
|
116
137
|
|
|
138
|
+
module.exports.decodeVLQ = decodeVLQ;
|
|
117
139
|
module.exports.encodeMappings = encodeMappings;
|
|
118
140
|
module.exports.encodeVLQ = encodeVLQ;
|