webpack 5.10.0 → 5.11.0
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.
Potentially problematic release.
This version of webpack might be problematic. Click here for more details.
- package/bin/webpack.js +0 -0
- package/lib/Compilation.js +5 -21
- package/lib/Compiler.js +58 -13
- package/lib/FlagAllModulesAsUsedPlugin.js +4 -0
- package/lib/MainTemplate.js +2 -2
- package/lib/Module.js +1 -1
- package/lib/ModuleInfoHeaderPlugin.js +1 -1
- package/lib/NormalModule.js +4 -2
- package/lib/RuntimeGlobals.js +11 -1
- package/lib/RuntimeModule.js +20 -0
- package/lib/RuntimeTemplate.js +4 -0
- package/lib/cache/PackFileCacheStrategy.js +4 -2
- package/lib/hmr/HotModuleReplacementRuntimeModule.js +1 -1
- package/lib/index.js +5 -0
- package/lib/javascript/JavascriptModulesPlugin.js +82 -26
- package/lib/node/NodeTargetPlugin.js +4 -0
- package/lib/node/ReadFileChunkLoadingRuntimeModule.js +1 -1
- package/lib/node/RequireChunkLoadingRuntimeModule.js +1 -1
- package/lib/optimize/SideEffectsFlagPlugin.js +9 -13
- package/lib/prefetch/ChunkPrefetchFunctionRuntimeModule.js +1 -1
- package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +1 -1
- package/lib/prefetch/ChunkPrefetchStartupRuntimeModule.js +1 -1
- package/lib/prefetch/ChunkPrefetchTriggerRuntimeModule.js +1 -1
- package/lib/rules/RuleSetCompiler.js +4 -2
- package/lib/runtime/AutoPublicPathRuntimeModule.js +1 -1
- package/lib/runtime/CompatRuntimeModule.js +1 -1
- package/lib/runtime/PublicPathRuntimeModule.js +1 -1
- package/lib/serialization/BinaryMiddleware.js +467 -136
- package/lib/serialization/FileMiddleware.js +227 -37
- package/lib/serialization/ObjectMiddleware.js +89 -5
- package/lib/sharing/ConsumeSharedRuntimeModule.js +1 -1
- package/lib/util/fs.js +4 -0
- package/lib/util/source.js +61 -0
- package/lib/validateSchema.js +84 -73
- package/lib/wasm-async/AsyncWasmChunkLoadingRuntimeModule.js +1 -1
- package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +1 -1
- package/lib/web/JsonpChunkLoadingRuntimeModule.js +54 -55
- package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +1 -1
- package/package.json +8 -8
- package/types.d.ts +1170 -578
@@ -4,6 +4,7 @@
|
|
4
4
|
|
5
5
|
"use strict";
|
6
6
|
|
7
|
+
const { constants } = require("buffer");
|
7
8
|
const createHash = require("../util/createHash");
|
8
9
|
const { dirname, join, mkdirp } = require("../util/fs");
|
9
10
|
const memorize = require("../util/memorize");
|
@@ -28,14 +29,35 @@ Section -> Buffer
|
|
28
29
|
|
29
30
|
*/
|
30
31
|
|
31
|
-
// "wpc" +
|
32
|
-
const VERSION =
|
32
|
+
// "wpc" + 1 in little-endian
|
33
|
+
const VERSION = 0x01637077;
|
33
34
|
const hashForName = buffers => {
|
34
35
|
const hash = createHash("md4");
|
35
36
|
for (const buf of buffers) hash.update(buf);
|
36
37
|
return /** @type {string} */ (hash.digest("hex"));
|
37
38
|
};
|
38
39
|
|
40
|
+
const writeUInt64LE = Buffer.prototype.writeBigUInt64LE
|
41
|
+
? (buf, value, offset) => {
|
42
|
+
buf.writeBigUInt64LE(BigInt(value), offset);
|
43
|
+
}
|
44
|
+
: (buf, value, offset) => {
|
45
|
+
const low = value % 0x100000000;
|
46
|
+
const high = (value - low) / 0x100000000;
|
47
|
+
buf.writeUInt32LE(low, offset);
|
48
|
+
buf.writeUInt32LE(high, offset + 4);
|
49
|
+
};
|
50
|
+
|
51
|
+
const readUInt64LE = Buffer.prototype.readBigUInt64LE
|
52
|
+
? (buf, offset) => {
|
53
|
+
return Number(buf.readBigUInt64LE(offset));
|
54
|
+
}
|
55
|
+
: (buf, offset) => {
|
56
|
+
const low = buf.readUInt32LE(offset);
|
57
|
+
const high = buf.readUInt32LE(offset + 4);
|
58
|
+
return high * 0x100000000 + low;
|
59
|
+
};
|
60
|
+
|
39
61
|
/**
|
40
62
|
* @typedef {Object} SerializeResult
|
41
63
|
* @property {string | false} name
|
@@ -122,24 +144,29 @@ const serialize = async (middleware, data, name, writeFile) => {
|
|
122
144
|
// create pointer buffer from size and name
|
123
145
|
const name = /** @type {string} */ (item.name);
|
124
146
|
const nameBuffer = Buffer.from(name);
|
125
|
-
const buf = Buffer.allocUnsafe(
|
126
|
-
buf
|
127
|
-
nameBuffer.copy(buf,
|
147
|
+
const buf = Buffer.allocUnsafe(8 + nameBuffer.length);
|
148
|
+
writeUInt64LE(buf, item.size, 0);
|
149
|
+
nameBuffer.copy(buf, 8, 0);
|
128
150
|
const lazy = resultToLazy.get(item);
|
129
151
|
SerializerMiddleware.setLazySerializedValue(lazy, buf);
|
130
152
|
return buf;
|
131
153
|
});
|
132
|
-
const lengths =
|
154
|
+
const lengths = [];
|
155
|
+
for (const item of resolvedData) {
|
133
156
|
if (Array.isArray(item)) {
|
134
157
|
let l = 0;
|
135
158
|
for (const b of item) l += b.length;
|
136
|
-
|
159
|
+
while (l > 0x7fffffff) {
|
160
|
+
lengths.push(0x7fffffff);
|
161
|
+
l -= 0x7fffffff;
|
162
|
+
}
|
163
|
+
lengths.push(l);
|
137
164
|
} else if (item) {
|
138
|
-
|
165
|
+
lengths.push(-item.length);
|
139
166
|
} else {
|
140
167
|
throw new Error("Unexpected falsy value in resolved data " + item);
|
141
168
|
}
|
142
|
-
}
|
169
|
+
}
|
143
170
|
const header = Buffer.allocUnsafe(8 + lengths.length * 4);
|
144
171
|
header.writeUInt32LE(VERSION, 0);
|
145
172
|
header.writeUInt32LE(lengths.length, 4);
|
@@ -173,45 +200,145 @@ const serialize = async (middleware, data, name, writeFile) => {
|
|
173
200
|
/**
|
174
201
|
* @param {FileMiddleware} middleware this
|
175
202
|
* @param {string | false} name filename
|
176
|
-
* @param {function(string | false): Promise<Buffer>} readFile read content of a file
|
203
|
+
* @param {function(string | false): Promise<Buffer[]>} readFile read content of a file
|
177
204
|
* @returns {Promise<BufferSerializableType[]>} deserialized data
|
178
205
|
*/
|
179
206
|
const deserialize = async (middleware, name, readFile) => {
|
180
|
-
const
|
181
|
-
if (
|
182
|
-
|
207
|
+
const contents = await readFile(name);
|
208
|
+
if (contents.length === 0) throw new Error("Empty file " + name);
|
209
|
+
let contentsIndex = 0;
|
210
|
+
let contentItem = contents[0];
|
211
|
+
let contentItemLength = contentItem.length;
|
212
|
+
let contentPosition = 0;
|
213
|
+
if (contentItemLength === 0) throw new Error("Empty file " + name);
|
214
|
+
const nextContent = () => {
|
215
|
+
contentsIndex++;
|
216
|
+
contentItem = contents[contentsIndex];
|
217
|
+
contentItemLength = contentItem.length;
|
218
|
+
contentPosition = 0;
|
219
|
+
};
|
220
|
+
const ensureData = n => {
|
221
|
+
if (contentPosition === contentItemLength) {
|
222
|
+
nextContent();
|
223
|
+
}
|
224
|
+
while (contentItemLength - contentPosition < n) {
|
225
|
+
const remaining = contentItem.slice(contentPosition);
|
226
|
+
let lengthFromNext = n - remaining.length;
|
227
|
+
const buffers = [remaining];
|
228
|
+
for (let i = contentsIndex + 1; i < contents.length; i++) {
|
229
|
+
const l = contents[i].length;
|
230
|
+
if (l > lengthFromNext) {
|
231
|
+
buffers.push(contents[i].slice(0, lengthFromNext));
|
232
|
+
contents[i] = contents[i].slice(lengthFromNext);
|
233
|
+
lengthFromNext = 0;
|
234
|
+
break;
|
235
|
+
} else {
|
236
|
+
buffers.push(contents[i]);
|
237
|
+
contentsIndex = i;
|
238
|
+
lengthFromNext -= l;
|
239
|
+
}
|
240
|
+
}
|
241
|
+
if (lengthFromNext > 0) throw new Error("Unexpected end of data");
|
242
|
+
contentItem = Buffer.concat(buffers, n);
|
243
|
+
contentItemLength = n;
|
244
|
+
contentPosition = 0;
|
245
|
+
}
|
246
|
+
};
|
247
|
+
const readUInt32LE = () => {
|
248
|
+
ensureData(4);
|
249
|
+
const value = contentItem.readUInt32LE(contentPosition);
|
250
|
+
contentPosition += 4;
|
251
|
+
return value;
|
252
|
+
};
|
253
|
+
const readInt32LE = () => {
|
254
|
+
ensureData(4);
|
255
|
+
const value = contentItem.readInt32LE(contentPosition);
|
256
|
+
contentPosition += 4;
|
257
|
+
return value;
|
258
|
+
};
|
259
|
+
const readSlice = l => {
|
260
|
+
ensureData(l);
|
261
|
+
if (contentPosition === 0 && contentItemLength === l) {
|
262
|
+
const result = contentItem;
|
263
|
+
if (contentsIndex + 1 < contents.length) {
|
264
|
+
nextContent();
|
265
|
+
} else {
|
266
|
+
contentPosition = l;
|
267
|
+
}
|
268
|
+
return result;
|
269
|
+
}
|
270
|
+
const result = contentItem.slice(contentPosition, contentPosition + l);
|
271
|
+
contentPosition += l;
|
272
|
+
// we clone the buffer here to allow the original content to be garbage collected
|
273
|
+
return l * 2 < contentItem.buffer.byteLength ? Buffer.from(result) : result;
|
274
|
+
};
|
275
|
+
const version = readUInt32LE();
|
183
276
|
if (version !== VERSION) {
|
184
277
|
throw new Error("Invalid file version");
|
185
278
|
}
|
186
|
-
const sectionCount =
|
279
|
+
const sectionCount = readUInt32LE();
|
187
280
|
const lengths = [];
|
188
281
|
for (let i = 0; i < sectionCount; i++) {
|
189
|
-
lengths.push(
|
282
|
+
lengths.push(readInt32LE());
|
190
283
|
}
|
191
|
-
|
192
|
-
|
193
|
-
const l = Math.abs(length);
|
194
|
-
const section = content.slice(position, position + l);
|
195
|
-
position += l;
|
284
|
+
const result = [];
|
285
|
+
for (let length of lengths) {
|
196
286
|
if (length < 0) {
|
197
|
-
|
198
|
-
const
|
199
|
-
const
|
200
|
-
const nameBuffer = clone.slice(4);
|
287
|
+
const slice = readSlice(-length);
|
288
|
+
const size = Number(readUInt64LE(slice, 0));
|
289
|
+
const nameBuffer = slice.slice(8);
|
201
290
|
const name = nameBuffer.toString();
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
291
|
+
result.push(
|
292
|
+
SerializerMiddleware.createLazy(
|
293
|
+
memorize(() => deserialize(middleware, name, readFile)),
|
294
|
+
middleware,
|
295
|
+
{
|
296
|
+
name,
|
297
|
+
size
|
298
|
+
},
|
299
|
+
slice
|
300
|
+
)
|
210
301
|
);
|
211
302
|
} else {
|
212
|
-
|
303
|
+
if (contentPosition === contentItemLength) {
|
304
|
+
nextContent();
|
305
|
+
} else if (contentPosition !== 0) {
|
306
|
+
if (length <= contentItemLength - contentPosition) {
|
307
|
+
result.push(
|
308
|
+
contentItem.slice(contentPosition, contentPosition + length)
|
309
|
+
);
|
310
|
+
contentPosition += length;
|
311
|
+
length = 0;
|
312
|
+
} else {
|
313
|
+
result.push(contentItem.slice(contentPosition));
|
314
|
+
length -= contentItemLength - contentPosition;
|
315
|
+
contentPosition = contentItemLength;
|
316
|
+
}
|
317
|
+
} else {
|
318
|
+
if (length >= contentItemLength) {
|
319
|
+
result.push(contentItem);
|
320
|
+
length -= contentItemLength;
|
321
|
+
contentPosition = contentItemLength;
|
322
|
+
} else {
|
323
|
+
result.push(contentItem.slice(0, length));
|
324
|
+
contentPosition += length;
|
325
|
+
length = 0;
|
326
|
+
}
|
327
|
+
}
|
328
|
+
while (length > 0) {
|
329
|
+
nextContent();
|
330
|
+
if (length >= contentItemLength) {
|
331
|
+
result.push(contentItem);
|
332
|
+
length -= contentItemLength;
|
333
|
+
contentPosition = contentItemLength;
|
334
|
+
} else {
|
335
|
+
result.push(contentItem.slice(0, length));
|
336
|
+
contentPosition += length;
|
337
|
+
length = 0;
|
338
|
+
}
|
339
|
+
}
|
213
340
|
}
|
214
|
-
}
|
341
|
+
}
|
215
342
|
return result;
|
216
343
|
};
|
217
344
|
|
@@ -309,9 +436,72 @@ class FileMiddleware extends SerializerMiddleware {
|
|
309
436
|
const file = name
|
310
437
|
? join(this.fs, filename, `../${name}${extension}`)
|
311
438
|
: filename;
|
312
|
-
|
313
|
-
if (err)
|
314
|
-
|
439
|
+
this.fs.stat(file, (err, stats) => {
|
440
|
+
if (err) {
|
441
|
+
reject(err);
|
442
|
+
return;
|
443
|
+
}
|
444
|
+
let remaining = stats.size;
|
445
|
+
let currentBuffer;
|
446
|
+
let currentBufferUsed;
|
447
|
+
const buf = [];
|
448
|
+
this.fs.open(file, "r", (err, fd) => {
|
449
|
+
if (err) {
|
450
|
+
reject(err);
|
451
|
+
return;
|
452
|
+
}
|
453
|
+
const read = () => {
|
454
|
+
if (currentBuffer === undefined) {
|
455
|
+
currentBuffer = Buffer.allocUnsafeSlow(
|
456
|
+
Math.min(constants.MAX_LENGTH, remaining)
|
457
|
+
);
|
458
|
+
currentBufferUsed = 0;
|
459
|
+
}
|
460
|
+
let readBuffer = currentBuffer;
|
461
|
+
let readOffset = currentBufferUsed;
|
462
|
+
let readLength = currentBuffer.length - currentBufferUsed;
|
463
|
+
if (readOffset > 0x7fffffff) {
|
464
|
+
readBuffer = currentBuffer.slice(readOffset);
|
465
|
+
readOffset = 0;
|
466
|
+
}
|
467
|
+
if (readLength > 0x7fffffff) {
|
468
|
+
readLength = 0x7fffffff;
|
469
|
+
}
|
470
|
+
this.fs.read(
|
471
|
+
fd,
|
472
|
+
readBuffer,
|
473
|
+
readOffset,
|
474
|
+
readLength,
|
475
|
+
null,
|
476
|
+
(err, bytesRead) => {
|
477
|
+
if (err) {
|
478
|
+
this.fs.close(fd, () => {
|
479
|
+
reject(err);
|
480
|
+
});
|
481
|
+
return;
|
482
|
+
}
|
483
|
+
currentBufferUsed += bytesRead;
|
484
|
+
remaining -= bytesRead;
|
485
|
+
if (currentBufferUsed === currentBuffer.length) {
|
486
|
+
buf.push(currentBuffer);
|
487
|
+
currentBuffer = undefined;
|
488
|
+
if (remaining === 0) {
|
489
|
+
this.fs.close(fd, err => {
|
490
|
+
if (err) {
|
491
|
+
reject(err);
|
492
|
+
return;
|
493
|
+
}
|
494
|
+
resolve(buf);
|
495
|
+
});
|
496
|
+
return;
|
497
|
+
}
|
498
|
+
}
|
499
|
+
read();
|
500
|
+
}
|
501
|
+
);
|
502
|
+
};
|
503
|
+
read();
|
504
|
+
});
|
315
505
|
});
|
316
506
|
});
|
317
507
|
return deserialize(this, false, readFile);
|
@@ -4,6 +4,7 @@
|
|
4
4
|
|
5
5
|
"use strict";
|
6
6
|
|
7
|
+
const createHash = require("../util/createHash");
|
7
8
|
const ArraySerializer = require("./ArraySerializer");
|
8
9
|
const DateObjectSerializer = require("./DateObjectSerializer");
|
9
10
|
const ErrorObjectSerializer = require("./ErrorObjectSerializer");
|
@@ -75,6 +76,12 @@ const setMapSize = (map, size) => {
|
|
75
76
|
}
|
76
77
|
};
|
77
78
|
|
79
|
+
const toHash = buffer => {
|
80
|
+
const hash = createHash("md4");
|
81
|
+
hash.update(buffer);
|
82
|
+
return /** @type {string} */ (hash.digest("latin1"));
|
83
|
+
};
|
84
|
+
|
78
85
|
const ESCAPE = null;
|
79
86
|
const ESCAPE_ESCAPE_VALUE = null;
|
80
87
|
const ESCAPE_END_OBJECT = true;
|
@@ -244,6 +251,68 @@ class ObjectMiddleware extends SerializerMiddleware {
|
|
244
251
|
const addReferenceable = item => {
|
245
252
|
referenceable.set(item, currentPos++);
|
246
253
|
};
|
254
|
+
const bufferDedupeMap = new Map();
|
255
|
+
const dedupeBuffer = buf => {
|
256
|
+
const len = buf.length;
|
257
|
+
const entry = bufferDedupeMap.get(len);
|
258
|
+
if (entry === undefined) {
|
259
|
+
bufferDedupeMap.set(len, buf);
|
260
|
+
return buf;
|
261
|
+
}
|
262
|
+
if (Buffer.isBuffer(entry)) {
|
263
|
+
if (len < 32) {
|
264
|
+
if (buf.equals(entry)) {
|
265
|
+
return entry;
|
266
|
+
}
|
267
|
+
bufferDedupeMap.set(len, [entry, buf]);
|
268
|
+
return buf;
|
269
|
+
} else {
|
270
|
+
const hash = toHash(entry);
|
271
|
+
const newMap = new Map();
|
272
|
+
newMap.set(hash, entry);
|
273
|
+
bufferDedupeMap.set(len, newMap);
|
274
|
+
const hashBuf = toHash(buf);
|
275
|
+
if (hash === hashBuf) {
|
276
|
+
return entry;
|
277
|
+
}
|
278
|
+
return buf;
|
279
|
+
}
|
280
|
+
} else if (Array.isArray(entry)) {
|
281
|
+
if (entry.length < 16) {
|
282
|
+
for (const item of entry) {
|
283
|
+
if (buf.equals(item)) {
|
284
|
+
return item;
|
285
|
+
}
|
286
|
+
}
|
287
|
+
entry.push(buf);
|
288
|
+
return buf;
|
289
|
+
} else {
|
290
|
+
const newMap = new Map();
|
291
|
+
const hash = toHash(buf);
|
292
|
+
let found;
|
293
|
+
for (const item of entry) {
|
294
|
+
const itemHash = toHash(item);
|
295
|
+
newMap.set(itemHash, item);
|
296
|
+
if (found === undefined && itemHash === hash) found = item;
|
297
|
+
}
|
298
|
+
bufferDedupeMap.set(len, newMap);
|
299
|
+
if (found === undefined) {
|
300
|
+
newMap.set(hash, buf);
|
301
|
+
return buf;
|
302
|
+
} else {
|
303
|
+
return found;
|
304
|
+
}
|
305
|
+
}
|
306
|
+
} else {
|
307
|
+
const hash = toHash(buf);
|
308
|
+
const item = entry.get(hash);
|
309
|
+
if (item !== undefined) {
|
310
|
+
return item;
|
311
|
+
}
|
312
|
+
entry.set(hash, buf);
|
313
|
+
return buf;
|
314
|
+
}
|
315
|
+
};
|
247
316
|
let currentPosTypeLookup = 0;
|
248
317
|
const objectTypeLookup = new Map();
|
249
318
|
const cycleStack = new Set();
|
@@ -339,6 +408,16 @@ class ObjectMiddleware extends SerializerMiddleware {
|
|
339
408
|
}
|
340
409
|
|
341
410
|
if (Buffer.isBuffer(item)) {
|
411
|
+
const alreadyUsedBuffer = dedupeBuffer(item);
|
412
|
+
if (alreadyUsedBuffer !== item) {
|
413
|
+
const ref = referenceable.get(alreadyUsedBuffer);
|
414
|
+
if (ref !== undefined) {
|
415
|
+
referenceable.set(item, ref);
|
416
|
+
result.push(ESCAPE, ref - currentPos);
|
417
|
+
return;
|
418
|
+
}
|
419
|
+
item = alreadyUsedBuffer;
|
420
|
+
}
|
342
421
|
addReferenceable(item);
|
343
422
|
|
344
423
|
result.push(item);
|
@@ -373,8 +452,8 @@ class ObjectMiddleware extends SerializerMiddleware {
|
|
373
452
|
|
374
453
|
addReferenceable(item);
|
375
454
|
} else if (typeof item === "string") {
|
376
|
-
if (item
|
377
|
-
//
|
455
|
+
if (item.length > 1) {
|
456
|
+
// short strings are shorter when not emitting a reference (this saves 1 byte per empty string)
|
378
457
|
addReferenceable(item);
|
379
458
|
}
|
380
459
|
|
@@ -449,13 +528,13 @@ class ObjectMiddleware extends SerializerMiddleware {
|
|
449
528
|
throw new Error("Version mismatch, serializer changed");
|
450
529
|
|
451
530
|
let currentPos = 0;
|
452
|
-
|
531
|
+
let referenceable = [];
|
453
532
|
const addReferenceable = item => {
|
454
533
|
referenceable.push(item);
|
455
534
|
currentPos++;
|
456
535
|
};
|
457
536
|
let currentPosTypeLookup = 0;
|
458
|
-
|
537
|
+
let objectTypeLookup = [];
|
459
538
|
const result = [];
|
460
539
|
const ctx = {
|
461
540
|
read() {
|
@@ -558,7 +637,7 @@ class ObjectMiddleware extends SerializerMiddleware {
|
|
558
637
|
}
|
559
638
|
}
|
560
639
|
} else if (typeof item === "string") {
|
561
|
-
if (item
|
640
|
+
if (item.length > 1) {
|
562
641
|
addReferenceable(item);
|
563
642
|
}
|
564
643
|
|
@@ -581,6 +660,11 @@ class ObjectMiddleware extends SerializerMiddleware {
|
|
581
660
|
result.push(decodeValue());
|
582
661
|
}
|
583
662
|
|
663
|
+
// Help the GC, as functions above might be cached in inline caches
|
664
|
+
referenceable = undefined;
|
665
|
+
objectTypeLookup = undefined;
|
666
|
+
data = undefined;
|
667
|
+
|
584
668
|
return result;
|
585
669
|
}
|
586
670
|
}
|
package/lib/util/fs.js
CHANGED
@@ -16,6 +16,7 @@ const path = require("path");
|
|
16
16
|
/** @typedef {function(NodeJS.ErrnoException=, Buffer|string=): void} BufferOrStringCallback */
|
17
17
|
/** @typedef {function(NodeJS.ErrnoException=, string[]=): void} StringArrayCallback */
|
18
18
|
/** @typedef {function(NodeJS.ErrnoException=, string=): void} StringCallback */
|
19
|
+
/** @typedef {function(NodeJS.ErrnoException=, number=): void} NumberCallback */
|
19
20
|
/** @typedef {function(NodeJS.ErrnoException=, NodeFsStats=): void} StatsCallback */
|
20
21
|
/** @typedef {function((NodeJS.ErrnoException | Error)=, any=): void} ReadJsonCallback */
|
21
22
|
|
@@ -73,6 +74,9 @@ const path = require("path");
|
|
73
74
|
* @typedef {Object} IntermediateFileSystemExtras
|
74
75
|
* @property {function(string): void} mkdirSync
|
75
76
|
* @property {function(string): import("fs").WriteStream} createWriteStream
|
77
|
+
* @property {function(string, string, NumberCallback): void} open
|
78
|
+
* @property {function(number, Buffer, number, number, number, NumberCallback): void} read
|
79
|
+
* @property {function(number, Callback): void} close
|
76
80
|
* @property {function(string, string, Callback): void} rename
|
77
81
|
*/
|
78
82
|
|
@@ -0,0 +1,61 @@
|
|
1
|
+
/*
|
2
|
+
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
+
Author Tobias Koppers @sokra
|
4
|
+
*/
|
5
|
+
|
6
|
+
"use strict";
|
7
|
+
|
8
|
+
/** @typedef {import("webpack-sources").Source} Source */
|
9
|
+
|
10
|
+
/** @type {WeakMap<Source, WeakMap<Source, boolean>>} */
|
11
|
+
const equalityCache = new WeakMap();
|
12
|
+
|
13
|
+
/**
|
14
|
+
* @param {Source} a a source
|
15
|
+
* @param {Source} b another source
|
16
|
+
* @returns {boolean} true, when both sources are equal
|
17
|
+
*/
|
18
|
+
const _isSourceEqual = (a, b) => {
|
19
|
+
// prefer .buffer(), it's called anyway during emit
|
20
|
+
/** @type {Buffer|string} */
|
21
|
+
let aSource = typeof a.buffer === "function" ? a.buffer() : a.source();
|
22
|
+
/** @type {Buffer|string} */
|
23
|
+
let bSource = typeof b.buffer === "function" ? b.buffer() : b.source();
|
24
|
+
if (aSource === bSource) return true;
|
25
|
+
if (typeof aSource === "string" && typeof bSource === "string") return false;
|
26
|
+
if (!Buffer.isBuffer(aSource)) aSource = Buffer.from(aSource, "utf-8");
|
27
|
+
if (!Buffer.isBuffer(bSource)) bSource = Buffer.from(bSource, "utf-8");
|
28
|
+
return aSource.equals(bSource);
|
29
|
+
};
|
30
|
+
|
31
|
+
/**
|
32
|
+
* @param {Source} a a source
|
33
|
+
* @param {Source} b another source
|
34
|
+
* @returns {boolean} true, when both sources are equal
|
35
|
+
*/
|
36
|
+
const isSourceEqual = (a, b) => {
|
37
|
+
if (a === b) return true;
|
38
|
+
const cache1 = equalityCache.get(a);
|
39
|
+
if (cache1 !== undefined) {
|
40
|
+
const result = cache1.get(b);
|
41
|
+
if (result !== undefined) return result;
|
42
|
+
}
|
43
|
+
const result = _isSourceEqual(a, b);
|
44
|
+
if (cache1 !== undefined) {
|
45
|
+
cache1.set(b, result);
|
46
|
+
} else {
|
47
|
+
const map = new WeakMap();
|
48
|
+
map.set(b, result);
|
49
|
+
equalityCache.set(a, map);
|
50
|
+
}
|
51
|
+
const cache2 = equalityCache.get(b);
|
52
|
+
if (cache2 !== undefined) {
|
53
|
+
cache2.set(a, result);
|
54
|
+
} else {
|
55
|
+
const map = new WeakMap();
|
56
|
+
map.set(a, result);
|
57
|
+
equalityCache.set(b, map);
|
58
|
+
}
|
59
|
+
return result;
|
60
|
+
};
|
61
|
+
exports.isSourceEqual = isSourceEqual;
|