| /* | ||
| MIT License http://www.opensource.org/licenses/mit-license.php | ||
| Author Tobias Koppers @sokra | ||
| */ | ||
| "use strict"; | ||
| const { fileURLToPath } = require("url"); | ||
| const WebpackError = require("../WebpackError"); | ||
| const BasicEvaluatedExpression = require("../javascript/BasicEvaluatedExpression"); | ||
| const { VariableInfo } = require("../javascript/JavascriptParser"); | ||
| const { | ||
| evaluateToString, | ||
| expressionIsUnsupported, | ||
| toConstantDependency | ||
| } = require("../javascript/JavascriptParserHelpers"); | ||
| const CommonJsImportsParserPlugin = require("./CommonJsImportsParserPlugin"); | ||
| const ConstDependency = require("./ConstDependency"); | ||
| /** @typedef {import("estree").CallExpression} CallExpression */ | ||
| /** @typedef {import("estree").Expression} Expression */ | ||
| /** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */ | ||
| /** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */ | ||
| /** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */ | ||
| /** @typedef {import("../javascript/JavascriptParser").ImportSource} ImportSource */ | ||
| /** @typedef {import("../javascript/JavascriptParser").Range} Range */ | ||
| /** | ||
| * @typedef {object} CommonJsImportSettings | ||
| * @property {string=} name | ||
| * @property {string} context | ||
| */ | ||
| const createRequireSpecifierTag = Symbol("createRequire"); | ||
| const createdRequireIdentifierTag = Symbol("createRequire()"); | ||
| const PLUGIN_NAME = "CreateRequireParserPlugin"; | ||
| const { | ||
| createProcessResolveHandler, | ||
| createRequireAsExpressionHandler, | ||
| createRequireCacheDependency, | ||
| createRequireHandler | ||
| } = CommonJsImportsParserPlugin; | ||
| class CreateRequireParserPlugin { | ||
| /** | ||
| * @param {JavascriptParserOptions} options parser options | ||
| */ | ||
| constructor(options) { | ||
| this.options = options; | ||
| } | ||
| /** | ||
| * @param {JavascriptParser} parser the parser | ||
| * @returns {void} | ||
| */ | ||
| apply(parser) { | ||
| const options = this.options; | ||
| if (!options.createRequire) return; | ||
| const getContext = () => { | ||
| if (parser.currentTagData) { | ||
| const { context } = | ||
| /** @type {CommonJsImportSettings} */ | ||
| (parser.currentTagData); | ||
| return context; | ||
| } | ||
| }; | ||
| /** | ||
| * @param {string | symbol} tag tag | ||
| */ | ||
| const tapRequireExpressionTag = (tag) => { | ||
| parser.hooks.typeof | ||
| .for(tag) | ||
| .tap( | ||
| PLUGIN_NAME, | ||
| toConstantDependency(parser, JSON.stringify("function")) | ||
| ); | ||
| parser.hooks.evaluateTypeof | ||
| .for(tag) | ||
| .tap(PLUGIN_NAME, evaluateToString("function")); | ||
| }; | ||
| /** | ||
| * @param {Expression} expr expression | ||
| * @returns {boolean} true when set undefined | ||
| */ | ||
| const defineUndefined = (expr) => { | ||
| const dep = new ConstDependency( | ||
| "undefined", | ||
| /** @type {Range} */ (expr.range) | ||
| ); | ||
| dep.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| parser.state.module.addPresentationalDependency(dep); | ||
| return false; | ||
| }; | ||
| const requireCache = createRequireCacheDependency(parser); | ||
| const requireAsExpressionHandler = createRequireAsExpressionHandler( | ||
| parser, | ||
| options, | ||
| getContext | ||
| ); | ||
| const createRequireCallHandler = createRequireHandler( | ||
| parser, | ||
| options, | ||
| getContext | ||
| ); | ||
| const processResolve = createProcessResolveHandler( | ||
| parser, | ||
| options, | ||
| getContext | ||
| ); | ||
| /** @type {ImportSource[]} */ | ||
| let moduleNames = []; | ||
| /** @type {string | undefined} */ | ||
| let specifierName; | ||
| if (options.createRequire === true) { | ||
| moduleNames = ["module", "node:module"]; | ||
| specifierName = "createRequire"; | ||
| } else if (typeof options.createRequire === "string") { | ||
| /** @type {undefined | string} */ | ||
| let parsedModuleName; | ||
| const match = /^(.*) from (.*)$/.exec(options.createRequire); | ||
| if (match) { | ||
| [, specifierName, parsedModuleName] = match; | ||
| } | ||
| if (!specifierName || !parsedModuleName) { | ||
| const err = new WebpackError( | ||
| `Parsing javascript parser option "createRequire" failed, got ${JSON.stringify( | ||
| options.createRequire | ||
| )}` | ||
| ); | ||
| err.details = | ||
| 'Expected string in format "createRequire from module", where "createRequire" is specifier name and "module" name of the module'; | ||
| throw err; | ||
| } | ||
| moduleNames = [parsedModuleName]; | ||
| } else { | ||
| return; | ||
| } | ||
| /** | ||
| * @param {CallExpression} expr call expression | ||
| * @returns {string | void} context | ||
| */ | ||
| const parseCreateRequireArguments = (expr) => { | ||
| const args = expr.arguments; | ||
| if (args.length !== 1) { | ||
| const err = new WebpackError( | ||
| "module.createRequire supports only one argument." | ||
| ); | ||
| err.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| parser.state.module.addWarning(err); | ||
| return; | ||
| } | ||
| const arg = args[0]; | ||
| const evaluated = parser.evaluateExpression(arg); | ||
| if (!evaluated.isString()) { | ||
| const err = new WebpackError( | ||
| "module.createRequire failed parsing argument." | ||
| ); | ||
| err.loc = /** @type {DependencyLocation} */ (arg.loc); | ||
| parser.state.module.addWarning(err); | ||
| return; | ||
| } | ||
| const ctx = /** @type {string} */ (evaluated.string).startsWith("file://") | ||
| ? fileURLToPath(/** @type {string} */ (evaluated.string)) | ||
| : /** @type {string} */ (evaluated.string); | ||
| // argument always should be a filename | ||
| return ctx.slice(0, ctx.lastIndexOf(ctx.startsWith("/") ? "/" : "\\")); | ||
| }; | ||
| tapRequireExpressionTag(createdRequireIdentifierTag); | ||
| tapRequireExpressionTag(createRequireSpecifierTag); | ||
| parser.hooks.evaluateCallExpression | ||
| .for(createRequireSpecifierTag) | ||
| .tap(PLUGIN_NAME, (expr) => { | ||
| const context = parseCreateRequireArguments(expr); | ||
| if (context === undefined) return; | ||
| const ident = parser.evaluatedVariable({ | ||
| tag: createdRequireIdentifierTag, | ||
| data: { context }, | ||
| next: undefined | ||
| }); | ||
| return new BasicEvaluatedExpression() | ||
| .setIdentifier(ident, ident, () => []) | ||
| .setSideEffects(false) | ||
| .setRange(/** @type {Range} */ (expr.range)); | ||
| }); | ||
| parser.hooks.unhandledExpressionMemberChain | ||
| .for(createdRequireIdentifierTag) | ||
| .tap(PLUGIN_NAME, (expr, members) => | ||
| expressionIsUnsupported( | ||
| parser, | ||
| `createRequire().${members.join(".")} is not supported by webpack.` | ||
| )(expr) | ||
| ); | ||
| parser.hooks.canRename | ||
| .for(createdRequireIdentifierTag) | ||
| .tap(PLUGIN_NAME, () => true); | ||
| parser.hooks.canRename | ||
| .for(createRequireSpecifierTag) | ||
| .tap(PLUGIN_NAME, () => true); | ||
| parser.hooks.rename | ||
| .for(createRequireSpecifierTag) | ||
| .tap(PLUGIN_NAME, defineUndefined); | ||
| parser.hooks.expression | ||
| .for(createdRequireIdentifierTag) | ||
| .tap(PLUGIN_NAME, requireAsExpressionHandler); | ||
| parser.hooks.call | ||
| .for(createdRequireIdentifierTag) | ||
| .tap(PLUGIN_NAME, createRequireCallHandler(false)); | ||
| parser.hooks.import.tap( | ||
| { | ||
| name: PLUGIN_NAME, | ||
| stage: -10 | ||
| }, | ||
| (statement, source) => { | ||
| if ( | ||
| !moduleNames.includes(source) || | ||
| statement.specifiers.length !== 1 || | ||
| statement.specifiers[0].type !== "ImportSpecifier" || | ||
| statement.specifiers[0].imported.type !== "Identifier" || | ||
| statement.specifiers[0].imported.name !== specifierName | ||
| ) { | ||
| return; | ||
| } | ||
| // clear for 'import { createRequire as x } from "module"' | ||
| // if any other specifier was used import module | ||
| const clearDep = new ConstDependency( | ||
| parser.isAsiPosition(/** @type {Range} */ (statement.range)[0]) | ||
| ? ";" | ||
| : "", | ||
| /** @type {Range} */ (statement.range) | ||
| ); | ||
| clearDep.loc = /** @type {DependencyLocation} */ (statement.loc); | ||
| parser.state.module.addPresentationalDependency(clearDep); | ||
| parser.unsetAsiPosition(/** @type {Range} */ (statement.range)[1]); | ||
| return true; | ||
| } | ||
| ); | ||
| parser.hooks.importSpecifier.tap( | ||
| { | ||
| name: PLUGIN_NAME, | ||
| stage: -10 | ||
| }, | ||
| (statement, source, id, name) => { | ||
| if (!moduleNames.includes(source) || id !== specifierName) return; | ||
| parser.tagVariable(name, createRequireSpecifierTag); | ||
| return true; | ||
| } | ||
| ); | ||
| parser.hooks.preDeclarator.tap(PLUGIN_NAME, (declarator) => { | ||
| if ( | ||
| declarator.id.type !== "Identifier" || | ||
| !declarator.init || | ||
| declarator.init.type !== "CallExpression" || | ||
| declarator.init.callee.type !== "Identifier" | ||
| ) { | ||
| return; | ||
| } | ||
| const variableInfo = parser.getVariableInfo(declarator.init.callee.name); | ||
| if ( | ||
| variableInfo instanceof VariableInfo && | ||
| variableInfo.tagInfo && | ||
| variableInfo.tagInfo.tag === createRequireSpecifierTag | ||
| ) { | ||
| const context = parseCreateRequireArguments(declarator.init); | ||
| if (context === undefined) return; | ||
| parser.tagVariable(declarator.id.name, createdRequireIdentifierTag, { | ||
| name: declarator.id.name, | ||
| context | ||
| }); | ||
| return true; | ||
| } | ||
| }); | ||
| parser.hooks.memberChainOfCallMemberChain | ||
| .for(createRequireSpecifierTag) | ||
| .tap(PLUGIN_NAME, (expr, calleeMembers, callExpr, members) => { | ||
| if ( | ||
| calleeMembers.length !== 0 || | ||
| members.length !== 1 || | ||
| members[0] !== "cache" | ||
| ) { | ||
| return; | ||
| } | ||
| // createRequire().cache | ||
| const context = parseCreateRequireArguments(callExpr); | ||
| if (context === undefined) return; | ||
| return requireCache(expr); | ||
| }); | ||
| parser.hooks.callMemberChainOfCallMemberChain | ||
| .for(createRequireSpecifierTag) | ||
| .tap(PLUGIN_NAME, (expr, calleeMembers, innerCallExpression, members) => { | ||
| if ( | ||
| calleeMembers.length !== 0 || | ||
| members.length !== 1 || | ||
| members[0] !== "resolve" | ||
| ) { | ||
| return; | ||
| } | ||
| // createRequire().resolve() | ||
| return processResolve(expr, false); | ||
| }); | ||
| parser.hooks.expressionMemberChain | ||
| .for(createdRequireIdentifierTag) | ||
| .tap(PLUGIN_NAME, (expr, members) => { | ||
| // require.cache | ||
| if (members.length === 1 && members[0] === "cache") { | ||
| return requireCache(expr); | ||
| } | ||
| }); | ||
| parser.hooks.callMemberChain | ||
| .for(createdRequireIdentifierTag) | ||
| .tap(PLUGIN_NAME, (expr, members) => { | ||
| // require.resolve() | ||
| if (members.length === 1 && members[0] === "resolve") { | ||
| return processResolve(expr, false); | ||
| } | ||
| }); | ||
| parser.hooks.call | ||
| .for(createRequireSpecifierTag) | ||
| .tap(PLUGIN_NAME, (expr) => { | ||
| const clearDep = new ConstDependency( | ||
| "/* createRequire() */ undefined", | ||
| /** @type {Range} */ (expr.range) | ||
| ); | ||
| clearDep.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| parser.state.module.addPresentationalDependency(clearDep); | ||
| return true; | ||
| }); | ||
| } | ||
| } | ||
| module.exports = CreateRequireParserPlugin; |
@@ -89,4 +89,16 @@ /* | ||
| /** | ||
| * @typedef {object} AssetModulesPluginOptions | ||
| * @property {boolean=} sideEffectFree | ||
| */ | ||
| class AssetModulesPlugin { | ||
| /** | ||
| * @param {AssetModulesPluginOptions} options options | ||
| */ | ||
| constructor(options) { | ||
| this.options = options; | ||
| } | ||
| /** | ||
| * Apply the plugin | ||
@@ -116,3 +128,6 @@ * @param {Compiler} compiler the compiler instance | ||
| ); | ||
| module.factoryMeta = { sideEffectFree: true }; | ||
| if (this.options.sideEffectFree) { | ||
| module.factoryMeta = { sideEffectFree: true }; | ||
| } | ||
| return module; | ||
@@ -119,0 +134,0 @@ }); |
@@ -45,5 +45,9 @@ /* | ||
| super(ASSET_MODULE_TYPE_RAW_DATA_URL, null); | ||
| /** @type {string} */ | ||
| this.url = url; | ||
| /** @type {Buffer | undefined} */ | ||
| this.urlBuffer = url ? Buffer.from(url) : undefined; | ||
| this.identifierStr = identifier || this.url; | ||
| /** @type {string} */ | ||
| this.identifierStr = identifier; | ||
| /** @type {string} */ | ||
| this.readableIdentifierStr = readableIdentifier || this.identifierStr; | ||
@@ -50,0 +54,0 @@ } |
@@ -372,2 +372,3 @@ /* | ||
| validate(options); | ||
| /** @type {CleanOptions & { dry: boolean }} */ | ||
| this.options = { dry: false, ...options }; | ||
@@ -374,0 +375,0 @@ } |
+14
-8
@@ -122,2 +122,3 @@ /* | ||
| /** @typedef {Record<string, ModuleId>} UserRequestMap */ | ||
| /** @typedef {Record<ModuleId, ModuleId[]>} UserRequestsMap */ | ||
@@ -715,3 +716,3 @@ class ContextModule extends Module { | ||
| * @param {ChunkGraph} chunkGraph chunk graph | ||
| * @returns {Map<string, ModuleId[] | undefined>} map with user requests | ||
| * @returns {UserRequestsMap} map with user requests | ||
| */ | ||
@@ -731,2 +732,3 @@ getModuleDeferredAsyncDepsMap(dependencies, chunkGraph) { | ||
| .sort(comparator); | ||
| /** @type {UserRequestsMap} */ | ||
| const map = Object.create(null); | ||
@@ -746,3 +748,3 @@ for (const module of sortedModules) { | ||
| /** | ||
| * @param {false | Map<string, ModuleId[] | undefined>} asyncDepsMap fake map | ||
| * @param {false | UserRequestsMap} asyncDepsMap fake map | ||
| * @returns {string} async deps map init statement | ||
@@ -1175,8 +1177,12 @@ */ | ||
| : `function webpackAsyncContext(req) { | ||
| if(!${RuntimeGlobals.hasOwnProperty}(map, req)) { | ||
| return Promise.resolve().then(${runtimeTemplate.basicFunction("", [ | ||
| 'var e = new Error("Cannot find module \'" + req + "\'");', | ||
| "e.code = 'MODULE_NOT_FOUND';", | ||
| "throw e;" | ||
| ])}); | ||
| try { | ||
| if(!${RuntimeGlobals.hasOwnProperty}(map, req)) { | ||
| return Promise.resolve().then(${runtimeTemplate.basicFunction("", [ | ||
| 'var e = new Error("Cannot find module \'" + req + "\'");', | ||
| "e.code = 'MODULE_NOT_FOUND';", | ||
| "throw e;" | ||
| ])}); | ||
| } | ||
| } catch(err) { | ||
| return Promise.reject(err); | ||
| } | ||
@@ -1183,0 +1189,0 @@ |
@@ -22,3 +22,2 @@ /* | ||
| const CssImportDependency = require("../dependencies/CssImportDependency"); | ||
| const EntryDependency = require("../dependencies/EntryDependency"); | ||
| const { getUndoPath } = require("../util/identifier"); | ||
@@ -476,7 +475,3 @@ const memoize = require("../util/memoize"); | ||
| let isEntryModule = false; | ||
| for (const connection of connections) { | ||
| if (connection.dependency instanceof EntryDependency) { | ||
| isEntryModule = true; | ||
| } | ||
| if ( | ||
@@ -508,3 +503,3 @@ exportType === "link" && | ||
| if (this._generatesJsOnly(module)) { | ||
| if (sourceTypes.has(JAVASCRIPT_TYPE) || isEntryModule) { | ||
| if (sourceTypes.has(JAVASCRIPT_TYPE)) { | ||
| return JAVASCRIPT_TYPES; | ||
@@ -584,1 +579,3 @@ } | ||
| module.exports = CssGenerator; | ||
| module.exports = CssGenerator; |
@@ -389,2 +389,9 @@ /* | ||
| if (module instanceof CssModule && module.hot) { | ||
| const exportType = /** @type {BuildMeta} */ (module.buildMeta) | ||
| .exportType; | ||
| // When exportType !== "link", modules behave like JavaScript modules | ||
| if (exportType && exportType !== "link") { | ||
| return source; | ||
| } | ||
| // For exportType === "link", we can optimize with self-acceptance | ||
| const cssData = /** @type {BuildInfo} */ (module.buildInfo).cssData; | ||
@@ -391,0 +398,0 @@ if (!cssData) { |
@@ -68,2 +68,6 @@ /* | ||
| get category() { | ||
| return "commonjs"; | ||
| } | ||
| /** | ||
@@ -70,0 +74,0 @@ * @returns {boolean | TRANSITIVE} true, when changes to the referenced module could affect the referencing module; TRANSITIVE, when changes to the referenced module could affect referencing modules of the referencing module |
@@ -8,9 +8,5 @@ /* | ||
| const { fileURLToPath } = require("url"); | ||
| const CommentCompilationWarning = require("../CommentCompilationWarning"); | ||
| const RuntimeGlobals = require("../RuntimeGlobals"); | ||
| const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning"); | ||
| const WebpackError = require("../WebpackError"); | ||
| const BasicEvaluatedExpression = require("../javascript/BasicEvaluatedExpression"); | ||
| const { VariableInfo } = require("../javascript/JavascriptParser"); | ||
| const { | ||
@@ -40,2 +36,3 @@ evaluateToIdentifier, | ||
| /** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */ | ||
| /** @typedef {import("../javascript/BasicEvaluatedExpression")} BasicEvaluatedExpression */ | ||
| /** @typedef {import("../javascript/JavascriptParser").ImportSource} ImportSource */ | ||
@@ -53,7 +50,296 @@ /** @typedef {import("../javascript/JavascriptParser").Range} Range */ | ||
| const createRequireSpecifierTag = Symbol("createRequire"); | ||
| const createdRequireIdentifierTag = Symbol("createRequire()"); | ||
| const PLUGIN_NAME = "CommonJsImportsParserPlugin"; | ||
| /** | ||
| * @param {JavascriptParser} parser parser | ||
| * @returns {(expr: Expression) => boolean} handler | ||
| */ | ||
| const createRequireCacheDependency = (parser) => | ||
| toConstantDependency(parser, RuntimeGlobals.moduleCache, [ | ||
| RuntimeGlobals.moduleCache, | ||
| RuntimeGlobals.moduleId, | ||
| RuntimeGlobals.moduleLoaded | ||
| ]); | ||
| /** | ||
| * @param {JavascriptParser} parser parser | ||
| * @param {JavascriptParserOptions} options options | ||
| * @param {() => undefined | string} getContext context accessor | ||
| * @returns {(expr: Expression) => boolean} handler | ||
| */ | ||
| const createRequireAsExpressionHandler = | ||
| (parser, options, getContext) => (expr) => { | ||
| const dep = new CommonJsRequireContextDependency( | ||
| { | ||
| request: /** @type {string} */ (options.unknownContextRequest), | ||
| recursive: /** @type {boolean} */ (options.unknownContextRecursive), | ||
| regExp: /** @type {RegExp} */ (options.unknownContextRegExp), | ||
| mode: "sync" | ||
| }, | ||
| /** @type {Range} */ (expr.range), | ||
| undefined, | ||
| parser.scope.inShorthand, | ||
| getContext() | ||
| ); | ||
| dep.critical = | ||
| options.unknownContextCritical && | ||
| "require function is used in a way in which dependencies cannot be statically extracted"; | ||
| dep.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| dep.optional = Boolean(parser.scope.inTry); | ||
| parser.state.current.addDependency(dep); | ||
| return true; | ||
| }; | ||
| /** | ||
| * @param {JavascriptParser} parser parser | ||
| * @param {JavascriptParserOptions} options options | ||
| * @param {() => undefined | string} getContext context accessor | ||
| * @returns {(callNew: boolean) => (expr: CallExpression | NewExpression) => (boolean | void)} handler factory | ||
| */ | ||
| const createRequireCallHandler = (parser, options, getContext) => { | ||
| /** | ||
| * @param {CallExpression | NewExpression} expr expression | ||
| * @param {BasicEvaluatedExpression} param param | ||
| * @returns {boolean | void} true when handled | ||
| */ | ||
| const processRequireItem = (expr, param) => { | ||
| if (param.isString()) { | ||
| const dep = new CommonJsRequireDependency( | ||
| /** @type {string} */ (param.string), | ||
| /** @type {Range} */ (param.range), | ||
| getContext() | ||
| ); | ||
| dep.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| dep.optional = Boolean(parser.scope.inTry); | ||
| parser.state.current.addDependency(dep); | ||
| return true; | ||
| } | ||
| }; | ||
| /** | ||
| * @param {CallExpression | NewExpression} expr expression | ||
| * @param {BasicEvaluatedExpression} param param | ||
| * @returns {boolean | void} true when handled | ||
| */ | ||
| const processRequireContext = (expr, param) => { | ||
| const dep = ContextDependencyHelpers.create( | ||
| CommonJsRequireContextDependency, | ||
| /** @type {Range} */ (expr.range), | ||
| param, | ||
| expr, | ||
| options, | ||
| { | ||
| category: "commonjs" | ||
| }, | ||
| parser, | ||
| undefined, | ||
| getContext() | ||
| ); | ||
| if (!dep) return; | ||
| dep.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| dep.optional = Boolean(parser.scope.inTry); | ||
| parser.state.current.addDependency(dep); | ||
| return true; | ||
| }; | ||
| return (callNew) => (expr) => { | ||
| if (options.commonjsMagicComments) { | ||
| const { options: requireOptions, errors: commentErrors } = | ||
| parser.parseCommentOptions(/** @type {Range} */ (expr.range)); | ||
| if (commentErrors) { | ||
| for (const e of commentErrors) { | ||
| const { comment } = e; | ||
| parser.state.module.addWarning( | ||
| new CommentCompilationWarning( | ||
| `Compilation error while processing magic comment(-s): /*${comment.value}*/: ${e.message}`, | ||
| /** @type {DependencyLocation} */ (comment.loc) | ||
| ) | ||
| ); | ||
| } | ||
| } | ||
| if (requireOptions && requireOptions.webpackIgnore !== undefined) { | ||
| if (typeof requireOptions.webpackIgnore !== "boolean") { | ||
| parser.state.module.addWarning( | ||
| new UnsupportedFeatureWarning( | ||
| `\`webpackIgnore\` expected a boolean, but received: ${requireOptions.webpackIgnore}.`, | ||
| /** @type {DependencyLocation} */ (expr.loc) | ||
| ) | ||
| ); | ||
| } else if (requireOptions.webpackIgnore) { | ||
| // Do not instrument `require()` if `webpackIgnore` is `true` | ||
| return true; | ||
| } | ||
| } | ||
| } | ||
| if (expr.arguments.length !== 1) return; | ||
| /** @type {null | LocalModule} */ | ||
| let localModule; | ||
| const param = parser.evaluateExpression(expr.arguments[0]); | ||
| if (param.isConditional()) { | ||
| let isExpression = false; | ||
| for (const p of /** @type {BasicEvaluatedExpression[]} */ ( | ||
| param.options | ||
| )) { | ||
| const result = processRequireItem(expr, p); | ||
| if (result === undefined) { | ||
| isExpression = true; | ||
| } | ||
| } | ||
| if (!isExpression) { | ||
| const dep = new RequireHeaderDependency( | ||
| /** @type {Range} */ (expr.callee.range) | ||
| ); | ||
| dep.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| parser.state.module.addPresentationalDependency(dep); | ||
| return true; | ||
| } | ||
| } | ||
| if ( | ||
| param.isString() && | ||
| (localModule = getLocalModule( | ||
| parser.state, | ||
| /** @type {string} */ (param.string) | ||
| )) | ||
| ) { | ||
| localModule.flagUsed(); | ||
| const dep = new LocalModuleDependency( | ||
| localModule, | ||
| /** @type {Range} */ (expr.range), | ||
| callNew | ||
| ); | ||
| dep.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| parser.state.module.addPresentationalDependency(dep); | ||
| } else { | ||
| const result = processRequireItem(expr, param); | ||
| if (result === undefined) { | ||
| processRequireContext(expr, param); | ||
| } else { | ||
| const dep = new RequireHeaderDependency( | ||
| /** @type {Range} */ (expr.callee.range) | ||
| ); | ||
| dep.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| parser.state.module.addPresentationalDependency(dep); | ||
| } | ||
| } | ||
| return true; | ||
| }; | ||
| }; | ||
| /** | ||
| * @param {JavascriptParser} parser parser | ||
| * @param {JavascriptParserOptions} options options | ||
| * @param {() => undefined | string} getContext context accessor | ||
| * @returns {(expr: CallExpression, weak: boolean) => (boolean | void)} resolver | ||
| */ | ||
| const createProcessResolveHandler = (parser, options, getContext) => { | ||
| /** | ||
| * @param {CallExpression} expr call expression | ||
| * @param {BasicEvaluatedExpression} param param | ||
| * @param {boolean} weak weak | ||
| * @returns {boolean | void} true when handled | ||
| */ | ||
| const processResolveItem = (expr, param, weak) => { | ||
| if (param.isString()) { | ||
| const dep = new RequireResolveDependency( | ||
| /** @type {string} */ (param.string), | ||
| /** @type {Range} */ (param.range), | ||
| getContext() | ||
| ); | ||
| dep.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| dep.optional = Boolean(parser.scope.inTry); | ||
| dep.weak = weak; | ||
| parser.state.current.addDependency(dep); | ||
| return true; | ||
| } | ||
| }; | ||
| /** | ||
| * @param {CallExpression} expr call expression | ||
| * @param {BasicEvaluatedExpression} param param | ||
| * @param {boolean} weak weak | ||
| * @returns {boolean | void} true when handled | ||
| */ | ||
| const processResolveContext = (expr, param, weak) => { | ||
| const dep = ContextDependencyHelpers.create( | ||
| RequireResolveContextDependency, | ||
| /** @type {Range} */ (param.range), | ||
| param, | ||
| expr, | ||
| options, | ||
| { | ||
| category: "commonjs", | ||
| mode: weak ? "weak" : "sync" | ||
| }, | ||
| parser, | ||
| getContext() | ||
| ); | ||
| if (!dep) return; | ||
| dep.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| dep.optional = Boolean(parser.scope.inTry); | ||
| parser.state.current.addDependency(dep); | ||
| return true; | ||
| }; | ||
| return (expr, weak) => { | ||
| if (!weak && options.commonjsMagicComments) { | ||
| const { options: requireOptions, errors: commentErrors } = | ||
| parser.parseCommentOptions(/** @type {Range} */ (expr.range)); | ||
| if (commentErrors) { | ||
| for (const e of commentErrors) { | ||
| const { comment } = e; | ||
| parser.state.module.addWarning( | ||
| new CommentCompilationWarning( | ||
| `Compilation error while processing magic comment(-s): /*${comment.value}*/: ${e.message}`, | ||
| /** @type {DependencyLocation} */ (comment.loc) | ||
| ) | ||
| ); | ||
| } | ||
| } | ||
| if (requireOptions && requireOptions.webpackIgnore !== undefined) { | ||
| if (typeof requireOptions.webpackIgnore !== "boolean") { | ||
| parser.state.module.addWarning( | ||
| new UnsupportedFeatureWarning( | ||
| `\`webpackIgnore\` expected a boolean, but received: ${requireOptions.webpackIgnore}.`, | ||
| /** @type {DependencyLocation} */ (expr.loc) | ||
| ) | ||
| ); | ||
| } else if (requireOptions.webpackIgnore) { | ||
| // Do not instrument `require()` if `webpackIgnore` is `true` | ||
| return true; | ||
| } | ||
| } | ||
| } | ||
| if (expr.arguments.length !== 1) return; | ||
| const param = parser.evaluateExpression(expr.arguments[0]); | ||
| if (param.isConditional()) { | ||
| for (const option of /** @type {BasicEvaluatedExpression[]} */ ( | ||
| param.options | ||
| )) { | ||
| const result = processResolveItem(expr, option, weak); | ||
| if (result === undefined) { | ||
| processResolveContext(expr, option, weak); | ||
| } | ||
| } | ||
| const dep = new RequireResolveHeaderDependency( | ||
| /** @type {Range} */ (expr.callee.range) | ||
| ); | ||
| dep.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| parser.state.module.addPresentationalDependency(dep); | ||
| return true; | ||
| } | ||
| const result = processResolveItem(expr, param, weak); | ||
| if (result === undefined) { | ||
| processResolveContext(expr, param, weak); | ||
| } | ||
| const dep = new RequireResolveHeaderDependency( | ||
| /** @type {Range} */ (expr.callee.range) | ||
| ); | ||
| dep.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| parser.state.module.addPresentationalDependency(dep); | ||
| return true; | ||
| }; | ||
| }; | ||
| class CommonJsImportsParserPlugin { | ||
@@ -104,16 +390,2 @@ /** | ||
| }; | ||
| /** | ||
| * @param {string | symbol} tag tag | ||
| */ | ||
| const tapRequireExpressionTag = (tag) => { | ||
| parser.hooks.typeof | ||
| .for(tag) | ||
| .tap( | ||
| PLUGIN_NAME, | ||
| toConstantDependency(parser, JSON.stringify("function")) | ||
| ); | ||
| parser.hooks.evaluateTypeof | ||
| .for(tag) | ||
| .tap(PLUGIN_NAME, evaluateToString("function")); | ||
| }; | ||
| tapRequireExpression("require", () => []); | ||
@@ -183,11 +455,3 @@ tapRequireExpression("require.resolve", () => ["resolve"]); | ||
| // #region Inspection | ||
| const requireCache = toConstantDependency( | ||
| parser, | ||
| RuntimeGlobals.moduleCache, | ||
| [ | ||
| RuntimeGlobals.moduleCache, | ||
| RuntimeGlobals.moduleId, | ||
| RuntimeGlobals.moduleLoaded | ||
| ] | ||
| ); | ||
| const requireCache = createRequireCacheDependency(parser); | ||
@@ -202,23 +466,7 @@ parser.hooks.expression.for("require.cache").tap(PLUGIN_NAME, requireCache); | ||
| */ | ||
| const requireAsExpressionHandler = (expr) => { | ||
| const dep = new CommonJsRequireContextDependency( | ||
| { | ||
| request: /** @type {string} */ (options.unknownContextRequest), | ||
| recursive: /** @type {boolean} */ (options.unknownContextRecursive), | ||
| regExp: /** @type {RegExp} */ (options.unknownContextRegExp), | ||
| mode: "sync" | ||
| }, | ||
| /** @type {Range} */ (expr.range), | ||
| undefined, | ||
| parser.scope.inShorthand, | ||
| getContext() | ||
| ); | ||
| dep.critical = | ||
| options.unknownContextCritical && | ||
| "require function is used in a way in which dependencies cannot be statically extracted"; | ||
| dep.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| dep.optional = Boolean(parser.scope.inTry); | ||
| parser.state.current.addDependency(dep); | ||
| return true; | ||
| }; | ||
| const requireAsExpressionHandler = createRequireAsExpressionHandler( | ||
| parser, | ||
| options, | ||
| getContext | ||
| ); | ||
| parser.hooks.expression | ||
@@ -231,131 +479,10 @@ .for("require") | ||
| /** | ||
| * @param {CallExpression | NewExpression} expr expression | ||
| * @param {BasicEvaluatedExpression} param param | ||
| * @returns {boolean | void} true when handled | ||
| */ | ||
| const processRequireItem = (expr, param) => { | ||
| if (param.isString()) { | ||
| const dep = new CommonJsRequireDependency( | ||
| /** @type {string} */ (param.string), | ||
| /** @type {Range} */ (param.range), | ||
| getContext() | ||
| ); | ||
| dep.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| dep.optional = Boolean(parser.scope.inTry); | ||
| parser.state.current.addDependency(dep); | ||
| return true; | ||
| } | ||
| }; | ||
| /** | ||
| * @param {CallExpression | NewExpression} expr expression | ||
| * @param {BasicEvaluatedExpression} param param | ||
| * @returns {boolean | void} true when handled | ||
| */ | ||
| const processRequireContext = (expr, param) => { | ||
| const dep = ContextDependencyHelpers.create( | ||
| CommonJsRequireContextDependency, | ||
| /** @type {Range} */ (expr.range), | ||
| param, | ||
| expr, | ||
| options, | ||
| { | ||
| category: "commonjs" | ||
| }, | ||
| parser, | ||
| undefined, | ||
| getContext() | ||
| ); | ||
| if (!dep) return; | ||
| dep.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| dep.optional = Boolean(parser.scope.inTry); | ||
| parser.state.current.addDependency(dep); | ||
| return true; | ||
| }; | ||
| /** | ||
| * @param {boolean} callNew true, when require is called with new | ||
| * @returns {(expr: CallExpression | NewExpression) => (boolean | void)} handler | ||
| */ | ||
| const createRequireHandler = (callNew) => (expr) => { | ||
| if (options.commonjsMagicComments) { | ||
| const { options: requireOptions, errors: commentErrors } = | ||
| parser.parseCommentOptions(/** @type {Range} */ (expr.range)); | ||
| if (commentErrors) { | ||
| for (const e of commentErrors) { | ||
| const { comment } = e; | ||
| parser.state.module.addWarning( | ||
| new CommentCompilationWarning( | ||
| `Compilation error while processing magic comment(-s): /*${comment.value}*/: ${e.message}`, | ||
| /** @type {DependencyLocation} */ (comment.loc) | ||
| ) | ||
| ); | ||
| } | ||
| } | ||
| if (requireOptions && requireOptions.webpackIgnore !== undefined) { | ||
| if (typeof requireOptions.webpackIgnore !== "boolean") { | ||
| parser.state.module.addWarning( | ||
| new UnsupportedFeatureWarning( | ||
| `\`webpackIgnore\` expected a boolean, but received: ${requireOptions.webpackIgnore}.`, | ||
| /** @type {DependencyLocation} */ (expr.loc) | ||
| ) | ||
| ); | ||
| } else if (requireOptions.webpackIgnore) { | ||
| // Do not instrument `require()` if `webpackIgnore` is `true` | ||
| return true; | ||
| } | ||
| } | ||
| } | ||
| if (expr.arguments.length !== 1) return; | ||
| /** @type {null | LocalModule} */ | ||
| let localModule; | ||
| const param = parser.evaluateExpression(expr.arguments[0]); | ||
| if (param.isConditional()) { | ||
| let isExpression = false; | ||
| for (const p of /** @type {BasicEvaluatedExpression[]} */ ( | ||
| param.options | ||
| )) { | ||
| const result = processRequireItem(expr, p); | ||
| if (result === undefined) { | ||
| isExpression = true; | ||
| } | ||
| } | ||
| if (!isExpression) { | ||
| const dep = new RequireHeaderDependency( | ||
| /** @type {Range} */ (expr.callee.range) | ||
| ); | ||
| dep.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| parser.state.module.addPresentationalDependency(dep); | ||
| return true; | ||
| } | ||
| } | ||
| if ( | ||
| param.isString() && | ||
| (localModule = getLocalModule( | ||
| parser.state, | ||
| /** @type {string} */ (param.string) | ||
| )) | ||
| ) { | ||
| localModule.flagUsed(); | ||
| const dep = new LocalModuleDependency( | ||
| localModule, | ||
| /** @type {Range} */ (expr.range), | ||
| callNew | ||
| ); | ||
| dep.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| parser.state.module.addPresentationalDependency(dep); | ||
| } else { | ||
| const result = processRequireItem(expr, param); | ||
| if (result === undefined) { | ||
| processRequireContext(expr, param); | ||
| } else { | ||
| const dep = new RequireHeaderDependency( | ||
| /** @type {Range} */ (expr.callee.range) | ||
| ); | ||
| dep.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| parser.state.module.addPresentationalDependency(dep); | ||
| } | ||
| } | ||
| return true; | ||
| }; | ||
| const createRequireHandler = createRequireCallHandler( | ||
| parser, | ||
| options, | ||
| getContext | ||
| ); | ||
| parser.hooks.call | ||
@@ -470,109 +597,8 @@ .for("require") | ||
| */ | ||
| const processResolve = (expr, weak) => { | ||
| if (!weak && options.commonjsMagicComments) { | ||
| const { options: requireOptions, errors: commentErrors } = | ||
| parser.parseCommentOptions(/** @type {Range} */ (expr.range)); | ||
| const processResolve = createProcessResolveHandler( | ||
| parser, | ||
| options, | ||
| getContext | ||
| ); | ||
| if (commentErrors) { | ||
| for (const e of commentErrors) { | ||
| const { comment } = e; | ||
| parser.state.module.addWarning( | ||
| new CommentCompilationWarning( | ||
| `Compilation error while processing magic comment(-s): /*${comment.value}*/: ${e.message}`, | ||
| /** @type {DependencyLocation} */ (comment.loc) | ||
| ) | ||
| ); | ||
| } | ||
| } | ||
| if (requireOptions && requireOptions.webpackIgnore !== undefined) { | ||
| if (typeof requireOptions.webpackIgnore !== "boolean") { | ||
| parser.state.module.addWarning( | ||
| new UnsupportedFeatureWarning( | ||
| `\`webpackIgnore\` expected a boolean, but received: ${requireOptions.webpackIgnore}.`, | ||
| /** @type {DependencyLocation} */ (expr.loc) | ||
| ) | ||
| ); | ||
| } else if (requireOptions.webpackIgnore) { | ||
| // Do not instrument `require()` if `webpackIgnore` is `true` | ||
| return true; | ||
| } | ||
| } | ||
| } | ||
| if (expr.arguments.length !== 1) return; | ||
| const param = parser.evaluateExpression(expr.arguments[0]); | ||
| if (param.isConditional()) { | ||
| for (const option of /** @type {BasicEvaluatedExpression[]} */ ( | ||
| param.options | ||
| )) { | ||
| const result = processResolveItem(expr, option, weak); | ||
| if (result === undefined) { | ||
| processResolveContext(expr, option, weak); | ||
| } | ||
| } | ||
| const dep = new RequireResolveHeaderDependency( | ||
| /** @type {Range} */ (expr.callee.range) | ||
| ); | ||
| dep.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| parser.state.module.addPresentationalDependency(dep); | ||
| return true; | ||
| } | ||
| const result = processResolveItem(expr, param, weak); | ||
| if (result === undefined) { | ||
| processResolveContext(expr, param, weak); | ||
| } | ||
| const dep = new RequireResolveHeaderDependency( | ||
| /** @type {Range} */ (expr.callee.range) | ||
| ); | ||
| dep.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| parser.state.module.addPresentationalDependency(dep); | ||
| return true; | ||
| }; | ||
| /** | ||
| * @param {CallExpression} expr call expression | ||
| * @param {BasicEvaluatedExpression} param param | ||
| * @param {boolean} weak weak | ||
| * @returns {boolean | void} true when handled | ||
| */ | ||
| const processResolveItem = (expr, param, weak) => { | ||
| if (param.isString()) { | ||
| const dep = new RequireResolveDependency( | ||
| /** @type {string} */ (param.string), | ||
| /** @type {Range} */ (param.range), | ||
| getContext() | ||
| ); | ||
| dep.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| dep.optional = Boolean(parser.scope.inTry); | ||
| dep.weak = weak; | ||
| parser.state.current.addDependency(dep); | ||
| return true; | ||
| } | ||
| }; | ||
| /** | ||
| * @param {CallExpression} expr call expression | ||
| * @param {BasicEvaluatedExpression} param param | ||
| * @param {boolean} weak weak | ||
| * @returns {boolean | void} true when handled | ||
| */ | ||
| const processResolveContext = (expr, param, weak) => { | ||
| const dep = ContextDependencyHelpers.create( | ||
| RequireResolveContextDependency, | ||
| /** @type {Range} */ (param.range), | ||
| param, | ||
| expr, | ||
| options, | ||
| { | ||
| category: "commonjs", | ||
| mode: weak ? "weak" : "sync" | ||
| }, | ||
| parser, | ||
| getContext() | ||
| ); | ||
| if (!dep) return; | ||
| dep.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| dep.optional = Boolean(parser.scope.inTry); | ||
| parser.state.current.addDependency(dep); | ||
| return true; | ||
| }; | ||
| parser.hooks.call | ||
@@ -585,227 +611,2 @@ .for("require.resolve") | ||
| // #endregion | ||
| // #region Create require | ||
| if (!options.createRequire) return; | ||
| /** @type {ImportSource[]} */ | ||
| let moduleName = []; | ||
| /** @type {string | undefined} */ | ||
| let specifierName; | ||
| if (options.createRequire === true) { | ||
| moduleName = ["module", "node:module"]; | ||
| specifierName = "createRequire"; | ||
| } else { | ||
| /** @type {undefined | string} */ | ||
| let moduleName; | ||
| const match = /^(.*) from (.*)$/.exec(options.createRequire); | ||
| if (match) { | ||
| [, specifierName, moduleName] = match; | ||
| } | ||
| if (!specifierName || !moduleName) { | ||
| const err = new WebpackError( | ||
| `Parsing javascript parser option "createRequire" failed, got ${JSON.stringify( | ||
| options.createRequire | ||
| )}` | ||
| ); | ||
| err.details = | ||
| 'Expected string in format "createRequire from module", where "createRequire" is specifier name and "module" name of the module'; | ||
| throw err; | ||
| } | ||
| } | ||
| tapRequireExpressionTag(createdRequireIdentifierTag); | ||
| tapRequireExpressionTag(createRequireSpecifierTag); | ||
| parser.hooks.evaluateCallExpression | ||
| .for(createRequireSpecifierTag) | ||
| .tap(PLUGIN_NAME, (expr) => { | ||
| const context = parseCreateRequireArguments(expr); | ||
| if (context === undefined) return; | ||
| const ident = parser.evaluatedVariable({ | ||
| tag: createdRequireIdentifierTag, | ||
| data: { context }, | ||
| next: undefined | ||
| }); | ||
| return new BasicEvaluatedExpression() | ||
| .setIdentifier(ident, ident, () => []) | ||
| .setSideEffects(false) | ||
| .setRange(/** @type {Range} */ (expr.range)); | ||
| }); | ||
| parser.hooks.unhandledExpressionMemberChain | ||
| .for(createdRequireIdentifierTag) | ||
| .tap(PLUGIN_NAME, (expr, members) => | ||
| expressionIsUnsupported( | ||
| parser, | ||
| `createRequire().${members.join(".")} is not supported by webpack.` | ||
| )(expr) | ||
| ); | ||
| parser.hooks.canRename | ||
| .for(createdRequireIdentifierTag) | ||
| .tap(PLUGIN_NAME, () => true); | ||
| parser.hooks.canRename | ||
| .for(createRequireSpecifierTag) | ||
| .tap(PLUGIN_NAME, () => true); | ||
| parser.hooks.rename | ||
| .for(createRequireSpecifierTag) | ||
| .tap(PLUGIN_NAME, defineUndefined); | ||
| parser.hooks.expression | ||
| .for(createdRequireIdentifierTag) | ||
| .tap(PLUGIN_NAME, requireAsExpressionHandler); | ||
| parser.hooks.call | ||
| .for(createdRequireIdentifierTag) | ||
| .tap(PLUGIN_NAME, createRequireHandler(false)); | ||
| /** | ||
| * @param {CallExpression} expr call expression | ||
| * @returns {string | void} context | ||
| */ | ||
| const parseCreateRequireArguments = (expr) => { | ||
| const args = expr.arguments; | ||
| if (args.length !== 1) { | ||
| const err = new WebpackError( | ||
| "module.createRequire supports only one argument." | ||
| ); | ||
| err.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| parser.state.module.addWarning(err); | ||
| return; | ||
| } | ||
| const arg = args[0]; | ||
| const evaluated = parser.evaluateExpression(arg); | ||
| if (!evaluated.isString()) { | ||
| const err = new WebpackError( | ||
| "module.createRequire failed parsing argument." | ||
| ); | ||
| err.loc = /** @type {DependencyLocation} */ (arg.loc); | ||
| parser.state.module.addWarning(err); | ||
| return; | ||
| } | ||
| const ctx = /** @type {string} */ (evaluated.string).startsWith("file://") | ||
| ? fileURLToPath(/** @type {string} */ (evaluated.string)) | ||
| : /** @type {string} */ (evaluated.string); | ||
| // argument always should be a filename | ||
| return ctx.slice(0, ctx.lastIndexOf(ctx.startsWith("/") ? "/" : "\\")); | ||
| }; | ||
| parser.hooks.import.tap( | ||
| { | ||
| name: PLUGIN_NAME, | ||
| stage: -10 | ||
| }, | ||
| (statement, source) => { | ||
| if ( | ||
| !moduleName.includes(source) || | ||
| statement.specifiers.length !== 1 || | ||
| statement.specifiers[0].type !== "ImportSpecifier" || | ||
| statement.specifiers[0].imported.type !== "Identifier" || | ||
| statement.specifiers[0].imported.name !== specifierName | ||
| ) { | ||
| return; | ||
| } | ||
| // clear for 'import { createRequire as x } from "module"' | ||
| // if any other specifier was used import module | ||
| const clearDep = new ConstDependency( | ||
| parser.isAsiPosition(/** @type {Range} */ (statement.range)[0]) | ||
| ? ";" | ||
| : "", | ||
| /** @type {Range} */ (statement.range) | ||
| ); | ||
| clearDep.loc = /** @type {DependencyLocation} */ (statement.loc); | ||
| parser.state.module.addPresentationalDependency(clearDep); | ||
| parser.unsetAsiPosition(/** @type {Range} */ (statement.range)[1]); | ||
| return true; | ||
| } | ||
| ); | ||
| parser.hooks.importSpecifier.tap( | ||
| { | ||
| name: PLUGIN_NAME, | ||
| stage: -10 | ||
| }, | ||
| (statement, source, id, name) => { | ||
| if (!moduleName.includes(source) || id !== specifierName) return; | ||
| parser.tagVariable(name, createRequireSpecifierTag); | ||
| return true; | ||
| } | ||
| ); | ||
| parser.hooks.preDeclarator.tap(PLUGIN_NAME, (declarator) => { | ||
| if ( | ||
| declarator.id.type !== "Identifier" || | ||
| !declarator.init || | ||
| declarator.init.type !== "CallExpression" || | ||
| declarator.init.callee.type !== "Identifier" | ||
| ) { | ||
| return; | ||
| } | ||
| const variableInfo = parser.getVariableInfo(declarator.init.callee.name); | ||
| if ( | ||
| variableInfo instanceof VariableInfo && | ||
| variableInfo.tagInfo && | ||
| variableInfo.tagInfo.tag === createRequireSpecifierTag | ||
| ) { | ||
| const context = parseCreateRequireArguments(declarator.init); | ||
| if (context === undefined) return; | ||
| parser.tagVariable(declarator.id.name, createdRequireIdentifierTag, { | ||
| name: declarator.id.name, | ||
| context | ||
| }); | ||
| return true; | ||
| } | ||
| }); | ||
| parser.hooks.memberChainOfCallMemberChain | ||
| .for(createRequireSpecifierTag) | ||
| .tap(PLUGIN_NAME, (expr, calleeMembers, callExpr, members) => { | ||
| if ( | ||
| calleeMembers.length !== 0 || | ||
| members.length !== 1 || | ||
| members[0] !== "cache" | ||
| ) { | ||
| return; | ||
| } | ||
| // createRequire().cache | ||
| const context = parseCreateRequireArguments(callExpr); | ||
| if (context === undefined) return; | ||
| return requireCache(expr); | ||
| }); | ||
| parser.hooks.callMemberChainOfCallMemberChain | ||
| .for(createRequireSpecifierTag) | ||
| .tap(PLUGIN_NAME, (expr, calleeMembers, innerCallExpression, members) => { | ||
| if ( | ||
| calleeMembers.length !== 0 || | ||
| members.length !== 1 || | ||
| members[0] !== "resolve" | ||
| ) { | ||
| return; | ||
| } | ||
| // createRequire().resolve() | ||
| return processResolve(expr, false); | ||
| }); | ||
| parser.hooks.expressionMemberChain | ||
| .for(createdRequireIdentifierTag) | ||
| .tap(PLUGIN_NAME, (expr, members) => { | ||
| // require.cache | ||
| if (members.length === 1 && members[0] === "cache") { | ||
| return requireCache(expr); | ||
| } | ||
| }); | ||
| parser.hooks.callMemberChain | ||
| .for(createdRequireIdentifierTag) | ||
| .tap(PLUGIN_NAME, (expr, members) => { | ||
| // require.resolve() | ||
| if (members.length === 1 && members[0] === "resolve") { | ||
| return processResolve(expr, false); | ||
| } | ||
| }); | ||
| parser.hooks.call | ||
| .for(createRequireSpecifierTag) | ||
| .tap(PLUGIN_NAME, (expr) => { | ||
| const clearDep = new ConstDependency( | ||
| "/* createRequire() */ undefined", | ||
| /** @type {Range} */ (expr.range) | ||
| ); | ||
| clearDep.loc = /** @type {DependencyLocation} */ (expr.loc); | ||
| parser.state.module.addPresentationalDependency(clearDep); | ||
| return true; | ||
| }); | ||
| // #endregion | ||
| } | ||
@@ -815,1 +616,6 @@ } | ||
| module.exports = CommonJsImportsParserPlugin; | ||
| module.exports.createProcessResolveHandler = createProcessResolveHandler; | ||
| module.exports.createRequireAsExpressionHandler = | ||
| createRequireAsExpressionHandler; | ||
| module.exports.createRequireCacheDependency = createRequireCacheDependency; | ||
| module.exports.createRequireHandler = createRequireCallHandler; |
@@ -42,10 +42,6 @@ /* | ||
| this.options = options; | ||
| this.exportPresenceMode = | ||
| options.reexportExportsPresence !== undefined | ||
| ? ExportPresenceModes.fromUserOption(options.reexportExportsPresence) | ||
| : options.exportsPresence !== undefined | ||
| ? ExportPresenceModes.fromUserOption(options.exportsPresence) | ||
| : options.strictExportPresence | ||
| ? ExportPresenceModes.ERROR | ||
| : ExportPresenceModes.AUTO; | ||
| this.exportPresenceMode = ExportPresenceModes.resolveFromOptions( | ||
| options.reexportExportsPresence, | ||
| options | ||
| ); | ||
| } | ||
@@ -52,0 +48,0 @@ |
@@ -56,5 +56,34 @@ /* | ||
| } | ||
| }, | ||
| /** | ||
| * Resolve export presence mode from parser options with a specific key and shared fallbacks. | ||
| * @param {string | false | undefined} specificValue the type-specific option value (e.g. importExportsPresence or reexportExportsPresence) | ||
| * @param {import("../../declarations/WebpackOptions").JavascriptParserOptions} options parser options | ||
| * @returns {ExportPresenceMode} resolved mode | ||
| */ | ||
| resolveFromOptions(specificValue, options) { | ||
| if (specificValue !== undefined) { | ||
| return ExportPresenceModes.fromUserOption(specificValue); | ||
| } | ||
| if (options.exportsPresence !== undefined) { | ||
| return ExportPresenceModes.fromUserOption(options.exportsPresence); | ||
| } | ||
| return options.strictExportPresence | ||
| ? ExportPresenceModes.ERROR | ||
| : ExportPresenceModes.AUTO; | ||
| } | ||
| }; | ||
| /** | ||
| * Get the non-optional leading part of a member chain. | ||
| * @param {string[]} members members | ||
| * @param {boolean[]} membersOptionals optionality for each member | ||
| * @returns {string[]} the non-optional prefix | ||
| */ | ||
| const getNonOptionalPart = (members, membersOptionals) => { | ||
| let i = 0; | ||
| while (i < members.length && membersOptionals[i] === false) i++; | ||
| return i !== members.length ? members.slice(0, i) : members; | ||
| }; | ||
| /** @typedef {string[]} Ids */ | ||
@@ -431,1 +460,2 @@ | ||
| module.exports.ExportPresenceModes = ExportPresenceModes; | ||
| module.exports.getNonOptionalPart = getNonOptionalPart; |
@@ -21,3 +21,6 @@ /* | ||
| const HarmonyExports = require("./HarmonyExports"); | ||
| const { ExportPresenceModes } = require("./HarmonyImportDependency"); | ||
| const { | ||
| ExportPresenceModes, | ||
| getNonOptionalPart | ||
| } = require("./HarmonyImportDependency"); | ||
| const HarmonyImportSideEffectDependency = require("./HarmonyImportSideEffectDependency"); | ||
@@ -86,10 +89,6 @@ const HarmonyImportSpecifierDependency = require("./HarmonyImportSpecifierDependency"); | ||
| /** @type {ExportPresenceMode} */ | ||
| this.exportPresenceMode = | ||
| options.importExportsPresence !== undefined | ||
| ? ExportPresenceModes.fromUserOption(options.importExportsPresence) | ||
| : options.exportsPresence !== undefined | ||
| ? ExportPresenceModes.fromUserOption(options.exportsPresence) | ||
| : options.strictExportPresence | ||
| ? ExportPresenceModes.ERROR | ||
| : ExportPresenceModes.AUTO; | ||
| this.exportPresenceMode = ExportPresenceModes.resolveFromOptions( | ||
| options.importExportsPresence, | ||
| options | ||
| ); | ||
| this.strictThisContextOnImports = options.strictThisContextOnImports; | ||
@@ -125,13 +124,2 @@ } | ||
| /** | ||
| * @param {Members} members members | ||
| * @param {MembersOptionals} membersOptionals members Optionals | ||
| * @returns {Ids} a non optional part | ||
| */ | ||
| function getNonOptionalPart(members, membersOptionals) { | ||
| let i = 0; | ||
| while (i < members.length && membersOptionals[i] === false) i++; | ||
| return i !== members.length ? members.slice(0, i) : members; | ||
| } | ||
| /** | ||
| * @param {MemberExpression} node member expression | ||
@@ -138,0 +126,0 @@ * @param {number} count count |
@@ -12,2 +12,3 @@ /* | ||
| } = require("../ModuleTypeConstants"); | ||
| const CreateRequireParserPlugin = require("./CreateRequireParserPlugin"); | ||
| const HarmonyAcceptDependency = require("./HarmonyAcceptDependency"); | ||
@@ -142,2 +143,5 @@ const HarmonyAcceptImportDependency = require("./HarmonyAcceptImportDependency"); | ||
| new HarmonyTopLevelThisParserPlugin().apply(parser); | ||
| if (parserOptions.createRequire) { | ||
| new CreateRequireParserPlugin(parserOptions).apply(parser); | ||
| } | ||
| }; | ||
@@ -144,0 +148,0 @@ |
@@ -17,2 +17,3 @@ /* | ||
| const ContextDependencyHelpers = require("./ContextDependencyHelpers"); | ||
| const { getNonOptionalPart } = require("./HarmonyImportDependency"); | ||
| const ImportContextDependency = require("./ImportContextDependency"); | ||
@@ -182,13 +183,2 @@ const ImportDependency = require("./ImportDependency"); | ||
| apply(parser) { | ||
| /** | ||
| * @param {Members} members members | ||
| * @param {MembersOptionals} membersOptionals members Optionals | ||
| * @returns {string[]} a non optional part | ||
| */ | ||
| function getNonOptionalPart(members, membersOptionals) { | ||
| let i = 0; | ||
| while (i < members.length && membersOptionals[i] === false) i++; | ||
| return i !== members.length ? members.slice(0, i) : members; | ||
| } | ||
| parser.hooks.collectDestructuringAssignmentProperties.tap( | ||
@@ -195,0 +185,0 @@ PLUGIN_NAME, |
@@ -30,2 +30,3 @@ /* | ||
| * @typedef {object} ImportPhaseUtils | ||
| * @property {(phase: ImportPhaseType) => boolean} isEvaluation true if phase is evaluation | ||
| * @property {(phase: ImportPhaseType) => boolean} isDefer true if phase is defer | ||
@@ -37,2 +38,5 @@ * @property {(phase: ImportPhaseType) => boolean} isSource true if phase is source | ||
| const ImportPhaseUtils = { | ||
| isEvaluation(phase) { | ||
| return phase === ImportPhase.Evaluation; | ||
| }, | ||
| isDefer(phase) { | ||
@@ -39,0 +43,0 @@ return phase === ImportPhase.Defer; |
@@ -230,3 +230,3 @@ /* | ||
| throw new Error( | ||
| "Dependency.getReference was removed in favor of Dependency.getReferencedExports, ModuleGraph.getModule and ModuleGraph.getConnection().active" | ||
| "Dependency.getReference was removed in favor of Dependency.getReferencedExports, ModuleGraph.getModule, ModuleGraph.getConnection(), and ModuleGraphConnection.getActiveState(runtime)" | ||
| ); | ||
@@ -233,0 +233,0 @@ } |
@@ -29,2 +29,3 @@ /* | ||
| this.name = "EnvironmentNotSupportAsyncWarning"; | ||
| /** @type {Module} */ | ||
| this.module = module; | ||
@@ -31,0 +32,0 @@ } |
@@ -46,4 +46,7 @@ /* | ||
| constructor(options = {}) { | ||
| /** @type {DevtoolNamespace} */ | ||
| this.namespace = options.namespace || ""; | ||
| /** @type {string} */ | ||
| this.sourceUrlComment = options.sourceUrlComment || "\n//# sourceURL=[url]"; | ||
| /** @type {DevtoolModuleFilenameTemplate} */ | ||
| this.moduleFilenameTemplate = | ||
@@ -50,0 +53,0 @@ options.moduleFilenameTemplate || |
@@ -20,6 +20,9 @@ /* | ||
| /** @typedef {import("webpack-sources").Source} Source */ | ||
| /** @typedef {import("../declarations/WebpackOptions").DevtoolNamespace} DevtoolNamespace */ | ||
| /** @typedef {import("../declarations/WebpackOptions").DevtoolModuleFilenameTemplate} DevtoolModuleFilenameTemplate */ | ||
| /** @typedef {import("../declarations/plugins/SourceMapDevToolPlugin").SourceMapDevToolPluginOptions} SourceMapDevToolPluginOptions */ | ||
| /** @typedef {import("../declarations/plugins/SourceMapDevToolPlugin").Rules} Rules */ | ||
| /** @typedef {import("./Compiler")} Compiler */ | ||
| /** @typedef {import("./ChunkGraph").ModuleId} ModuleId */ | ||
| /** @typedef {import("./Compiler")} Compiler */ | ||
| /** @typedef {import("./TemplatedPathPlugin").TemplatePath} TemplatePath */ | ||
@@ -55,2 +58,3 @@ /** @type {WeakMap<Source, Source>} */ | ||
| } | ||
| /** @type {string} */ | ||
| this.sourceMapComment = | ||
@@ -60,6 +64,9 @@ options.append && typeof options.append !== "function" | ||
| : "//# sourceURL=[module]\n//# sourceMappingURL=[url]"; | ||
| /** @type {DevtoolModuleFilenameTemplate} */ | ||
| this.moduleFilenameTemplate = | ||
| options.moduleFilenameTemplate || | ||
| "webpack://[namespace]/[resource-path]?[hash]"; | ||
| /** @type {DevtoolNamespace} */ | ||
| this.namespace = options.namespace || ""; | ||
| /** @type {SourceMapDevToolPluginOptions} */ | ||
| this.options = options; | ||
@@ -66,0 +73,0 @@ } |
+0
-30
@@ -936,32 +936,2 @@ /* | ||
| // TODO webpack 5 remove | ||
| /** | ||
| * @private | ||
| * @param {EXPECTED_ANY} v v | ||
| */ | ||
| set used(v) { | ||
| throw new Error("REMOVED"); | ||
| } | ||
| // TODO webpack 5 remove | ||
| /** @private */ | ||
| get used() { | ||
| throw new Error("REMOVED"); | ||
| } | ||
| // TODO webpack 5 remove | ||
| /** | ||
| * @private | ||
| * @param {EXPECTED_ANY} v v | ||
| */ | ||
| set usedName(v) { | ||
| throw new Error("REMOVED"); | ||
| } | ||
| // TODO webpack 5 remove | ||
| /** @private */ | ||
| get usedName() { | ||
| throw new Error("REMOVED"); | ||
| } | ||
| get canMangle() { | ||
@@ -968,0 +938,0 @@ switch (this.canMangleProvide) { |
@@ -998,3 +998,3 @@ /* | ||
| const data = new Map(); | ||
| data.set("url", { javascript: request }); | ||
| data.set("url", { javascript: /** @type {string} */ (request) }); | ||
| return { sources, runtimeRequirements: RUNTIME_REQUIREMENTS, data }; | ||
@@ -1007,3 +1007,3 @@ } | ||
| const data = new Map(); | ||
| data.set("url", { "css-url": request }); | ||
| data.set("url", { "css-url": /** @type {string} */ (request) }); | ||
| return { sources, runtimeRequirements: RUNTIME_REQUIREMENTS, data }; | ||
@@ -1010,0 +1010,0 @@ } |
@@ -59,2 +59,3 @@ /* | ||
| /** @typedef {import("../ChunkGraph")} ChunkGraph */ | ||
| /** @typedef {import("../ChunkGraph").EntryModuleWithChunkGroup} EntryModuleWithChunkGroup */ | ||
| /** @typedef {import("../CodeGenerationResults")} CodeGenerationResults */ | ||
@@ -79,2 +80,5 @@ /** @typedef {import("../Compilation").ChunkHashContext} ChunkHashContext */ | ||
| /** @type {WeakMap<ChunkGraph, WeakMap<Chunk, boolean>>} */ | ||
| const chunkHasJsCache = new WeakMap(); | ||
| /** | ||
@@ -85,4 +89,10 @@ * @param {Chunk} chunk a chunk | ||
| */ | ||
| const chunkHasJs = (chunk, chunkGraph) => { | ||
| if (chunkGraph.getNumberOfEntryModules(chunk) > 0) return true; | ||
| const _chunkHasJs = (chunk, chunkGraph) => { | ||
| if (chunkGraph.getNumberOfEntryModules(chunk) > 0) { | ||
| for (const module of chunkGraph.getChunkEntryModulesIterable(chunk)) { | ||
| if (chunkGraph.getModuleSourceTypes(module).has(JAVASCRIPT_TYPE)) { | ||
| return true; | ||
| } | ||
| } | ||
| } | ||
@@ -99,3 +109,29 @@ return Boolean( | ||
| */ | ||
| const chunkHasJs = (chunk, chunkGraph) => { | ||
| let innerCache = chunkHasJsCache.get(chunkGraph); | ||
| if (innerCache === undefined) { | ||
| innerCache = new WeakMap(); | ||
| chunkHasJsCache.set(chunkGraph, innerCache); | ||
| } | ||
| const cachedResult = innerCache.get(chunk); | ||
| if (cachedResult !== undefined) { | ||
| return cachedResult; | ||
| } | ||
| const result = _chunkHasJs(chunk, chunkGraph); | ||
| innerCache.set(chunk, result); | ||
| return result; | ||
| }; | ||
| /** | ||
| * @param {Chunk} chunk a chunk | ||
| * @param {ChunkGraph} chunkGraph the chunk graph | ||
| * @returns {boolean} true, when a JS file is needed for this chunk | ||
| */ | ||
| const chunkHasRuntimeOrJs = (chunk, chunkGraph) => { | ||
| if (chunkHasJs(chunk, chunkGraph)) { | ||
| return true; | ||
| } | ||
| if ( | ||
@@ -107,8 +143,11 @@ chunkGraph.getChunkModulesIterableBySourceType( | ||
| ) { | ||
| return true; | ||
| for (const chunkGroup of chunk.groupsIterable) { | ||
| for (const c of chunkGroup.chunks) { | ||
| if (chunkHasJs(c, chunkGraph)) return true; | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
| return Boolean( | ||
| chunkGraph.getChunkModulesIterableBySourceType(chunk, JAVASCRIPT_TYPE) | ||
| ); | ||
| return false; | ||
| }; | ||
@@ -1320,3 +1359,5 @@ | ||
| buf2.push("// Load entry module and return exports"); | ||
| let i = chunkGraph.getNumberOfEntryModules(chunk); | ||
| /** @type {EntryModuleWithChunkGroup[]} */ | ||
| const jsEntries = []; | ||
| for (const [ | ||
@@ -1327,7 +1368,10 @@ entryModule, | ||
| if ( | ||
| !chunkGraph.getModuleSourceTypes(entryModule).has(JAVASCRIPT_TYPE) | ||
| chunkGraph.getModuleSourceTypes(entryModule).has(JAVASCRIPT_TYPE) | ||
| ) { | ||
| i--; | ||
| jsEntries.push([entryModule, entrypoint]); | ||
| continue; | ||
| } | ||
| } | ||
| let i = jsEntries.length; | ||
| for (const [entryModule, entrypoint] of jsEntries) { | ||
| const chunks = | ||
@@ -1556,2 +1600,21 @@ /** @type {Entrypoint} */ | ||
| const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk); | ||
| /** | ||
| * @param {string} condition guard expression | ||
| * @returns {string[]} source | ||
| */ | ||
| const renderMissingModuleError = (condition) => | ||
| outputOptions.pathinfo | ||
| ? [ | ||
| `if (${condition}) {`, | ||
| Template.indent([ | ||
| "delete __webpack_module_cache__[moduleId];", | ||
| 'var e = new Error("Cannot find module \'" + moduleId + "\'");', | ||
| "e.code = 'MODULE_NOT_FOUND';", | ||
| "throw e;" | ||
| ]), | ||
| "}" | ||
| ] | ||
| : []; | ||
| const moduleExecution = runtimeRequirements.has( | ||
@@ -1563,2 +1626,3 @@ RuntimeGlobals.interceptModuleExecution | ||
| `${RuntimeGlobals.interceptModuleExecution}.forEach(function(handler) { handler(execOptions); });`, | ||
| ...renderMissingModuleError("!execOptions.factory"), | ||
| "module = execOptions.module;", | ||
@@ -1569,5 +1633,7 @@ "execOptions.factory.call(module.exports, module, module.exports, execOptions.require);" | ||
| ? Template.asString([ | ||
| ...renderMissingModuleError("!(moduleId in __webpack_modules__)"), | ||
| `__webpack_modules__[moduleId].call(module.exports, module, module.exports, ${RuntimeGlobals.require});` | ||
| ]) | ||
| : Template.asString([ | ||
| ...renderMissingModuleError("!(moduleId in __webpack_modules__)"), | ||
| `__webpack_modules__[moduleId](module, module.exports, ${RuntimeGlobals.require});` | ||
@@ -1593,15 +1659,2 @@ ]); | ||
| "}", | ||
| // Add helpful error message in development mode when module is not found | ||
| ...(outputOptions.pathinfo | ||
| ? [ | ||
| "// Check if module exists (development only)", | ||
| "if (__webpack_modules__[moduleId] === undefined) {", | ||
| Template.indent([ | ||
| 'var e = new Error("Cannot find module \'" + moduleId + "\'");', | ||
| "e.code = 'MODULE_NOT_FOUND';", | ||
| "throw e;" | ||
| ]), | ||
| "}" | ||
| ] | ||
| : []), | ||
| "// Create a new module (and put it into the cache)", | ||
@@ -1608,0 +1661,0 @@ "var module = __webpack_module_cache__[moduleId] = {", |
+30
-5
@@ -107,8 +107,33 @@ /* | ||
| /** @typedef {Map<"topLevelDeclarations", Set<string>> & Map<"chunkInitFragments", InitFragment<EXPECTED_ANY>[]>} KnownCodeGenerationResultDataForJavascriptModules */ | ||
| /** @typedef {Map<"url", { ["css-url"]: string }>} KnownCodeGenerationResultDataForCssModules */ | ||
| /** @typedef {Map<"filename", string> & Map<"assetInfo", AssetInfo> & Map<"fullContentHash", string> & Map<"url", { javascript: string }>} KnownCodeGenerationResultDataForAssetModules */ | ||
| /** @typedef {Map<"share-init", [{ shareScope: string, initStage: number, init: string }]>} KnownCodeGenerationResultForSharing */ | ||
| /** @typedef {KnownCodeGenerationResultDataForJavascriptModules & KnownCodeGenerationResultDataForCssModules & KnownCodeGenerationResultDataForAssetModules & KnownCodeGenerationResultForSharing & Map<string, EXPECTED_ANY>} CodeGenerationResultData */ | ||
| /** | ||
| * @typedef {object} AllCodeGenerationSchemas | ||
| * @property {Set<string>} topLevelDeclarations top level declarations for javascript modules | ||
| * @property {InitFragment<EXPECTED_ANY>[]} chunkInitFragments chunk init fragments for javascript modules | ||
| * @property {{ javascript?: string, ["css-url"]?: string }} url url for css and javascript modules | ||
| * @property {string} filename a filename for asset modules | ||
| * @property {AssetInfo} assetInfo an asset info for asset modules | ||
| * @property {string} fullContentHash a full content hash for asset modules | ||
| * @property {[{ shareScope: string, initStage: number, init: string }]} share-init share-init for modules federation | ||
| */ | ||
| /* eslint-disable jsdoc/type-formatting */ | ||
| /** | ||
| * @template {string} K | ||
| * @typedef {K extends keyof AllCodeGenerationSchemas ? AllCodeGenerationSchemas[K] : EXPECTED_ANY} CodeGenValue | ||
| */ | ||
| /* eslint-enable jsdoc/type-formatting */ | ||
| /* eslint-disable jsdoc/require-template */ | ||
| /** | ||
| * @typedef {object} CodeGenMapOverloads | ||
| * @property {<K extends string>(key: K) => CodeGenValue<K> | undefined} get | ||
| * @property {<K extends string>(key: K, value: CodeGenValue<K>) => CodeGenerationResultData} set | ||
| * @property {<K extends string>(key: K) => boolean} has | ||
| * @property {<K extends string>(key: K) => boolean} delete | ||
| */ | ||
| /** | ||
| * @typedef {Omit<Map<string, EXPECTED_ANY>, "get" | "set" | "has" | "delete"> & CodeGenMapOverloads} CodeGenerationResultData | ||
| */ | ||
| /** @typedef {Map<SourceType, Source>} Sources */ | ||
@@ -115,0 +140,0 @@ |
@@ -187,11 +187,2 @@ /* | ||
| } | ||
| // TODO webpack 5 remove | ||
| get active() { | ||
| throw new Error("Use getActiveState instead"); | ||
| } | ||
| set active(value) { | ||
| throw new Error("Use setActive instead"); | ||
| } | ||
| } | ||
@@ -198,0 +189,0 @@ |
@@ -31,2 +31,3 @@ /* | ||
| this.name = "AssetsOverSizeLimitWarning"; | ||
| /** @type {AssetDetails[]} */ | ||
| this.assets = assetsOverSizeLimit; | ||
@@ -33,0 +34,0 @@ } |
@@ -34,2 +34,3 @@ /* | ||
| this.name = "EntrypointsOverSizeLimitWarning"; | ||
| /** @type {EntrypointDetails[]} */ | ||
| this.entrypoints = entrypoints; | ||
@@ -36,0 +37,0 @@ } |
@@ -49,2 +49,3 @@ /* | ||
| constructor(options) { | ||
| /** @type {PerformanceOptions["hints"]} */ | ||
| this.hints = options.hints; | ||
@@ -51,0 +52,0 @@ /** @type {number | undefined} */ |
@@ -32,8 +32,16 @@ /* | ||
| const isNeutralPlatform = runtimeTemplate.isNeutralPlatform(); | ||
| const toImmutableBytes = runtimeTemplate.basicFunction("value", [ | ||
| runtimeTemplate.destructureObject(["buffer"], "value"), | ||
| `${runtimeTemplate.renderConst()} throwErr = ${runtimeTemplate.basicFunction("", ["throw new TypeError('ArrayBuffer is immutable');"])};`, | ||
| "Object.defineProperties(buffer, { immutable: { value: true }, resize: { value: throwErr }, transfer: { value: throwErr }, transferToFixedLength: { value: throwErr } });", | ||
| "Object.freeze(buffer);", | ||
| "return value;" | ||
| ]); | ||
| return Template.asString([ | ||
| "// define to binary helper", | ||
| `${runtimeTemplate.renderConst()} toImmutableBytes = ${toImmutableBytes}`, | ||
| `${fn} = ${isNeutralPlatform ? "typeof Buffer !== 'undefined' ? " : ""}${ | ||
| isNodePlatform || isNeutralPlatform | ||
| ? `${runtimeTemplate.returningFunction("new Uint8Array(Buffer.from(base64, 'base64'))", "base64")}` | ||
| ? `${runtimeTemplate.returningFunction("toImmutableBytes(new Uint8Array(Buffer.from(base64, 'base64')))", "base64")}` | ||
| : "" | ||
@@ -43,10 +51,10 @@ } ${isNeutralPlatform ? ": " : ""}${ | ||
| ? `(${runtimeTemplate.basicFunction("", [ | ||
| "var table = new Uint8Array(128);", | ||
| `${runtimeTemplate.renderConst()} table = new Uint8Array(128);`, | ||
| "for (var i = 0; i < 64; i++) table[i < 26 ? i + 65 : i < 52 ? i + 71 : i < 62 ? i - 4 : i * 4 - 205] = i;", | ||
| `return ${runtimeTemplate.basicFunction("base64", [ | ||
| "var n = base64.length, bytes = new Uint8Array((n - (base64[n - 1] == '=') - (base64[n - 2] == '=')) * 3 / 4 | 0);", | ||
| `${runtimeTemplate.renderConst()} n = base64.length, bytes = new Uint8Array((n - (base64[n - 1] == '=') - (base64[n - 2] == '=')) * 3 / 4 | 0);`, | ||
| "for (var i = 0, j = 0; i < n;) {", | ||
| Template.indent([ | ||
| "var c0 = table[base64.charCodeAt(i++)], c1 = table[base64.charCodeAt(i++)];", | ||
| "var c2 = table[base64.charCodeAt(i++)], c3 = table[base64.charCodeAt(i++)];", | ||
| `${runtimeTemplate.renderConst()} c0 = table[base64.charCodeAt(i++)], c1 = table[base64.charCodeAt(i++)];`, | ||
| `${runtimeTemplate.renderConst()} c2 = table[base64.charCodeAt(i++)], c3 = table[base64.charCodeAt(i++)];`, | ||
| "bytes[j++] = (c0 << 2) | (c1 >> 4);", | ||
@@ -57,3 +65,3 @@ "bytes[j++] = (c1 << 4) | (c2 >> 2);", | ||
| "}", | ||
| "return bytes" | ||
| "return toImmutableBytes(bytes)" | ||
| ])}` | ||
@@ -60,0 +68,0 @@ ])})();` |
@@ -20,2 +20,3 @@ /* | ||
| constructor(options = {}) { | ||
| /** @type {SourceMapDevToolPluginOptions} */ | ||
| this.options = options; | ||
@@ -22,0 +23,0 @@ } |
@@ -22,2 +22,5 @@ /* | ||
| /** @typedef {import("webpack-sources").Source} Source */ | ||
| /** @typedef {import("../declarations/WebpackOptions").DevtoolNamespace} DevtoolNamespace */ | ||
| /** @typedef {import("../declarations/WebpackOptions").DevtoolModuleFilenameTemplate} DevtoolModuleFilenameTemplate */ | ||
| /** @typedef {import("../declarations/WebpackOptions").DevtoolFallbackModuleFilenameTemplate} DevtoolFallbackModuleFilenameTemplate */ | ||
| /** @typedef {import("../declarations/plugins/SourceMapDevToolPlugin").SourceMapDevToolPluginOptions} SourceMapDevToolPluginOptions */ | ||
@@ -144,4 +147,5 @@ /** @typedef {import("../declarations/plugins/SourceMapDevToolPlugin").Rules} Rules */ | ||
| this.sourceMapFilename = /** @type {string | false} */ (options.filename); | ||
| /** @type {false | TemplatePath}} */ | ||
| /** @type {undefined | null | false | string} */ | ||
| this.sourceMapFilename = options.filename; | ||
| /** @type {false | TemplatePath} */ | ||
| this.sourceMappingURLComment = | ||
@@ -152,8 +156,12 @@ options.append === false | ||
| options.append || "\n//# source" + "MappingURL=[url]"; | ||
| /** @type {DevtoolModuleFilenameTemplate} */ | ||
| this.moduleFilenameTemplate = | ||
| options.moduleFilenameTemplate || "webpack://[namespace]/[resourcePath]"; | ||
| /** @type {DevtoolFallbackModuleFilenameTemplate} */ | ||
| this.fallbackModuleFilenameTemplate = | ||
| options.fallbackModuleFilenameTemplate || | ||
| "webpack://[namespace]/[resourcePath]?[hash]"; | ||
| /** @type {DevtoolNamespace} */ | ||
| this.namespace = options.namespace || ""; | ||
| /** @type {SourceMapDevToolPluginOptions} */ | ||
| this.options = options; | ||
@@ -160,0 +168,0 @@ } |
+79
-109
@@ -11,4 +11,3 @@ /* | ||
| const DONE_MARKER = 2; | ||
| const DONE_MAYBE_ROOT_CYCLE_MARKER = 3; | ||
| const DONE_AND_ROOT_MARKER = 4; | ||
| const CANDIDATE_MARKER = 3; | ||
@@ -22,8 +21,3 @@ /** | ||
| * @template T | ||
| * @typedef {Set<Cycle<T>>} Cycles | ||
| */ | ||
| /** | ||
| * @template T | ||
| */ | ||
| class Node { | ||
@@ -37,5 +31,7 @@ /** | ||
| this.dependencies = new Set(); | ||
| this.marker = NO_MARKER; | ||
| /** @type {Cycle<T> | undefined} */ | ||
| this.cycle = undefined; | ||
| /** @type {SCC<T>} */ | ||
| this.scc = new SCC(); | ||
| // Each node starts as a single-node SCC | ||
| this.scc.nodes.add(this); | ||
| /** @type {number} */ | ||
| this.incoming = 0; | ||
@@ -46,8 +42,10 @@ } | ||
| /** | ||
| * SCC (strongly connected component) | ||
| * @template T | ||
| */ | ||
| class Cycle { | ||
| class SCC { | ||
| constructor() { | ||
| /** @type {Nodes<T>} */ | ||
| this.nodes = new Set(); | ||
| this.marker = NO_MARKER; | ||
| } | ||
@@ -77,6 +75,6 @@ } | ||
| // early exit when there is only a single item | ||
| // Early exit when there is only one node | ||
| if (itemToNode.size <= 1) return items; | ||
| // grab all the dependencies | ||
| // Build graph edges | ||
| for (const node of itemToNode.values()) { | ||
@@ -91,23 +89,12 @@ for (const dep of getDependencies(node.item)) { | ||
| // Set of current root modules | ||
| // items will be removed if a new reference to it has been found | ||
| /** @type {Nodes<T>} */ | ||
| const roots = new Set(); | ||
| // All candidate root SCCs, they will be removed once an incoming edge is found | ||
| /** @type {Set<SCC<T>>} */ | ||
| const rootSCCs = new Set(); | ||
| // Set of current cycles without references to it | ||
| // cycles will be removed if a new reference to it has been found | ||
| // that is not part of the cycle | ||
| /** @type {Cycles<T>} */ | ||
| const rootCycles = new Set(); | ||
| // For all non-marked nodes | ||
| for (const selectedNode of itemToNode.values()) { | ||
| if (selectedNode.marker === NO_MARKER) { | ||
| // deep-walk all referenced modules | ||
| // in a non-recursive way | ||
| // DFS walk only once per unseen SCC | ||
| if (selectedNode.scc.marker === NO_MARKER) { | ||
| selectedNode.scc.marker = IN_PROGRESS_MARKER; | ||
| // start by entering the selected node | ||
| selectedNode.marker = IN_PROGRESS_MARKER; | ||
| // keep a stack to avoid recursive walk | ||
| // Keep a stack to avoid recursive walk | ||
| /** @type {StackEntry<T>[]} */ | ||
@@ -121,16 +108,14 @@ const stack = [ | ||
| // process the top item until stack is empty | ||
| while (stack.length > 0) { | ||
| const topOfStack = stack[stack.length - 1]; | ||
| // Are there still edges unprocessed in the current node? | ||
| // Process one unvisited outgoing edge if available | ||
| if (topOfStack.openEdges.length > 0) { | ||
| // Process one dependency | ||
| const dependency = | ||
| /** @type {Node<T>} */ | ||
| (topOfStack.openEdges.pop()); | ||
| switch (dependency.marker) { | ||
| const depSCC = dependency.scc; | ||
| switch (depSCC.marker) { | ||
| case NO_MARKER: | ||
| // dependency has not be visited yet | ||
| // mark it as in-progress and recurse | ||
| // First time we see this SCC: enter it | ||
| stack.push({ | ||
@@ -140,110 +125,95 @@ node: dependency, | ||
| }); | ||
| dependency.marker = IN_PROGRESS_MARKER; | ||
| depSCC.marker = IN_PROGRESS_MARKER; | ||
| break; | ||
| case IN_PROGRESS_MARKER: { | ||
| // It's a in-progress cycle | ||
| let cycle = dependency.cycle; | ||
| if (!cycle) { | ||
| cycle = new Cycle(); | ||
| cycle.nodes.add(dependency); | ||
| dependency.cycle = cycle; | ||
| } | ||
| // set cycle property for each node in the cycle | ||
| // if nodes are already part of a cycle | ||
| // we merge the cycles to a shared cycle | ||
| // Back-edge to an SCC that is still on the stack | ||
| // Example: | ||
| // A -> B -> C -> D | ||
| // ^ | | ||
| // |_________| | ||
| // If we are at `D` and traverse `D` -> `B`, then `B/C/D` must be in one SCC | ||
| /** @type {Set<SCC<T>>} */ | ||
| const sccsToMerge = new Set(); | ||
| for ( | ||
| let i = stack.length - 1; | ||
| stack[i].node !== dependency; | ||
| stack[i].node.scc !== depSCC; | ||
| i-- | ||
| ) { | ||
| const node = stack[i].node; | ||
| if (node.cycle) { | ||
| if (node.cycle !== cycle) { | ||
| // merge cycles | ||
| for (const cycleNode of node.cycle.nodes) { | ||
| cycleNode.cycle = cycle; | ||
| cycle.nodes.add(cycleNode); | ||
| } | ||
| } | ||
| } else { | ||
| node.cycle = cycle; | ||
| cycle.nodes.add(node); | ||
| sccsToMerge.add(stack[i].node.scc); | ||
| } | ||
| for (const sccToMerge of sccsToMerge) { | ||
| for (const nodeInMergedSCC of sccToMerge.nodes) { | ||
| nodeInMergedSCC.scc = depSCC; | ||
| depSCC.nodes.add(nodeInMergedSCC); | ||
| } | ||
| } | ||
| // don't recurse into dependencies | ||
| // these are already on the stack | ||
| break; | ||
| } | ||
| case DONE_AND_ROOT_MARKER: | ||
| // This node has be visited yet and is currently a root node | ||
| // But as this is a new reference to the node | ||
| // it's not really a root | ||
| // so we have to convert it to a normal node | ||
| dependency.marker = DONE_MARKER; | ||
| roots.delete(dependency); | ||
| case CANDIDATE_MARKER: | ||
| // This finished SCC was previously considered as root SCC | ||
| // We just found a new incoming edge, so it is no longer a candidate | ||
| rootSCCs.delete(/** @type {SCC<T>} */ (depSCC)); | ||
| depSCC.marker = DONE_MARKER; | ||
| break; | ||
| case DONE_MAYBE_ROOT_CYCLE_MARKER: | ||
| // This node has be visited yet and | ||
| // is maybe currently part of a completed root cycle | ||
| // we found a new reference to the cycle | ||
| // so it's not really a root cycle | ||
| // remove the cycle from the root cycles | ||
| // and convert it to a normal node | ||
| rootCycles.delete(/** @type {Cycle<T>} */ (dependency.cycle)); | ||
| dependency.marker = DONE_MARKER; | ||
| case DONE_MARKER: | ||
| // Already finalized and not a candidate | ||
| break; | ||
| // DONE_MARKER: nothing to do, don't recurse into dependencies | ||
| } | ||
| } else { | ||
| // All dependencies of the current node has been visited | ||
| // we leave the node | ||
| // All dependencies of the current node have been processed | ||
| // So we leave the node | ||
| stack.pop(); | ||
| topOfStack.node.marker = DONE_MARKER; | ||
| // Mark an SCC as DONE only when the popped node is the last | ||
| // node from that SCC remaining on the current stack. | ||
| // A -> B -> C -> D | ||
| // ^ | | ||
| // |_________| | ||
| // If `B` is popped and the new stack top is `A`, they are in | ||
| // different SCCs, so B's SCC can be finalized. | ||
| if ( | ||
| stack.length && | ||
| topOfStack.node.scc !== stack[stack.length - 1].node.scc | ||
| ) { | ||
| topOfStack.node.scc.marker = DONE_MARKER; | ||
| } | ||
| } | ||
| } | ||
| const cycle = selectedNode.cycle; | ||
| if (cycle) { | ||
| for (const node of cycle.nodes) { | ||
| node.marker = DONE_MAYBE_ROOT_CYCLE_MARKER; | ||
| } | ||
| rootCycles.add(cycle); | ||
| } else { | ||
| selectedNode.marker = DONE_AND_ROOT_MARKER; | ||
| roots.add(selectedNode); | ||
| } | ||
| const scc = selectedNode.scc; | ||
| // This SCC is complete and currently has no known incoming edge | ||
| scc.marker = CANDIDATE_MARKER; | ||
| rootSCCs.add(scc); | ||
| } | ||
| } | ||
| // Extract roots from root cycles | ||
| // We take the nodes with most incoming edges | ||
| // inside of the cycle | ||
| for (const cycle of rootCycles) { | ||
| /** @type {Set<T>} */ | ||
| const rootNodes = new Set(); | ||
| // For each root SCC, we select node with the most incoming edges | ||
| // from within the same SCC | ||
| for (const scc of rootSCCs) { | ||
| let max = 0; | ||
| /** @type {Nodes<T>} */ | ||
| const cycleRoots = new Set(); | ||
| const nodes = cycle.nodes; | ||
| for (const node of nodes) { | ||
| const nodes = new Set(scc.nodes); | ||
| for (const node of scc.nodes) { | ||
| for (const dep of node.dependencies) { | ||
| if (nodes.has(dep)) { | ||
| if (scc.nodes.has(dep)) { | ||
| dep.incoming++; | ||
| if (dep.incoming < max) continue; | ||
| if (dep.incoming > max) { | ||
| cycleRoots.clear(); | ||
| nodes.clear(); | ||
| max = dep.incoming; | ||
| } | ||
| cycleRoots.add(dep); | ||
| nodes.add(dep); | ||
| } | ||
| } | ||
| } | ||
| for (const cycleRoot of cycleRoots) { | ||
| roots.add(cycleRoot); | ||
| for (const node of nodes) { | ||
| rootNodes.add(node.item); | ||
| } | ||
| } | ||
| // When roots were found, return them | ||
| if (roots.size > 0) { | ||
| return Array.from(roots, (r) => r.item); | ||
| } | ||
| // When root nodes were found, return them | ||
| if (rootNodes.size > 0) return rootNodes; | ||
| throw new Error("Implementation of findGraphRoots is broken"); | ||
| }; |
@@ -63,2 +63,3 @@ /* | ||
| const JavascriptModulesPlugin = require("./javascript/JavascriptModulesPlugin"); | ||
| const JavascriptParser = require("./javascript/JavascriptParser"); | ||
@@ -375,3 +376,5 @@ const JsonModulesPlugin = require("./json/JsonModulesPlugin"); | ||
| new JsonModulesPlugin().apply(compiler); | ||
| new AssetModulesPlugin().apply(compiler); | ||
| new AssetModulesPlugin({ | ||
| sideEffectFree: options.experiments.futureDefaults | ||
| }).apply(compiler); | ||
@@ -488,7 +491,14 @@ if (!options.experiments.outputModule) { | ||
| if (options.experiments.deferImport) { | ||
| const JavascriptParser = require("./javascript/JavascriptParser"); | ||
| if ( | ||
| options.experiments.deferImport && | ||
| !( | ||
| /** @type {typeof JavascriptParser & { __importPhasesExtended?: true }} */ | ||
| (JavascriptParser).__importPhasesExtended | ||
| ) | ||
| ) { | ||
| const importPhases = require("acorn-import-phases"); | ||
| JavascriptParser.extend(importPhases({ source: false })); | ||
| /** @type {typeof JavascriptParser & { __importPhasesExtended?: true }} */ | ||
| (JavascriptParser).__importPhasesExtended = true; | ||
| } | ||
@@ -495,0 +505,0 @@ |
+12
-9
| { | ||
| "name": "webpack", | ||
| "version": "5.105.2", | ||
| "version": "5.105.3", | ||
| "description": "Packs ECMAScript/CommonJs/AMD modules for the browser. Allows you to split your codebase into multiple bundles, which can be loaded on demand. Supports loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.", | ||
@@ -60,2 +60,3 @@ "homepage": "https://github.com/webpack/webpack", | ||
| "test:integration": "yarn test:base --testMatch \"<rootDir>/test/*.{basictest,longtest,test}.js\"", | ||
| "test:test262": "yarn test:base --testMatch \"<rootDir>/test/*.spectest.js\"", | ||
| "test:base:deno": "deno --allow-read --allow-env --allow-sys --allow-ffi --allow-write --allow-run --v8-flags='--max-old-space-size=4096' ./node_modules/jest-cli/bin/jest.js --logHeapUsage", | ||
@@ -75,3 +76,4 @@ "test:update-snapshots": "yarn test:base -u", | ||
| "cover:integration:a": "yarn cover:base --testMatch \"<rootDir>/test/*.{basictest,test}.js\" --coverage", | ||
| "cover:integration:b": "yarn cover:base --testMatch \"<rootDir>/test/*.longtest.js\" --coverage" | ||
| "cover:integration:b": "yarn cover:base --testMatch \"<rootDir>/test/*.longtest.js\" --coverage", | ||
| "cover:test262": "yarn cover:base --testMatch \"<rootDir>/test/*.spectest.js\" --coverage" | ||
| }, | ||
@@ -94,3 +96,3 @@ "lint-staged": { | ||
| "@webassemblyjs/wasm-parser": "^1.14.1", | ||
| "acorn": "^8.15.0", | ||
| "acorn": "^8.16.0", | ||
| "acorn-import-phases": "^1.0.3", | ||
@@ -113,3 +115,3 @@ "browserslist": "^4.28.1", | ||
| "watchpack": "^2.5.1", | ||
| "webpack-sources": "^3.3.3" | ||
| "webpack-sources": "^3.3.4" | ||
| }, | ||
@@ -121,3 +123,3 @@ "devDependencies": { | ||
| "@changesets/get-github-info": "^0.7.0", | ||
| "@codspeed/core": "^5.1.0", | ||
| "@codspeed/core": "^5.2.0", | ||
| "@types/glob-to-regexp": "^0.4.4", | ||
@@ -142,3 +144,3 @@ "@types/graceful-fs": "^4.1.9", | ||
| "eslint": "^9.39.2", | ||
| "eslint-config-webpack": "^4.9.1", | ||
| "eslint-config-webpack": "^4.9.3", | ||
| "file-loader": "^6.0.0", | ||
@@ -169,4 +171,5 @@ "fork-ts-checker-webpack-plugin": "^9.0.2", | ||
| "node-gyp": "^12.1.0", | ||
| "nyc": "^17.1.0", | ||
| "nyc": "^18.0.0", | ||
| "open-cli": "^8.0.0", | ||
| "oxc-parser": "^0.115.0", | ||
| "pkg-pr-new": "^0.0.63", | ||
@@ -193,6 +196,6 @@ "prettier": "^3.7.4", | ||
| "terser": "^5.43.1", | ||
| "three": "^0.182.0", | ||
| "three": "^0.183.1", | ||
| "tinybench": "^6.0.0", | ||
| "toml": "^3.0.0", | ||
| "tooling": "webpack/tooling#v1.24.5", | ||
| "tooling": "webpack/tooling#v1.24.6", | ||
| "ts-loader": "^9.5.4", | ||
@@ -199,0 +202,0 @@ "typescript": "^5.9.3", |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Network access
Supply chain riskThis module accesses the network.
Found 4 instances in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 2 instances in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 3 instances in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 5 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 4 instances in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 2 instances in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 3 instances in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 5 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
5793608
0.19%709
0.14%166016
0.18%267
-0.74%87
1.16%Updated
Updated