diff --git a/lib/APIPlugin.js b/lib/APIPlugin.js index 7a3719198ef..56dcf63e0be 100644 --- a/lib/APIPlugin.js +++ b/lib/APIPlugin.js @@ -190,13 +190,11 @@ class APIPlugin { PLUGIN_NAME, (source, module, renderContext) => { if (/** @type {BuildInfo} */ (module.buildInfo).needCreateRequire) { - const needPrefix = - renderContext.runtimeTemplate.supportNodePrefixForCoreModules(); const chunkInitFragments = [ new InitFragment( - `import { createRequire as __WEBPACK_EXTERNAL_createRequire } from "${ - needPrefix ? "node:" : "" - }module";\n`, + `import { createRequire as __WEBPACK_EXTERNAL_createRequire } from ${renderContext.runtimeTemplate.renderNodePrefixForCoreModule( + "module" + )};\n`, InitFragment.STAGE_HARMONY_IMPORTS, 0, "external module node-commonjs" diff --git a/lib/ExternalModule.js b/lib/ExternalModule.js index 9726d6398c9..ced3598d3f7 100644 --- a/lib/ExternalModule.js +++ b/lib/ExternalModule.js @@ -125,21 +125,24 @@ const getSourceForCommonJsExternal = (moduleAndSpecifiers) => { }; /** - * @param {string|string[]} moduleAndSpecifiers the module request - * @param {string} importMetaName import.meta name - * @param {boolean} needPrefix need to use `node:` prefix for `module` import + * @param {string | string[]} moduleAndSpecifiers the module request + * @param {RuntimeTemplate} runtimeTemplate the runtime template * @returns {SourceData} the generated source */ const getSourceForCommonJsExternalInNodeModule = ( moduleAndSpecifiers, - importMetaName, - needPrefix + runtimeTemplate ) => { + const importMetaName = + /** @type {string} */ + (runtimeTemplate.outputOptions.importMetaName); + + // /** @type {boolean} */ + // (runtimeTemplate.supportNodePrefixForCoreModules()) + const chunkInitFragments = [ new InitFragment( - `import { createRequire as __WEBPACK_EXTERNAL_createRequire } from "${ - needPrefix ? "node:" : "" - }module";\n`, + `import { createRequire as __WEBPACK_EXTERNAL_createRequire } from ${runtimeTemplate.renderNodePrefixForCoreModule("module")};\n`, InitFragment.STAGE_HARMONY_IMPORTS, 0, "external module node-commonjs" @@ -763,13 +766,7 @@ class ExternalModule extends Module { return getSourceForCommonJsExternal(request); case "node-commonjs": return /** @type {BuildInfo} */ (this.buildInfo).javascriptModule - ? getSourceForCommonJsExternalInNodeModule( - request, - /** @type {string} */ - (runtimeTemplate.outputOptions.importMetaName), - /** @type {boolean} */ - (runtimeTemplate.supportNodePrefixForCoreModules()) - ) + ? getSourceForCommonJsExternalInNodeModule(request, runtimeTemplate) : getSourceForCommonJsExternal(request); case "amd": case "amd-require": diff --git a/lib/NodeStuffPlugin.js b/lib/NodeStuffPlugin.js index a5a794135a7..6cd44b8d53f 100644 --- a/lib/NodeStuffPlugin.js +++ b/lib/NodeStuffPlugin.js @@ -118,7 +118,8 @@ class NodeStuffPlugin { .tap(PLUGIN_NAME, (expr) => { const dep = new CachedConstDependency( JSON.stringify(fn(parser.state.module)), - /** @type {Range} */ (expr.range), + /** @type {Range} */ + (expr.range), expressionName ); dep.loc = /** @type {DependencyLocation} */ (expr.loc); @@ -186,12 +187,17 @@ class NodeStuffPlugin { "__filename is a Node.js feature and isn't available in browsers." ); break; - case "node-module": + case "node-module": { + const importMetaName = + /** @type {string} */ + (compilation.outputOptions.importMetaName); + setUrlModuleConstant( "__filename", - (functionName) => `${functionName}(import.meta.url)` + (functionName) => `${functionName}(${importMetaName}.url)` ); break; + } case true: setModuleConstant("__filename", (module) => relative( @@ -223,13 +229,18 @@ class NodeStuffPlugin { "__dirname is a Node.js feature and isn't available in browsers." ); break; - case "node-module": + case "node-module": { + const importMetaName = + /** @type {string} */ + (compilation.outputOptions.importMetaName); + setUrlModuleConstant( "__dirname", (functionName) => - `${functionName}(import.meta.url + "/..").slice(0, -1)` + `${functionName}(${importMetaName}.url + "/..").slice(0, -1)` ); break; + } case true: setModuleConstant("__dirname", (module) => relative( @@ -246,7 +257,8 @@ class NodeStuffPlugin { .tap(PLUGIN_NAME, (expr) => { if (!parser.state.module) return; return evaluateToString( - /** @type {string} */ (parser.state.module.context) + /** @type {string} */ + (parser.state.module.context) )(expr); }); } diff --git a/lib/RuntimeTemplate.js b/lib/RuntimeTemplate.js index 44f68a3e4fd..fd11bb8859e 100644 --- a/lib/RuntimeTemplate.js +++ b/lib/RuntimeTemplate.js @@ -162,6 +162,16 @@ class RuntimeTemplate { return this.outputOptions.environment.nodePrefixForCoreModules; } + /** + * @param {string} mod a module + * @returns {string} a module with `node:` prefix when supported, otherwise an original name + */ + renderNodePrefixForCoreModule(mod) { + return this.outputOptions.environment.nodePrefixForCoreModules + ? `"node:${mod}"` + : `"${mod}"`; + } + /** * @param {string} returnValue return value * @param {string} args arguments diff --git a/lib/node/ReadFileChunkLoadingRuntimeModule.js b/lib/node/ReadFileChunkLoadingRuntimeModule.js index db5da4c6522..dcf763d67ff 100644 --- a/lib/node/ReadFileChunkLoadingRuntimeModule.js +++ b/lib/node/ReadFileChunkLoadingRuntimeModule.js @@ -21,6 +21,7 @@ const { getUndoPath } = require("../util/identifier"); /** @typedef {import("../Chunk")} Chunk */ /** @typedef {import("../ChunkGraph")} ChunkGraph */ /** @typedef {import("../Compilation")} Compilation */ +/** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */ /** @typedef {import("../Module").ReadOnlyRuntimeRequirements} ReadOnlyRuntimeRequirements */ class ReadFileChunkLoadingRuntimeModule extends RuntimeModule { @@ -36,15 +37,16 @@ class ReadFileChunkLoadingRuntimeModule extends RuntimeModule { * @private * @param {Chunk} chunk chunk * @param {string} rootOutputDir root output directory + * @param {RuntimeTemplate} runtimeTemplate the runtime template * @returns {string} generated code */ - _generateBaseUri(chunk, rootOutputDir) { + _generateBaseUri(chunk, rootOutputDir, runtimeTemplate) { const options = chunk.getEntryOptions(); if (options && options.baseUri) { return `${RuntimeGlobals.baseURI} = ${JSON.stringify(options.baseUri)};`; } - return `${RuntimeGlobals.baseURI} = require("url").pathToFileURL(${ + return `${RuntimeGlobals.baseURI} = require(${runtimeTemplate.renderNodePrefixForCoreModule("url")}).pathToFileURL(${ rootOutputDir ? `__dirname + ${JSON.stringify(`/${rootOutputDir}`)}` : "__filename" @@ -99,7 +101,7 @@ class ReadFileChunkLoadingRuntimeModule extends RuntimeModule { return Template.asString([ withBaseURI - ? this._generateBaseUri(chunk, rootOutputDir) + ? this._generateBaseUri(chunk, rootOutputDir, runtimeTemplate) : "// no baseURI", "", "// object to store loaded chunks", @@ -171,17 +173,17 @@ class ReadFileChunkLoadingRuntimeModule extends RuntimeModule { "var promise = new Promise(function(resolve, reject) {", Template.indent([ "installedChunkData = installedChunks[chunkId] = [resolve, reject];", - `var filename = require('path').join(__dirname, ${JSON.stringify( + `var filename = require(${runtimeTemplate.renderNodePrefixForCoreModule("path")}).join(__dirname, ${JSON.stringify( rootOutputDir )} + ${ RuntimeGlobals.getChunkScriptFilename }(chunkId));`, - "require('fs').readFile(filename, 'utf-8', function(err, content) {", + `require(${runtimeTemplate.renderNodePrefixForCoreModule("fs")}).readFile(filename, 'utf-8', function(err, content) {`, Template.indent([ "if(err) return reject(err);", "var chunk = {};", - "require('vm').runInThisContext('(function(exports, require, __dirname, __filename) {' + content + '\\n})', filename)" + - "(chunk, require, require('path').dirname(filename), filename);", + `require(${runtimeTemplate.renderNodePrefixForCoreModule("vm")}).runInThisContext('(function(exports, require, __dirname, __filename) {' + content + '\\n})', filename)` + + `(chunk, require, require(${runtimeTemplate.renderNodePrefixForCoreModule("path")}).dirname(filename), filename);`, "installChunk(chunk);" ]), "});" @@ -215,15 +217,15 @@ class ReadFileChunkLoadingRuntimeModule extends RuntimeModule { Template.indent([ "return new Promise(function(resolve, reject) {", Template.indent([ - `var filename = require('path').join(__dirname, ${JSON.stringify( + `var filename = require(${runtimeTemplate.renderNodePrefixForCoreModule("path")}).join(__dirname, ${JSON.stringify( rootOutputDir )} + ${RuntimeGlobals.getChunkUpdateScriptFilename}(chunkId));`, - "require('fs').readFile(filename, 'utf-8', function(err, content) {", + `require(${runtimeTemplate.renderNodePrefixForCoreModule("fs")}).readFile(filename, 'utf-8', function(err, content) {`, Template.indent([ "if(err) return reject(err);", "var update = {};", - "require('vm').runInThisContext('(function(exports, require, __dirname, __filename) {' + content + '\\n})', filename)" + - "(update, require, require('path').dirname(filename), filename);", + `require(${runtimeTemplate.renderNodePrefixForCoreModule("vm")}).runInThisContext('(function(exports, require, __dirname, __filename) {' + content + '\\n})', filename)` + + `(update, require, require(${runtimeTemplate.renderNodePrefixForCoreModule("path")}).dirname(filename), filename);`, "var updatedModules = update.modules;", "var runtime = update.runtime;", "for(var moduleId in updatedModules) {", @@ -255,10 +257,10 @@ class ReadFileChunkLoadingRuntimeModule extends RuntimeModule { Template.indent([ "return new Promise(function(resolve, reject) {", Template.indent([ - `var filename = require('path').join(__dirname, ${JSON.stringify( + `var filename = require(${runtimeTemplate.renderNodePrefixForCoreModule("path")}).join(__dirname, ${JSON.stringify( rootOutputDir )} + ${RuntimeGlobals.getUpdateManifestFilename}());`, - "require('fs').readFile(filename, 'utf-8', function(err, content) {", + `require(${runtimeTemplate.renderNodePrefixForCoreModule("fs")}).readFile(filename, 'utf-8', function(err, content) {`, Template.indent([ "if(err) {", Template.indent([ diff --git a/lib/node/ReadFileCompileAsyncWasmPlugin.js b/lib/node/ReadFileCompileAsyncWasmPlugin.js index b4464774fb4..bf8f273d813 100644 --- a/lib/node/ReadFileCompileAsyncWasmPlugin.js +++ b/lib/node/ReadFileCompileAsyncWasmPlugin.js @@ -76,8 +76,8 @@ class ReadFileCompileAsyncWasmPlugin { Template.indent([ "try {", Template.indent([ - "var { readFile } = require('fs');", - "var { join } = require('path');", + `var { readFile } = require(${compilation.runtimeTemplate.renderNodePrefixForCoreModule("fs")});`, + `var { join } = require(${compilation.runtimeTemplate.renderNodePrefixForCoreModule("path")});`, "", `readFile(join(__dirname, ${path}), function(err, buffer){`, Template.indent([ diff --git a/lib/node/ReadFileCompileWasmPlugin.js b/lib/node/ReadFileCompileWasmPlugin.js index cb1c1b1e128..bbc1f4dd7de 100644 --- a/lib/node/ReadFileCompileWasmPlugin.js +++ b/lib/node/ReadFileCompileWasmPlugin.js @@ -77,8 +77,8 @@ class ReadFileCompileWasmPlugin { Template.asString([ "new Promise(function (resolve, reject) {", Template.indent([ - "var { readFile } = require('fs');", - "var { join } = require('path');", + `var { readFile } = require(${compilation.runtimeTemplate.renderNodePrefixForCoreModule("fs")});`, + `var { join } = require(${compilation.runtimeTemplate.renderNodePrefixForCoreModule("path")});`, "", "try {", Template.indent([ diff --git a/lib/node/RequireChunkLoadingRuntimeModule.js b/lib/node/RequireChunkLoadingRuntimeModule.js index bb9fee926d2..52fda8aebc2 100644 --- a/lib/node/RequireChunkLoadingRuntimeModule.js +++ b/lib/node/RequireChunkLoadingRuntimeModule.js @@ -21,6 +21,7 @@ const { getUndoPath } = require("../util/identifier"); /** @typedef {import("../Chunk")} Chunk */ /** @typedef {import("../ChunkGraph")} ChunkGraph */ /** @typedef {import("../Compilation")} Compilation */ +/** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */ /** @typedef {import("../Module").ReadOnlyRuntimeRequirements} ReadOnlyRuntimeRequirements */ class RequireChunkLoadingRuntimeModule extends RuntimeModule { @@ -36,15 +37,16 @@ class RequireChunkLoadingRuntimeModule extends RuntimeModule { * @private * @param {Chunk} chunk chunk * @param {string} rootOutputDir root output directory + * @param {RuntimeTemplate} runtimeTemplate the runtime template * @returns {string} generated code */ - _generateBaseUri(chunk, rootOutputDir) { + _generateBaseUri(chunk, rootOutputDir, runtimeTemplate) { const options = chunk.getEntryOptions(); if (options && options.baseUri) { return `${RuntimeGlobals.baseURI} = ${JSON.stringify(options.baseUri)};`; } - return `${RuntimeGlobals.baseURI} = require("url").pathToFileURL(${ + return `${RuntimeGlobals.baseURI} = require(${runtimeTemplate.renderNodePrefixForCoreModule("url")}).pathToFileURL(${ rootOutputDir !== "./" ? `__dirname + ${JSON.stringify(`/${rootOutputDir}`)}` : "__filename" @@ -99,7 +101,7 @@ class RequireChunkLoadingRuntimeModule extends RuntimeModule { return Template.asString([ withBaseURI - ? this._generateBaseUri(chunk, rootOutputDir) + ? this._generateBaseUri(chunk, rootOutputDir, runtimeTemplate) : "// no baseURI", "", "// object to store loaded chunks", diff --git a/package.json b/package.json index 67a02206592..641fba83850 100644 --- a/package.json +++ b/package.json @@ -110,7 +110,7 @@ "devDependencies": { "@babel/core": "^7.27.1", "@babel/preset-react": "^7.27.1", - "@codspeed/tinybench-plugin": "^4.0.1", + "@codspeed/core": "^4.0.1", "@eslint/js": "^9.29.0", "@eslint/markdown": "^7.0.0", "@stylistic/eslint-plugin": "^5.0.0", diff --git a/test/BenchmarkTestCases.benchmark.mjs b/test/BenchmarkTestCases.benchmark.mjs index 1755c6ff90d..cd19c0f85f1 100644 --- a/test/BenchmarkTestCases.benchmark.mjs +++ b/test/BenchmarkTestCases.benchmark.mjs @@ -2,7 +2,6 @@ import { constants, writeFile } from "fs"; import fs from "fs/promises"; import path from "path"; import { fileURLToPath, pathToFileURL } from "url"; -import { withCodSpeed } from "@codspeed/tinybench-plugin"; import { simpleGit } from "simple-git"; import { Bench, hrtimeNow } from "tinybench"; @@ -277,11 +276,15 @@ function buildConfiguration( `baseline-${baseline.name}` ); config.plugins = config.plugins || []; - if (config.cache) { config.cache.cacheDirectory = path.resolve(config.output.path, ".cache"); } - + if (watch) { + config.cache = { + type: "memory", + maxGenerations: 1 + }; + } return config; } @@ -319,12 +322,120 @@ const scenarios = [ const baseOutputPath = path.join(__dirname, "js", "benchmark"); -const bench = withCodSpeed( +const withCodSpeed = async (/** @type {import("tinybench").Bench} */ bench) => { + const { Measurement, getGitDir, mongoMeasurement, setupCore, teardownCore } = + await import("@codspeed/core"); + + if (!Measurement.isInstrumented()) { + const rawRun = bench.run; + bench.run = async () => { + console.warn( + `[CodSpeed] ${bench.tasks.length} benches detected but no instrumentation found, falling back to tinybench` + ); + return await rawRun.bind(bench)(); + }; + return bench; + } + + const getStackTrace = (belowFn) => { + const oldLimit = Error.stackTraceLimit; + Error.stackTraceLimit = Infinity; + const dummyObject = {}; + const v8Handler = Error.prepareStackTrace; + Error.prepareStackTrace = (dummyObject, v8StackTrace) => v8StackTrace; + Error.captureStackTrace(dummyObject, belowFn || getStackTrace); + const v8StackTrace = dummyObject.stack; + Error.prepareStackTrace = v8Handler; + Error.stackTraceLimit = oldLimit; + return v8StackTrace; + }; + + const getCallingFile = () => { + const stack = getStackTrace(); + let callingFile = stack[2].getFileName(); // [here, withCodSpeed, actual caller] + const gitDir = getGitDir(callingFile); + if (gitDir === undefined) { + throw new Error("Could not find a git repository"); + } + if (callingFile.startsWith("file://")) { + callingFile = fileURLToPath(callingFile); + } + return path.relative(gitDir, callingFile); + }; + + const rawAdd = bench.add; + bench.add = (name, fn, opts) => { + const callingFile = getCallingFile(); + const uri = `${callingFile}::${name}`; + const options = { ...opts, uri }; + return rawAdd.bind(bench)(name, fn, options); + }; + const rootCallingFile = getCallingFile(); + bench.run = async function run() { + const iterations = bench.opts.iterations - 1; + console.log("[CodSpeed] running"); + setupCore(); + for (const task of bench.tasks) { + await bench.opts.setup?.(task, "run"); + await task.fnOpts.beforeAll?.call(task); + const samples = []; + async function iteration() { + try { + await task.fnOpts.beforeEach?.call(task, "run"); + const start = bench.opts.now(); + await task.fn(); + samples.push(bench.opts.now() - start || 0); + await task.fnOpts.afterEach?.call(this, "run"); + } catch (err) { + if (bench.opts.throws) { + throw err; + } + } + } + while (samples.length < iterations) { + await iteration(); + } + // Codspeed Measure + const uri = + task.opts && "uri" in task.options + ? task.opts.uri + : `${rootCallingFile}::${task.name}`; + await task.fnOpts.beforeEach?.call(task); + await mongoMeasurement.start(uri); + await (async function __codspeed_root_frame__() { + Measurement.startInstrumentation(); + await task.fn(); + Measurement.stopInstrumentation(uri); + })(); + await mongoMeasurement.stop(uri); + await task.fnOpts.afterEach?.call(task); + console.log(`[Codspeed] ✔ Measured ${uri}`); + await task.fnOpts.afterAll?.call(task); + + await bench.opts.teardown?.(task, "run"); + task.processRunResult({ latencySamples: samples }); + } + teardownCore(); + console.log(`[CodSpeed] Done running ${bench.tasks.length} benches.`); + return bench.tasks; + }; + return bench; +}; + +const bench = await withCodSpeed( new Bench({ now: hrtimeNow, throws: true, warmup: true, - time: 30000 + warmupIterations: 2, + iterations: 8, + setup(task, mode) { + global.gc(); + console.log(`Setup (${mode} mode): ${task.name}`); + }, + teardown(task, mode) { + console.log(`Teardown (${mode} mode): ${task.name}`); + } }) ); @@ -393,6 +504,8 @@ async function registerSuite(bench, test, baselines) { bench.add( benchName, async () => { + console.time(`Time: ${benchName}`); + const watchingPromise = new Promise((res) => { watchingResolve = res; }); @@ -407,9 +520,11 @@ async function registerSuite(bench, test, baselines) { } watchingPromise.then((stats) => { + watchingResolve = undefined; + // Construct and print stats to be more accurate with real life projects stats.toString(); - + console.timeEnd(`Time: ${benchName}`); resolve(); }); } @@ -463,6 +578,8 @@ async function registerSuite(bench, test, baselines) { benchName, async () => { await new Promise((resolve, reject) => { + console.time(`Time: ${benchName}`); + const baseCompiler = webpack(config); baseCompiler.run((err, stats) => { @@ -483,7 +600,7 @@ async function registerSuite(bench, test, baselines) { // Construct and print stats to be more accurate with real life projects stats.toString(); - + console.timeEnd(`Time: ${benchName}`); resolve(); }); }); @@ -625,7 +742,7 @@ bench.addEventListener("cycle", (event) => { const collectBy = task.collectBy; const allStats = statsByTests.get(collectBy); - console.log(`Done: ${task.name} ${confidence} (${runs} runs sampled)`); + console.log(`Cycle: ${task.name} ${confidence} (${runs} runs sampled)`); const info = { ...latency, text, minConfidence, maxConfidence }; @@ -646,11 +763,4 @@ bench.addEventListener("cycle", (event) => { ); }); -// Fix for https://github.com/CodSpeedHQ/codspeed-node/issues/44 -for (const name of bench.tasks.map((task) => task.name)) { - const task = bench.getTask(name); - - task.opts = task.fnOpts; -} - -await bench.run(); +bench.run(); diff --git a/test/benchmarkCases/cache-filesystem/webpack.config.js b/test/benchmarkCases/cache-filesystem/webpack.config.js index 9f553f1bd80..c8d2a58d3cf 100644 --- a/test/benchmarkCases/cache-filesystem/webpack.config.js +++ b/test/benchmarkCases/cache-filesystem/webpack.config.js @@ -4,6 +4,9 @@ module.exports = { entry: "./index", cache: { - type: "filesystem" + type: "filesystem", + // For benchmark stability + maxMemoryGenerations: 0, + idleTimeoutForInitialStore: 0 } }; diff --git a/test/benchmarkCases/md4-and-xxhash64-unit/index.bench.mjs b/test/benchmarkCases/md4-and-xxhash64-unit/index.bench.mjs deleted file mode 100644 index 3a7da1296dd..00000000000 --- a/test/benchmarkCases/md4-and-xxhash64-unit/index.bench.mjs +++ /dev/null @@ -1,62 +0,0 @@ -import crypto from "crypto"; -import createHash from "../../../lib/util/createHash.js"; - -function factoryXxhash64(longString) { - return function xxhash64String() { - const hash = createHash("xxhash64"); - hash.update(longString); - return hash.digest("hex"); - }; -} - -function factoryMd4(longString) { - return function md4String() { - const hash = createHash("md4"); - hash.update(longString); - return hash.digest("hex"); - }; -} - -export default function xxhash64AndMd4Benchmarks(suite) { - for (const size of [ - 1, 10, 20, 40, 60, 80, 100, 200, 400, 1000, 1001, 5000, 8183, 8184, 8185, - 10000, 20000, 32768, 32769, 50000, 100000, 200000 - ]) { - const longString = crypto.randomBytes(size).toString("hex"); - const subName1 = `string benchmark (length: ${longString.length})`; - - const fn1 = factoryXxhash64(longString); - const fn2 = factoryMd4(longString); - - suite.add(`xxhash64 ${subName1}`, fn1, { - beforeAll() { - this.collectBy = subName1; - } - }); - - suite.add(`md4 ${subName1}`, fn2, { - beforeAll() { - this.collectBy = subName1; - } - }); - - const bufferSize = size * 2; - const buffer = crypto.randomBytes(bufferSize); - const subName2 = `buffer benchmark (size: ${bufferSize})`; - - const fn3 = factoryXxhash64(buffer); - const fn4 = factoryMd4(buffer); - - suite.add(`xxhash64 ${subName2}`, fn3, { - beforeAll() { - this.collectBy = subName2; - } - }); - - suite.add(`md4 ${subName2}`, fn4, { - beforeAll() { - this.collectBy = subName2; - } - }); - } -} diff --git a/test/benchmarkCases/minimal/index.js b/test/benchmarkCases/minimal/index.js deleted file mode 100644 index b179ee95347..00000000000 --- a/test/benchmarkCases/minimal/index.js +++ /dev/null @@ -1 +0,0 @@ -console.log("Hello world"); diff --git a/test/benchmarkCases/minimal/webpack.config.js b/test/benchmarkCases/minimal/webpack.config.js deleted file mode 100644 index 618e121cccd..00000000000 --- a/test/benchmarkCases/minimal/webpack.config.js +++ /dev/null @@ -1,6 +0,0 @@ -"use strict"; - -/** @type {import("../../../").Configuration} */ -module.exports = { - entry: "./index" -}; diff --git a/test/configCases/node/filename-and-dirname-eval-only/index.js b/test/configCases/node/filename-and-dirname-eval-only/index.js new file mode 100644 index 00000000000..9b7c32817d2 --- /dev/null +++ b/test/configCases/node/filename-and-dirname-eval-only/index.js @@ -0,0 +1,6 @@ +import path from "path"; + +it("should use custom name", () => { + expect(__dirname).toBe(__STATS__.outputPath); + expect(__filename).toBe(path.join(__STATS__.outputPath, "./bundle0.js")); +}); diff --git a/test/configCases/node/filename-and-dirname-eval-only/webpack.config.js b/test/configCases/node/filename-and-dirname-eval-only/webpack.config.js new file mode 100644 index 00000000000..cbda8c605d5 --- /dev/null +++ b/test/configCases/node/filename-and-dirname-eval-only/webpack.config.js @@ -0,0 +1,10 @@ +"use strict"; + +/** @type {import("../../../../").Configuration} */ +module.exports = { + target: "node", + node: { + __filename: "eval-only", + __dirname: "eval-only" + } +}; diff --git a/test/configCases/node/filename-and-dirname-node-module/index.js b/test/configCases/node/filename-and-dirname-node-module/index.js new file mode 100644 index 00000000000..00adc327ada --- /dev/null +++ b/test/configCases/node/filename-and-dirname-node-module/index.js @@ -0,0 +1,6 @@ +import path from "path"; + +it("should use custom name", () => { + expect(__dirname).toBe(__STATS__.outputPath); + expect(__filename).toBe(path.join(__STATS__.outputPath, "./bundle0.mjs")); +}); diff --git a/test/configCases/node/filename-and-dirname-node-module/test.config.js b/test/configCases/node/filename-and-dirname-node-module/test.config.js new file mode 100644 index 00000000000..f270e2a8535 --- /dev/null +++ b/test/configCases/node/filename-and-dirname-node-module/test.config.js @@ -0,0 +1,12 @@ +"use strict"; + +const path = require("path"); +const { pathToFileURL } = require("url"); + +module.exports = { + moduleScope(scope, options) { + scope.custom = { + url: pathToFileURL(path.join(options.output.path, "bundle0.mjs")) + }; + } +}; diff --git a/test/configCases/node/filename-and-dirname-node-module/test.filter.js b/test/configCases/node/filename-and-dirname-node-module/test.filter.js new file mode 100644 index 00000000000..03c7ecb753f --- /dev/null +++ b/test/configCases/node/filename-and-dirname-node-module/test.filter.js @@ -0,0 +1,5 @@ +"use strict"; + +const supportsNodePrefix = require("../../../helpers/supportsNodePrefix"); + +module.exports = () => supportsNodePrefix(); diff --git a/test/configCases/node/filename-and-dirname-node-module/webpack.config.js b/test/configCases/node/filename-and-dirname-node-module/webpack.config.js new file mode 100644 index 00000000000..aa469f23126 --- /dev/null +++ b/test/configCases/node/filename-and-dirname-node-module/webpack.config.js @@ -0,0 +1,17 @@ +"use strict"; + +/** @type {import("../../../../").Configuration} */ +module.exports = { + target: "node", + experiments: { + outputModule: true + }, + output: { + module: true, + importMetaName: "custom" + }, + node: { + __filename: "node-module", + __dirname: "node-module" + } +}; diff --git a/test/configCases/node/prefix-in-runtime/test.filter.js b/test/configCases/node/prefix-in-runtime/test.filter.js index 974a477676a..03c7ecb753f 100644 --- a/test/configCases/node/prefix-in-runtime/test.filter.js +++ b/test/configCases/node/prefix-in-runtime/test.filter.js @@ -1,3 +1,5 @@ "use strict"; -module.exports = () => !process.version.startsWith("v10."); +const supportsNodePrefix = require("../../../helpers/supportsNodePrefix"); + +module.exports = () => supportsNodePrefix(); diff --git a/test/configCases/worker/node-worker-hmr/webpack.config.js b/test/configCases/worker/node-worker-hmr/webpack.config.js index 39bc5180f5d..954614a3751 100644 --- a/test/configCases/worker/node-worker-hmr/webpack.config.js +++ b/test/configCases/worker/node-worker-hmr/webpack.config.js @@ -11,7 +11,10 @@ module.exports = { d: { import: "./index.js?d", filename: "[name].js" } }, output: { - filename: "[name].[contenthash].js" + filename: "[name].[contenthash].js", + environment: { + nodePrefixForCoreModules: false + } }, plugins: [new webpack.HotModuleReplacementPlugin()] }; diff --git a/test/configCases/worker/node-worker-named/webpack.config.js b/test/configCases/worker/node-worker-named/webpack.config.js index efd42df19b2..9849d6a24b2 100644 --- a/test/configCases/worker/node-worker-named/webpack.config.js +++ b/test/configCases/worker/node-worker-named/webpack.config.js @@ -3,6 +3,9 @@ /** @type {import("../../../../").Configuration} */ module.exports = { output: { - filename: "[name].js" + filename: "[name].js", + environment: { + nodePrefixForCoreModules: false + } } }; diff --git a/test/configCases/worker/node-worker/webpack.config.js b/test/configCases/worker/node-worker/webpack.config.js index eaa296489c9..fe9fca45005 100644 --- a/test/configCases/worker/node-worker/webpack.config.js +++ b/test/configCases/worker/node-worker/webpack.config.js @@ -9,6 +9,9 @@ module.exports = { d: { import: "./index.js?d", filename: "[name].js" } }, output: { - filename: "[name].[contenthash].js" + filename: "[name].[contenthash].js", + environment: { + nodePrefixForCoreModules: false + } } }; diff --git a/test/configCases/worker/worker-contenthash/webpack.config.js b/test/configCases/worker/worker-contenthash/webpack.config.js index 9d814fc1a2c..16e562cd7a2 100644 --- a/test/configCases/worker/worker-contenthash/webpack.config.js +++ b/test/configCases/worker/worker-contenthash/webpack.config.js @@ -9,6 +9,9 @@ module.exports = { } }, output: { - filename: "[name]-[contenthash].js" + filename: "[name]-[contenthash].js", + environment: { + nodePrefixForCoreModules: false + } } }; diff --git a/test/helpers/supportsNodePrefix.js b/test/helpers/supportsNodePrefix.js new file mode 100644 index 00000000000..5768b441d4d --- /dev/null +++ b/test/helpers/supportsNodePrefix.js @@ -0,0 +1,12 @@ +"use strict"; + +module.exports = function supportsNodePrefix() { + try { + eval("require('node:path')"); + return true; + } catch (_err) { + // Ignore + } + + return false; +}; diff --git a/test/hotCases/worker/move-between-runtime/webpack.config.js b/test/hotCases/worker/move-between-runtime/webpack.config.js new file mode 100644 index 00000000000..5b89ed624a5 --- /dev/null +++ b/test/hotCases/worker/move-between-runtime/webpack.config.js @@ -0,0 +1,10 @@ +"use strict"; + +/** @type {import("../../../../").Configuration} */ +module.exports = { + output: { + environment: { + nodePrefixForCoreModules: false + } + } +}; diff --git a/test/hotCases/worker/remove-add-worker/webpack.config.js b/test/hotCases/worker/remove-add-worker/webpack.config.js new file mode 100644 index 00000000000..5b89ed624a5 --- /dev/null +++ b/test/hotCases/worker/remove-add-worker/webpack.config.js @@ -0,0 +1,10 @@ +"use strict"; + +/** @type {import("../../../../").Configuration} */ +module.exports = { + output: { + environment: { + nodePrefixForCoreModules: false + } + } +}; diff --git a/test/hotCases/worker/update-in-worker/webpack.config.js b/test/hotCases/worker/update-in-worker/webpack.config.js new file mode 100644 index 00000000000..5b89ed624a5 --- /dev/null +++ b/test/hotCases/worker/update-in-worker/webpack.config.js @@ -0,0 +1,10 @@ +"use strict"; + +/** @type {import("../../../../").Configuration} */ +module.exports = { + output: { + environment: { + nodePrefixForCoreModules: false + } + } +}; diff --git a/types.d.ts b/types.d.ts index 037527bdd52..01ac4e67f25 100644 --- a/types.d.ts +++ b/types.d.ts @@ -14966,6 +14966,7 @@ declare abstract class RuntimeTemplate { supportsEcmaScriptModuleSyntax(): undefined | boolean; supportTemplateLiteral(): undefined | boolean; supportNodePrefixForCoreModules(): undefined | boolean; + renderNodePrefixForCoreModule(mod: string): string; returningFunction(returnValue: string, args?: string): string; basicFunction(args: string, body: string | string[]): string; concatenation(...args: (string | { expr: string })[]): string; diff --git a/yarn.lock b/yarn.lock index c87686fc9af..b5e16e9545f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -350,14 +350,6 @@ form-data "^4.0.0" node-gyp-build "^4.6.0" -"@codspeed/tinybench-plugin@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@codspeed/tinybench-plugin/-/tinybench-plugin-4.0.1.tgz#b0e27a963c03e6ca84c99685ee86abdbd3aa5c9f" - integrity sha512-hga1xif6XU8p/FZqTHzUrDPrBSLqxc3NuxMX8m4P8AIdhORsPrvgSNe09uVYlVOtD6jG7kPsmx5DZscez4wKrQ== - dependencies: - "@codspeed/core" "^4.0.1" - stack-trace "1.0.0-pre2" - "@cspell/cspell-bundled-dicts@9.1.3": version "9.1.3" resolved "https://registry.yarnpkg.com/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-9.1.3.tgz#ad26ab92489fb5ac45e3a967ba2afd71560d8aab" @@ -2146,12 +2138,12 @@ available-typed-arrays@^1.0.7: possible-typed-array-names "^1.0.0" axios@^1.4.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.10.0.tgz#af320aee8632eaf2a400b6a1979fa75856f38d54" - integrity sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw== + version "1.11.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.11.0.tgz#c2ec219e35e414c025b2095e8b8280278478fdb6" + integrity sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA== dependencies: follow-redirects "^1.15.6" - form-data "^4.0.0" + form-data "^4.0.4" proxy-from-env "^1.1.0" babel-jest@30.0.4: @@ -3874,7 +3866,7 @@ fork-ts-checker-webpack-plugin@^9.0.2: semver "^7.3.5" tapable "^2.2.1" -form-data@^4.0.0: +form-data@^4.0.0, form-data@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.4.tgz#784cdcce0669a9d68e94d11ac4eea98088edd2c4" integrity sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow== @@ -7467,11 +7459,6 @@ ssri@^12.0.0: dependencies: minipass "^7.0.3" -stack-trace@1.0.0-pre2: - version "1.0.0-pre2" - resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-1.0.0-pre2.tgz#46a83a79f1b287807e9aaafc6a5dd8bcde626f9c" - integrity sha512-2ztBJRek8IVofG9DBJqdy2N5kulaacX30Nz7xmkYF6ale9WBVmIy6mFBchvGX7Vx/MyjBhx+Rcxqrj+dbOnQ6A== - stack-utils@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f"