diff --git a/lib/TemplatedPathPlugin.js b/lib/TemplatedPathPlugin.js index 27d5faf31..5cfa7e23c 100644 --- a/lib/TemplatedPathPlugin.js +++ b/lib/TemplatedPathPlugin.js @@ -116,32 +116,30 @@ const replacePathVariables = (path, data, assetInfo) => { // [path] - /some/path/ // [name] - file // [ext] - .js - if (data.filename) { - if (typeof data.filename === "string") { - const { path: file, query, fragment } = parseResource(data.filename); + if (typeof data.filename === "string") { + const { path: file, query, fragment } = parseResource(data.filename); - const ext = extname(file); - const base = basename(file); - const name = base.slice(0, base.length - ext.length); - const path = file.slice(0, file.length - base.length); + const ext = extname(file); + const base = basename(file); + const name = base.slice(0, base.length - ext.length); + const path = file.slice(0, file.length - base.length); - replacements.set("file", replacer(file)); - replacements.set("query", replacer(query, true)); - replacements.set("fragment", replacer(fragment, true)); - replacements.set("path", replacer(path, true)); - replacements.set("base", replacer(base)); - replacements.set("name", replacer(name)); - replacements.set("ext", replacer(ext, true)); - // Legacy - replacements.set( - "filebase", - deprecated( - replacer(base), - "[filebase] is now [base]", - "DEP_WEBPACK_TEMPLATE_PATH_PLUGIN_REPLACE_PATH_VARIABLES_FILENAME" - ) - ); - } + replacements.set("file", replacer(file)); + replacements.set("query", replacer(query, true)); + replacements.set("fragment", replacer(fragment, true)); + replacements.set("path", replacer(path, true)); + replacements.set("base", replacer(base)); + replacements.set("name", replacer(name)); + replacements.set("ext", replacer(ext, true)); + // Legacy + replacements.set( + "filebase", + deprecated( + replacer(base), + "[filebase] is now [base]", + "DEP_WEBPACK_TEMPLATE_PATH_PLUGIN_REPLACE_PATH_VARIABLES_FILENAME" + ) + ); } // Compilation context diff --git a/lib/serialization/BinaryMiddleware.js b/lib/serialization/BinaryMiddleware.js index e95d0f359..da5178360 100644 --- a/lib/serialization/BinaryMiddleware.js +++ b/lib/serialization/BinaryMiddleware.js @@ -165,12 +165,23 @@ class BinaryMiddleware extends SerializerMiddleware { }; const flush = () => { if (currentBuffer !== null) { - buffers.push(currentBuffer.slice(0, currentPosition)); + buffers.push( + Buffer.from( + currentBuffer.buffer, + currentBuffer.byteOffset, + currentPosition + ) + ); if ( !leftOverBuffer || leftOverBuffer.length < currentBuffer.length - currentPosition - ) - leftOverBuffer = currentBuffer.slice(currentPosition); + ) { + leftOverBuffer = Buffer.from( + currentBuffer.buffer, + currentBuffer.byteOffset + currentPosition, + currentBuffer.byteLength - currentPosition + ); + } currentBuffer = null; buffersTotalLength += currentPosition; currentPosition = 0; @@ -554,10 +565,8 @@ class BinaryMiddleware extends SerializerMiddleware { if (rem < n) { return Buffer.concat([read(rem), read(n - rem)]); } - const res = /** @type {Buffer} */ (currentBuffer).slice( - currentPosition, - currentPosition + n - ); + const b = /** @type {Buffer} */ (currentBuffer); + const res = Buffer.from(b.buffer, b.byteOffset + currentPosition, n); currentPosition += n; checkOverflow(); return res; @@ -579,10 +588,8 @@ class BinaryMiddleware extends SerializerMiddleware { if (rem < n) { n = rem; } - const res = /** @type {Buffer} */ (currentBuffer).slice( - currentPosition, - currentPosition + n - ); + const b = /** @type {Buffer} */ (currentBuffer); + const res = Buffer.from(b.buffer, b.byteOffset + currentPosition, n); currentPosition += n; checkOverflow(); return res; @@ -735,7 +742,7 @@ class BinaryMiddleware extends SerializerMiddleware { case STRING_HEADER: return () => { const len = readU32(); - if (isInCurrentBuffer(len)) { + if (isInCurrentBuffer(len) && currentPosition + len < 0x7fffffff) { result.push( currentBuffer.toString( undefined, @@ -753,7 +760,7 @@ class BinaryMiddleware extends SerializerMiddleware { return () => result.push(""); case SHORT_STRING_HEADER | 1: return () => { - if (currentIsBuffer) { + if (currentIsBuffer && currentPosition < 0x7ffffffe) { result.push( currentBuffer.toString( "latin1", @@ -785,7 +792,10 @@ class BinaryMiddleware extends SerializerMiddleware { } else if ((header & SHORT_STRING_HEADER) === SHORT_STRING_HEADER) { const len = header & SHORT_STRING_LENGTH_MASK; return () => { - if (isInCurrentBuffer(len)) { + if ( + isInCurrentBuffer(len) && + currentPosition + len < 0x7fffffff + ) { result.push( currentBuffer.toString( "latin1", diff --git a/lib/serialization/FileMiddleware.js b/lib/serialization/FileMiddleware.js index badde8a88..fd5f2afee 100644 --- a/lib/serialization/FileMiddleware.js +++ b/lib/serialization/FileMiddleware.js @@ -280,8 +280,16 @@ const deserialize = async (middleware, name, readFile) => { } const sectionCount = readUInt32LE(); const lengths = []; + let lastLengthPositive = false; for (let i = 0; i < sectionCount; i++) { - lengths.push(readInt32LE()); + const value = readInt32LE(); + const valuePositive = value >= 0; + if (lastLengthPositive && valuePositive) { + lengths[lengths.length - 1] += value; + } else { + lengths.push(value); + lastLengthPositive = valuePositive; + } } const result = []; for (let length of lengths) { @@ -316,13 +324,15 @@ const deserialize = async (middleware, name, readFile) => { contentPosition += length; length = 0; } else { + const l = contentItemLength - contentPosition; result.push( Buffer.from( contentItem.buffer, - contentItem.byteOffset + contentPosition + contentItem.byteOffset + contentPosition, + l ) ); - length -= contentItemLength - contentPosition; + length -= l; contentPosition = contentItemLength; } } else { @@ -331,7 +341,9 @@ const deserialize = async (middleware, name, readFile) => { length -= contentItemLength; contentPosition = contentItemLength; } else { - result.push(contentItem.slice(0, length)); + result.push( + Buffer.from(contentItem.buffer, contentItem.byteOffset, length) + ); contentPosition += length; length = 0; } @@ -343,7 +355,9 @@ const deserialize = async (middleware, name, readFile) => { length -= contentItemLength; contentPosition = contentItemLength; } else { - result.push(contentItem.slice(0, length)); + result.push( + Buffer.from(contentItem.buffer, contentItem.byteOffset, length) + ); contentPosition += length; length = 0; } diff --git a/test/TestCases.template.js b/test/TestCases.template.js index 518c1d005..8501be895 100644 --- a/test/TestCases.template.js +++ b/test/TestCases.template.js @@ -95,6 +95,11 @@ const describeCases = config => { category.name, testName ); + let testConfig = {}; + const testConfigPath = path.join(testDirectory, "test.config.js"); + if (fs.existsSync(testConfigPath)) { + testConfig = require(testConfigPath); + } const options = { context: casesPath, entry: "./" + category.name + "/" + testName + "/", @@ -196,34 +201,42 @@ const describeCases = config => { rimraf(cacheDirectory, done); }); if (config.cache) { - it(`${testName} should pre-compile to fill disk cache (1st)`, done => { - const oldPath = options.output.path; - options.output.path = path.join( - options.output.path, - "cache1" - ); - const deprecationTracker = deprecationTracking.start(); - webpack(options, err => { - deprecationTracker(); - options.output.path = oldPath; - if (err) return done(err); - done(); - }); - }, 60000); - it(`${testName} should pre-compile to fill disk cache (2nd)`, done => { - const oldPath = options.output.path; - options.output.path = path.join( - options.output.path, - "cache2" - ); - const deprecationTracker = deprecationTracking.start(); - webpack(options, err => { - deprecationTracker(); - options.output.path = oldPath; - if (err) return done(err); - done(); - }); - }, 10000); + it( + `${testName} should pre-compile to fill disk cache (1st)`, + done => { + const oldPath = options.output.path; + options.output.path = path.join( + options.output.path, + "cache1" + ); + const deprecationTracker = deprecationTracking.start(); + webpack(options, err => { + deprecationTracker(); + options.output.path = oldPath; + if (err) return done(err); + done(); + }); + }, + testConfig.timeout || 60000 + ); + it( + `${testName} should pre-compile to fill disk cache (2nd)`, + done => { + const oldPath = options.output.path; + options.output.path = path.join( + options.output.path, + "cache2" + ); + const deprecationTracker = deprecationTracking.start(); + webpack(options, err => { + deprecationTracker(); + options.output.path = oldPath; + if (err) return done(err); + done(); + }); + }, + testConfig.cachedTimeout || testConfig.timeout || 10000 + ); } it( testName + " should compile", @@ -303,7 +316,9 @@ const describeCases = config => { run(); } }, - config.cache ? 20000 : 60000 + testConfig.cachedTimeout || + testConfig.timeout || + (config.cache ? 20000 : 60000) ); it( @@ -415,7 +430,7 @@ const describeCases = config => { const { it: _it, getNumberOfTests } = createLazyTestEnv( jasmine.getEnv(), - 10000 + testConfig.timeout || 10000 ); }); }); diff --git a/test/cases/large/big-assets/generate-big-asset-loader.js b/test/cases/large/big-assets/generate-big-asset-loader.js new file mode 100644 index 000000000..c298e2a42 --- /dev/null +++ b/test/cases/large/big-assets/generate-big-asset-loader.js @@ -0,0 +1,6 @@ +/** @type {import("../../../../").RawLoaderDefinition<{ size: string }>} */ +module.exports = function () { + const options = this.getOptions(); + return Buffer.alloc(+options.size); +}; +module.exports.raw = true; diff --git a/test/cases/large/big-assets/index.js b/test/cases/large/big-assets/index.js new file mode 100644 index 000000000..81a0f9590 --- /dev/null +++ b/test/cases/large/big-assets/index.js @@ -0,0 +1,26 @@ +it("should compile fine", () => { + const a = new URL( + "./generate-big-asset-loader.js?size=100000000!", + import.meta.url + ); + const b = new URL( + "./generate-big-asset-loader.js?size=200000000!", + import.meta.url + ); + const c = new URL( + "./generate-big-asset-loader.js?size=300000000!", + import.meta.url + ); + const d = new URL( + "./generate-big-asset-loader.js?size=400000000!", + import.meta.url + ); + const e = new URL( + "./generate-big-asset-loader.js?size=500000000!", + import.meta.url + ); + const f = new URL( + "./generate-big-asset-loader.js?size=600000000!", + import.meta.url + ); +}); diff --git a/test/cases/large/big-assets/test.config.js b/test/cases/large/big-assets/test.config.js new file mode 100644 index 000000000..7ab4fa5ee --- /dev/null +++ b/test/cases/large/big-assets/test.config.js @@ -0,0 +1,3 @@ +module.exports = { + timeout: 120000 +}; diff --git a/test/cases/large/big-assets/test.filter.js b/test/cases/large/big-assets/test.filter.js new file mode 100644 index 000000000..71a71e594 --- /dev/null +++ b/test/cases/large/big-assets/test.filter.js @@ -0,0 +1,3 @@ +module.exports = function (config) { + return !process.env.CI; +};