Merge branch 'main' into main

This commit is contained in:
Yadunandan Bhat 2022-08-01 10:33:10 +05:30 committed by GitHub
commit d0c699651b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
92 changed files with 1838 additions and 351 deletions

View File

@ -13,13 +13,16 @@ on:
- main
- dev-1
permissions:
contents: read
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Use Node.js
uses: actions/setup-node@v2
uses: actions/setup-node@v3
with:
node-version: 17.x
cache: "yarn"
@ -33,9 +36,9 @@ jobs:
basic:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Use Node.js
uses: actions/setup-node@v2
uses: actions/setup-node@v3
with:
node-version: 17.x
cache: "yarn"
@ -43,16 +46,16 @@ jobs:
- run: yarn link --frozen-lockfile || true
- run: yarn link webpack --frozen-lockfile
- run: yarn test:basic --ci
- uses: codecov/codecov-action@v1
- uses: codecov/codecov-action@v3
with:
flags: basic
functionalities: gcov
unit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Use Node.js
uses: actions/setup-node@v2
uses: actions/setup-node@v3
with:
node-version: 17.x
cache: "yarn"
@ -65,7 +68,7 @@ jobs:
key: jest-unit-${{ env.GITHUB_SHA }}
restore-keys: jest-unit-
- run: yarn cover:unit --ci --cacheDirectory .jest-cache
- uses: codecov/codecov-action@v1
- uses: codecov/codecov-action@v3
with:
flags: unit
functionalities: gcov
@ -89,23 +92,23 @@ jobs:
part: a
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: "yarn"
- run: yarn --frozen-lockfile
- run: yarn link --frozen-lockfile || true
- run: yarn link webpack --frozen-lockfile
- uses: actions/cache@v1
- uses: actions/cache@v2
with:
path: .jest-cache
key: jest-integration-${{ env.GITHUB_SHA }}
restore-keys: jest-integration-
- run: yarn cover:integration:${{ matrix.part }} --ci --cacheDirectory .jest-cache || yarn cover:integration:${{ matrix.part }} --ci --cacheDirectory .jest-cache -f
- run: yarn cover:merge
- uses: codecov/codecov-action@v1
- uses: codecov/codecov-action@v3
with:
flags: integration
functionalities: gcov

View File

@ -15,6 +15,9 @@
[![PR's welcome][prs]][prs-url]
<br>
<a href="https://docs.github.com/en/code-security/dependabot/dependabot-security-updates/about-dependabot-security-updates#about-compatibility-scores">
<img src="https://api.dependabot.com/badges/compatibility_score?dependency-name=webpack&package-manager=npm_and_yarn&previous-version=5.72.1&new-version=5.73.0">
</a>
<a href="https://npmcharts.com/compare/webpack?minimal=true">
<img src="https://img.shields.io/npm/dm/webpack.svg">
</a>
@ -110,6 +113,7 @@ within webpack itself use this plugin interface. This makes webpack very
| [mini-css-extract-plugin][mini-css] | ![mini-css-npm] | ![mini-css-size] | Extracts CSS into separate files. It creates a CSS file per JS file which contains CSS. |
| [compression-webpack-plugin][compression] | ![compression-npm] | ![compression-size] | Prepares compressed versions of assets to serve them with Content-Encoding |
| [html-webpack-plugin][html-plugin] | ![html-plugin-npm] | ![html-plugin-size] | Simplifies creation of HTML files (`index.html`) to serve your bundles |
| [pug-plugin][pug-plugin] | ![pug-plugin-npm] | ![pug-plugin-size] | Renders Pug files to HTML, extracts JS and CSS from sources specified directly in Pug. |
[common-npm]: https://img.shields.io/npm/v/webpack.svg
[mini-css]: https://github.com/webpack-contrib/mini-css-extract-plugin
@ -124,6 +128,9 @@ within webpack itself use this plugin interface. This makes webpack very
[html-plugin]: https://github.com/jantimon/html-webpack-plugin
[html-plugin-npm]: https://img.shields.io/npm/v/html-webpack-plugin.svg
[html-plugin-size]: https://packagephobia.com/badge?p=html-webpack-plugin
[pug-plugin]: https://github.com/webdiscus/pug-plugin
[pug-plugin-npm]: https://img.shields.io/npm/v/pug-plugin.svg
[pug-plugin-size]: https://packagephobia.com/badge?p=pug-plugin
### [Loaders](https://webpack.js.org/loaders/)
@ -170,18 +177,21 @@ or are automatically applied via regex from your webpack configuration.
#### Templating
| Name | Status | Install Size | Description |
| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------: | :--------------: | :-------------------------------------------------------------------------------------- |
| <a href="https://github.com/webpack-contrib/html-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/html5.svg"></a> | ![html-npm] | ![html-size] | Exports HTML as string, requires references to static resources |
| <a href="https://github.com/pugjs/pug-loader"><img width="48" height="48" src="https://cdn.rawgit.com/pugjs/pug-logo/master/SVG/pug-final-logo-_-colour-128.svg"></a> | ![pug-npm] | ![pug-size] | Loads Pug templates and returns a function |
| <a href="https://github.com/peerigon/markdown-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/markdown.svg"></a> | ![md-npm] | ![md-size] | Compiles Markdown to HTML |
| <a href="https://github.com/posthtml/posthtml-loader"><img width="48" height="48" src="https://posthtml.github.io/posthtml/logo.svg"></a> | ![posthtml-npm] | ![posthtml-size] | Loads and transforms a HTML file using [PostHTML](https://github.com/posthtml/posthtml) |
| <a href="https://github.com/pcardune/handlebars-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/handlebars-1.svg"></a> | ![hbs-npm] | ![hbs-size] | Compiles Handlebars to HTML |
| Name | Status | Install Size | Description |
| :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------: | :--------------: | :-------------------------------------------------------------------------------------- |
| <a href="https://github.com/webpack-contrib/html-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/html5.svg"></a> | ![html-npm] | ![html-size] | Exports HTML as string, requires references to static resources |
| <a href="https://github.com/pugjs/pug-loader"><img width="48" height="48" src="https://cdn.rawgit.com/pugjs/pug-logo/master/SVG/pug-final-logo-_-colour-128.svg"></a> | ![pug-npm] | ![pug-size] | Loads Pug templates and returns a function |
| <a href="https://github.com/webdiscus/pug-loader"><img width="48" height="48" src="https://cdn.rawgit.com/pugjs/pug-logo/master/SVG/pug-final-logo-_-colour-128.svg"></a> | ![pug3-npm] | ![pug3-size] | Compiles Pug to a function or HTML string, useful for use with Vue, React, Angular |
| <a href="https://github.com/peerigon/markdown-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/markdown.svg"></a> | ![md-npm] | ![md-size] | Compiles Markdown to HTML |
| <a href="https://github.com/posthtml/posthtml-loader"><img width="48" height="48" src="https://posthtml.github.io/posthtml/logo.svg"></a> | ![posthtml-npm] | ![posthtml-size] | Loads and transforms a HTML file using [PostHTML](https://github.com/posthtml/posthtml) |
| <a href="https://github.com/pcardune/handlebars-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/handlebars-1.svg"></a> | ![hbs-npm] | ![hbs-size] | Compiles Handlebars to HTML |
[html-npm]: https://img.shields.io/npm/v/html-loader.svg
[html-size]: https://packagephobia.com/badge?p=html-loader
[pug-npm]: https://img.shields.io/npm/v/pug-loader.svg
[pug-size]: https://packagephobia.com/badge?p=pug-loader
[pug3-npm]: https://img.shields.io/npm/v/@webdiscus/pug-loader.svg
[pug3-size]: https://packagephobia.com/badge?p=@webdiscus/pug-loader
[jade-npm]: https://img.shields.io/npm/v/jade-loader.svg
[jade-size]: https://packagephobia.com/badge?p=jade-loader
[md-npm]: https://img.shields.io/npm/v/markdown-loader.svg

View File

@ -1505,6 +1505,15 @@ export interface ResolveOptions {
* Field names from the description file (usually package.json) which are used to provide entry points of a package.
*/
exportsFields?: string[];
/**
* An object which maps extension to extension aliases.
*/
extensionAlias?: {
/**
* Extension alias.
*/
[k: string]: string[] | string;
};
/**
* Extensions added to the request when trying to find the file.
*/
@ -2929,6 +2938,22 @@ export interface JavascriptParserOptions {
* Enable/disable parsing of magic comments in CommonJs syntax.
*/
commonjsMagicComments?: boolean;
/**
* Enable/disable parsing "import { createRequire } from "module"" and evaluating createRequire().
*/
createRequire?: boolean | string;
/**
* Specifies global mode for dynamic import.
*/
dynamicImportMode?: "eager" | "weak" | "lazy" | "lazy-once";
/**
* Specifies global prefetch for dynamic import.
*/
dynamicImportPrefetch?: number | boolean;
/**
* Specifies global preload for dynamic import.
*/
dynamicImportPreload?: number | boolean;
/**
* Specifies the behavior of invalid export names in "import ... from ..." and "export ... from ...".
*/
@ -3498,11 +3523,11 @@ export interface ExperimentsNormalizedExtra {
/**
* Enable css support.
*/
css?: CssExperimentOptions;
css?: false | CssExperimentOptions;
/**
* Compile entrypoints and import()s only when they are accessed.
*/
lazyCompilation?: LazyCompilationOptions;
lazyCompilation?: false | LazyCompilationOptions;
}
/**
* If an dependency matches exactly a property of the object, the property value is used as dependency.

View File

@ -4241,7 +4241,11 @@ This prevents using hashes of each other and should be avoided.`);
if (!isSourceEqual(this.assets[file], source)) {
this.errors.push(
new WebpackError(
`Conflict: Multiple assets emit different content to the same filename ${file}`
`Conflict: Multiple assets emit different content to the same filename ${file}${
assetInfo.sourceFilename
? `. Original source ${assetInfo.sourceFilename}`
: ""
}`
)
);
this.assets[file] = source;

View File

@ -8,6 +8,7 @@
const { create: createResolver } = require("enhanced-resolve");
const nodeModule = require("module");
const asyncLib = require("neo-async");
const { isAbsolute } = require("path");
const AsyncQueue = require("./util/AsyncQueue");
const StackedCacheMap = require("./util/StackedCacheMap");
const createHash = require("./util/createHash");
@ -207,6 +208,12 @@ class SnapshotIterable {
class Snapshot {
constructor() {
this._flags = 0;
/** @type {Iterable<string> | undefined} */
this._cachedFileIterable = undefined;
/** @type {Iterable<string> | undefined} */
this._cachedContextIterable = undefined;
/** @type {Iterable<string> | undefined} */
this._cachedMissingIterable = undefined;
/** @type {number | undefined} */
this.startTime = undefined;
/** @type {Map<string, FileSystemInfoEntry | null> | undefined} */
@ -417,31 +424,43 @@ class Snapshot {
* @returns {Iterable<string>} iterable
*/
getFileIterable() {
return this._createIterable(s => [
s.fileTimestamps,
s.fileHashes,
s.fileTshs,
s.managedFiles
]);
if (this._cachedFileIterable === undefined) {
this._cachedFileIterable = this._createIterable(s => [
s.fileTimestamps,
s.fileHashes,
s.fileTshs,
s.managedFiles
]);
}
return this._cachedFileIterable;
}
/**
* @returns {Iterable<string>} iterable
*/
getContextIterable() {
return this._createIterable(s => [
s.contextTimestamps,
s.contextHashes,
s.contextTshs,
s.managedContexts
]);
if (this._cachedContextIterable === undefined) {
this._cachedContextIterable = this._createIterable(s => [
s.contextTimestamps,
s.contextHashes,
s.contextTshs,
s.managedContexts
]);
}
return this._cachedContextIterable;
}
/**
* @returns {Iterable<string>} iterable
*/
getMissingIterable() {
return this._createIterable(s => [s.missingExistence, s.managedMissing]);
if (this._cachedMissingIterable === undefined) {
this._cachedMissingIterable = this._createIterable(s => [
s.missingExistence,
s.managedMissing
]);
}
return this._cachedMissingIterable;
}
}
@ -1633,7 +1652,9 @@ class FileSystemInfo {
let request = relative(this.fs, context, childPath);
if (request.endsWith(".js")) request = request.slice(0, -3);
request = request.replace(/\\/g, "/");
if (!request.startsWith("../")) request = `./${request}`;
if (!request.startsWith("../") && !isAbsolute(request)) {
request = `./${request}`;
}
push({
type: RBDT_RESOLVE_CJS_FILE,
context,

View File

@ -64,7 +64,7 @@ class NodeStuffPlugin {
new NodeStuffInWebError(
dep.loc,
"global",
"The global namespace object is Node.js feature and doesn't present in browser."
"The global namespace object is a Node.js feature and isn't available in browsers."
)
);
}
@ -117,7 +117,7 @@ class NodeStuffPlugin {
setConstant(
"__filename",
"/index.js",
"The __filename is Node.js feature and doesn't present in browser."
"__filename is a Node.js feature and isn't available in browsers."
);
break;
case true:
@ -144,7 +144,7 @@ class NodeStuffPlugin {
setConstant(
"__dirname",
"/",
"The __dirname is Node.js feature and doesn't present in browser."
"__dirname is a Node.js feature and isn't available in browsers."
);
break;
case true:

View File

@ -26,6 +26,7 @@ const GlobalRuntimeModule = require("./runtime/GlobalRuntimeModule");
const HasOwnPropertyRuntimeModule = require("./runtime/HasOwnPropertyRuntimeModule");
const LoadScriptRuntimeModule = require("./runtime/LoadScriptRuntimeModule");
const MakeNamespaceObjectRuntimeModule = require("./runtime/MakeNamespaceObjectRuntimeModule");
const NonceRuntimeModule = require("./runtime/NonceRuntimeModule");
const OnChunksLoadedRuntimeModule = require("./runtime/OnChunksLoadedRuntimeModule");
const PublicPathRuntimeModule = require("./runtime/PublicPathRuntimeModule");
const RelativeUrlRuntimeModule = require("./runtime/RelativeUrlRuntimeModule");
@ -431,6 +432,12 @@ class RuntimePlugin {
return true;
}
});
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.scriptNonce)
.tap("RuntimePlugin", chunk => {
compilation.addRuntimeModule(chunk, new NonceRuntimeModule());
return true;
});
// TODO webpack 6: remove CompatRuntimeModule
compilation.hooks.additionalTreeRuntimeRequirements.tap(
"RuntimePlugin",

View File

@ -190,7 +190,8 @@ const applyWebpackOptionsDefaults = options => {
syncWebAssembly: options.experiments.syncWebAssembly,
asyncWebAssembly: options.experiments.asyncWebAssembly,
css: options.experiments.css,
futureDefaults
futureDefaults,
isNode: targetProperties && targetProperties.node === true
});
applyOutputDefaults(options.output, {
@ -451,11 +452,12 @@ const applySnapshotDefaults = (snapshot, { production, futureDefaults }) => {
* @param {JavascriptParserOptions} parserOptions parser options
* @param {Object} options options
* @param {boolean} options.futureDefaults is future defaults enabled
* @param {boolean} options.isNode is node target platform
* @returns {void}
*/
const applyJavascriptParserOptionsDefaults = (
parserOptions,
{ futureDefaults }
{ futureDefaults, isNode }
) => {
D(parserOptions, "unknownContextRequest", ".");
D(parserOptions, "unknownContextRegExp", false);
@ -470,6 +472,10 @@ const applyJavascriptParserOptionsDefaults = (
D(parserOptions, "wrappedContextCritical", false);
D(parserOptions, "strictThisContextOnImports", false);
D(parserOptions, "importMeta", true);
D(parserOptions, "dynamicImportMode", "lazy");
D(parserOptions, "dynamicImportPrefetch", false);
D(parserOptions, "dynamicImportPreload", false);
D(parserOptions, "createRequire", isNode);
if (futureDefaults) D(parserOptions, "exportsPresence", "error");
};
@ -479,13 +485,14 @@ const applyJavascriptParserOptionsDefaults = (
* @param {boolean} options.cache is caching enabled
* @param {boolean} options.syncWebAssembly is syncWebAssembly enabled
* @param {boolean} options.asyncWebAssembly is asyncWebAssembly enabled
* @param {CssExperimentOptions} options.css is css enabled
* @param {CssExperimentOptions|false} options.css is css enabled
* @param {boolean} options.futureDefaults is future defaults enabled
* @param {boolean} options.isNode is node target platform
* @returns {void}
*/
const applyModuleDefaults = (
module,
{ cache, syncWebAssembly, asyncWebAssembly, css, futureDefaults }
{ cache, syncWebAssembly, asyncWebAssembly, css, futureDefaults, isNode }
) => {
if (cache) {
D(module, "unsafeCache", module => {
@ -504,7 +511,8 @@ const applyModuleDefaults = (
F(module.parser, "javascript", () => ({}));
applyJavascriptParserOptionsDefaults(module.parser.javascript, {
futureDefaults
futureDefaults,
isNode
});
A(module, "defaultRules", () => {
@ -1114,7 +1122,7 @@ const applyPerformanceDefaults = (performance, { production }) => {
* @param {Object} options options
* @param {boolean} options.production is production
* @param {boolean} options.development is development
* @param {CssExperimentOptions} options.css is css enabled
* @param {CssExperimentOptions|false} options.css is css enabled
* @param {boolean} options.records using records
* @returns {void}
*/

View File

@ -178,11 +178,10 @@ const getNormalizedWebpackOptions = config => {
),
lazyCompilation: optionalNestedConfig(
experiments.lazyCompilation,
options =>
options === true ? {} : options === false ? undefined : options
options => (options === true ? {} : options)
),
css: optionalNestedConfig(experiments.css, options =>
options === true ? {} : options === false ? undefined : options
options === true ? {} : options
)
})),
externals: config.externals,

View File

@ -65,6 +65,7 @@ class ModuleFederationPlugin {
library,
filename: options.filename,
runtime: options.runtime,
shareScope: options.shareScope,
exposes: options.exposes
}).apply(compiler);
}
@ -76,6 +77,7 @@ class ModuleFederationPlugin {
) {
new ContainerReferencePlugin({
remoteType,
shareScope: options.shareScope,
remotes: options.remotes
}).apply(compiler);
}

View File

@ -108,13 +108,15 @@ class CssLoadingRuntimeModule extends RuntimeModule {
'link.rel = "stylesheet";',
"link.href = url;",
crossOriginLoading
? Template.asString([
"if (link.src.indexOf(window.location.origin + '/') !== 0) {",
Template.indent(
`link.crossOrigin = ${JSON.stringify(crossOriginLoading)};`
),
"}"
])
? crossOriginLoading === "use-credentials"
? 'link.crossOrigin = "use-credentials";'
: Template.asString([
"if (link.src.indexOf(window.location.origin + '/') !== 0) {",
Template.indent(
`link.crossOrigin = ${JSON.stringify(crossOriginLoading)};`
),
"}"
])
: ""
]);

View File

@ -5,9 +5,12 @@
"use strict";
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 {
evaluateToIdentifier,
evaluateToString,
@ -26,8 +29,12 @@ const RequireResolveContextDependency = require("./RequireResolveContextDependen
const RequireResolveDependency = require("./RequireResolveDependency");
const RequireResolveHeaderDependency = require("./RequireResolveHeaderDependency");
/** @typedef {import("estree").CallExpression} CallExpressionNode */
/** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
const createRequireSpecifierTag = Symbol("createRequire");
const createdRequireIdentifierTag = Symbol("createRequire()");
class CommonJsImportsParserPlugin {
/**
* @param {JavascriptParserOptions} options parser options
@ -39,51 +46,72 @@ class CommonJsImportsParserPlugin {
apply(parser) {
const options = this.options;
// metadata //
const getContext = () => {
if (parser.currentTagData) {
const { context } = parser.currentTagData;
return context;
}
};
//#region metadata
const tapRequireExpression = (expression, getMembers) => {
parser.hooks.typeof
.for(expression)
.tap(
"CommonJsPlugin",
"CommonJsImportsParserPlugin",
toConstantDependency(parser, JSON.stringify("function"))
);
parser.hooks.evaluateTypeof
.for(expression)
.tap("CommonJsPlugin", evaluateToString("function"));
.tap("CommonJsImportsParserPlugin", evaluateToString("function"));
parser.hooks.evaluateIdentifier
.for(expression)
.tap(
"CommonJsPlugin",
"CommonJsImportsParserPlugin",
evaluateToIdentifier(expression, "require", getMembers, true)
);
};
const tapRequireExpressionTag = tag => {
parser.hooks.typeof
.for(tag)
.tap(
"CommonJsImportsParserPlugin",
toConstantDependency(parser, JSON.stringify("function"))
);
parser.hooks.evaluateTypeof
.for(tag)
.tap("CommonJsImportsParserPlugin", evaluateToString("function"));
};
tapRequireExpression("require", () => []);
tapRequireExpression("require.resolve", () => ["resolve"]);
tapRequireExpression("require.resolveWeak", () => ["resolveWeak"]);
//#endregion
// Weird stuff //
parser.hooks.assign.for("require").tap("CommonJsPlugin", expr => {
// to not leak to global "require", we need to define a local require here.
const dep = new ConstDependency("var require;", 0);
dep.loc = expr.loc;
parser.state.module.addPresentationalDependency(dep);
return true;
});
parser.hooks.assign
.for("require")
.tap("CommonJsImportsParserPlugin", expr => {
// to not leak to global "require", we need to define a local require here.
const dep = new ConstDependency("var require;", 0);
dep.loc = expr.loc;
parser.state.module.addPresentationalDependency(dep);
return true;
});
// Unsupported //
//#region Unsupported
parser.hooks.expression
.for("require.main.require")
.for("require.main")
.tap(
"CommonJsPlugin",
"CommonJsImportsParserPlugin",
expressionIsUnsupported(
parser,
"require.main.require is not supported by webpack."
"require.main is not supported by webpack."
)
);
parser.hooks.call
.for("require.main.require")
.tap(
"CommonJsPlugin",
"CommonJsImportsParserPlugin",
expressionIsUnsupported(
parser,
"require.main.require is not supported by webpack."
@ -92,7 +120,7 @@ class CommonJsImportsParserPlugin {
parser.hooks.expression
.for("module.parent.require")
.tap(
"CommonJsPlugin",
"CommonJsImportsParserPlugin",
expressionIsUnsupported(
parser,
"module.parent.require is not supported by webpack."
@ -101,63 +129,81 @@ class CommonJsImportsParserPlugin {
parser.hooks.call
.for("module.parent.require")
.tap(
"CommonJsPlugin",
"CommonJsImportsParserPlugin",
expressionIsUnsupported(
parser,
"module.parent.require is not supported by webpack."
)
);
//#endregion
// renaming //
parser.hooks.canRename.for("require").tap("CommonJsPlugin", () => true);
parser.hooks.rename.for("require").tap("CommonJsPlugin", expr => {
//#region Renaming
const defineUndefined = expr => {
// To avoid "not defined" error, replace the value with undefined
const dep = new ConstDependency("undefined", expr.range);
dep.loc = expr.loc;
parser.state.module.addPresentationalDependency(dep);
return false;
});
};
parser.hooks.canRename
.for("require")
.tap("CommonJsImportsParserPlugin", () => true);
parser.hooks.rename
.for("require")
.tap("CommonJsImportsParserPlugin", defineUndefined);
//#endregion
//#region Inspection
const requireCache = toConstantDependency(
parser,
RuntimeGlobals.moduleCache,
[
RuntimeGlobals.moduleCache,
RuntimeGlobals.moduleId,
RuntimeGlobals.moduleLoaded
]
);
// inspection //
parser.hooks.expression
.for("require.cache")
.tap(
"CommonJsImportsParserPlugin",
toConstantDependency(parser, RuntimeGlobals.moduleCache, [
RuntimeGlobals.moduleCache,
RuntimeGlobals.moduleId,
RuntimeGlobals.moduleLoaded
])
);
.tap("CommonJsImportsParserPlugin", requireCache);
//#endregion
// require as expression //
//#region Require as expression
const requireAsExpressionHandler = expr => {
const dep = new CommonJsRequireContextDependency(
{
request: options.unknownContextRequest,
recursive: options.unknownContextRecursive,
regExp: options.unknownContextRegExp,
mode: "sync"
},
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 = expr.loc;
dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep);
return true;
};
parser.hooks.expression
.for("require")
.tap("CommonJsImportsParserPlugin", expr => {
const dep = new CommonJsRequireContextDependency(
{
request: options.unknownContextRequest,
recursive: options.unknownContextRecursive,
regExp: options.unknownContextRegExp,
mode: "sync"
},
expr.range,
undefined,
parser.scope.inShorthand
);
dep.critical =
options.unknownContextCritical &&
"require function is used in a way in which dependencies cannot be statically extracted";
dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep);
return true;
});
.tap("CommonJsImportsParserPlugin", requireAsExpressionHandler);
//#endregion
// require //
//#region Require
const processRequireItem = (expr, param) => {
if (param.isString()) {
const dep = new CommonJsRequireDependency(param.string, param.range);
const dep = new CommonJsRequireDependency(
param.string,
param.range,
getContext()
);
dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep);
@ -174,7 +220,9 @@ class CommonJsImportsParserPlugin {
{
category: "commonjs"
},
parser
parser,
undefined,
getContext()
);
if (!dep) return;
dep.loc = expr.loc;
@ -268,8 +316,9 @@ class CommonJsImportsParserPlugin {
parser.hooks.new
.for("module.require")
.tap("CommonJsImportsParserPlugin", createRequireHandler(true));
//#endregion
// require with property access //
//#region Require with property access
const chainHandler = (expr, calleeMembers, callExpr, members) => {
if (callExpr.arguments.length !== 1) return;
const param = parser.evaluateExpression(callExpr.arguments[0]);
@ -316,8 +365,9 @@ class CommonJsImportsParserPlugin {
parser.hooks.callMemberChainOfCallMemberChain
.for("module.require")
.tap("CommonJsImportsParserPlugin", callChainHandler);
//#endregion
// require.resolve //
//#region Require.resolve
const processResolve = (expr, weak) => {
if (expr.arguments.length !== 1) return;
const param = parser.evaluateExpression(expr.arguments[0]);
@ -345,7 +395,11 @@ class CommonJsImportsParserPlugin {
};
const processResolveItem = (expr, param, weak) => {
if (param.isString()) {
const dep = new RequireResolveDependency(param.string, param.range);
const dep = new RequireResolveDependency(
param.string,
param.range,
getContext()
);
dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry;
dep.weak = weak;
@ -364,7 +418,8 @@ class CommonJsImportsParserPlugin {
category: "commonjs",
mode: weak ? "weak" : "sync"
},
parser
parser,
getContext()
);
if (!dep) return;
dep.loc = expr.loc;
@ -375,14 +430,240 @@ class CommonJsImportsParserPlugin {
parser.hooks.call
.for("require.resolve")
.tap("RequireResolveDependencyParserPlugin", expr => {
.tap("CommonJsImportsParserPlugin", expr => {
return processResolve(expr, false);
});
parser.hooks.call
.for("require.resolveWeak")
.tap("RequireResolveDependencyParserPlugin", expr => {
.tap("CommonJsImportsParserPlugin", expr => {
return processResolve(expr, true);
});
//#endregion
//#region Create require
if (!options.createRequire) return;
let moduleName;
let specifierName;
if (options.createRequire === true) {
moduleName = "module";
specifierName = "createRequire";
} else {
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("CommonJsImportsParserPlugin", 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(expr.range);
});
parser.hooks.unhandledExpressionMemberChain
.for(createdRequireIdentifierTag)
.tap("CommonJsImportsParserPlugin", (expr, members) => {
return expressionIsUnsupported(
parser,
`createRequire().${members.join(".")} is not supported by webpack.`
)(expr);
});
parser.hooks.canRename
.for(createdRequireIdentifierTag)
.tap("CommonJsImportsParserPlugin", () => true);
parser.hooks.canRename
.for(createRequireSpecifierTag)
.tap("CommonJsImportsParserPlugin", () => true);
parser.hooks.rename
.for(createRequireSpecifierTag)
.tap("CommonJsImportsParserPlugin", defineUndefined);
parser.hooks.expression
.for(createdRequireIdentifierTag)
.tap("CommonJsImportsParserPlugin", requireAsExpressionHandler);
parser.hooks.call
.for(createdRequireIdentifierTag)
.tap("CommonJsImportsParserPlugin", createRequireHandler(false));
/**
* @param {CallExpressionNode} expr call expression
* @returns {string} context
*/
const parseCreateRequireArguments = expr => {
const args = expr.arguments;
if (args.length !== 1) {
const err = new WebpackError(
"module.createRequire supports only one argument."
);
err.loc = 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 = arg.loc;
parser.state.module.addWarning(err);
return;
}
const ctx = evaluated.string.startsWith("file://")
? fileURLToPath(evaluated.string)
: evaluated.string;
// argument always should be a filename
return ctx.slice(0, ctx.lastIndexOf(ctx.startsWith("/") ? "/" : "\\"));
};
parser.hooks.import.tap(
{
name: "CommonJsImportsParserPlugin",
stage: -10
},
(statement, source) => {
if (
source !== moduleName ||
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(statement.range[0]) ? ";" : "",
statement.range
);
clearDep.loc = statement.loc;
parser.state.module.addPresentationalDependency(clearDep);
parser.unsetAsiPosition(statement.range[1]);
return true;
}
);
parser.hooks.importSpecifier.tap(
{
name: "CommonJsImportsParserPlugin",
stage: -10
},
(statement, source, id, name) => {
if (source !== moduleName || id !== specifierName) return;
parser.tagVariable(name, createRequireSpecifierTag);
return true;
}
);
parser.hooks.preDeclarator.tap(
"CommonJsImportsParserPlugin",
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 &&
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(
"CommonJsImportsParserPlugin",
(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(
"CommonJsImportsParserPlugin",
(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("CommonJsImportsParserPlugin", (expr, members) => {
// require.cache
if (members.length === 1 && members[0] === "cache") {
return requireCache(expr);
}
});
parser.hooks.callMemberChain
.for(createdRequireIdentifierTag)
.tap("CommonJsImportsParserPlugin", (expr, members) => {
// require.resolve()
if (members.length === 1 && members[0] === "resolve") {
return processResolve(expr, false);
}
});
parser.hooks.call
.for(createRequireSpecifierTag)
.tap("CommonJsImportsParserPlugin", expr => {
const clearDep = new ConstDependency(
"/* createRequire() */ undefined",
expr.range
);
clearDep.loc = expr.loc;
parser.state.module.addPresentationalDependency(clearDep);
return true;
});
//#endregion
}
}
module.exports = CommonJsImportsParserPlugin;

View File

@ -10,8 +10,8 @@ const ContextDependency = require("./ContextDependency");
const ContextDependencyTemplateAsRequireCall = require("./ContextDependencyTemplateAsRequireCall");
class CommonJsRequireContextDependency extends ContextDependency {
constructor(options, range, valueRange, inShorthand) {
super(options);
constructor(options, range, valueRange, inShorthand, context) {
super(options, context);
this.range = range;
this.valueRange = valueRange;

View File

@ -10,9 +10,10 @@ const ModuleDependency = require("./ModuleDependency");
const ModuleDependencyTemplateAsId = require("./ModuleDependencyTemplateAsId");
class CommonJsRequireDependency extends ModuleDependency {
constructor(request, range) {
constructor(request, range, context) {
super(request);
this.range = range;
this._context = context;
}
get type() {

View File

@ -26,8 +26,9 @@ const regExpToString = r => (r ? r + "" : "");
class ContextDependency extends Dependency {
/**
* @param {ContextDependencyOptions} options options for the context module
* @param {string=} context request context
*/
constructor(options) {
constructor(options, context) {
super();
this.options = options;
@ -50,6 +51,14 @@ class ContextDependency extends Dependency {
this.inShorthand = undefined;
// TODO refactor this
this.replaces = undefined;
this._requestContext = context;
}
/**
* @returns {string | undefined} a request context
*/
getContext() {
return this._requestContext;
}
get category() {
@ -68,7 +77,9 @@ class ContextDependency extends Dependency {
*/
getResourceIdentifier() {
return (
`context${this.options.request} ${this.options.recursive} ` +
`context${this._requestContext || ""}|ctx request${
this.options.request
} ${this.options.recursive} ` +
`${regExpToString(this.options.regExp)} ${regExpToString(
this.options.include
)} ${regExpToString(this.options.exclude)} ` +
@ -112,6 +123,7 @@ class ContextDependency extends Dependency {
write(this.critical);
write(this.hadGlobalOrStickyRegExp);
write(this.request);
write(this._requestContext);
write(this.range);
write(this.valueRange);
write(this.prepend);
@ -128,6 +140,7 @@ class ContextDependency extends Dependency {
this.critical = read();
this.hadGlobalOrStickyRegExp = read();
this.request = read();
this._requestContext = read();
this.range = read();
this.valueRange = read();
this.prepend = read();

View File

@ -39,7 +39,7 @@ const splitContextFromPrefix = prefix => {
/** @typedef {Partial<Omit<ContextDependencyOptions, "resource">>} PartialContextDependencyOptions */
/** @typedef {{ new(options: ContextDependencyOptions, range: [number, number], valueRange: [number, number]): ContextDependency }} ContextDependencyConstructor */
/** @typedef {{ new(options: ContextDependencyOptions, range: [number, number], valueRange: [number, number], ...args: any[]): ContextDependency }} ContextDependencyConstructor */
/**
* @param {ContextDependencyConstructor} Dep the Dependency class
@ -49,9 +49,19 @@ const splitContextFromPrefix = prefix => {
* @param {Pick<JavascriptParserOptions, `${"expr"|"wrapped"}Context${"Critical"|"Recursive"|"RegExp"}` | "exprContextRequest">} options options for context creation
* @param {PartialContextDependencyOptions} contextOptions options for the ContextModule
* @param {JavascriptParser} parser the parser
* @param {...any} depArgs depArgs
* @returns {ContextDependency} the created Dependency
*/
exports.create = (Dep, range, param, expr, options, contextOptions, parser) => {
exports.create = (
Dep,
range,
param,
expr,
options,
contextOptions,
parser,
...depArgs
) => {
if (param.isTemplateString()) {
let prefixRaw = param.quasis[0].string;
let postfixRaw =
@ -97,7 +107,8 @@ exports.create = (Dep, range, param, expr, options, contextOptions, parser) => {
...contextOptions
},
range,
valueRange
valueRange,
...depArgs
);
dep.loc = expr.loc;
const replaces = [];
@ -180,7 +191,8 @@ exports.create = (Dep, range, param, expr, options, contextOptions, parser) => {
...contextOptions
},
range,
valueRange
valueRange,
...depArgs
);
dep.loc = expr.loc;
const replaces = [];
@ -218,7 +230,8 @@ exports.create = (Dep, range, param, expr, options, contextOptions, parser) => {
...contextOptions
},
range,
param.range
param.range,
...depArgs
);
dep.loc = expr.loc;
dep.critical =

View File

@ -49,20 +49,6 @@ class ContextElementDependency extends ModuleDependency {
return "context element";
}
/**
* @returns {string | undefined} a request context
*/
getContext() {
return this._context;
}
/**
* @returns {string | null} an identifier to merge equal requests
*/
getResourceIdentifier() {
return `context${this._context || ""}|${super.getResourceIdentifier()}`;
}
get category() {
return this._category;
}
@ -86,7 +72,6 @@ class ContextElementDependency extends ModuleDependency {
const { write } = context;
write(this._typePrefix);
write(this._category);
write(this._context);
write(this.referencedExports);
super.serialize(context);
}
@ -95,7 +80,6 @@ class ContextElementDependency extends ModuleDependency {
const { read } = context;
this._typePrefix = read();
this._category = read();
this._context = read();
this.referencedExports = read();
super.deserialize(context);
}

View File

@ -103,7 +103,7 @@ HarmonyEvaluatedImportSpecifierDependency.Template = class HarmonyEvaluatedImpor
}
if (typeof value === "boolean") {
source.replace(dep.range[0], dep.range[1] - 1, `${value}`);
source.replace(dep.range[0], dep.range[1] - 1, ` ${value}`);
} else {
const usedName = exportsInfo.getUsedName(ids, runtime);

View File

@ -14,10 +14,14 @@ const ImportDependency = require("./ImportDependency");
const ImportEagerDependency = require("./ImportEagerDependency");
const ImportWeakDependency = require("./ImportWeakDependency");
/** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
/** @typedef {import("../ChunkGroup").RawChunkGroupOptions} RawChunkGroupOptions */
/** @typedef {import("../ContextModule").ContextMode} ContextMode */
class ImportParserPlugin {
/**
* @param {JavascriptParserOptions} options options
*/
constructor(options) {
this.options = options;
}
@ -28,7 +32,7 @@ class ImportParserPlugin {
let chunkName = null;
/** @type {ContextMode} */
let mode = "lazy";
let mode = this.options.dynamicImportMode;
let include = null;
let exclude = null;
/** @type {string[][] | null} */
@ -36,6 +40,17 @@ class ImportParserPlugin {
/** @type {RawChunkGroupOptions} */
const groupOptions = {};
const { dynamicImportPreload, dynamicImportPrefetch } = this.options;
if (dynamicImportPreload !== undefined && dynamicImportPreload !== false)
groupOptions.preloadOrder =
dynamicImportPreload === true ? 0 : dynamicImportPreload;
if (
dynamicImportPrefetch !== undefined &&
dynamicImportPrefetch !== false
)
groupOptions.prefetchOrder =
dynamicImportPrefetch === true ? 0 : dynamicImportPrefetch;
const { options: importOptions, errors: commentErrors } =
parser.parseCommentOptions(expr.range);
@ -175,16 +190,22 @@ class ImportParserPlugin {
}
}
if (param.isString()) {
if (mode !== "lazy" && mode !== "eager" && mode !== "weak") {
parser.state.module.addWarning(
new UnsupportedFeatureWarning(
`\`webpackMode\` expected 'lazy', 'eager' or 'weak', but received: ${mode}.`,
expr.loc
)
);
}
if (
mode !== "lazy" &&
mode !== "lazy-once" &&
mode !== "eager" &&
mode !== "weak"
) {
parser.state.module.addWarning(
new UnsupportedFeatureWarning(
`\`webpackMode\` expected 'lazy', 'lazy-once', 'eager' or 'weak', but received: ${mode}.`,
expr.loc
)
);
mode = "lazy";
}
if (param.isString()) {
if (mode === "eager") {
const dep = new ImportEagerDependency(
param.string,
@ -215,21 +236,6 @@ class ImportParserPlugin {
}
return true;
} else {
if (
mode !== "lazy" &&
mode !== "lazy-once" &&
mode !== "eager" &&
mode !== "weak"
) {
parser.state.module.addWarning(
new UnsupportedFeatureWarning(
`\`webpackMode\` expected 'lazy', 'lazy-once', 'eager' or 'weak', but received: ${mode}.`,
expr.loc
)
);
mode = "lazy";
}
if (mode === "weak") {
mode = "async-weak";
}

View File

@ -13,18 +13,21 @@ const NullDependency = require("./NullDependency");
/** @typedef {import("../Dependency").ExportsSpec} ExportsSpec */
/** @typedef {import("../Dependency").UpdateHashContext} UpdateHashContext */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
/** @typedef {import("../json/JsonData")} JsonData */
/** @typedef {import("../util/Hash")} Hash */
const getExportsFromData = data => {
if (data && typeof data === "object") {
if (Array.isArray(data)) {
return data.map((item, idx) => {
return {
name: `${idx}`,
canMangle: true,
exports: getExportsFromData(item)
};
});
return data.length < 100
? data.map((item, idx) => {
return {
name: `${idx}`,
canMangle: true,
exports: getExportsFromData(item)
};
})
: undefined;
} else {
const exports = [];
for (const key of Object.keys(data)) {
@ -42,12 +45,11 @@ const getExportsFromData = data => {
class JsonExportsDependency extends NullDependency {
/**
* @param {(string | ExportSpec)[]} exports json exports
* @param {JsonData=} data json data
*/
constructor(exports) {
constructor(data) {
super();
this.exports = exports;
this._hashUpdate = undefined;
this.data = data;
}
get type() {
@ -61,7 +63,7 @@ class JsonExportsDependency extends NullDependency {
*/
getExports(moduleGraph) {
return {
exports: this.exports,
exports: getExportsFromData(this.data && this.data.get()),
dependencies: undefined
};
}
@ -73,23 +75,18 @@ class JsonExportsDependency extends NullDependency {
* @returns {void}
*/
updateHash(hash, context) {
if (this._hashUpdate === undefined) {
this._hashUpdate = this.exports
? JSON.stringify(this.exports)
: "undefined";
}
hash.update(this._hashUpdate);
this.data.updateHash(hash);
}
serialize(context) {
const { write } = context;
write(this.exports);
write(this.data);
super.serialize(context);
}
deserialize(context) {
const { read } = context;
this.exports = read();
this.data = read();
super.deserialize(context);
}
}
@ -100,4 +97,3 @@ makeSerializable(
);
module.exports = JsonExportsDependency;
module.exports.getExportsFromData = getExportsFromData;

View File

@ -26,13 +26,21 @@ class ModuleDependency extends Dependency {
// assertions must be serialized by subclasses that use it
/** @type {Record<string, any> | undefined} */
this.assertions = undefined;
this._context = undefined;
}
/**
* @returns {string | undefined} a request context
*/
getContext() {
return this._context;
}
/**
* @returns {string | null} an identifier to merge equal requests
*/
getResourceIdentifier() {
let str = `module${this.request}`;
let str = `context${this._context || ""}|module${this.request}`;
if (this.assertions !== undefined) {
str += JSON.stringify(this.assertions);
}
@ -63,6 +71,7 @@ class ModuleDependency extends Dependency {
const { write } = context;
write(this.request);
write(this.userRequest);
write(this._context);
write(this.range);
super.serialize(context);
}
@ -71,6 +80,7 @@ class ModuleDependency extends Dependency {
const { read } = context;
this.request = read();
this.userRequest = read();
this._context = read();
this.range = read();
super.deserialize(context);
}

View File

@ -5,19 +5,21 @@
"use strict";
const Dependency = require("../Dependency");
const InitFragment = require("../InitFragment");
const makeSerializable = require("../util/makeSerializable");
const ModuleDependency = require("./ModuleDependency");
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
/** @typedef {import("../ChunkGraph")} ChunkGraph */
/** @typedef {import("../Dependency")} Dependency */
/** @typedef {import("../Dependency").ReferencedExport} ReferencedExport */
/** @typedef {import("../Dependency").UpdateHashContext} UpdateHashContext */
/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
/** @typedef {import("../DependencyTemplates")} DependencyTemplates */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
/** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
/** @typedef {import("../util/Hash")} Hash */
/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
/**
* @param {string[]|null} path the property path array
@ -29,10 +31,16 @@ const pathToString = path =>
: "";
class ProvidedDependency extends ModuleDependency {
constructor(request, identifier, path, range) {
/**
* @param {string} request request
* @param {string} identifier identifier
* @param {string[]} ids ids
* @param {[number, number]} range range
*/
constructor(request, identifier, ids, range) {
super(request);
this.identifier = identifier;
this.path = path;
this.ids = ids;
this.range = range;
this._hashUpdate = undefined;
}
@ -45,6 +53,18 @@ class ProvidedDependency extends ModuleDependency {
return "esm";
}
/**
* Returns list of exports referenced by this dependency
* @param {ModuleGraph} moduleGraph module graph
* @param {RuntimeSpec} runtime the runtime for which the module is analysed
* @returns {(string[] | ReferencedExport)[]} referenced exports
*/
getReferencedExports(moduleGraph, runtime) {
let ids = this.ids;
if (ids.length === 0) return Dependency.EXPORTS_OBJECT_REFERENCED;
return [ids];
}
/**
* Update the hash
* @param {Hash} hash hash to be updated
@ -53,8 +73,7 @@ class ProvidedDependency extends ModuleDependency {
*/
updateHash(hash, context) {
if (this._hashUpdate === undefined) {
this._hashUpdate =
this.identifier + (this.path ? this.path.join(",") : "null");
this._hashUpdate = this.identifier + (this.ids ? this.ids.join(",") : "");
}
hash.update(this._hashUpdate);
}
@ -62,14 +81,14 @@ class ProvidedDependency extends ModuleDependency {
serialize(context) {
const { write } = context;
write(this.identifier);
write(this.path);
write(this.ids);
super.serialize(context);
}
deserialize(context) {
const { read } = context;
this.identifier = read();
this.path = read();
this.ids = read();
super.deserialize(context);
}
}
@ -90,6 +109,7 @@ class ProvidedDependencyTemplate extends ModuleDependency.Template {
dependency,
source,
{
runtime,
runtimeTemplate,
moduleGraph,
chunkGraph,
@ -98,6 +118,9 @@ class ProvidedDependencyTemplate extends ModuleDependency.Template {
}
) {
const dep = /** @type {ProvidedDependency} */ (dependency);
const connection = moduleGraph.getConnection(dep);
const exportsInfo = moduleGraph.getExportsInfo(connection.module);
const usedName = exportsInfo.getUsedName(dep.ids, runtime);
initFragments.push(
new InitFragment(
`/* provided dependency */ var ${
@ -107,7 +130,7 @@ class ProvidedDependencyTemplate extends ModuleDependency.Template {
chunkGraph,
request: dep.request,
runtimeRequirements
})}${pathToString(dep.path)};\n`,
})}${pathToString(/** @type {string[]} */ (usedName))};\n`,
InitFragment.STAGE_PROVIDES,
1,
`provided ${dep.identifier}`

View File

@ -10,8 +10,8 @@ const ContextDependency = require("./ContextDependency");
const ContextDependencyTemplateAsId = require("./ContextDependencyTemplateAsId");
class RequireResolveContextDependency extends ContextDependency {
constructor(options, range, valueRange) {
super(options);
constructor(options, range, valueRange, context) {
super(options, context);
this.range = range;
this.valueRange = valueRange;

View File

@ -15,10 +15,11 @@ const ModuleDependencyAsId = require("./ModuleDependencyTemplateAsId");
/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
class RequireResolveDependency extends ModuleDependency {
constructor(request, range) {
constructor(request, range, context) {
super(request);
this.range = range;
this._context = context;
}
get type() {

View File

@ -5,12 +5,15 @@
"use strict";
const { pathToFileURL } = require("url");
const BasicEvaluatedExpression = require("../javascript/BasicEvaluatedExpression");
const { approve } = require("../javascript/JavascriptParserHelpers");
const InnerGraph = require("../optimize/InnerGraph");
const URLDependency = require("./URLDependency");
/** @typedef {import("estree").NewExpression} NewExpressionNode */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../NormalModule")} NormalModule */
/** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
class URLPlugin {
@ -27,6 +30,13 @@ class URLPlugin {
new URLDependency.Template()
);
/**
* @param {NormalModule} module module
* @returns {URL} file url
*/
const getUrl = module => {
return pathToFileURL(module.resource);
};
/**
* @param {JavascriptParser} parser parser
* @param {object} parserOptions options
@ -67,6 +77,17 @@ class URLPlugin {
};
parser.hooks.canRename.for("URL").tap("URLPlugin", approve);
parser.hooks.evaluateNewExpression
.for("URL")
.tap("URLPlugin", expr => {
const request = getUrlRequest(expr);
if (!request) return;
const url = new URL(request, getUrl(parser.state.module));
return new BasicEvaluatedExpression()
.setString(url.toString())
.setRange(expr.range);
});
parser.hooks.new.for("URL").tap("URLPlugin", _expr => {
const expr = /** @type {NewExpressionNode} */ (_expr);

View File

@ -28,6 +28,7 @@ const memoize = require("./util/memoize");
/** @typedef {import("./Compilation").Asset} Asset */
/** @typedef {import("./Compilation").AssetInfo} AssetInfo */
/** @typedef {import("./Compilation").EntryOptions} EntryOptions */
/** @typedef {import("./Compilation").PathData} PathData */
/** @typedef {import("./Compiler").AssetEmittedInfo} AssetEmittedInfo */
/** @typedef {import("./MultiStats")} MultiStats */
/** @typedef {import("./Parser").ParserState} ParserState */
@ -341,6 +342,9 @@ module.exports = mergeExports(fn, {
get ModuleDependency() {
return require("./dependencies/ModuleDependency");
},
get HarmonyImportDependency() {
return require("./dependencies/HarmonyImportDependency");
},
get ConstDependency() {
return require("./dependencies/ConstDependency");
},

View File

@ -165,6 +165,14 @@ class JavascriptParser extends Parser {
evaluateDefinedIdentifier: new HookMap(
() => new SyncBailHook(["expression"])
),
/** @type {HookMap<SyncBailHook<[NewExpressionNode], BasicEvaluatedExpression | undefined | null>>} */
evaluateNewExpression: new HookMap(
() => new SyncBailHook(["expression"])
),
/** @type {HookMap<SyncBailHook<[CallExpressionNode], BasicEvaluatedExpression | undefined | null>>} */
evaluateCallExpression: new HookMap(
() => new SyncBailHook(["expression"])
),
/** @type {HookMap<SyncBailHook<[CallExpressionNode, BasicEvaluatedExpression | undefined], BasicEvaluatedExpression | undefined | null>>} */
evaluateCallExpressionMember: new HookMap(
() => new SyncBailHook(["expression", "param"])
@ -361,9 +369,14 @@ class JavascriptParser extends Parser {
this.hooks.evaluate.for("NewExpression").tap("JavascriptParser", _expr => {
const expr = /** @type {NewExpressionNode} */ (_expr);
const callee = expr.callee;
if (
callee.type !== "Identifier" ||
callee.name !== "RegExp" ||
if (callee.type !== "Identifier") return;
if (callee.name !== "RegExp") {
return this.callHooksForName(
this.hooks.evaluateNewExpression,
callee.name,
expr
);
} else if (
expr.arguments.length > 2 ||
this.getVariableInfo("RegExp") !== "RegExp"
)
@ -1036,24 +1049,28 @@ class JavascriptParser extends Parser {
this.hooks.evaluate.for("CallExpression").tap("JavascriptParser", _expr => {
const expr = /** @type {CallExpressionNode} */ (_expr);
if (
expr.callee.type !== "MemberExpression" ||
expr.callee.property.type !==
expr.callee.type === "MemberExpression" &&
expr.callee.property.type ===
(expr.callee.computed ? "Literal" : "Identifier")
) {
return;
}
// type Super also possible here
const param = this.evaluateExpression(
/** @type {ExpressionNode} */ (expr.callee.object)
);
const property =
expr.callee.property.type === "Literal"
? `${expr.callee.property.value}`
: expr.callee.property.name;
const hook = this.hooks.evaluateCallExpressionMember.get(property);
if (hook !== undefined) {
return hook.call(expr, param);
// type Super also possible here
const param = this.evaluateExpression(
/** @type {ExpressionNode} */ (expr.callee.object)
);
const property =
expr.callee.property.type === "Literal"
? `${expr.callee.property.value}`
: expr.callee.property.name;
const hook = this.hooks.evaluateCallExpressionMember.get(property);
if (hook !== undefined) {
return hook.call(expr, param);
}
} else if (expr.callee.type === "Identifier") {
return this.callHooksForName(
this.hooks.evaluateCallExpression,
expr.callee.name,
expr
);
}
});
this.hooks.evaluateCallExpressionMember
@ -1430,6 +1447,11 @@ class JavascriptParser extends Parser {
this.walkExpression(classElement.value);
this.scope.topLevelScope = wasTopLevel;
}
} else if (classElement.type === "StaticBlock") {
const wasTopLevel = this.scope.topLevelScope;
this.scope.topLevelScope = false;
this.walkBlockStatement(classElement);
this.scope.topLevelScope = wasTopLevel;
}
}
}
@ -1886,7 +1908,7 @@ class JavascriptParser extends Parser {
!this.hooks.importSpecifier.call(
statement,
source,
specifier.imported.name,
specifier.imported.name || specifier.imported.value,
name
)
) {
@ -1956,7 +1978,7 @@ class JavascriptParser extends Parser {
const specifier = statement.specifiers[specifierIndex];
switch (specifier.type) {
case "ExportSpecifier": {
const name = specifier.exported.name;
const name = specifier.exported.name || specifier.exported.value;
if (source) {
this.hooks.exportImportSpecifier.call(
statement,
@ -3603,6 +3625,10 @@ class JavascriptParser extends Parser {
}
}
evaluatedVariable(tagInfo) {
return new VariableInfo(this.scope, undefined, tagInfo);
}
parseCommentOptions(range) {
const comments = this.getComments(range);
if (comments.length === 0) {

View File

@ -24,6 +24,14 @@ class JsonData {
}
return this._data;
}
updateHash(hash) {
if (this._buffer === undefined && this._data !== undefined) {
this._buffer = Buffer.from(JSON.stringify(this._data));
}
if (this._buffer) return hash.update(this._buffer);
}
}
register(JsonData, "webpack/lib/json/JsonData", null, {

View File

@ -41,15 +41,13 @@ class JsonParser extends Parser {
typeof source === "object"
? source
: parseFn(source[0] === "\ufeff" ? source.slice(1) : source);
state.module.buildInfo.jsonData = new JsonData(data);
const jsonData = new JsonData(data);
state.module.buildInfo.jsonData = jsonData;
state.module.buildInfo.strict = true;
state.module.buildMeta.exportsType = "default";
state.module.buildMeta.defaultObject =
typeof data === "object" ? "redirect-warn" : false;
state.module.addDependency(
new JsonExportsDependency(JsonExportsDependency.getExportsFromData(data))
);
state.module.addDependency(new JsonExportsDependency(jsonData));
return state;
}
}

View File

@ -21,7 +21,7 @@ const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency
const JavascriptParser = require("../javascript/JavascriptParser");
const { equals } = require("../util/ArrayHelpers");
const LazySet = require("../util/LazySet");
const { concatComparators, keepOriginalOrder } = require("../util/comparators");
const { concatComparators } = require("../util/comparators");
const createHash = require("../util/createHash");
const { makePathsRelative } = require("../util/identifier");
const makeSerializable = require("../util/makeSerializable");
@ -185,23 +185,25 @@ const RESERVED_NAMES = new Set(
.split(",")
);
const bySourceOrder = (a, b) => {
const aOrder = a.sourceOrder;
const bOrder = b.sourceOrder;
if (isNaN(aOrder)) {
if (!isNaN(bOrder)) {
const createComparator = (property, comparator) => (a, b) =>
comparator(a[property], b[property]);
const compareNumbers = (a, b) => {
if (isNaN(a)) {
if (!isNaN(b)) {
return 1;
}
} else {
if (isNaN(bOrder)) {
if (isNaN(b)) {
return -1;
}
if (aOrder !== bOrder) {
return aOrder < bOrder ? -1 : 1;
if (a !== b) {
return a < b ? -1 : 1;
}
}
return 0;
};
const bySourceOrder = createComparator("sourceOrder", compareNumbers);
const byRangeStart = createComparator("rangeStart", compareNumbers);
const joinIterableWithComma = iterable => {
// This is more performant than Array.from().join(", ")
@ -885,6 +887,9 @@ class ConcatenatedModule extends Module {
for (const c of moduleGraph.getOutgoingConnections(this))
connections.push(c);
}
/**
* @type {Array<{ connection: ModuleGraphConnection, sourceOrder: number, rangeStart: number }>}
*/
const references = connections
.filter(connection => {
if (!(connection.dependency instanceof HarmonyImportDependency))
@ -896,15 +901,33 @@ class ConcatenatedModule extends Module {
connection.isTargetActive(runtime)
);
})
.map(connection => ({
connection,
sourceOrder: /** @type {HarmonyImportDependency} */ (
.map(connection => {
const dep = /** @type {HarmonyImportDependency} */ (
connection.dependency
).sourceOrder
}));
references.sort(
concatComparators(bySourceOrder, keepOriginalOrder(references))
);
);
return {
connection,
sourceOrder: dep.sourceOrder,
rangeStart: dep.range && dep.range[0]
};
});
/**
* bySourceOrder
* @example
* import a from "a"; // sourceOrder=1
* import b from "b"; // sourceOrder=2
*
* byRangeStart
* @example
* import {a, b} from "a"; // sourceOrder=1
* a.a(); // first range
* b.b(); // second range
*
* If there is no reexport, we have the same source.
* If there is reexport, but module has side effects, this will lead to reexport module only.
* If there is side-effects-free reexport, we can get simple deterministic result with range start comparison.
*/
references.sort(concatComparators(bySourceOrder, byRangeStart));
/** @type {Map<Module, { connection: ModuleGraphConnection, runtimeCondition: RuntimeSpec | true }>} */
const referencesMap = new Map();
for (const { connection } of references) {

View File

@ -20,12 +20,13 @@ class AsyncModuleRuntimeModule extends HelperRuntimeModule {
const { runtimeTemplate } = this.compilation;
const fn = RuntimeGlobals.asyncModule;
return Template.asString([
'var webpackThen = typeof Symbol === "function" ? Symbol("webpack then") : "__webpack_then__";',
'var webpackQueues = typeof Symbol === "function" ? Symbol("webpack queues") : "__webpack_queues__";',
'var webpackExports = typeof Symbol === "function" ? Symbol("webpack exports") : "__webpack_exports__";',
'var webpackError = typeof Symbol === "function" ? Symbol("webpack error") : "__webpack_error__";',
`var completeQueue = ${runtimeTemplate.basicFunction("queue", [
"if(queue) {",
`var resolveQueue = ${runtimeTemplate.basicFunction("queue", [
"if(queue && !queue.d) {",
Template.indent([
"queue.d = 1;",
`queue.forEach(${runtimeTemplate.expressionFunction(
"fn.r--",
"fn"
@ -37,35 +38,26 @@ class AsyncModuleRuntimeModule extends HelperRuntimeModule {
]),
"}"
])}`,
`var completeFunction = ${runtimeTemplate.expressionFunction(
"!--fn.r && fn()",
"fn"
)};`,
`var queueFunction = ${runtimeTemplate.expressionFunction(
"queue ? queue.push(fn) : completeFunction(fn)",
"queue, fn"
)};`,
`var wrapDeps = ${runtimeTemplate.returningFunction(
`deps.map(${runtimeTemplate.basicFunction("dep", [
'if(dep !== null && typeof dep === "object") {',
Template.indent([
"if(dep[webpackThen]) return dep;",
"if(dep[webpackQueues]) return dep;",
"if(dep.then) {",
Template.indent([
"var queue = [];",
"queue.d = 0;",
`dep.then(${runtimeTemplate.basicFunction("r", [
"obj[webpackExports] = r;",
"completeQueue(queue);",
"queue = 0;"
"resolveQueue(queue);"
])}, ${runtimeTemplate.basicFunction("e", [
"obj[webpackError] = e;",
"completeQueue(queue);",
"queue = 0;"
"resolveQueue(queue);"
])});`,
"var obj = {};",
`obj[webpackThen] = ${runtimeTemplate.expressionFunction(
"queueFunction(queue, fn), dep['catch'](reject)",
"fn, reject"
`obj[webpackQueues] = ${runtimeTemplate.expressionFunction(
`fn(queue)`,
"fn"
)};`,
"return obj;"
]),
@ -73,54 +65,28 @@ class AsyncModuleRuntimeModule extends HelperRuntimeModule {
]),
"}",
"var ret = {};",
`ret[webpackThen] = ${runtimeTemplate.expressionFunction(
"completeFunction(fn)",
"fn"
)};`,
`ret[webpackQueues] = ${runtimeTemplate.emptyFunction()};`,
"ret[webpackExports] = dep;",
"return ret;"
])})`,
"deps"
)};`,
`${fn} = ${runtimeTemplate.basicFunction("module, body, hasAwait", [
"var queue = hasAwait && [];",
"var queue;",
"hasAwait && ((queue = []).d = 1);",
"var depQueues = new Set();",
"var exports = module.exports;",
"var currentDeps;",
"var outerResolve;",
"var reject;",
"var isEvaluating = true;",
"var nested = false;",
`var whenAll = ${runtimeTemplate.basicFunction(
"deps, onResolve, onReject",
[
"if (nested) return;",
"nested = true;",
"onResolve.r += deps.length;",
`deps.map(${runtimeTemplate.expressionFunction(
"dep[webpackThen](onResolve, onReject)",
"dep, i"
)});`,
"nested = false;"
]
)};`,
`var promise = new Promise(${runtimeTemplate.basicFunction(
"resolve, rej",
[
"reject = rej;",
`outerResolve = ${runtimeTemplate.expressionFunction(
"resolve(exports), completeQueue(queue), queue = 0"
)};`
]
["reject = rej;", "outerResolve = resolve;"]
)});`,
"promise[webpackExports] = exports;",
`promise[webpackThen] = ${runtimeTemplate.basicFunction(
"fn, rejectFn",
[
"if (isEvaluating) { return completeFunction(fn); }",
"if (currentDeps) whenAll(currentDeps, fn, rejectFn);",
"queueFunction(queue, fn);",
"promise['catch'](rejectFn);"
]
`promise[webpackQueues] = ${runtimeTemplate.expressionFunction(
`queue && fn(queue), depQueues.forEach(fn), promise["catch"](${runtimeTemplate.emptyFunction()})`,
"fn"
)};`,
"module.exports = promise;",
`body(${runtimeTemplate.basicFunction("deps", [
@ -133,21 +99,29 @@ class AsyncModuleRuntimeModule extends HelperRuntimeModule {
])})`
)}`,
`var promise = new Promise(${runtimeTemplate.basicFunction(
"resolve, reject",
"resolve",
[
`fn = ${runtimeTemplate.expressionFunction(
"resolve(getResult)"
"resolve(getResult)",
""
)};`,
"fn.r = 0;",
"whenAll(currentDeps, fn, reject);"
`var fnQueue = ${runtimeTemplate.expressionFunction(
"q !== queue && !depQueues.has(q) && (depQueues.add(q), q && !q.d && (fn.r++, q.push(fn)))",
"q"
)};`,
`currentDeps.map(${runtimeTemplate.expressionFunction(
"dep[webpackQueues](fnQueue)",
"dep"
)});`
]
)});`,
"return fn.r ? promise : getResult();"
])}, ${runtimeTemplate.expressionFunction(
"err && reject(promise[webpackError] = err), outerResolve()",
"(err ? reject(promise[webpackError] = err) : outerResolve(exports)), resolveQueue(queue)",
"err"
)});`,
"isEvaluating = false;"
"queue && (queue.d = 0);"
])};`
]);
}

View File

@ -87,13 +87,15 @@ class LoadScriptRuntimeModule extends HelperRuntimeModule {
: "url"
};`,
crossOriginLoading
? Template.asString([
"if (script.src.indexOf(window.location.origin + '/') !== 0) {",
Template.indent(
`script.crossOrigin = ${JSON.stringify(crossOriginLoading)};`
),
"}"
])
? crossOriginLoading === "use-credentials"
? 'script.crossOrigin = "use-credentials";'
: Template.asString([
"if (script.src.indexOf(window.location.origin + '/') !== 0) {",
Template.indent(
`script.crossOrigin = ${JSON.stringify(crossOriginLoading)};`
),
"}"
])
: ""
]);

View File

@ -0,0 +1,24 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Ivan Kopeykin @vankop
*/
"use strict";
const RuntimeGlobals = require("../RuntimeGlobals");
const RuntimeModule = require("../RuntimeModule");
class NonceRuntimeModule extends RuntimeModule {
constructor() {
super("nonce", RuntimeModule.STAGE_ATTACH);
}
/**
* @returns {string} runtime code
*/
generate() {
return `${RuntimeGlobals.scriptNonce} = undefined;`;
}
}
module.exports = NonceRuntimeModule;

View File

@ -129,8 +129,7 @@ class ProvideSharedPlugin {
details =
"No description file (usually package.json) found. Add description file with name and version, or manually specify version in shared config.";
} else if (!descriptionFileData.version) {
details =
"No version in description file (usually package.json). Add version to description file, or manually specify version in shared config.";
details = `No version in description file (usually package.json). Add version to description file ${resourceResolveData.descriptionFilePath}, or manually specify version in shared config.`;
} else {
version = descriptionFileData.version;
}

View File

@ -263,15 +263,17 @@ class JsonpChunkLoadingRuntimeModule extends RuntimeModule {
'link.as = "script";',
`link.href = ${RuntimeGlobals.publicPath} + ${RuntimeGlobals.getChunkScriptFilename}(chunkId);`,
crossOriginLoading
? Template.asString([
"if (link.href.indexOf(window.location.origin + '/') !== 0) {",
Template.indent(
`link.crossOrigin = ${JSON.stringify(
crossOriginLoading
)};`
),
"}"
])
? crossOriginLoading === "use-credentials"
? 'link.crossOrigin = "use-credentials";'
: Template.asString([
"if (link.href.indexOf(window.location.origin + '/') !== 0) {",
Template.indent(
`link.crossOrigin = ${JSON.stringify(
crossOriginLoading
)};`
),
"}"
])
: ""
]),
chunk

View File

@ -1,6 +1,6 @@
{
"name": "webpack",
"version": "5.72.0",
"version": "5.74.0",
"author": "Tobias Koppers @sokra",
"description": "Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.",
"license": "MIT",
@ -10,11 +10,11 @@
"@webassemblyjs/ast": "1.11.1",
"@webassemblyjs/wasm-edit": "1.11.1",
"@webassemblyjs/wasm-parser": "1.11.1",
"acorn": "^8.4.1",
"acorn": "^8.7.1",
"acorn-import-assertions": "^1.7.6",
"browserslist": "^4.14.5",
"chrome-trace-event": "^1.0.2",
"enhanced-resolve": "^5.9.3",
"enhanced-resolve": "^5.10.0",
"es-module-lexer": "^0.9.0",
"eslint-scope": "5.1.1",
"events": "^3.2.0",
@ -27,7 +27,7 @@
"schema-utils": "^3.1.0",
"tapable": "^2.1.1",
"terser-webpack-plugin": "^5.1.3",
"watchpack": "^2.3.1",
"watchpack": "^2.4.0",
"webpack-sources": "^3.2.3"
},
"peerDependenciesMeta": {
@ -121,6 +121,7 @@
"url": "https://opencollective.com/webpack"
},
"homepage": "https://github.com/webpack/webpack",
"bugs": "https://github.com/webpack/webpack/issues",
"main": "lib/index.js",
"bin": {
"webpack": "bin/webpack.js"

File diff suppressed because one or more lines are too long

View File

@ -897,7 +897,10 @@
},
"css": {
"description": "Enable css support.",
"oneOf": [
"anyOf": [
{
"enum": [false]
},
{
"$ref": "#/definitions/CssExperimentOptions"
}
@ -913,7 +916,10 @@
},
"lazyCompilation": {
"description": "Compile entrypoints and import()s only when they are accessed.",
"oneOf": [
"anyOf": [
{
"enum": [false]
},
{
"$ref": "#/definitions/LazyCompilationOptions"
}
@ -1580,6 +1586,43 @@
"description": "Enable/disable parsing of magic comments in CommonJs syntax.",
"type": "boolean"
},
"createRequire": {
"description": "Enable/disable parsing \"import { createRequire } from \"module\"\" and evaluating createRequire().",
"anyOf": [
{
"type": "boolean"
},
{
"type": "string"
}
]
},
"dynamicImportMode": {
"description": "Specifies global mode for dynamic import.",
"enum": ["eager", "weak", "lazy", "lazy-once"]
},
"dynamicImportPrefetch": {
"description": "Specifies global prefetch for dynamic import.",
"anyOf": [
{
"type": "number"
},
{
"type": "boolean"
}
]
},
"dynamicImportPreload": {
"description": "Specifies global preload for dynamic import.",
"anyOf": [
{
"type": "number"
},
{
"type": "boolean"
}
]
},
"exportsPresence": {
"description": "Specifies the behavior of invalid export names in \"import ... from ...\" and \"export ... from ...\".",
"enum": ["error", "warn", "auto", false]
@ -3700,6 +3743,29 @@
"type": "string"
}
},
"extensionAlias": {
"description": "An object which maps extension to extension aliases.",
"type": "object",
"additionalProperties": {
"description": "Extension alias.",
"anyOf": [
{
"description": "Multiple extensions.",
"type": "array",
"items": {
"description": "Aliased extension.",
"type": "string",
"minLength": 1
}
},
{
"description": "Aliased extension.",
"type": "string",
"minLength": 1
}
]
}
},
"extensions": {
"description": "Extensions added to the request when trying to find the file.",
"type": "array",

View File

@ -214,6 +214,10 @@ describe("snapshots", () => {
},
},
"javascript": Object {
"createRequire": false,
"dynamicImportMode": "lazy",
"dynamicImportPrefetch": false,
"dynamicImportPreload": false,
"exprContextCritical": true,
"exprContextRecursive": true,
"exprContextRegExp": false,
@ -1266,6 +1270,9 @@ describe("snapshots", () => {
- "target": "web",
+ "target": "node",
@@ ... @@
- "createRequire": false,
+ "createRequire": true,
@@ ... @@
- "__dirname": "mock",
- "__filename": "mock",
- "global": true,
@ -1407,6 +1414,9 @@ describe("snapshots", () => {
- "target": "web",
+ "target": "electron-main",
@@ ... @@
- "createRequire": false,
+ "createRequire": true,
@@ ... @@
- "__dirname": "mock",
- "__filename": "mock",
- "global": true,
@ -1530,6 +1540,9 @@ describe("snapshots", () => {
- "target": "web",
+ "target": "electron-preload",
@@ ... @@
- "createRequire": false,
+ "createRequire": true,
@@ ... @@
- "__dirname": "mock",
- "__filename": "mock",
- "global": true,
@ -2208,6 +2221,84 @@ describe("snapshots", () => {
+ /^(.+?[\\\\/]node_modules[\\\\/])/,
`)
);
test(
"experiments.futureDefaults w/ experiments.css disabled",
{
experiments: {
css: false,
futureDefaults: true
}
},
e =>
e.toMatchInlineSnapshot(`
- Expected
+ Received
@@ ... @@
- "asyncWebAssembly": false,
- "backCompat": true,
+ "asyncWebAssembly": true,
+ "backCompat": false,
@@ ... @@
- "cacheUnaffected": false,
- "css": undefined,
- "futureDefaults": false,
+ "cacheUnaffected": true,
+ "css": false,
+ "futureDefaults": true,
@@ ... @@
- "topLevelAwait": false,
+ "topLevelAwait": true,
@@ ... @@
+ },
+ Object {
+ "rules": Array [
+ Object {
+ "descriptionData": Object {
+ "type": "module",
+ },
+ "resolve": Object {
+ "fullySpecified": true,
+ },
+ },
+ ],
+ "test": /\\.wasm$/i,
+ "type": "webassembly/async",
@@ ... @@
+ "mimetype": "application/wasm",
+ "rules": Array [
+ Object {
+ "descriptionData": Object {
+ "type": "module",
+ },
+ "resolve": Object {
+ "fullySpecified": true,
+ },
+ },
+ ],
+ "type": "webassembly/async",
+ },
+ Object {
@@ ... @@
+ "exportsPresence": "error",
@@ ... @@
- "__dirname": "mock",
- "__filename": "mock",
- "global": true,
+ "__dirname": "warn-mock",
+ "__filename": "warn-mock",
+ "global": "warn",
@@ ... @@
- "hashDigestLength": 20,
- "hashFunction": "md4",
+ "hashDigestLength": 16,
+ "hashFunction": "xxhash64",
@@ ... @@
- "<cwd>/node_modules/",
+ /^(.+?[\\\\/]node_modules[\\\\/])/,
`)
);
});
it("should result in the same target options for same target", () => {

View File

@ -363,4 +363,50 @@ ${details(snapshot)}`)
}
});
}
describe("stable iterables identity", () => {
const options = { timestamp: true };
/**
* @param {function((WebpackError | null)=, (Snapshot | null)=): void} callback callback function
*/
function getSnapshot(callback) {
const fs = createFs();
const fsInfo = createFsInfo(fs);
fsInfo.createSnapshot(
Date.now() + 10000,
files,
directories,
missing,
options,
callback
);
}
it("should return same iterable for getFileIterable()", done => {
getSnapshot((err, snapshot) => {
if (err) done(err);
expect(snapshot.getFileIterable()).toEqual(snapshot.getFileIterable());
done();
});
});
it("should return same iterable for getContextIterable()", done => {
getSnapshot((err, snapshot) => {
if (err) done(err);
expect(snapshot.getContextIterable()).toEqual(
snapshot.getContextIterable()
);
done();
});
});
it("should return same iterable for getMissingIterable()", done => {
getSnapshot((err, snapshot) => {
if (err) done(err);
expect(snapshot.getFileIterable()).toEqual(snapshot.getFileIterable());
done();
});
});
});
});

View File

@ -0,0 +1,131 @@
"use strict";
require("./helpers/warmup-webpack");
const path = require("path");
const fs = require("graceful-fs");
const rimraf = require("rimraf");
const captureStdio = require("./helpers/captureStdio");
const webpack = require("..");
const toMiB = bytes => `${Math.round(bytes / 1024 / 1024)}MiB`;
const base = path.join(__dirname, "memoryLimitCases");
const outputBase = path.join(__dirname, "js", "memoryLimit");
const tests = fs
.readdirSync(base)
.filter(
testName =>
fs.existsSync(path.join(base, testName, "index.js")) ||
fs.existsSync(path.join(base, testName, "webpack.config.js"))
)
.filter(testName => {
const testDirectory = path.join(base, testName);
const filterPath = path.join(testDirectory, "test.filter.js");
if (fs.existsSync(filterPath) && !require(filterPath)()) {
describe.skip(testName, () => it("filtered"));
return false;
}
return true;
});
describe("MemoryLimitTestCases", () => {
jest.setTimeout(40000);
let stderr;
beforeEach(() => {
stderr = captureStdio(process.stderr, true);
if (global.gc) {
global.gc();
global.gc();
}
});
afterEach(() => {
stderr.restore();
});
tests.forEach(testName => {
let testConfig = {
heapSizeLimitBytes: 250 * 1024 * 1024
};
try {
// try to load a test file
testConfig = Object.assign(
testConfig,
require(path.join(base, testName, "test.config.js"))
);
} catch (e) {
// ignored
}
it(`should build ${JSON.stringify(testName)} with heap limit of ${toMiB(
testConfig.heapSizeLimitBytes
)}`, done => {
const outputDirectory = path.join(outputBase, testName);
rimraf.sync(outputDirectory);
fs.mkdirSync(outputDirectory, { recursive: true });
let options = {
mode: "development",
entry: "./index",
output: {
filename: "bundle.js"
}
};
if (fs.existsSync(path.join(base, testName, "webpack.config.js"))) {
options = require(path.join(base, testName, "webpack.config.js"));
}
(Array.isArray(options) ? options : [options]).forEach(options => {
if (!options.context) options.context = path.join(base, testName);
if (!options.output) options.output = options.output || {};
if (!options.output.path) options.output.path = outputDirectory;
if (!options.plugins) options.plugins = [];
if (!options.optimization) options.optimization = {};
if (options.optimization.minimize === undefined)
options.optimization.minimize = false;
});
const heapSizeStart = process.memoryUsage().heapUsed;
const c = webpack(options);
const compilers = c.compilers ? c.compilers : [c];
compilers.forEach(c => {
const ifs = c.inputFileSystem;
c.inputFileSystem = Object.create(ifs);
c.inputFileSystem.readFile = function () {
const args = Array.prototype.slice.call(arguments);
const callback = args.pop();
ifs.readFile.apply(
ifs,
args.concat([
(err, result) => {
if (err) return callback(err);
if (!/\.(js|json|txt)$/.test(args[0]))
return callback(null, result);
callback(null, result.toString("utf-8").replace(/\r/g, ""));
}
])
);
};
});
c.run((err, stats) => {
if (err) return done(err);
if (/error$/.test(testName)) {
expect(stats.hasErrors()).toBe(true);
} else if (stats.hasErrors()) {
return done(
new Error(
stats.toString({
all: false,
errors: true,
errorStack: true,
errorDetails: true
})
)
);
}
const heapUsed = process.memoryUsage().heapUsed - heapSizeStart;
if (heapUsed > testConfig.heapSizeLimitBytes) {
return done(
new Error(`Out of memory limit with ${toMiB(heapUsed)} heap used`)
);
}
if (testConfig.validate) testConfig.validate(stats, stderr.toString());
done();
});
});
});
});

View File

@ -1503,6 +1503,82 @@ Object {
"multiple": false,
"simpleType": "boolean",
},
"module-parser-javascript-auto-create-require": Object {
"configs": Array [
Object {
"description": "Enable/disable parsing \\"import { createRequire } from \\"module\\"\\" and evaluating createRequire().",
"multiple": false,
"path": "module.parser.javascript/auto.createRequire",
"type": "boolean",
},
Object {
"description": "Enable/disable parsing \\"import { createRequire } from \\"module\\"\\" and evaluating createRequire().",
"multiple": false,
"path": "module.parser.javascript/auto.createRequire",
"type": "string",
},
],
"description": "Enable/disable parsing \\"import { createRequire } from \\"module\\"\\" and evaluating createRequire().",
"multiple": false,
"simpleType": "string",
},
"module-parser-javascript-auto-dynamic-import-mode": Object {
"configs": Array [
Object {
"description": "Specifies global mode for dynamic import.",
"multiple": false,
"path": "module.parser.javascript/auto.dynamicImportMode",
"type": "enum",
"values": Array [
"eager",
"weak",
"lazy",
"lazy-once",
],
},
],
"description": "Specifies global mode for dynamic import.",
"multiple": false,
"simpleType": "string",
},
"module-parser-javascript-auto-dynamic-import-prefetch": Object {
"configs": Array [
Object {
"description": "Specifies global prefetch for dynamic import.",
"multiple": false,
"path": "module.parser.javascript/auto.dynamicImportPrefetch",
"type": "number",
},
Object {
"description": "Specifies global prefetch for dynamic import.",
"multiple": false,
"path": "module.parser.javascript/auto.dynamicImportPrefetch",
"type": "boolean",
},
],
"description": "Specifies global prefetch for dynamic import.",
"multiple": false,
"simpleType": "string",
},
"module-parser-javascript-auto-dynamic-import-preload": Object {
"configs": Array [
Object {
"description": "Specifies global preload for dynamic import.",
"multiple": false,
"path": "module.parser.javascript/auto.dynamicImportPreload",
"type": "number",
},
Object {
"description": "Specifies global preload for dynamic import.",
"multiple": false,
"path": "module.parser.javascript/auto.dynamicImportPreload",
"type": "boolean",
},
],
"description": "Specifies global preload for dynamic import.",
"multiple": false,
"simpleType": "string",
},
"module-parser-javascript-auto-exports-presence": Object {
"configs": Array [
Object {
@ -2025,6 +2101,25 @@ Object {
"multiple": false,
"simpleType": "boolean",
},
"module-parser-javascript-create-require": Object {
"configs": Array [
Object {
"description": "Enable/disable parsing \\"import { createRequire } from \\"module\\"\\" and evaluating createRequire().",
"multiple": false,
"path": "module.parser.javascript.createRequire",
"type": "boolean",
},
Object {
"description": "Enable/disable parsing \\"import { createRequire } from \\"module\\"\\" and evaluating createRequire().",
"multiple": false,
"path": "module.parser.javascript.createRequire",
"type": "string",
},
],
"description": "Enable/disable parsing \\"import { createRequire } from \\"module\\"\\" and evaluating createRequire().",
"multiple": false,
"simpleType": "string",
},
"module-parser-javascript-dynamic-amd": Object {
"configs": Array [
Object {
@ -2080,6 +2175,82 @@ Object {
"multiple": false,
"simpleType": "boolean",
},
"module-parser-javascript-dynamic-create-require": Object {
"configs": Array [
Object {
"description": "Enable/disable parsing \\"import { createRequire } from \\"module\\"\\" and evaluating createRequire().",
"multiple": false,
"path": "module.parser.javascript/dynamic.createRequire",
"type": "boolean",
},
Object {
"description": "Enable/disable parsing \\"import { createRequire } from \\"module\\"\\" and evaluating createRequire().",
"multiple": false,
"path": "module.parser.javascript/dynamic.createRequire",
"type": "string",
},
],
"description": "Enable/disable parsing \\"import { createRequire } from \\"module\\"\\" and evaluating createRequire().",
"multiple": false,
"simpleType": "string",
},
"module-parser-javascript-dynamic-dynamic-import-mode": Object {
"configs": Array [
Object {
"description": "Specifies global mode for dynamic import.",
"multiple": false,
"path": "module.parser.javascript/dynamic.dynamicImportMode",
"type": "enum",
"values": Array [
"eager",
"weak",
"lazy",
"lazy-once",
],
},
],
"description": "Specifies global mode for dynamic import.",
"multiple": false,
"simpleType": "string",
},
"module-parser-javascript-dynamic-dynamic-import-prefetch": Object {
"configs": Array [
Object {
"description": "Specifies global prefetch for dynamic import.",
"multiple": false,
"path": "module.parser.javascript/dynamic.dynamicImportPrefetch",
"type": "number",
},
Object {
"description": "Specifies global prefetch for dynamic import.",
"multiple": false,
"path": "module.parser.javascript/dynamic.dynamicImportPrefetch",
"type": "boolean",
},
],
"description": "Specifies global prefetch for dynamic import.",
"multiple": false,
"simpleType": "string",
},
"module-parser-javascript-dynamic-dynamic-import-preload": Object {
"configs": Array [
Object {
"description": "Specifies global preload for dynamic import.",
"multiple": false,
"path": "module.parser.javascript/dynamic.dynamicImportPreload",
"type": "number",
},
Object {
"description": "Specifies global preload for dynamic import.",
"multiple": false,
"path": "module.parser.javascript/dynamic.dynamicImportPreload",
"type": "boolean",
},
],
"description": "Specifies global preload for dynamic import.",
"multiple": false,
"simpleType": "string",
},
"module-parser-javascript-dynamic-exports-presence": Object {
"configs": Array [
Object {
@ -2228,6 +2399,63 @@ Object {
"multiple": false,
"simpleType": "boolean",
},
"module-parser-javascript-dynamic-import-mode": Object {
"configs": Array [
Object {
"description": "Specifies global mode for dynamic import.",
"multiple": false,
"path": "module.parser.javascript.dynamicImportMode",
"type": "enum",
"values": Array [
"eager",
"weak",
"lazy",
"lazy-once",
],
},
],
"description": "Specifies global mode for dynamic import.",
"multiple": false,
"simpleType": "string",
},
"module-parser-javascript-dynamic-import-prefetch": Object {
"configs": Array [
Object {
"description": "Specifies global prefetch for dynamic import.",
"multiple": false,
"path": "module.parser.javascript.dynamicImportPrefetch",
"type": "number",
},
Object {
"description": "Specifies global prefetch for dynamic import.",
"multiple": false,
"path": "module.parser.javascript.dynamicImportPrefetch",
"type": "boolean",
},
],
"description": "Specifies global prefetch for dynamic import.",
"multiple": false,
"simpleType": "string",
},
"module-parser-javascript-dynamic-import-preload": Object {
"configs": Array [
Object {
"description": "Specifies global preload for dynamic import.",
"multiple": false,
"path": "module.parser.javascript.dynamicImportPreload",
"type": "number",
},
Object {
"description": "Specifies global preload for dynamic import.",
"multiple": false,
"path": "module.parser.javascript.dynamicImportPreload",
"type": "boolean",
},
],
"description": "Specifies global preload for dynamic import.",
"multiple": false,
"simpleType": "string",
},
"module-parser-javascript-dynamic-node": Object {
"configs": Array [
Object {
@ -2618,6 +2846,82 @@ Object {
"multiple": false,
"simpleType": "boolean",
},
"module-parser-javascript-esm-create-require": Object {
"configs": Array [
Object {
"description": "Enable/disable parsing \\"import { createRequire } from \\"module\\"\\" and evaluating createRequire().",
"multiple": false,
"path": "module.parser.javascript/esm.createRequire",
"type": "boolean",
},
Object {
"description": "Enable/disable parsing \\"import { createRequire } from \\"module\\"\\" and evaluating createRequire().",
"multiple": false,
"path": "module.parser.javascript/esm.createRequire",
"type": "string",
},
],
"description": "Enable/disable parsing \\"import { createRequire } from \\"module\\"\\" and evaluating createRequire().",
"multiple": false,
"simpleType": "string",
},
"module-parser-javascript-esm-dynamic-import-mode": Object {
"configs": Array [
Object {
"description": "Specifies global mode for dynamic import.",
"multiple": false,
"path": "module.parser.javascript/esm.dynamicImportMode",
"type": "enum",
"values": Array [
"eager",
"weak",
"lazy",
"lazy-once",
],
},
],
"description": "Specifies global mode for dynamic import.",
"multiple": false,
"simpleType": "string",
},
"module-parser-javascript-esm-dynamic-import-prefetch": Object {
"configs": Array [
Object {
"description": "Specifies global prefetch for dynamic import.",
"multiple": false,
"path": "module.parser.javascript/esm.dynamicImportPrefetch",
"type": "number",
},
Object {
"description": "Specifies global prefetch for dynamic import.",
"multiple": false,
"path": "module.parser.javascript/esm.dynamicImportPrefetch",
"type": "boolean",
},
],
"description": "Specifies global prefetch for dynamic import.",
"multiple": false,
"simpleType": "string",
},
"module-parser-javascript-esm-dynamic-import-preload": Object {
"configs": Array [
Object {
"description": "Specifies global preload for dynamic import.",
"multiple": false,
"path": "module.parser.javascript/esm.dynamicImportPreload",
"type": "number",
},
Object {
"description": "Specifies global preload for dynamic import.",
"multiple": false,
"path": "module.parser.javascript/esm.dynamicImportPreload",
"type": "boolean",
},
],
"description": "Specifies global preload for dynamic import.",
"multiple": false,
"simpleType": "string",
},
"module-parser-javascript-esm-exports-presence": Object {
"configs": Array [
Object {

View File

@ -1192,6 +1192,17 @@ cacheable modules 142 bytes
webpack x.x.x compiled successfully in X ms"
`;
exports[`StatsTestCases should print correct stats for import-weak-parser-option 1`] = `
"asset entry.js 13 KiB [emitted] (name: entry)
asset 836.js 138 bytes [emitted]
runtime modules 7.68 KiB 10 modules
orphan modules 37 bytes [orphan] 1 module
cacheable modules 116 bytes
./entry.js 94 bytes [built] [code generated]
./modules/b.js 22 bytes [built] [code generated]
webpack x.x.x compiled successfully in X ms"
`;
exports[`StatsTestCases should print correct stats for import-with-invalid-options-comments 1`] = `
"runtime modules 8.6 KiB 12 modules
cacheable modules 559 bytes
@ -4600,8 +4611,8 @@ webpack x.x.x compiled with 1 warning in X ms"
`;
exports[`StatsTestCases should print correct stats for wasm-explorer-examples-sync 1`] = `
"assets by path *.js 22.2 KiB
asset bundle.js 16.7 KiB [emitted] (name: main)
"assets by path *.js 21.7 KiB
asset bundle.js 16.2 KiB [emitted] (name: main)
asset 325.bundle.js 3.9 KiB [emitted]
asset 795.bundle.js 557 bytes [emitted]
asset 526.bundle.js 366 bytes [emitted] (id hint: vendors)
@ -4617,8 +4628,8 @@ assets by path *.wasm 1.37 KiB
asset 0301cb3f9f4151b567f5.module.wasm 120 bytes [emitted] [immutable]
chunk (runtime: main) 20.bundle.js 50 bytes (javascript) 531 bytes (webassembly) [rendered]
./duff.wasm 50 bytes (javascript) 531 bytes (webassembly) [built] [code generated]
chunk (runtime: main) bundle.js (main) 586 bytes (javascript) 9.49 KiB (runtime) [entry] [rendered]
runtime modules 9.49 KiB 11 modules
chunk (runtime: main) bundle.js (main) 586 bytes (javascript) 9.12 KiB (runtime) [entry] [rendered]
runtime modules 9.12 KiB 11 modules
./index.js 586 bytes [built] [code generated]
chunk (runtime: main) 189.bundle.js 50 bytes (javascript) 156 bytes (webassembly) [rendered]
./Q_rsqrt.wasm 50 bytes (javascript) 156 bytes (webassembly) [built] [code generated]
@ -4632,7 +4643,7 @@ chunk (runtime: main) 526.bundle.js (id hint: vendors) 34 bytes [rendered] split
chunk (runtime: main) 795.bundle.js 110 bytes (javascript) 444 bytes (webassembly) [rendered]
./fact.wasm 50 bytes (javascript) 154 bytes (webassembly) [built] [code generated]
./fast-math.wasm 60 bytes (javascript) 290 bytes (webassembly) [built] [code generated]
runtime modules 9.49 KiB 11 modules
runtime modules 9.12 KiB 11 modules
cacheable modules 2.31 KiB (javascript) 1.37 KiB (webassembly)
webassembly modules 310 bytes (javascript) 1.37 KiB (webassembly)
./Q_rsqrt.wasm 50 bytes (javascript) 156 bytes (webassembly) [built] [code generated]

View File

@ -0,0 +1,2 @@
await 1;
export default 1;

View File

@ -0,0 +1,5 @@
it("should not take too long to evaluate nested async modules", async () => {
const start = Date.now();
await import(/* webpackMode: "eager" */ "./loader.js?i=40!./loader.js");
expect(Date.now() - start).toBeLessThan(100);
});

View File

@ -0,0 +1,14 @@
/** @type {import("../../../../").LoaderDefinition<{ i: string }>} */
module.exports = function () {
const options = this.getOptions();
const i = +options.i;
let src = `import n from "./async.js";\n`;
if (i > 0) {
src += `import a from "./loader.js?i=${i - 1}&a!./loader.js";\n`;
src += `import b from "./loader.js?i=${i - 1}&b!./loader.js";\n`;
src += `export default n + a + b;\n`;
} else {
src += `export default n;\n`;
}
return src;
};

View File

@ -0,0 +1,4 @@
let value = 0;
const add = () => value++;
export { value, add }

View File

@ -0,0 +1,20 @@
import { "\0 add" as add } from './reexport';
export default class Foo {
static {
new Foo(add);
}
constructor(fn) {
this.#foo = fn;
this.#add();
}
#foo = undefined;
#add() {
if (#foo in this && this.#foo) {
this.#foo();
}
}
}

View File

@ -0,0 +1,7 @@
import { value, add } from "./counter";
import Foo from "./es2022";
it("should compile and run", () => {
new Foo(add);
expect(value).toBe(2);
});

View File

@ -0,0 +1 @@
export { add as "\0 add" } from "./counter";

View File

@ -0,0 +1,11 @@
module.exports = function(config) {
// terser doesn't support static {}
if (config.mode === "production") return false;
try {
eval("class A { static {} }");
return true;
} catch {
return false;
}
};

View File

@ -6,7 +6,7 @@ import { b1, usedB1, usedB2, usedB3, usedB4 } from "./b.js";
import { usedE1, usedE2 } from "./e.js";
import { h } from "./h.js";
import * as m from "./m";
import {object as obj} from "./m";
import { object as obj } from "./m";
import cjs from "./cjs2";
import * as o from "./o";
import * as p from "./p";
@ -79,3 +79,12 @@ it("should handle 'm in n' case", () => {
expect(m.canMangleA).toBe(true);
}
});
it("issue-15759", () => {
function foo() {
// PLEASE CONFIRM there is no space after return
// prettier-ignore
return"usedA"in m;
}
expect(foo.call()).toBe(true);
});

View File

@ -1,3 +1,5 @@
module.exports = [
// each time sets different assetsInfo object instance in webpack.config.js:54
// this prevents hit in inmemory cache
/^Pack got invalid because of write to: TerserWebpackPlugin|bundle0\.js$/
];

View File

@ -0,0 +1,11 @@
import { b, a, c } from "dep";
c.cc();
b.bbb();
a.aa();
import { order } from "dep/order.js";
it("should import side-effect-free modules in deterministic order (usage order)", () => {
expect(order).toEqual(["c", "b", "a"]);
});

View File

@ -0,0 +1,4 @@
import { track } from "./order.js";
track("a");
export function aa() {}
export function aaa() {}

View File

@ -0,0 +1,4 @@
import { track } from "./order.js";
track("b");
export function bb() {}
export function bbb() {}

View File

@ -0,0 +1,4 @@
import { track } from "./order.js";
track("c");
export function cc() {}
export function ccc() {}

View File

@ -0,0 +1,8 @@
import * as a from "./a.js";
import * as b from "./b.js";
import * as c from "./c.js";
export {
a,
b,
c
}

View File

@ -0,0 +1,4 @@
export let order = [];
export function track(name) {
order.push(name);
}

View File

@ -0,0 +1,6 @@
{
"name": "dep",
"version": "1.0.0",
"type": "module",
"sideEffects": false
}

View File

@ -0,0 +1,6 @@
/** @type {import("../../../../").Configuration} */
module.exports = {
optimization: {
concatenateModules: true
}
};

View File

@ -0,0 +1,2 @@
export * as c from "./b";
export * as c2 from "./harmony2";

View File

@ -0,0 +1,7 @@
export function square(x) {
return x * x;
}
export function cube(x) {
return x * x * x;
}

View File

@ -0,0 +1,2 @@
export const a = 1;
export const aUsed = __webpack_exports_info__.a.used;

View File

@ -48,6 +48,11 @@ it("should provide a module for a property request", function() {
expect(x).toBe("fff");
});
it("should tree-shake unused exports", function() {
expect(aa1(2)).toBe(8);
expect(es2015_aUsed).toBe(false);
});
it("should provide ES2015 modules", function() {
expect((es2015.default)).toBe("ECMAScript 2015");
expect((es2015.alias)).toBe("ECMAScript Harmony");

View File

@ -6,6 +6,8 @@ module.exports = {
aaa: "./aaa",
"bbb.ccc": "./bbbccc",
dddeeefff: ["./ddd", "eee", "3-f"],
aa1: ["./a", "c", "cube"],
es2015_aUsed: ["./harmony2", "aUsed"],
"process.env.NODE_ENV": "./env",
es2015: "./harmony",
es2015_name: ["./harmony", "default"],

View File

@ -1,3 +1,5 @@
module.exports = [
// each time returns different OriginalSource in webpack.config.js:78
// this prevents hit in inmemory cache
/^Pack got invalid because of write to: RealContentHashPlugin|analyse|index\.html$/
];

View File

@ -0,0 +1 @@
module.exports = 1;

View File

@ -0,0 +1 @@
module.exports = 2;

View File

@ -0,0 +1 @@
module.exports = 3;

View File

@ -0,0 +1 @@
module.exports = 4;

View File

@ -0,0 +1 @@
module.exports = 5;

View File

@ -0,0 +1,58 @@
import { createRequire as _createRequire } from "module";
import { createRequire as __createRequire, builtinModules } from "module";
it("should evaluate require/createRequire", () => {
expect(
(function() { return typeof _createRequire; }).toString()
).toBe('function() { return "function"; }');
expect(
(function() { if (typeof _createRequire); }).toString()
).toBe('function() { if (true); }');
const require = __createRequire(import.meta.url);
expect(
(function() { return typeof require; }).toString()
).toBe('function() { return "function"; }');
expect(
(function() { if (typeof require); }).toString()
).toBe('function() { if (true); }');
});
it("should create require", () => {
const require = _createRequire(import.meta.url);
expect(require("./a")).toBe(1);
expect(_createRequire(import.meta.url)("./c")).toBe(3);
});
it("should resolve using created require", () => {
const require = _createRequire(import.meta.url);
expect(require.resolve("./b")).toBe("./b.js");
expect(_createRequire(import.meta.url).resolve("./b")).toBe("./b.js");
});
it("should provide require.cache", () => {
const _require = _createRequire(import.meta.url);
expect(require.cache).toBe(_require.cache);
expect(require.cache).toBe(_createRequire(import.meta.url).cache);
});
it("should provide dependency context", () => {
const _require = _createRequire(new URL("./foo/c.js", import.meta.url));
expect(_require("./a")).toBe(4);
const _require1 = _createRequire(new URL("./foo/", import.meta.url));
expect(_require1("./c")).toBe(5);
});
it("should add warning on using as expression", () => {
let _require = _createRequire(new URL("./foo/c.js", import.meta.url));
const a = _require;
expect(typeof a).toBe("function");
});
it("should add warning on using require.main", () => {
let _require = _createRequire(new URL("./foo/c.js", import.meta.url));
expect(_require.main).toBe(undefined);
});
it("should import Node.js module", () => {
expect(Array.isArray(builtinModules)).toBe(true);
});

View File

@ -0,0 +1,4 @@
module.exports = [
/require function is used in a way in which dependencies cannot be statically extracted/,
/createRequire\(\)\.main is not supported by webpack/
];

View File

@ -0,0 +1,7 @@
/** @type {import("../../../../").Configuration} */
module.exports = {
target: "node",
optimization: {
moduleIds: "named"
}
};

View File

@ -0,0 +1,5 @@
import "./nonce";
it("should set nonce", () => {
expect(__webpack_nonce__).toBe("nonce");
});

View File

@ -0,0 +1 @@
__webpack_nonce__ = "nonce";

View File

@ -0,0 +1,7 @@
const webpack = require("../../../../");
/** @type {import("../../../../").Configuration} */
module.exports = {
target: "web",
// plugin that intercepts __webpack_require__
plugins: [new webpack.HotModuleReplacementPlugin()]
};

View File

@ -0,0 +1 @@
const ctx = require.context("./src", false, /\.json$/);

View File

@ -0,0 +1 @@
{"type":"Topology","box":[-73.9958013,45.3984821,-73.4742952,45.7047897],"transform":{"scale":[0.0005225512024048059,0.00030692144288576825],"translate":[-73.9958013,45.3984821]},"objects":{"boundary":{"type":"Polygon","arcs":[[0]],"id":"relation/8508277","properties":{"admin_level":"6","alt_name:1":"Montréal","boundary":"administrative","name":"Agglomération de Montréal","name:en":"Urban agglomeration of Montreal","name:fr":"Agglomération de Montréal","type":"boundary","wikidata":"Q2826806","wikipedia":"fr:Agglomération de Montréal","id":"relation/8508277"}}},"arcs":[[[992,804],[-2,23],[-15,31],[-3,32],[4,45],[12,24],[2,14],[5,9],[3,8],[-4,7],[-23,-3],[-4,4],[-8,-1],[-5,-2],[-22,-7],[-18,-7],[-10,-1],[-8,-25],[-5,-18],[-6,-11],[-11,-9],[-18,-14],[-29,-31],[-25,-20],[-6,-5],[-53,-44],[-17,-21],[-14,-17],[-17,-22],[-3,-9],[-6,-16],[-5,-24],[-2,-6],[-6,-22],[-13,-25],[-11,-21],[-5,-11],[-2,-3],[-12,-28],[-1,-3],[-1,-25],[-11,-22],[-2,-3],[-1,-4],[-3,-8],[0,-2],[-4,-6],[-6,-6],[-23,-7],[-7,-3],[-6,-3],[-14,-11],[-6,-11],[-11,-7],[-7,-3],[-3,-1],[-16,-17],[-11,-8],[-8,-5],[-3,-5],[-9,-22],[-11,-3],[-11,-8],[-5,-10],[-5,-5],[-4,-1],[-10,-3],[-27,3],[-20,4],[-11,9],[-8,0],[-10,7],[-15,-5],[-5,0],[-21,8],[-20,0],[-2,-2],[-3,-1],[-3,-4],[-7,-12],[-3,-3],[-1,-1],[-2,-1],[-2,1],[-6,12],[-8,4],[-3,5],[-1,5],[-7,1],[-14,1],[-7,0],[-8,3],[-11,6],[-7,5],[-7,6],[-11,-4],[-11,-9],[-6,-7],[-7,-12],[-8,-11],[-7,-9],[-21,-21],[-19,-13],[-14,-19],[-10,-19],[-5,-16],[-7,-13],[-11,-26],[-14,-17],[-15,-20],[-10,-6],[-12,-4],[-4,0],[5,-17],[0,-3],[1,-2],[1,-6],[3,-10],[2,-12],[2,-9],[2,-9],[2,-5],[2,-19],[0,-25],[10,-13],[17,-16],[14,-14],[5,-6],[6,-7],[2,-2],[1,0],[1,-1],[1,0],[11,-5],[6,-3],[2,-1],[6,0],[16,1],[21,2],[12,5],[13,3],[3,2],[6,3],[2,2],[8,7],[12,5],[5,2],[3,0],[4,0],[6,-2],[18,-9],[13,-5],[25,-6],[36,-6],[29,-3],[9,-2],[22,-5],[7,11],[4,7],[5,7],[5,4],[1,1],[3,4],[7,5],[7,5],[8,4],[9,6],[8,5],[12,8],[49,5],[14,1],[5,1],[13,2],[45,1],[12,1],[12,0],[4,0],[8,-1],[11,-2],[8,-3],[9,-3],[12,-5],[3,-2],[6,-3],[18,-10],[10,-6],[9,-3],[5,-1],[1,0],[7,-1],[2,0],[12,1],[13,1],[16,1],[6,1],[7,1],[36,4],[24,4],[15,4],[20,7],[13,8],[7,5],[4,3],[14,14],[9,15],[7,21],[2,7],[3,26],[1,14],[-1,23],[0,5],[0,5],[0,21],[-2,7],[-2,7],[-5,16],[-2,23],[-1,6],[-4,10],[7,5],[2,1],[1,3],[1,1],[2,2],[3,4],[-1,5],[2,2],[-2,10],[-3,16],[-8,45],[-2,7],[0,3],[-2,9],[0,3],[-4,29],[-2,10],[19,25],[14,32],[10,25],[14,35],[1,4],[0,17],[3,18],[-4,33],[-2,25],[3,20],[4,12],[17,40],[9,21],[4,11],[10,33]]]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,3 @@
import("./modules/a");
import("./modules/b");
import(/* webpackMode: "lazy" */"./modules/b");

View File

@ -0,0 +1,2 @@
import("./b");
module.exports = "a";

View File

@ -0,0 +1 @@
module.exports = "b";

View File

@ -0,0 +1,14 @@
/** @type {import("../../../").Configuration} */
module.exports = {
mode: "production",
entry: {
entry: "./entry"
},
module: {
parser: {
javascript: {
dynamicImportMode: "weak"
}
}
}
};

102
types.d.ts vendored
View File

@ -2503,11 +2503,11 @@ declare interface ContextHash {
}
type ContextMode =
| "weak"
| "sync"
| "eager"
| "async-weak"
| "lazy"
| "lazy-once";
| "lazy-once"
| "sync"
| "async-weak";
declare abstract class ContextModuleFactory extends ModuleFactory {
hooks: Readonly<{
beforeResolve: AsyncSeriesWaterfallHook<[any]>;
@ -3543,12 +3543,12 @@ declare interface ExperimentsNormalizedExtra {
/**
* Enable css support.
*/
css?: CssExperimentOptions;
css?: false | CssExperimentOptions;
/**
* Compile entrypoints and import()s only when they are accessed.
*/
lazyCompilation?: LazyCompilationOptions;
lazyCompilation?: false | LazyCompilationOptions;
}
declare abstract class ExportInfo {
name: string;
@ -3847,6 +3847,13 @@ declare interface ExpressionExpressionInfo {
getMembers: () => string[];
getMembersOptionals: () => boolean[];
}
declare interface ExtensionAliasOption {
alias: string | string[];
extension: string;
}
declare interface ExtensionAliasOptions {
[index: string]: string | string[];
}
type ExternalItem =
| string
| RegExp
@ -4502,6 +4509,42 @@ declare interface HandleModuleCreationOptions {
*/
connectOrigin?: boolean;
}
declare class HarmonyImportDependency extends ModuleDependency {
constructor(
request: string,
sourceOrder: number,
assertions?: Record<string, any>
);
sourceOrder: number;
getImportVar(moduleGraph: ModuleGraph): string;
getImportStatement(
update: boolean,
__1: DependencyTemplateContext
): [string, string];
getLinkingErrors(
moduleGraph: ModuleGraph,
ids: string[],
additionalMessage: string
): undefined | WebpackError[];
static Template: typeof HarmonyImportDependencyTemplate;
static ExportPresenceModes: {
NONE: 0;
WARN: 1;
AUTO: 2;
ERROR: 3;
fromUserOption(str?: any): 0 | 1 | 2 | 3;
};
static NO_EXPORTS_REFERENCED: string[][];
static EXPORTS_OBJECT_REFERENCED: string[][];
static TRANSITIVE: typeof TRANSITIVE;
}
declare class HarmonyImportDependencyTemplate extends DependencyTemplate {
constructor();
static getImportEmittedRuntime(
module: Module,
referencedModule: Module
): undefined | string | boolean | SortableSet<string>;
}
declare class Hash {
constructor();
@ -4902,6 +4945,15 @@ declare class JavascriptParser extends Parser {
undefined | null | BasicEvaluatedExpression
>
>;
evaluateNewExpression: HookMap<
SyncBailHook<[NewExpression], undefined | null | BasicEvaluatedExpression>
>;
evaluateCallExpression: HookMap<
SyncBailHook<
[CallExpression],
undefined | null | BasicEvaluatedExpression
>
>;
evaluateCallExpressionMember: HookMap<
SyncBailHook<
[CallExpression, undefined | BasicEvaluatedExpression],
@ -5410,6 +5462,7 @@ declare class JavascriptParser extends Parser {
isVariableDefined(name?: any): boolean;
getVariableInfo(name: string): ExportedVariableInfo;
setVariable(name: string, variableInfo: ExportedVariableInfo): void;
evaluatedVariable(tagInfo?: any): VariableInfo;
parseCommentOptions(
range?: any
): { options: null; errors: null } | { options: object; errors: unknown[] };
@ -5490,6 +5543,26 @@ declare interface JavascriptParserOptions {
*/
commonjsMagicComments?: boolean;
/**
* Enable/disable parsing "import { createRequire } from "module"" and evaluating createRequire().
*/
createRequire?: string | boolean;
/**
* Specifies global mode for dynamic import.
*/
dynamicImportMode?: "weak" | "eager" | "lazy" | "lazy-once";
/**
* Specifies global prefetch for dynamic import.
*/
dynamicImportPrefetch?: number | boolean;
/**
* Specifies global preload for dynamic import.
*/
dynamicImportPreload?: number | boolean;
/**
* Specifies the behavior of invalid export names in "import ... from ..." and "export ... from ...".
*/
@ -9544,6 +9617,7 @@ declare interface ResolveOptionsTypes {
alias: AliasOption[];
fallback: AliasOption[];
aliasFields: Set<string | string[]>;
extensionAlias: ExtensionAliasOption[];
cachePredicate: (arg0: ResolveRequest) => boolean;
cacheWithContext: boolean;
@ -9642,6 +9716,11 @@ declare interface ResolveOptionsWebpackOptions {
*/
exportsFields?: string[];
/**
* An object which maps extension to extension aliases.
*/
extensionAlias?: { [index: string]: string | string[] };
/**
* Extensions added to the request when trying to find the file.
*/
@ -11854,6 +11933,11 @@ declare interface UserResolveOptions {
*/
fallback?: AliasOption[] | AliasOptions;
/**
* An object which maps extension to extension aliases
*/
extensionAlias?: ExtensionAliasOptions;
/**
* A list of alias fields in description files
*/
@ -12691,7 +12775,12 @@ declare namespace exports {
) => void;
}
export namespace dependencies {
export { ModuleDependency, ConstDependency, NullDependency };
export {
ModuleDependency,
HarmonyImportDependency,
ConstDependency,
NullDependency
};
}
export namespace ids {
export {
@ -13063,6 +13152,7 @@ declare namespace exports {
Asset,
AssetInfo,
EntryOptions,
PathData,
AssetEmittedInfo,
MultiStats,
ParserState,

View File

@ -1230,10 +1230,10 @@ acorn@^7.1.1, acorn@^7.4.0:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
acorn@^8.2.4, acorn@^8.4.1:
version "8.7.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf"
integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==
acorn@^8.2.4, acorn@^8.7.1:
version "8.7.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30"
integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==
agent-base@6:
version "6.0.2"
@ -2259,10 +2259,10 @@ enhanced-resolve@^4.0.0:
memory-fs "^0.5.0"
tapable "^1.0.0"
enhanced-resolve@^5.9.3:
version "5.9.3"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz#44a342c012cbc473254af5cc6ae20ebd0aae5d88"
integrity sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==
enhanced-resolve@^5.10.0:
version "5.10.0"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz#0dc579c3bb2a1032e357ac45b8f3a6f3ad4fb1e6"
integrity sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==
dependencies:
graceful-fs "^4.2.4"
tapable "^2.2.0"
@ -6082,10 +6082,10 @@ wast-loader@^1.11.0:
dependencies:
wabt "1.0.0-nightly.20180421"
watchpack@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.3.1.tgz#4200d9447b401156eeca7767ee610f8809bc9d25"
integrity sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==
watchpack@^2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d"
integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==
dependencies:
glob-to-regexp "^0.4.1"
graceful-fs "^4.1.2"