mirror of https://github.com/webpack/webpack.git
Merge branch 'main' into feature-14072
# Conflicts: # lib/DependencyTemplate.js # lib/javascript/JavascriptGenerator.js # schemas/WebpackOptions.check.js # types.d.ts
This commit is contained in:
commit
d6d6fb584d
|
|
@ -3,4 +3,5 @@ test/statsCases/** eol=lf
|
|||
examples/* eol=lf
|
||||
bin/* eol=lf
|
||||
*.svg eol=lf
|
||||
*.css eol=lf
|
||||
**/*webpack.lock.data/** -text
|
||||
|
|
|
|||
74
.travis.yml
74
.travis.yml
|
|
@ -1,74 +0,0 @@
|
|||
dist: trusty
|
||||
language: node_js
|
||||
|
||||
branches:
|
||||
only:
|
||||
- webpack-4
|
||||
- main
|
||||
- next
|
||||
- dev-1
|
||||
|
||||
cache:
|
||||
yarn: true
|
||||
directories:
|
||||
- ".jest-cache"
|
||||
- ".eslintcache"
|
||||
|
||||
stages:
|
||||
- basic
|
||||
- advanced
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
node_js: "12"
|
||||
env: NO_WATCH_TESTS=1 JEST="--maxWorkers=2 --cacheDirectory .jest-cache" JOB_PART=basic
|
||||
stage: basic
|
||||
- os: linux
|
||||
node_js: "12"
|
||||
env: NO_WATCH_TESTS=1 JEST="--maxWorkers=2 --cacheDirectory .jest-cache" JOB_PART=lintunit
|
||||
stage: advanced
|
||||
- os: linux
|
||||
node_js: "12"
|
||||
env: NO_WATCH_TESTS=1 JEST="--maxWorkers=2 --cacheDirectory .jest-cache" JOB_PART=integration
|
||||
stage: advanced
|
||||
- os: linux
|
||||
node_js: "12"
|
||||
env: NO_WATCH_TESTS=1 ALTERNATIVE_SORT=1 JEST="--maxWorkers=2 --cacheDirectory .jest-cache" JOB_PART=integration
|
||||
stage: advanced
|
||||
- os: linux
|
||||
node_js: "10"
|
||||
env:
|
||||
- NODEJS_VERSION=v15.0.0-nightly2020082003293aa3a1
|
||||
- YARN_EXTRA_ARGS="--ignore-engines"
|
||||
- NO_WATCH_TESTS=1
|
||||
- JEST="--maxWorkers=2 --cacheDirectory .jest-cache"
|
||||
- JOB_PART=integration
|
||||
stage: advanced
|
||||
fast_finish: true
|
||||
|
||||
before_install:
|
||||
- |
|
||||
if [ "$NODEJS_VERSION" != "" ];
|
||||
then
|
||||
mkdir /opt/node
|
||||
curl --silent "https://nodejs.org/download/nightly/$NODEJS_VERSION/node-$NODEJS_VERSION-linux-x64.tar.gz" | tar -zxf - --directory /opt/node
|
||||
export PATH="/opt/node/node-$NODEJS_VERSION-linux-x64/bin:$PATH"
|
||||
node --version
|
||||
fi
|
||||
|
||||
install:
|
||||
- yarn --frozen-lockfile $YARN_EXTRA_ARGS
|
||||
- yarn link --frozen-lockfile $YARN_EXTRA_ARGS || true
|
||||
- yarn link webpack --frozen-lockfile $YARN_EXTRA_ARGS
|
||||
|
||||
script: yarn travis:$JOB_PART
|
||||
|
||||
after_success:
|
||||
- cat ./coverage/lcov.info | node_modules/.bin/coveralls --verbose
|
||||
- bash <(curl -s https://codecov.io/bash) -F $JOB_PART -X gcov
|
||||
- rm -f .jest-cache/haste-map* .jest-cache/perf-cache*
|
||||
|
||||
notifications:
|
||||
slack:
|
||||
secure: JduSdKWwbnLCwo7Z4E59SGE+Uw832UwnXzQiKEpg1BV45MYDPRiGltly1tRHmPh9OGjvGx3XSkC2tNGOBLtL4UL2SCkf012x0t7jDutKRfcv/njynl8jk8l+UhPmaWiHXDQAgGiiKdL4RfzPLW3HeVHCOWm0LKMzcarTa8tw+rE=
|
||||
|
|
@ -687,7 +687,7 @@ src="https://static.monei.net/monei-logo.svg" height="30" alt="MONEI"></a>
|
|||
|
||||
- [@google](https://github.com/google) for [Google Web Toolkit (GWT)](http://www.gwtproject.org/), which aims to compile Java to JavaScript. It features a similar [Code Splitting](http://www.gwtproject.org/doc/latest/DevGuideCodeSplitting.html) as webpack.
|
||||
- [@medikoo](https://github.com/medikoo) for [modules-webmake](https://github.com/medikoo/modules-webmake), which is a similar project. webpack was born because I wanted Code Splitting for modules-webmake. Interestingly the [Code Splitting issue is still open](https://github.com/medikoo/modules-webmake/issues/7) (thanks also to @Phoscur for the discussion).
|
||||
- [@substack](https://github.com/substack) for [browserify](http://browserify.org/), which is a similar project and source for many ideas.
|
||||
- [@substack](https://github.com/substack) for [browserify](https://browserify.org/), which is a similar project and source for many ideas.
|
||||
- [@jrburke](https://github.com/jrburke) for [require.js](https://requirejs.org/), which is a similar project and source for many ideas.
|
||||
- [@defunctzombie](https://github.com/defunctzombie) for the [browser-field spec](https://github.com/defunctzombie/package-browser-field-spec), which makes modules available for node.js, browserify and webpack.
|
||||
- Every early webpack user, which contributed to webpack by writing issues or PRs. You influenced the direction...
|
||||
|
|
|
|||
497
cspell.json
497
cspell.json
|
|
@ -1,241 +1,308 @@
|
|||
{
|
||||
"version": "0.1",
|
||||
"version": "0.2",
|
||||
"language": "en",
|
||||
"words": [
|
||||
"webpack",
|
||||
"webpack's",
|
||||
"endregion",
|
||||
"entrypoint",
|
||||
"entrypoints",
|
||||
"splitted",
|
||||
"dedupe",
|
||||
"deduplication",
|
||||
"deduplicating",
|
||||
"unoptimized",
|
||||
"prefetch",
|
||||
"prefetching",
|
||||
"prefetched",
|
||||
"preload",
|
||||
"preloading",
|
||||
"preloaded",
|
||||
"gzipping",
|
||||
"brotli",
|
||||
"submodule",
|
||||
"submodules",
|
||||
"typeof",
|
||||
"devtool",
|
||||
"wasi",
|
||||
"wasm",
|
||||
"webassembly",
|
||||
"IIFE",
|
||||
"IIFE's",
|
||||
"bigint",
|
||||
"unexception",
|
||||
"etag",
|
||||
"builtins",
|
||||
"uncacheable",
|
||||
"cacheable",
|
||||
"mergeable",
|
||||
"devtools",
|
||||
"transpiled",
|
||||
"mixins",
|
||||
"subdir",
|
||||
"errored",
|
||||
"eval",
|
||||
"multiplicator",
|
||||
"finalizer",
|
||||
"promisify",
|
||||
"absolutify",
|
||||
"camelcase",
|
||||
"filebase",
|
||||
"moduleid",
|
||||
"modulehash",
|
||||
"chunkfilename",
|
||||
"chunkname",
|
||||
"chunkhash",
|
||||
"fullhash",
|
||||
"contenthash",
|
||||
"hashable",
|
||||
"hotupdatechunk",
|
||||
"middleware",
|
||||
"middlewares",
|
||||
"serializer",
|
||||
"serializers",
|
||||
"deserialization",
|
||||
"referenceable",
|
||||
"polyfilled",
|
||||
"transpiling",
|
||||
"transpile",
|
||||
"transpiles",
|
||||
"snapshotting",
|
||||
"sourcemap",
|
||||
"nosources",
|
||||
"filepath",
|
||||
"subpath",
|
||||
"pathinfo",
|
||||
"undelayed",
|
||||
"microtask",
|
||||
"microtasks",
|
||||
"deopt",
|
||||
"deopts",
|
||||
"sandboxed",
|
||||
"mangleable",
|
||||
"passthrough",
|
||||
"prioritise",
|
||||
"booleanized",
|
||||
"serializables",
|
||||
"unreviewed",
|
||||
"unshifted",
|
||||
"nonrecursive",
|
||||
"symlinked",
|
||||
"subfolder",
|
||||
"prettierrc",
|
||||
"templated",
|
||||
"templating",
|
||||
"kibibytes",
|
||||
"mebibytes",
|
||||
"gibibytes",
|
||||
"typechecker",
|
||||
"recurse",
|
||||
"preparsed",
|
||||
"acircular",
|
||||
"amdmodule",
|
||||
"asmjs",
|
||||
"assemblyscript",
|
||||
"asyncloader",
|
||||
"atlaskit",
|
||||
"autocrlf",
|
||||
"lcov",
|
||||
"lcovonly",
|
||||
"gcov",
|
||||
"lintunit",
|
||||
"instanceof",
|
||||
"loglevel",
|
||||
"runtime",
|
||||
"runtimes",
|
||||
"mimetype",
|
||||
"testvalue",
|
||||
"unusedkey",
|
||||
"unusedvalue",
|
||||
"performant",
|
||||
"watchings",
|
||||
"jsons",
|
||||
"exitance",
|
||||
"ident",
|
||||
"idents",
|
||||
"globstar",
|
||||
"inversed",
|
||||
"concated",
|
||||
"RBDT",
|
||||
"opensource",
|
||||
"babeljs",
|
||||
"backport",
|
||||
"backported",
|
||||
"basictest",
|
||||
"bigint",
|
||||
"Biró",
|
||||
"bitfield",
|
||||
"bomfile",
|
||||
"booleanized",
|
||||
"boolish",
|
||||
"brotli",
|
||||
"browserified",
|
||||
"browserslist",
|
||||
"browserslistrc",
|
||||
"Brumme",
|
||||
"bugfix",
|
||||
"bugfixes",
|
||||
"declarators",
|
||||
"rrrlll",
|
||||
"undefine",
|
||||
"finializer",
|
||||
"quasis",
|
||||
"hashs",
|
||||
"functype",
|
||||
"funcindex",
|
||||
"Descr",
|
||||
"valtype",
|
||||
"informations",
|
||||
"reexecuted",
|
||||
"global's",
|
||||
"unsplittable",
|
||||
"builtins",
|
||||
"cacheable",
|
||||
"callme",
|
||||
"camelcase",
|
||||
"chainable",
|
||||
"metacharacters",
|
||||
"Xarray",
|
||||
"Xfactory",
|
||||
"Xmodule",
|
||||
"Xexports",
|
||||
"moji",
|
||||
"bitfield",
|
||||
"precompute",
|
||||
"toplevel",
|
||||
"modulos",
|
||||
"untaint",
|
||||
"ufeff",
|
||||
"timestamping",
|
||||
"loadername",
|
||||
"laof",
|
||||
"chunkfilename",
|
||||
"chunkhash",
|
||||
"chunkname",
|
||||
"cmodule",
|
||||
"codecov",
|
||||
"cofounder",
|
||||
"hashchange",
|
||||
"popstate",
|
||||
"hotpink",
|
||||
"navigations",
|
||||
"Collet's",
|
||||
"compat",
|
||||
"noimport",
|
||||
"tmpl",
|
||||
"concated",
|
||||
"contenthash",
|
||||
"contextifies",
|
||||
"crossorigin",
|
||||
"csvg",
|
||||
"repo",
|
||||
"repos",
|
||||
"triaging",
|
||||
"valign",
|
||||
"returnfalse",
|
||||
"return'development",
|
||||
"datastructures",
|
||||
"prewalking",
|
||||
"overridables",
|
||||
"overridable",
|
||||
"cujojs",
|
||||
"Dani",
|
||||
"darkblue",
|
||||
"darkgreen",
|
||||
"darkred",
|
||||
"eqeqeq",
|
||||
"boolish",
|
||||
"analysing",
|
||||
"etags",
|
||||
"datastructures",
|
||||
"declarators",
|
||||
"dedupe",
|
||||
"deduplicating",
|
||||
"deduplication",
|
||||
"defunctzombie",
|
||||
"deopt",
|
||||
"deopts",
|
||||
"dependabot",
|
||||
"Descr",
|
||||
"deserialization",
|
||||
"destructure",
|
||||
"onconnect",
|
||||
"nwjs",
|
||||
"redeclaration",
|
||||
"kaios",
|
||||
"parallelism",
|
||||
"gitattributes",
|
||||
"hashbang",
|
||||
|
||||
"webassemblyjs",
|
||||
"assemblyscript",
|
||||
"fsevents",
|
||||
"watchpack",
|
||||
"tapable",
|
||||
"junit",
|
||||
"memfs",
|
||||
"rimraf",
|
||||
"devtool",
|
||||
"devtools",
|
||||
"donotcallme",
|
||||
"endregion",
|
||||
"entrypoint",
|
||||
"entrypoints",
|
||||
"Eoksni",
|
||||
"eqeqeq",
|
||||
"errored",
|
||||
"esmodule",
|
||||
"estree",
|
||||
"posthtml",
|
||||
"etag",
|
||||
"etags",
|
||||
"eval",
|
||||
"Ewald",
|
||||
"exitance",
|
||||
"filebase",
|
||||
"fileoverview",
|
||||
"filepath",
|
||||
"finalizer",
|
||||
"finializer",
|
||||
"fsevents",
|
||||
"fullhash",
|
||||
"funcindex",
|
||||
"functype",
|
||||
"gcov",
|
||||
"gibibytes",
|
||||
"gitattributes",
|
||||
"gitter",
|
||||
"global's",
|
||||
"globstar",
|
||||
"gzipping",
|
||||
"hashable",
|
||||
"hashbang",
|
||||
"hashchange",
|
||||
"hashs",
|
||||
"hotpink",
|
||||
"hotupdatechunk",
|
||||
"ident",
|
||||
"idents",
|
||||
"IIFE's",
|
||||
"IIFE",
|
||||
"informations",
|
||||
"instanceof",
|
||||
"inversed",
|
||||
"jhnns",
|
||||
"jrburke",
|
||||
"jsfile",
|
||||
"jsons",
|
||||
"junit",
|
||||
"Junya",
|
||||
"kaios",
|
||||
"Kees",
|
||||
"kibibytes",
|
||||
"Kluskens",
|
||||
"Koppers",
|
||||
"laof",
|
||||
"Larkin",
|
||||
"lcov",
|
||||
"lcovonly",
|
||||
"lintunit",
|
||||
"loadername",
|
||||
"loglevel",
|
||||
"longnameforexport",
|
||||
"mangleable",
|
||||
"MCEP",
|
||||
"mebibytes",
|
||||
"medikoo",
|
||||
"membertest",
|
||||
"memfs",
|
||||
"mergeable",
|
||||
"metacharacters",
|
||||
"microtask",
|
||||
"microtasks",
|
||||
"middleware",
|
||||
"middlewares",
|
||||
"mimetype",
|
||||
"mixins",
|
||||
"modulehash",
|
||||
"moduleid",
|
||||
"modulos",
|
||||
"moji",
|
||||
"MONEI",
|
||||
"mult",
|
||||
"multiplicator",
|
||||
"mylibrary",
|
||||
"mynamespace",
|
||||
"navigations",
|
||||
"nmodule",
|
||||
"noimport",
|
||||
"nonexistentfile",
|
||||
"nonrecursive",
|
||||
"nosource",
|
||||
"nosources",
|
||||
"nwjs",
|
||||
"onconnect",
|
||||
"opencollective",
|
||||
"opensource",
|
||||
"opuuus",
|
||||
"overridable",
|
||||
"overridables",
|
||||
"parallelism",
|
||||
"passthrough",
|
||||
"pathinfo",
|
||||
"performant",
|
||||
"Phoscur",
|
||||
"pmodule",
|
||||
"pnpm",
|
||||
"polyfilled",
|
||||
"popstate",
|
||||
"posthtml",
|
||||
"precompute",
|
||||
"prefetch",
|
||||
"prefetched",
|
||||
"prefetching",
|
||||
"preload",
|
||||
"preloaded",
|
||||
"preloading",
|
||||
"preparsed",
|
||||
"prettierrc",
|
||||
"prewalking",
|
||||
"prioritise",
|
||||
"promisify",
|
||||
"quasis",
|
||||
"queryloader",
|
||||
"querystrings",
|
||||
"RBDT",
|
||||
"recurse",
|
||||
"redeclaration",
|
||||
"reexecuted",
|
||||
"referenceable",
|
||||
"referencer",
|
||||
"repo",
|
||||
"repos",
|
||||
"return'development",
|
||||
"returnfalse",
|
||||
"revparse",
|
||||
"rimraf",
|
||||
"Rivest",
|
||||
"rrrlll",
|
||||
"runtime",
|
||||
"runtimes",
|
||||
"samsunginternet",
|
||||
"sandboxed",
|
||||
"serializables",
|
||||
"serializer",
|
||||
"serializers",
|
||||
"shama",
|
||||
"skypack",
|
||||
"snapshotting",
|
||||
"sokra",
|
||||
"somepackage",
|
||||
"somepath",
|
||||
"sourcemap",
|
||||
"sourcemapped",
|
||||
"splitted",
|
||||
"stylesheet",
|
||||
"subdir",
|
||||
"subfolder",
|
||||
"submodule",
|
||||
"submodules",
|
||||
"subpath",
|
||||
"substack",
|
||||
"symlinked",
|
||||
"syncloader",
|
||||
"systemjs",
|
||||
"tapable",
|
||||
"templated",
|
||||
"templating",
|
||||
"testcase",
|
||||
"testlink",
|
||||
"testloader",
|
||||
"testvalue",
|
||||
"timestamping",
|
||||
"tmpl",
|
||||
"toplevel",
|
||||
"traceur",
|
||||
"atlaskit",
|
||||
"transpile",
|
||||
"transpiled",
|
||||
"transpiles",
|
||||
"transpiling",
|
||||
"triaging",
|
||||
"Tshs",
|
||||
"typechecker",
|
||||
"typeof",
|
||||
"ufeff",
|
||||
"uncacheable",
|
||||
"undefine",
|
||||
"undelayed",
|
||||
"unexception",
|
||||
"unoptimized",
|
||||
"unreviewed",
|
||||
"unshifted",
|
||||
"unsplittable",
|
||||
"untaint",
|
||||
"unusedkey",
|
||||
"unusedvalue",
|
||||
"url's",
|
||||
"valign",
|
||||
"valtype",
|
||||
"wasi",
|
||||
"wasm",
|
||||
"watchings",
|
||||
"watchpack",
|
||||
"webassembly",
|
||||
"webassemblyjs",
|
||||
"webmake",
|
||||
"webpack's",
|
||||
"webpack",
|
||||
"Xarray",
|
||||
"Xexports",
|
||||
"Xfactory",
|
||||
"Xmodule",
|
||||
"xxhash",
|
||||
"xxhashjs",
|
||||
"systemjs",
|
||||
"skypack",
|
||||
|
||||
"sokra",
|
||||
"Koppers",
|
||||
"Junya",
|
||||
"Eoksni",
|
||||
"Ewald",
|
||||
"Larkin",
|
||||
"Kees",
|
||||
"Kluskens",
|
||||
"Phoscur",
|
||||
"defunctzombie",
|
||||
"shama",
|
||||
"jhnns",
|
||||
"substack",
|
||||
"MONEI",
|
||||
"medikoo",
|
||||
"webmake",
|
||||
"jrburke",
|
||||
"gitter",
|
||||
"codecov",
|
||||
"opencollective",
|
||||
"dependabot",
|
||||
"browserslist",
|
||||
"samsunginternet",
|
||||
"pnpm"
|
||||
"Yann"
|
||||
],
|
||||
"ignoreRegExpList": [
|
||||
"/Author.+/",
|
||||
"/data:.*/",
|
||||
"/\"mappings\":\".+\"/",
|
||||
"/toMatchInlineSnapshot\\(\\s*`[^`]*`\\s*\\)/"
|
||||
],
|
||||
"ignoreRegExpList": ["/Author.+/", "/data:.*/", "/\"mappings\":\".+\"/"],
|
||||
"ignorePaths": [
|
||||
"**/dist/**",
|
||||
"examples/**/README.md",
|
||||
"**/webpack.lock.data/**"
|
||||
"**/webpack.lock.data/**",
|
||||
"package.json",
|
||||
"yarn.lock",
|
||||
"types.d.ts",
|
||||
"**/**/*.snap",
|
||||
"test/cases/json/weird-properties/globals.json",
|
||||
"**/*.svg",
|
||||
"*.log",
|
||||
"**/*.wasm",
|
||||
"coverage/**",
|
||||
"test/**/module.js",
|
||||
"test/js/**",
|
||||
"test/cases/**",
|
||||
"test/configCases/**",
|
||||
"test/statsCases/**",
|
||||
"test/fixtures/**"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ declare module "@webassemblyjs/ast" {
|
|||
raw?: string
|
||||
): FloatLiteral;
|
||||
export function global(globalType: string, nodes: Node[]): Global;
|
||||
export function identifier(indentifier: string): Identifier;
|
||||
export function identifier(identifier: string): Identifier;
|
||||
export function funcParam(valType: string, id: Identifier): FuncParam;
|
||||
export function instruction(inst: string, args?: Node[]): Instruction;
|
||||
export function callInstruction(funcIndex: Index): CallInstruction;
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ export type LibraryExport = string[] | string;
|
|||
*/
|
||||
export type LibraryName = string[] | string | LibraryCustomUmdObject;
|
||||
/**
|
||||
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
|
||||
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'commonjs-static', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
|
||||
*/
|
||||
export type LibraryType =
|
||||
| (
|
||||
|
|
@ -110,6 +110,7 @@ export type LibraryType =
|
|||
| "commonjs"
|
||||
| "commonjs2"
|
||||
| "commonjs-module"
|
||||
| "commonjs-static"
|
||||
| "amd"
|
||||
| "amd-require"
|
||||
| "umd"
|
||||
|
|
@ -189,6 +190,7 @@ export type ExternalsType =
|
|||
| "commonjs"
|
||||
| "commonjs2"
|
||||
| "commonjs-module"
|
||||
| "commonjs-static"
|
||||
| "amd"
|
||||
| "amd-require"
|
||||
| "umd"
|
||||
|
|
@ -443,6 +445,14 @@ export type CompareBeforeEmit = boolean;
|
|||
* This option enables cross-origin loading of chunks.
|
||||
*/
|
||||
export type CrossOriginLoading = false | "anonymous" | "use-credentials";
|
||||
/**
|
||||
* Specifies the filename template of non-initial output css files on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
|
||||
*/
|
||||
export type CssChunkFilename = FilenameTemplate;
|
||||
/**
|
||||
* Specifies the filename template of output css files on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
|
||||
*/
|
||||
export type CssFilename = FilenameTemplate;
|
||||
/**
|
||||
* Similar to `output.devtoolModuleFilenameTemplate`, but used in the case of duplicate module identifiers.
|
||||
*/
|
||||
|
|
@ -671,7 +681,7 @@ export type AssetGeneratorDataUrl =
|
|||
| AssetGeneratorDataUrlOptions
|
||||
| AssetGeneratorDataUrlFunction;
|
||||
/**
|
||||
* Function that executes for module and should return an DataUrl string.
|
||||
* Function that executes for module and should return an DataUrl string. It can have a string as 'ident' property which contributes to the module hash.
|
||||
*/
|
||||
export type AssetGeneratorDataUrlFunction = (
|
||||
source: string | Buffer,
|
||||
|
|
@ -682,6 +692,15 @@ export type AssetGeneratorDataUrlFunction = (
|
|||
*/
|
||||
export type AssetGeneratorOptions = AssetInlineGeneratorOptions &
|
||||
AssetResourceGeneratorOptions;
|
||||
/**
|
||||
* Emit the asset in the specified folder relative to 'output.path'. This should only be needed when custom 'publicPath' is specified to match the folder structure there.
|
||||
*/
|
||||
export type AssetModuleOutputPath =
|
||||
| string
|
||||
| ((
|
||||
pathData: import("../lib/Compilation").PathData,
|
||||
assetInfo?: import("../lib/Compilation").AssetInfo
|
||||
) => string);
|
||||
/**
|
||||
* Function that executes for module and should return whenever asset should be inlined as DataUrl.
|
||||
*/
|
||||
|
|
@ -1023,6 +1042,10 @@ export interface EntryDescription {
|
|||
* Enable/disable creating async chunks that are loaded on demand.
|
||||
*/
|
||||
asyncChunks?: boolean;
|
||||
/**
|
||||
* Base uri for this entry.
|
||||
*/
|
||||
baseUri?: string;
|
||||
/**
|
||||
* The method of loading chunks (methods included by default are 'jsonp' (web), 'import' (ESM), 'importScripts' (WebWorker), 'require' (sync node.js), 'async-node' (async node.js), but others might be added by plugins).
|
||||
*/
|
||||
|
|
@ -1077,7 +1100,7 @@ export interface LibraryOptions {
|
|||
*/
|
||||
name?: LibraryName;
|
||||
/**
|
||||
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
|
||||
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'commonjs-static', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
|
||||
*/
|
||||
type: LibraryType;
|
||||
/**
|
||||
|
|
@ -1982,6 +2005,14 @@ export interface Output {
|
|||
* This option enables cross-origin loading of chunks.
|
||||
*/
|
||||
crossOriginLoading?: CrossOriginLoading;
|
||||
/**
|
||||
* Specifies the filename template of non-initial output css files on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
|
||||
*/
|
||||
cssChunkFilename?: CssChunkFilename;
|
||||
/**
|
||||
* Specifies the filename template of output css files on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
|
||||
*/
|
||||
cssFilename?: CssFilename;
|
||||
/**
|
||||
* Similar to `output.devtoolModuleFilenameTemplate`, but used in the case of duplicate module identifiers.
|
||||
*/
|
||||
|
|
@ -2067,7 +2098,7 @@ export interface Output {
|
|||
*/
|
||||
libraryExport?: LibraryExport;
|
||||
/**
|
||||
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
|
||||
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'commonjs-static', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
|
||||
*/
|
||||
libraryTarget?: LibraryType;
|
||||
/**
|
||||
|
|
@ -2693,11 +2724,32 @@ export interface AssetResourceGeneratorOptions {
|
|||
* Specifies the filename template of output files on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
|
||||
*/
|
||||
filename?: FilenameTemplate;
|
||||
/**
|
||||
* Emit the asset in the specified folder relative to 'output.path'. This should only be needed when custom 'publicPath' is specified to match the folder structure there.
|
||||
*/
|
||||
outputPath?: AssetModuleOutputPath;
|
||||
/**
|
||||
* The 'publicPath' specifies the public URL address of the output files when referenced in a browser.
|
||||
*/
|
||||
publicPath?: RawPublicPath;
|
||||
}
|
||||
/**
|
||||
* Options for css handling.
|
||||
*/
|
||||
export interface CssExperimentOptions {
|
||||
/**
|
||||
* Avoid generating and loading a stylesheet and only embed exports from css into output javascript files.
|
||||
*/
|
||||
exportsOnly?: boolean;
|
||||
}
|
||||
/**
|
||||
* Generator options for css modules.
|
||||
*/
|
||||
export interface CssGeneratorOptions {}
|
||||
/**
|
||||
* Parser options for css modules.
|
||||
*/
|
||||
export interface CssParserOptions {}
|
||||
/**
|
||||
* No generator options are supported for this module type.
|
||||
*/
|
||||
|
|
@ -2714,6 +2766,10 @@ export interface EntryDescriptionNormalized {
|
|||
* Enable/disable creating async chunks that are loaded on demand.
|
||||
*/
|
||||
asyncChunks?: boolean;
|
||||
/**
|
||||
* Base uri for this entry.
|
||||
*/
|
||||
baseUri?: string;
|
||||
/**
|
||||
* The method of loading chunks (methods included by default are 'jsonp' (web), 'import' (ESM), 'importScripts' (WebWorker), 'require' (sync node.js), 'async-node' (async node.js), but others might be added by plugins).
|
||||
*/
|
||||
|
|
@ -2850,6 +2906,10 @@ export interface HttpUriOptions {
|
|||
* Location of the lockfile.
|
||||
*/
|
||||
lockfileLocation?: string;
|
||||
/**
|
||||
* Proxy configuration, which can be used to specify a proxy server to use for HTTP requests.
|
||||
*/
|
||||
proxy?: string;
|
||||
/**
|
||||
* When set, resources of existing lockfile entries will be fetched and entries will be upgraded when resource content has changed.
|
||||
*/
|
||||
|
|
@ -2907,6 +2967,14 @@ export interface JavascriptParserOptions {
|
|||
* Specifies the behavior of invalid export names in "import ... from ...".
|
||||
*/
|
||||
importExportsPresence?: "error" | "warn" | "auto" | false;
|
||||
/**
|
||||
* Enable/disable evaluating import.meta.
|
||||
*/
|
||||
importMeta?: boolean;
|
||||
/**
|
||||
* Enable/disable evaluating import.meta.webpackContext.
|
||||
*/
|
||||
importMetaContext?: boolean;
|
||||
/**
|
||||
* Include polyfills or mocks for various node stuff.
|
||||
*/
|
||||
|
|
@ -3118,6 +3186,14 @@ export interface OutputNormalized {
|
|||
* This option enables cross-origin loading of chunks.
|
||||
*/
|
||||
crossOriginLoading?: CrossOriginLoading;
|
||||
/**
|
||||
* Specifies the filename template of non-initial output css files on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
|
||||
*/
|
||||
cssChunkFilename?: CssChunkFilename;
|
||||
/**
|
||||
* Specifies the filename template of output css files on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
|
||||
*/
|
||||
cssFilename?: CssFilename;
|
||||
/**
|
||||
* Similar to `output.devtoolModuleFilenameTemplate`, but used in the case of duplicate module identifiers.
|
||||
*/
|
||||
|
|
@ -3408,6 +3484,10 @@ export interface ExperimentsExtra {
|
|||
* Build http(s): urls using a lockfile and resource content cache.
|
||||
*/
|
||||
buildHttp?: HttpUriAllowedUris | HttpUriOptions;
|
||||
/**
|
||||
* Enable css support.
|
||||
*/
|
||||
css?: boolean | CssExperimentOptions;
|
||||
/**
|
||||
* Compile entrypoints and import()s only when they are accessed.
|
||||
*/
|
||||
|
|
@ -3421,6 +3501,10 @@ export interface ExperimentsNormalizedExtra {
|
|||
* Build http(s): urls using a lockfile and resource content cache.
|
||||
*/
|
||||
buildHttp?: HttpUriOptions;
|
||||
/**
|
||||
* Enable css support.
|
||||
*/
|
||||
css?: CssExperimentOptions;
|
||||
/**
|
||||
* Compile entrypoints and import()s only when they are accessed.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -38,6 +38,10 @@ export interface BannerPluginOptions {
|
|||
* Exclude all modules matching any of these conditions.
|
||||
*/
|
||||
exclude?: Rules;
|
||||
/**
|
||||
* If true, banner will be placed at the end of the output.
|
||||
*/
|
||||
footer?: boolean;
|
||||
/**
|
||||
* Include all modules matching any of these conditions.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export type LibraryExport = string[] | string;
|
|||
*/
|
||||
export type LibraryName = string[] | string | LibraryCustomUmdObject;
|
||||
/**
|
||||
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
|
||||
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'commonjs-static', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
|
||||
*/
|
||||
export type LibraryType =
|
||||
| (
|
||||
|
|
@ -44,6 +44,7 @@ export type LibraryType =
|
|||
| "commonjs"
|
||||
| "commonjs2"
|
||||
| "commonjs-module"
|
||||
| "commonjs-static"
|
||||
| "amd"
|
||||
| "amd-require"
|
||||
| "umd"
|
||||
|
|
@ -126,7 +127,7 @@ export interface LibraryOptions {
|
|||
*/
|
||||
name?: LibraryName;
|
||||
/**
|
||||
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
|
||||
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'commonjs-static', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
|
||||
*/
|
||||
type: LibraryType;
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ export type ExternalsType =
|
|||
| "commonjs"
|
||||
| "commonjs2"
|
||||
| "commonjs-module"
|
||||
| "commonjs-static"
|
||||
| "amd"
|
||||
| "amd-require"
|
||||
| "umd"
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export type LibraryExport = string[] | string;
|
|||
*/
|
||||
export type LibraryName = string[] | string | LibraryCustomUmdObject;
|
||||
/**
|
||||
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
|
||||
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'commonjs-static', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
|
||||
*/
|
||||
export type LibraryType =
|
||||
| (
|
||||
|
|
@ -44,6 +44,7 @@ export type LibraryType =
|
|||
| "commonjs"
|
||||
| "commonjs2"
|
||||
| "commonjs-module"
|
||||
| "commonjs-static"
|
||||
| "amd"
|
||||
| "amd-require"
|
||||
| "umd"
|
||||
|
|
@ -70,6 +71,7 @@ export type ExternalsType =
|
|||
| "commonjs"
|
||||
| "commonjs2"
|
||||
| "commonjs-module"
|
||||
| "commonjs-static"
|
||||
| "amd"
|
||||
| "amd-require"
|
||||
| "umd"
|
||||
|
|
@ -182,7 +184,7 @@ export interface LibraryOptions {
|
|||
*/
|
||||
name?: LibraryName;
|
||||
/**
|
||||
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
|
||||
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'commonjs-static', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
|
||||
*/
|
||||
type: LibraryType;
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -34,6 +34,10 @@ export interface HttpUriOptions {
|
|||
* Location of the lockfile.
|
||||
*/
|
||||
lockfileLocation?: string;
|
||||
/**
|
||||
* Proxy configuration, which can be used to specify a proxy server to use for HTTP requests.
|
||||
*/
|
||||
proxy?: string;
|
||||
/**
|
||||
* When set, resources of existing lockfile entries will be fetched and entries will be upgraded when resource content has changed.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,536 @@
|
|||
# example.js
|
||||
|
||||
```javascript
|
||||
import "./style.css";
|
||||
import "./style2.css";
|
||||
import { main } from "./style.module.css";
|
||||
import("./lazy-style.css");
|
||||
|
||||
document.getElementsByTagName("main")[0].className = main;
|
||||
```
|
||||
|
||||
# style.css
|
||||
|
||||
```javascript
|
||||
@import "style-imported.css";
|
||||
@import "https://fonts.googleapis.com/css?family=Open+Sans";
|
||||
|
||||
body {
|
||||
background: green;
|
||||
font-family: "Open Sans";
|
||||
}
|
||||
```
|
||||
|
||||
# dist/output.js
|
||||
|
||||
```javascript
|
||||
/******/ (() => { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
/******/ var __webpack_modules__ = ({
|
||||
|
||||
/***/ 3:
|
||||
/*!*************************!*\
|
||||
!*** ./images/file.png ***!
|
||||
\*************************/
|
||||
/*! default exports */
|
||||
/*! exports [not provided] [no usage info] */
|
||||
/*! runtime requirements: module, __webpack_require__.p, __webpack_require__.* */
|
||||
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
||||
|
||||
module.exports = __webpack_require__.p + "89a353e9c515885abd8e.png";
|
||||
|
||||
/***/ })
|
||||
|
||||
/******/ });
|
||||
```
|
||||
|
||||
<details><summary><code>/* webpack runtime code */</code></summary>
|
||||
|
||||
``` js
|
||||
/************************************************************************/
|
||||
/******/ // The module cache
|
||||
/******/ var __webpack_module_cache__ = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/ // Check if module is in cache
|
||||
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
||||
/******/ if (cachedModule !== undefined) {
|
||||
/******/ return cachedModule.exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = __webpack_module_cache__[moduleId] = {
|
||||
/******/ // no module.id needed
|
||||
/******/ // no module.loaded needed
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = __webpack_modules__;
|
||||
/******/
|
||||
/************************************************************************/
|
||||
/******/ /* webpack/runtime/ensure chunk */
|
||||
/******/ (() => {
|
||||
/******/ __webpack_require__.f = {};
|
||||
/******/ // This file contains only the entry chunk.
|
||||
/******/ // The chunk loading function for additional chunks
|
||||
/******/ __webpack_require__.e = (chunkId) => {
|
||||
/******/ return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => {
|
||||
/******/ __webpack_require__.f[key](chunkId, promises);
|
||||
/******/ return promises;
|
||||
/******/ }, []));
|
||||
/******/ };
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/get css chunk filename */
|
||||
/******/ (() => {
|
||||
/******/ // This function allow to reference async chunks
|
||||
/******/ __webpack_require__.k = (chunkId) => {
|
||||
/******/ // return url for filenames based on template
|
||||
/******/ return "" + chunkId + ".output.css";
|
||||
/******/ };
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/get javascript chunk filename */
|
||||
/******/ (() => {
|
||||
/******/ // This function allow to reference async chunks
|
||||
/******/ __webpack_require__.u = (chunkId) => {
|
||||
/******/ // return url for filenames based on template
|
||||
/******/ return "" + chunkId + ".output.js";
|
||||
/******/ };
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
||||
/******/ (() => {
|
||||
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/load script */
|
||||
/******/ (() => {
|
||||
/******/ var inProgress = {};
|
||||
/******/ var dataWebpackPrefix = "app:";
|
||||
/******/ // loadScript function to load a script via script tag
|
||||
/******/ __webpack_require__.l = (url, done, key, chunkId) => {
|
||||
/******/ if(inProgress[url]) { inProgress[url].push(done); return; }
|
||||
/******/ var script, needAttach;
|
||||
/******/ if(key !== undefined) {
|
||||
/******/ var scripts = document.getElementsByTagName("script");
|
||||
/******/ for(var i = 0; i < scripts.length; i++) {
|
||||
/******/ var s = scripts[i];
|
||||
/******/ if(s.getAttribute("src") == url || s.getAttribute("data-webpack") == dataWebpackPrefix + key) { script = s; break; }
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ if(!script) {
|
||||
/******/ needAttach = true;
|
||||
/******/ script = document.createElement('script');
|
||||
/******/
|
||||
/******/ script.charset = 'utf-8';
|
||||
/******/ script.timeout = 120;
|
||||
/******/ if (__webpack_require__.nc) {
|
||||
/******/ script.setAttribute("nonce", __webpack_require__.nc);
|
||||
/******/ }
|
||||
/******/ script.setAttribute("data-webpack", dataWebpackPrefix + key);
|
||||
/******/ script.src = url;
|
||||
/******/ }
|
||||
/******/ inProgress[url] = [done];
|
||||
/******/ var onScriptComplete = (prev, event) => {
|
||||
/******/ // avoid mem leaks in IE.
|
||||
/******/ script.onerror = script.onload = null;
|
||||
/******/ clearTimeout(timeout);
|
||||
/******/ var doneFns = inProgress[url];
|
||||
/******/ delete inProgress[url];
|
||||
/******/ script.parentNode && script.parentNode.removeChild(script);
|
||||
/******/ doneFns && doneFns.forEach((fn) => (fn(event)));
|
||||
/******/ if(prev) return prev(event);
|
||||
/******/ }
|
||||
/******/ ;
|
||||
/******/ var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000);
|
||||
/******/ script.onerror = onScriptComplete.bind(null, script.onerror);
|
||||
/******/ script.onload = onScriptComplete.bind(null, script.onload);
|
||||
/******/ needAttach && document.head.appendChild(script);
|
||||
/******/ };
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/make namespace object */
|
||||
/******/ (() => {
|
||||
/******/ // define __esModule on exports
|
||||
/******/ __webpack_require__.r = (exports) => {
|
||||
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
||||
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
||||
/******/ }
|
||||
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
||||
/******/ };
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/publicPath */
|
||||
/******/ (() => {
|
||||
/******/ __webpack_require__.p = "dist/";
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/css loading */
|
||||
/******/ (() => {
|
||||
/******/ // object to store loaded and loading chunks
|
||||
/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched
|
||||
/******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
|
||||
/******/ var installedChunks = {};
|
||||
/******/
|
||||
/******/ var uniqueName = "app";
|
||||
/******/ var loadCssChunkData = (target, link, chunkId) => {
|
||||
/******/ var data, token = "", token2, exports = {}, exportsWithId = [], exportsWithDashes = [], i = 0, cc = 1;
|
||||
/******/ try { if(!link) link = loadStylesheet(chunkId); data = link.sheet.cssRules; data = data[data.length - 1].style; } catch(e) { data = getComputedStyle(document.head); }
|
||||
/******/ data = data.getPropertyValue("--webpack-" + uniqueName + "-" + chunkId);
|
||||
/******/ if(!data) return [];
|
||||
/******/ for(; cc; i++) {
|
||||
/******/ cc = data.charCodeAt(i);
|
||||
/******/ if(cc == 40) { token2 = token; token = ""; }
|
||||
/******/ else if(cc == 41) { exports[token2.replace(/^_/, "")] = token.replace(/^_/, ""); token = ""; }
|
||||
/******/ else if(cc == 47 || cc == 37) { token = token.replace(/^_/, ""); exports[token] = token; exportsWithId.push(token); if(cc == 37) exportsWithDashes.push(token); token = ""; }
|
||||
/******/ else if(!cc || cc == 44) { token = token.replace(/^_/, ""); exportsWithId.forEach((x) => (exports[x] = uniqueName + "-" + token + "-" + exports[x])); exportsWithDashes.forEach((x) => (exports[x] = "--" + exports[x])); __webpack_require__.r(exports); target[token] = ((exports, module) => {
|
||||
/******/ module.exports = exports;
|
||||
/******/ }).bind(null, exports); token = ""; exports = {}; exportsWithId.length = 0; }
|
||||
/******/ else if(cc == 92) { token += data[++i] }
|
||||
/******/ else { token += data[i]; }
|
||||
/******/ }
|
||||
/******/ installedChunks[chunkId] = 0;
|
||||
/******/
|
||||
/******/ }
|
||||
/******/ var loadingAttribute = "data-webpack-loading";
|
||||
/******/ var loadStylesheet = (chunkId, url, done) => {
|
||||
/******/ var link, needAttach, key = "chunk-" + chunkId;
|
||||
/******/
|
||||
/******/ var links = document.getElementsByTagName("link");
|
||||
/******/ for(var i = 0; i < links.length; i++) {
|
||||
/******/ var l = links[i];
|
||||
/******/ if(l.rel == "stylesheet" && (l.href == url || l.getAttribute("href") == url || l.getAttribute("data-webpack") == uniqueName + ":" + key)) { link = l; break; }
|
||||
/******/ }
|
||||
/******/ if(!done) return link;
|
||||
/******/
|
||||
/******/ if(!link) {
|
||||
/******/ needAttach = true;
|
||||
/******/ link = document.createElement('link');
|
||||
/******/ link.setAttribute("data-webpack", uniqueName + ":" + key);
|
||||
/******/ link.setAttribute(loadingAttribute, 1);
|
||||
/******/ link.rel = "stylesheet";
|
||||
/******/ link.href = url;
|
||||
/******/ }
|
||||
/******/ var onLinkComplete = (prev, event) => {
|
||||
/******/ link.onerror = link.onload = null;
|
||||
/******/ link.removeAttribute(loadingAttribute);
|
||||
/******/ clearTimeout(timeout);
|
||||
/******/ if(event && event.type != "load") link.parentNode.removeChild(link)
|
||||
/******/ done(event);
|
||||
/******/ if(prev) return prev(event);
|
||||
/******/ };
|
||||
/******/ if(link.getAttribute(loadingAttribute)) {
|
||||
/******/ var timeout = setTimeout(onLinkComplete.bind(null, undefined, { type: 'timeout', target: link }), 120000);
|
||||
/******/ link.onerror = onLinkComplete.bind(null, link.onerror);
|
||||
/******/ link.onload = onLinkComplete.bind(null, link.onload);
|
||||
/******/ } else onLinkComplete(undefined, { type: 'load', target: link });
|
||||
/******/
|
||||
/******/ needAttach && document.head.appendChild(link);
|
||||
/******/ return link;
|
||||
/******/ };
|
||||
/******/ loadCssChunkData(__webpack_require__.m, 0, 0);
|
||||
/******/
|
||||
/******/ __webpack_require__.f.css = (chunkId, promises) => {
|
||||
/******/ // css chunk loading
|
||||
/******/ var installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;
|
||||
/******/ if(installedChunkData !== 0) { // 0 means "already installed".
|
||||
/******/
|
||||
/******/ // a Promise means "currently loading".
|
||||
/******/ if(installedChunkData) {
|
||||
/******/ promises.push(installedChunkData[2]);
|
||||
/******/ } else {
|
||||
/******/ if(true) { // all chunks have CSS
|
||||
/******/ // setup Promise in chunk cache
|
||||
/******/ var promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject]));
|
||||
/******/ promises.push(installedChunkData[2] = promise);
|
||||
/******/
|
||||
/******/ // start chunk loading
|
||||
/******/ var url = __webpack_require__.p + __webpack_require__.k(chunkId);
|
||||
/******/ // create error before stack unwound to get useful stacktrace later
|
||||
/******/ var error = new Error();
|
||||
/******/ var loadingEnded = (event) => {
|
||||
/******/ if(__webpack_require__.o(installedChunks, chunkId)) {
|
||||
/******/ installedChunkData = installedChunks[chunkId];
|
||||
/******/ if(installedChunkData !== 0) installedChunks[chunkId] = undefined;
|
||||
/******/ if(installedChunkData) {
|
||||
/******/ if(event.type !== "load") {
|
||||
/******/ var errorType = event && event.type;
|
||||
/******/ var realSrc = event && event.target && event.target.src;
|
||||
/******/ error.message = 'Loading css chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')';
|
||||
/******/ error.name = 'ChunkLoadError';
|
||||
/******/ error.type = errorType;
|
||||
/******/ error.request = realSrc;
|
||||
/******/ installedChunkData[1](error);
|
||||
/******/ } else {
|
||||
/******/ loadCssChunkData(__webpack_require__.m, link, chunkId);
|
||||
/******/ installedChunkData[0]();
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/ var link = loadStylesheet(chunkId, url, loadingEnded);
|
||||
/******/ } else installedChunks[chunkId] = 0;
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // no hmr
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/jsonp chunk loading */
|
||||
/******/ (() => {
|
||||
/******/ // no baseURI
|
||||
/******/
|
||||
/******/ // object to store loaded and loading chunks
|
||||
/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched
|
||||
/******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
|
||||
/******/ var installedChunks = {
|
||||
/******/ 0: 0
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ __webpack_require__.f.j = (chunkId, promises) => {
|
||||
/******/ // JSONP chunk loading for javascript
|
||||
/******/ var installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;
|
||||
/******/ if(installedChunkData !== 0) { // 0 means "already installed".
|
||||
/******/
|
||||
/******/ // a Promise means "currently loading".
|
||||
/******/ if(installedChunkData) {
|
||||
/******/ promises.push(installedChunkData[2]);
|
||||
/******/ } else {
|
||||
/******/ if(0 == chunkId) {
|
||||
/******/ // setup Promise in chunk cache
|
||||
/******/ var promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject]));
|
||||
/******/ promises.push(installedChunkData[2] = promise);
|
||||
/******/
|
||||
/******/ // start chunk loading
|
||||
/******/ var url = __webpack_require__.p + __webpack_require__.u(chunkId);
|
||||
/******/ // create error before stack unwound to get useful stacktrace later
|
||||
/******/ var error = new Error();
|
||||
/******/ var loadingEnded = (event) => {
|
||||
/******/ if(__webpack_require__.o(installedChunks, chunkId)) {
|
||||
/******/ installedChunkData = installedChunks[chunkId];
|
||||
/******/ if(installedChunkData !== 0) installedChunks[chunkId] = undefined;
|
||||
/******/ if(installedChunkData) {
|
||||
/******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type);
|
||||
/******/ var realSrc = event && event.target && event.target.src;
|
||||
/******/ error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')';
|
||||
/******/ error.name = 'ChunkLoadError';
|
||||
/******/ error.type = errorType;
|
||||
/******/ error.request = realSrc;
|
||||
/******/ installedChunkData[1](error);
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/ __webpack_require__.l(url, loadingEnded, "chunk-" + chunkId, chunkId);
|
||||
/******/ } else installedChunks[chunkId] = 0;
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // no prefetching
|
||||
/******/
|
||||
/******/ // no preloaded
|
||||
/******/
|
||||
/******/ // no HMR
|
||||
/******/
|
||||
/******/ // no HMR manifest
|
||||
/******/
|
||||
/******/ // no on chunks loaded
|
||||
/******/
|
||||
/******/ // install a JSONP callback for chunk loading
|
||||
/******/ var webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
|
||||
/******/ var [chunkIds, moreModules, runtime] = data;
|
||||
/******/ // add "moreModules" to the modules object,
|
||||
/******/ // then flag all "chunkIds" as loaded and fire callback
|
||||
/******/ var moduleId, chunkId, i = 0;
|
||||
/******/ if(chunkIds.some((id) => (installedChunks[id] !== 0))) {
|
||||
/******/ for(moduleId in moreModules) {
|
||||
/******/ if(__webpack_require__.o(moreModules, moduleId)) {
|
||||
/******/ __webpack_require__.m[moduleId] = moreModules[moduleId];
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ if(runtime) var result = runtime(__webpack_require__);
|
||||
/******/ }
|
||||
/******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
|
||||
/******/ for(;i < chunkIds.length; i++) {
|
||||
/******/ chunkId = chunkIds[i];
|
||||
/******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
|
||||
/******/ installedChunks[chunkId][0]();
|
||||
/******/ }
|
||||
/******/ installedChunks[chunkId] = 0;
|
||||
/******/ }
|
||||
/******/
|
||||
/******/ }
|
||||
/******/
|
||||
/******/ var chunkLoadingGlobal = self["webpackChunkapp"] = self["webpackChunkapp"] || [];
|
||||
/******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
|
||||
/******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
|
||||
/******/ })();
|
||||
/******/
|
||||
/************************************************************************/
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
``` js
|
||||
var __webpack_exports__ = {};
|
||||
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
|
||||
(() => {
|
||||
/*!********************!*\
|
||||
!*** ./example.js ***!
|
||||
\********************/
|
||||
/*! namespace exports */
|
||||
/*! exports [not provided] [no usage info] */
|
||||
/*! runtime requirements: __webpack_require__, __webpack_require__.r, __webpack_exports__, __webpack_require__.e, __webpack_require__.* */
|
||||
__webpack_require__.r(__webpack_exports__);
|
||||
/* harmony import */ var _style_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./style.css */ 1);
|
||||
/* harmony import */ var _style2_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./style2.css */ 5);
|
||||
/* harmony import */ var _style_module_css__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./style.module.css */ 6);
|
||||
|
||||
|
||||
|
||||
__webpack_require__.e(/*! import() */ 1).then(__webpack_require__.bind(__webpack_require__, /*! ./lazy-style.css */ 7));
|
||||
|
||||
document.getElementsByTagName("main")[0].className = _style_module_css__WEBPACK_IMPORTED_MODULE_2__.main;
|
||||
|
||||
})();
|
||||
|
||||
/******/ })()
|
||||
;
|
||||
```
|
||||
|
||||
# dist/output.css
|
||||
|
||||
```javascript
|
||||
@import url("https://fonts.googleapis.com/css?family=Open+Sans");
|
||||
.img {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
background: url(89a353e9c515885abd8e.png);
|
||||
}
|
||||
|
||||
|
||||
body {
|
||||
background: green;
|
||||
font-family: "Open Sans";
|
||||
}
|
||||
|
||||
body {
|
||||
background: red;
|
||||
}
|
||||
|
||||
:root {
|
||||
--app-6-large: 72px;
|
||||
}
|
||||
|
||||
.app-6-main {
|
||||
font-size: var(--app-6-large);
|
||||
color: darkblue;
|
||||
}
|
||||
|
||||
head{--webpack-app-0:_4,_2,_1,_5,large%main/_6;}
|
||||
```
|
||||
|
||||
## production
|
||||
|
||||
```javascript
|
||||
@import url("https://fonts.googleapis.com/css?family=Open+Sans");
|
||||
.img {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
background: url(89a353e9c515885abd8e.png);
|
||||
}
|
||||
|
||||
|
||||
body {
|
||||
background: green;
|
||||
font-family: "Open Sans";
|
||||
}
|
||||
|
||||
body {
|
||||
background: red;
|
||||
}
|
||||
|
||||
:root {
|
||||
--app-491-b: 72px;
|
||||
}
|
||||
|
||||
.app-491-D {
|
||||
font-size: var(--app-491-b);
|
||||
color: darkblue;
|
||||
}
|
||||
|
||||
head{--webpack-app-179:_548,_431,_258,_268,b%D/_491;}
|
||||
```
|
||||
|
||||
# dist/1.output.css
|
||||
|
||||
```javascript
|
||||
body {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
head{--webpack-app-1:_7;}
|
||||
```
|
||||
|
||||
# Info
|
||||
|
||||
## Unoptimized
|
||||
|
||||
```
|
||||
assets by chunk 16.9 KiB (name: main)
|
||||
asset output.js 16.5 KiB [emitted] (name: main)
|
||||
asset output.css 385 bytes [emitted] (name: main)
|
||||
asset 89a353e9c515885abd8e.png 14.6 KiB [emitted] [immutable] [from: images/file.png] (auxiliary name: main)
|
||||
asset 1.output.css 49 bytes [emitted]
|
||||
Entrypoint main 16.9 KiB (14.6 KiB) = output.js 16.5 KiB output.css 385 bytes 1 auxiliary asset
|
||||
chunk (runtime: main) output.js, output.css (main) 218 bytes (javascript) 335 bytes (css) 14.6 KiB (asset) 42 bytes (css-import) 10 KiB (runtime) [entry] [rendered]
|
||||
> ./example.js main
|
||||
runtime modules 10 KiB 9 modules
|
||||
dependent modules 42 bytes (javascript) 14.6 KiB (asset) 335 bytes (css) 42 bytes (css-import) [dependent] 6 modules
|
||||
./example.js 176 bytes [built] [code generated]
|
||||
[no exports]
|
||||
[used exports unknown]
|
||||
entry ./example.js main
|
||||
chunk (runtime: main) 1.output.css 23 bytes
|
||||
> ./lazy-style.css ./example.js 4:0-26
|
||||
./lazy-style.css 23 bytes [built] [code generated]
|
||||
[no exports]
|
||||
[used exports unknown]
|
||||
import() ./lazy-style.css ./example.js 4:0-26
|
||||
webpack 5.66.0 compiled successfully
|
||||
```
|
||||
|
||||
## Production mode
|
||||
|
||||
```
|
||||
assets by chunk 4.25 KiB (name: main)
|
||||
asset output.js 3.87 KiB [emitted] [minimized] (name: main)
|
||||
asset output.css 385 bytes [emitted] (name: main)
|
||||
asset 89a353e9c515885abd8e.png 14.6 KiB [emitted] [immutable] [from: images/file.png] (auxiliary name: main)
|
||||
asset 159.output.css 53 bytes [emitted]
|
||||
Entrypoint main 4.25 KiB (14.6 KiB) = output.js 3.87 KiB output.css 385 bytes 1 auxiliary asset
|
||||
chunk (runtime: main) 159.output.css 23 bytes
|
||||
> ./lazy-style.css ./example.js 4:0-26
|
||||
./lazy-style.css 23 bytes [built] [code generated]
|
||||
[no exports]
|
||||
import() ./lazy-style.css ./example.js 4:0-26
|
||||
chunk (runtime: main) output.js, output.css (main) 218 bytes (javascript) 335 bytes (css) 14.6 KiB (asset) 42 bytes (css-import) 10 KiB (runtime) [entry] [rendered]
|
||||
> ./example.js main
|
||||
runtime modules 10 KiB 9 modules
|
||||
dependent modules 42 bytes (javascript) 14.6 KiB (asset) 335 bytes (css) 42 bytes (css-import) [dependent] 6 modules
|
||||
./example.js 176 bytes [built] [code generated]
|
||||
[no exports]
|
||||
[no exports used]
|
||||
entry ./example.js main
|
||||
webpack 5.66.0 compiled successfully
|
||||
```
|
||||
|
|
@ -0,0 +1 @@
|
|||
require("../build-common");
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
import "./style.css";
|
||||
import "./style2.css";
|
||||
import { main } from "./style.module.css";
|
||||
import("./lazy-style.css");
|
||||
|
||||
document.getElementsByTagName("main")[0].className = main;
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
|
|
@ -0,0 +1,10 @@
|
|||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="dist/output.css" data-webpack="app:chunk-0" />
|
||||
</head>
|
||||
<body>
|
||||
<main>Hello World</main>
|
||||
<p class="img"></p>
|
||||
<script src="dist/output.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
color: blue;
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
.img {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
background: url("./images/file.png");
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
@import "style-imported.css";
|
||||
@import "https://fonts.googleapis.com/css?family=Open+Sans";
|
||||
|
||||
body {
|
||||
background: green;
|
||||
font-family: "Open Sans";
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
:root {
|
||||
--large: 72px;
|
||||
}
|
||||
|
||||
.main {
|
||||
font-size: var(--large);
|
||||
color: darkblue;
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
background: red;
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
# example.js
|
||||
|
||||
```javascript
|
||||
_{{example.js}}_
|
||||
```
|
||||
|
||||
# style.css
|
||||
|
||||
```javascript
|
||||
_{{style.css}}_
|
||||
```
|
||||
|
||||
# dist/output.js
|
||||
|
||||
```javascript
|
||||
_{{dist/output.js}}_
|
||||
```
|
||||
|
||||
# dist/output.css
|
||||
|
||||
```javascript
|
||||
_{{dist/output.css}}_
|
||||
```
|
||||
|
||||
## production
|
||||
|
||||
```javascript
|
||||
_{{production:dist/output.css}}_
|
||||
```
|
||||
|
||||
# dist/1.output.css
|
||||
|
||||
```javascript
|
||||
_{{dist/1.output.css}}_
|
||||
```
|
||||
|
||||
# Info
|
||||
|
||||
## Unoptimized
|
||||
|
||||
```
|
||||
_{{stdout}}_
|
||||
```
|
||||
|
||||
## Production mode
|
||||
|
||||
```
|
||||
_{{production:stdout}}_
|
||||
```
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
module.exports = {
|
||||
output: {
|
||||
uniqueName: "app"
|
||||
},
|
||||
experiments: {
|
||||
css: true
|
||||
}
|
||||
};
|
||||
|
|
@ -67,7 +67,7 @@
|
|||
<!-- A spinner -->
|
||||
<div class="spinner"></div>
|
||||
|
||||
<!-- This script only contains boostrapping logic -->
|
||||
<!-- This script only contains bootstrapping logic -->
|
||||
<!-- It will load all other scripts if necessary -->
|
||||
<script src="/dist/aaa/app.js" async></script>
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ exports.replaceResults = (template, baseDir, stdout, prefix) => {
|
|||
const regexp = new RegExp("_\\{\\{" + (prefix ? prefix + ":" : "") + "([^:\\}]+)\\}\\}_", "g");
|
||||
|
||||
return template.replace(regexp, function(match) {
|
||||
match = match.substr(3 + (prefix ? prefix.length + 1 : 0), match.length - 6 - (prefix ? prefix.length + 1 : 0));
|
||||
match = match.slice(3 + (prefix ? prefix.length + 1 : 0), -3);
|
||||
if(match === "stdout")
|
||||
return stdout;
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
/*globals __resourceQuery */
|
||||
if (module.hot) {
|
||||
var hotPollInterval = +__resourceQuery.substr(1) || 10 * 60 * 1000;
|
||||
var hotPollInterval = +__resourceQuery.slice(1) || 10 * 60 * 1000;
|
||||
var log = require("./log");
|
||||
|
||||
var checkForUpdate = function checkForUpdate(fromUpdate) {
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ if (module.hot) {
|
|||
});
|
||||
};
|
||||
|
||||
process.on(__resourceQuery.substr(1) || "SIGUSR2", function () {
|
||||
process.on(__resourceQuery.slice(1) || "SIGUSR2", function () {
|
||||
if (module.hot.status() !== "idle") {
|
||||
log(
|
||||
"warning",
|
||||
|
|
|
|||
|
|
@ -201,6 +201,39 @@ class APIPlugin {
|
|||
)
|
||||
.setRange(expr.range)
|
||||
);
|
||||
|
||||
parser.hooks.expression
|
||||
.for("__webpack_module__.id")
|
||||
.tap("APIPlugin", expr => {
|
||||
parser.state.module.buildInfo.moduleConcatenationBailout =
|
||||
"__webpack_module__.id";
|
||||
const dep = new ConstDependency(
|
||||
parser.state.module.moduleArgument + ".id",
|
||||
expr.range,
|
||||
[RuntimeGlobals.moduleId]
|
||||
);
|
||||
dep.loc = expr.loc;
|
||||
parser.state.module.addPresentationalDependency(dep);
|
||||
return true;
|
||||
});
|
||||
|
||||
parser.hooks.expression
|
||||
.for("__webpack_module__")
|
||||
.tap("APIPlugin", expr => {
|
||||
parser.state.module.buildInfo.moduleConcatenationBailout =
|
||||
"__webpack_module__";
|
||||
const dep = new ConstDependency(
|
||||
parser.state.module.moduleArgument,
|
||||
expr.range,
|
||||
[RuntimeGlobals.module]
|
||||
);
|
||||
dep.loc = expr.loc;
|
||||
parser.state.module.addPresentationalDependency(dep);
|
||||
return true;
|
||||
});
|
||||
parser.hooks.evaluateTypeof
|
||||
.for("__webpack_module__")
|
||||
.tap("APIPlugin", evaluateToString("object"));
|
||||
};
|
||||
|
||||
normalModuleFactory.hooks.parser
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ class BannerPlugin {
|
|||
undefined,
|
||||
options
|
||||
);
|
||||
const cache = new WeakMap();
|
||||
|
||||
compiler.hooks.compilation.tap("BannerPlugin", compilation => {
|
||||
compilation.hooks.processAssets.tap(
|
||||
|
|
@ -102,10 +103,17 @@ class BannerPlugin {
|
|||
|
||||
const comment = compilation.getPath(banner, data);
|
||||
|
||||
compilation.updateAsset(
|
||||
file,
|
||||
old => new ConcatSource(comment, "\n", old)
|
||||
);
|
||||
compilation.updateAsset(file, old => {
|
||||
let cached = cache.get(old);
|
||||
if (!cached || cached.comment !== comment) {
|
||||
const source = options.footer
|
||||
? new ConcatSource(old, "\n", comment)
|
||||
: new ConcatSource(comment, "\n", old);
|
||||
cache.set(old, { source, comment });
|
||||
return source;
|
||||
}
|
||||
return cached.source;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ const {
|
|||
/**
|
||||
* @template T
|
||||
* @callback CallbackCache
|
||||
* @param {WebpackError=} err
|
||||
* @param {(WebpackError | null)=} err
|
||||
* @param {T=} result
|
||||
* @returns {void}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { forEachBail } = require("enhanced-resolve");
|
||||
const asyncLib = require("neo-async");
|
||||
const getLazyHashedEtag = require("./cache/getLazyHashedEtag");
|
||||
const mergeEtags = require("./cache/mergeEtags");
|
||||
|
|
@ -18,7 +19,7 @@ const mergeEtags = require("./cache/mergeEtags");
|
|||
/**
|
||||
* @template T
|
||||
* @callback CallbackCache
|
||||
* @param {WebpackError=} err
|
||||
* @param {(WebpackError | null)=} err
|
||||
* @param {T=} result
|
||||
* @returns {void}
|
||||
*/
|
||||
|
|
@ -26,7 +27,7 @@ const mergeEtags = require("./cache/mergeEtags");
|
|||
/**
|
||||
* @template T
|
||||
* @callback CallbackNormalErrorCache
|
||||
* @param {Error=} err
|
||||
* @param {(Error | null)=} err
|
||||
* @param {T=} result
|
||||
* @returns {void}
|
||||
*/
|
||||
|
|
@ -46,15 +47,7 @@ class MultiItemCache {
|
|||
* @returns {void}
|
||||
*/
|
||||
get(callback) {
|
||||
const next = i => {
|
||||
this._items[i].get((err, result) => {
|
||||
if (err) return callback(err);
|
||||
if (result !== undefined) return callback(null, result);
|
||||
if (++i >= this._items.length) return callback();
|
||||
next(i);
|
||||
});
|
||||
};
|
||||
next(0);
|
||||
forEachBail(this._items, (item, callback) => item.get(callback), callback);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -80,6 +80,8 @@ class Chunk {
|
|||
this.preventIntegration = false;
|
||||
/** @type {(string | function(PathData, AssetInfo=): string)?} */
|
||||
this.filenameTemplate = undefined;
|
||||
/** @type {(string | function(PathData, AssetInfo=): string)?} */
|
||||
this.cssFilenameTemplate = undefined;
|
||||
/** @private @type {SortableSet<ChunkGroup>} */
|
||||
this._groups = new SortableSet(undefined, compareChunkGroupsByIndex);
|
||||
/** @type {RuntimeSpec} */
|
||||
|
|
@ -688,7 +690,7 @@ class Chunk {
|
|||
for (const childGroup of group.childrenIterable) {
|
||||
for (const key of Object.keys(childGroup.options)) {
|
||||
if (key.endsWith("Order")) {
|
||||
const name = key.substr(0, key.length - "Order".length);
|
||||
const name = key.slice(0, key.length - "Order".length);
|
||||
let list = lists.get(name);
|
||||
if (list === undefined) {
|
||||
list = [];
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ const compareModuleIterables = compareIterables(compareModulesByIdentifier);
|
|||
|
||||
/** @typedef {(c: Chunk, chunkGraph: ChunkGraph) => boolean} ChunkFilterPredicate */
|
||||
/** @typedef {(m: Module) => boolean} ModuleFilterPredicate */
|
||||
/** @typedef {[Module, Entrypoint | undefined]} EntryModuleWithChunkGroup */
|
||||
|
||||
/**
|
||||
* @typedef {Object} ChunkSizeOptions
|
||||
|
|
@ -1180,8 +1181,6 @@ class ChunkGraph {
|
|||
return cgc.dependentHashModules;
|
||||
}
|
||||
|
||||
/** @typedef {[Module, Entrypoint | undefined]} EntryModuleWithChunkGroup */
|
||||
|
||||
/**
|
||||
* @param {Chunk} chunk the chunk
|
||||
* @returns {Iterable<EntryModuleWithChunkGroup>} iterable of modules (do not modify)
|
||||
|
|
|
|||
|
|
@ -486,7 +486,7 @@ class ChunkGroup {
|
|||
for (const childGroup of this._children) {
|
||||
for (const key of Object.keys(childGroup.options)) {
|
||||
if (key.endsWith("Order")) {
|
||||
const name = key.substr(0, key.length - "Order".length);
|
||||
const name = key.slice(0, key.length - "Order".length);
|
||||
let list = lists.get(name);
|
||||
if (list === undefined) {
|
||||
lists.set(name, (list = []));
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ const processAsyncTree = require("./util/processAsyncTree");
|
|||
/** @typedef {import("./util/fs").StatsCallback} StatsCallback */
|
||||
|
||||
/** @typedef {(function(string):boolean)|RegExp} IgnoreItem */
|
||||
/** @typedef {Map<string, number>} Assets */
|
||||
/** @typedef {function(IgnoreItem): void} AddToIgnoreCallback */
|
||||
|
||||
/**
|
||||
|
|
@ -40,18 +41,32 @@ const validate = createSchemaValidation(
|
|||
baseDataPath: "options"
|
||||
}
|
||||
);
|
||||
const _10sec = 10 * 1000;
|
||||
|
||||
/**
|
||||
* marge assets map 2 into map 1
|
||||
* @param {Assets} as1 assets
|
||||
* @param {Assets} as2 assets
|
||||
* @returns {void}
|
||||
*/
|
||||
const mergeAssets = (as1, as2) => {
|
||||
for (const [key, value1] of as2) {
|
||||
const value2 = as1.get(key);
|
||||
if (!value2 || value1 > value2) as1.set(key, value1);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {OutputFileSystem} fs filesystem
|
||||
* @param {string} outputPath output path
|
||||
* @param {Set<string>} currentAssets filename of the current assets (must not start with .. or ., must only use / as path separator)
|
||||
* @param {function(Error=, Set<string>=): void} callback returns the filenames of the assets that shouldn't be there
|
||||
* @param {Map<string, number>} currentAssets filename of the current assets (must not start with .. or ., must only use / as path separator)
|
||||
* @param {function((Error | null)=, Set<string>=): void} callback returns the filenames of the assets that shouldn't be there
|
||||
* @returns {void}
|
||||
*/
|
||||
const getDiffToFs = (fs, outputPath, currentAssets, callback) => {
|
||||
const directories = new Set();
|
||||
// get directories of assets
|
||||
for (const asset of currentAssets) {
|
||||
for (const [asset] of currentAssets) {
|
||||
directories.add(asset.replace(/(^|\/)[^/]*$/, ""));
|
||||
}
|
||||
// and all parent directories
|
||||
|
|
@ -91,13 +106,15 @@ const getDiffToFs = (fs, outputPath, currentAssets, callback) => {
|
|||
};
|
||||
|
||||
/**
|
||||
* @param {Set<string>} currentAssets assets list
|
||||
* @param {Set<string>} oldAssets old assets list
|
||||
* @param {Assets} currentAssets assets list
|
||||
* @param {Assets} oldAssets old assets list
|
||||
* @returns {Set<string>} diff
|
||||
*/
|
||||
const getDiffToOldAssets = (currentAssets, oldAssets) => {
|
||||
const diff = new Set();
|
||||
for (const asset of oldAssets) {
|
||||
const now = Date.now();
|
||||
for (const [asset, ts] of oldAssets) {
|
||||
if (ts >= now) continue;
|
||||
if (!currentAssets.has(asset)) diff.add(asset);
|
||||
}
|
||||
return diff;
|
||||
|
|
@ -124,7 +141,7 @@ const doStat = (fs, filename, callback) => {
|
|||
* @param {Logger} logger logger
|
||||
* @param {Set<string>} diff filenames of the assets that shouldn't be there
|
||||
* @param {function(string): boolean} isKept check if the entry is ignored
|
||||
* @param {function(Error=): void} callback callback
|
||||
* @param {function(Error=, Assets=): void} callback callback
|
||||
* @returns {void}
|
||||
*/
|
||||
const applyDiff = (fs, outputPath, dry, logger, diff, isKept, callback) => {
|
||||
|
|
@ -137,11 +154,13 @@ const applyDiff = (fs, outputPath, dry, logger, diff, isKept, callback) => {
|
|||
};
|
||||
/** @typedef {{ type: "check" | "unlink" | "rmdir", filename: string, parent: { remaining: number, job: Job } | undefined }} Job */
|
||||
/** @type {Job[]} */
|
||||
const jobs = Array.from(diff, filename => ({
|
||||
const jobs = Array.from(diff.keys(), filename => ({
|
||||
type: "check",
|
||||
filename,
|
||||
parent: undefined
|
||||
}));
|
||||
/** @type {Assets} */
|
||||
const keptAssets = new Map();
|
||||
processAsyncTree(
|
||||
jobs,
|
||||
10,
|
||||
|
|
@ -161,6 +180,7 @@ const applyDiff = (fs, outputPath, dry, logger, diff, isKept, callback) => {
|
|||
switch (type) {
|
||||
case "check":
|
||||
if (isKept(filename)) {
|
||||
keptAssets.set(filename, 0);
|
||||
// do not decrement parent entry as we don't want to delete the parent
|
||||
log(`${filename} will be kept`);
|
||||
return process.nextTick(callback);
|
||||
|
|
@ -247,7 +267,10 @@ const applyDiff = (fs, outputPath, dry, logger, diff, isKept, callback) => {
|
|||
break;
|
||||
}
|
||||
},
|
||||
callback
|
||||
err => {
|
||||
if (err) return callback(err);
|
||||
callback(undefined, keptAssets);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
|
|
@ -302,6 +325,7 @@ class CleanPlugin {
|
|||
// We assume that no external modification happens while the compiler is active
|
||||
// So we can store the old assets and only diff to them to avoid fs access on
|
||||
// incremental builds
|
||||
/** @type {undefined|Assets} */
|
||||
let oldAssets;
|
||||
|
||||
compiler.hooks.emit.tapAsync(
|
||||
|
|
@ -322,7 +346,9 @@ class CleanPlugin {
|
|||
);
|
||||
}
|
||||
|
||||
const currentAssets = new Set();
|
||||
/** @type {Assets} */
|
||||
const currentAssets = new Map();
|
||||
const now = Date.now();
|
||||
for (const asset of Object.keys(compilation.assets)) {
|
||||
if (/^[A-Za-z]:\\|^\/|^\\\\/.test(asset)) continue;
|
||||
let normalizedAsset;
|
||||
|
|
@ -335,7 +361,12 @@ class CleanPlugin {
|
|||
);
|
||||
} while (newNormalizedAsset !== normalizedAsset);
|
||||
if (normalizedAsset.startsWith("../")) continue;
|
||||
currentAssets.add(normalizedAsset);
|
||||
const assetInfo = compilation.assetsInfo.get(asset);
|
||||
if (assetInfo && assetInfo.hotModuleReplacement) {
|
||||
currentAssets.set(normalizedAsset, now + _10sec);
|
||||
} else {
|
||||
currentAssets.set(normalizedAsset, 0);
|
||||
}
|
||||
}
|
||||
|
||||
const outputPath = compilation.getPath(compiler.outputPath, {});
|
||||
|
|
@ -346,19 +377,34 @@ class CleanPlugin {
|
|||
return keepFn(path);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Error=} err err
|
||||
* @param {Set<string>=} diff diff
|
||||
*/
|
||||
const diffCallback = (err, diff) => {
|
||||
if (err) {
|
||||
oldAssets = undefined;
|
||||
return callback(err);
|
||||
}
|
||||
applyDiff(fs, outputPath, dry, logger, diff, isKept, err => {
|
||||
if (err) {
|
||||
oldAssets = undefined;
|
||||
} else {
|
||||
oldAssets = currentAssets;
|
||||
}
|
||||
callback(err);
|
||||
});
|
||||
return;
|
||||
}
|
||||
applyDiff(
|
||||
fs,
|
||||
outputPath,
|
||||
dry,
|
||||
logger,
|
||||
diff,
|
||||
isKept,
|
||||
(err, keptAssets) => {
|
||||
if (err) {
|
||||
oldAssets = undefined;
|
||||
} else {
|
||||
if (oldAssets) mergeAssets(currentAssets, oldAssets);
|
||||
oldAssets = currentAssets;
|
||||
if (keptAssets) mergeAssets(oldAssets, keptAssets);
|
||||
}
|
||||
callback(err);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
if (oldAssets) {
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ const Module = require("./Module");
|
|||
const ModuleDependencyError = require("./ModuleDependencyError");
|
||||
const ModuleDependencyWarning = require("./ModuleDependencyWarning");
|
||||
const ModuleGraph = require("./ModuleGraph");
|
||||
const ModuleHashingError = require("./ModuleHashingError");
|
||||
const ModuleNotFoundError = require("./ModuleNotFoundError");
|
||||
const ModuleProfile = require("./ModuleProfile");
|
||||
const ModuleRestoreError = require("./ModuleRestoreError");
|
||||
|
|
@ -116,34 +117,34 @@ const { isSourceEqual } = require("./util/source");
|
|||
|
||||
/**
|
||||
* @callback Callback
|
||||
* @param {WebpackError=} err
|
||||
* @param {(WebpackError | null)=} err
|
||||
* @returns {void}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @callback ModuleCallback
|
||||
* @param {WebpackError=} err
|
||||
* @param {(WebpackError | null)=} err
|
||||
* @param {Module=} result
|
||||
* @returns {void}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @callback ModuleFactoryResultCallback
|
||||
* @param {WebpackError=} err
|
||||
* @param {(WebpackError | null)=} err
|
||||
* @param {ModuleFactoryResult=} result
|
||||
* @returns {void}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @callback ModuleOrFactoryResultCallback
|
||||
* @param {WebpackError=} err
|
||||
* @param {(WebpackError | null)=} err
|
||||
* @param {Module | ModuleFactoryResult=} result
|
||||
* @returns {void}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @callback ExecuteModuleCallback
|
||||
* @param {WebpackError=} err
|
||||
* @param {(WebpackError | null)=} err
|
||||
* @param {ExecuteModuleResult=} result
|
||||
* @returns {void}
|
||||
*/
|
||||
|
|
@ -182,6 +183,7 @@ const { isSourceEqual } = require("./util/source");
|
|||
|
||||
/**
|
||||
* @typedef {Object} ChunkHashContext
|
||||
* @property {CodeGenerationResults} codeGenerationResults results of code generation
|
||||
* @property {RuntimeTemplate} runtimeTemplate the runtime template
|
||||
* @property {ModuleGraph} moduleGraph the module graph
|
||||
* @property {ChunkGraph} chunkGraph the chunk graph
|
||||
|
|
@ -1020,7 +1022,9 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|||
/** @type {Map<DepConstructor, ModuleFactory>} */
|
||||
this.dependencyFactories = new Map();
|
||||
/** @type {DependencyTemplates} */
|
||||
this.dependencyTemplates = new DependencyTemplates();
|
||||
this.dependencyTemplates = new DependencyTemplates(
|
||||
this.outputOptions.hashFunction
|
||||
);
|
||||
this.childrenCounters = {};
|
||||
/** @type {Set<number|string>} */
|
||||
this.usedChunkIds = null;
|
||||
|
|
@ -1432,7 +1436,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|||
* @returns {void}
|
||||
*/
|
||||
_processModuleDependencies(module, callback) {
|
||||
/** @type {Array<{factory: ModuleFactory, dependencies: Dependency[], originModule: Module|null}>} */
|
||||
/** @type {Array<{factory: ModuleFactory, dependencies: Dependency[], context: string|undefined, originModule: Module|null}>} */
|
||||
const sortedDependencies = [];
|
||||
|
||||
/** @type {DependenciesBlock} */
|
||||
|
|
@ -1664,6 +1668,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|||
sortedDependencies.push({
|
||||
factory: factoryCacheKey2,
|
||||
dependencies: list,
|
||||
context: dep.getContext(),
|
||||
originModule: module
|
||||
});
|
||||
}
|
||||
|
|
@ -3193,47 +3198,87 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
|
|||
this;
|
||||
const results = this.codeGenerationResults;
|
||||
const errors = [];
|
||||
asyncLib.eachLimit(
|
||||
jobs,
|
||||
this.options.parallelism,
|
||||
({ module, hash, runtime, runtimes }, callback) => {
|
||||
this._codeGenerationModule(
|
||||
module,
|
||||
runtime,
|
||||
runtimes,
|
||||
hash,
|
||||
dependencyTemplates,
|
||||
chunkGraph,
|
||||
moduleGraph,
|
||||
runtimeTemplate,
|
||||
errors,
|
||||
results,
|
||||
(err, codeGenerated) => {
|
||||
if (codeGenerated) statModulesGenerated++;
|
||||
else statModulesFromCache++;
|
||||
callback(err);
|
||||
/** @type {Set<Module> | undefined} */
|
||||
let notCodeGeneratedModules = undefined;
|
||||
const runIteration = () => {
|
||||
let delayedJobs = [];
|
||||
let delayedModules = new Set();
|
||||
asyncLib.eachLimit(
|
||||
jobs,
|
||||
this.options.parallelism,
|
||||
(job, callback) => {
|
||||
const { module } = job;
|
||||
const { codeGenerationDependencies } = module;
|
||||
if (codeGenerationDependencies !== undefined) {
|
||||
if (
|
||||
notCodeGeneratedModules === undefined ||
|
||||
codeGenerationDependencies.some(dep => {
|
||||
const referencedModule = moduleGraph.getModule(dep);
|
||||
return notCodeGeneratedModules.has(referencedModule);
|
||||
})
|
||||
) {
|
||||
delayedJobs.push(job);
|
||||
delayedModules.add(module);
|
||||
return callback();
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
err => {
|
||||
if (err) return callback(err);
|
||||
if (errors.length > 0) {
|
||||
errors.sort(
|
||||
compareSelect(err => err.module, compareModulesByIdentifier)
|
||||
const { hash, runtime, runtimes } = job;
|
||||
this._codeGenerationModule(
|
||||
module,
|
||||
runtime,
|
||||
runtimes,
|
||||
hash,
|
||||
dependencyTemplates,
|
||||
chunkGraph,
|
||||
moduleGraph,
|
||||
runtimeTemplate,
|
||||
errors,
|
||||
results,
|
||||
(err, codeGenerated) => {
|
||||
if (codeGenerated) statModulesGenerated++;
|
||||
else statModulesFromCache++;
|
||||
callback(err);
|
||||
}
|
||||
);
|
||||
for (const error of errors) {
|
||||
this.errors.push(error);
|
||||
},
|
||||
err => {
|
||||
if (err) return callback(err);
|
||||
if (delayedJobs.length > 0) {
|
||||
if (delayedJobs.length === jobs.length) {
|
||||
return callback(
|
||||
new Error(
|
||||
`Unable to make progress during code generation because of circular code generation dependency: ${Array.from(
|
||||
delayedModules,
|
||||
m => m.identifier()
|
||||
).join(", ")}`
|
||||
)
|
||||
);
|
||||
}
|
||||
jobs = delayedJobs;
|
||||
delayedJobs = [];
|
||||
notCodeGeneratedModules = delayedModules;
|
||||
delayedModules = new Set();
|
||||
return runIteration();
|
||||
}
|
||||
if (errors.length > 0) {
|
||||
errors.sort(
|
||||
compareSelect(err => err.module, compareModulesByIdentifier)
|
||||
);
|
||||
for (const error of errors) {
|
||||
this.errors.push(error);
|
||||
}
|
||||
}
|
||||
this.logger.log(
|
||||
`${Math.round(
|
||||
(100 * statModulesGenerated) /
|
||||
(statModulesGenerated + statModulesFromCache)
|
||||
)}% code generated (${statModulesGenerated} generated, ${statModulesFromCache} from cache)`
|
||||
);
|
||||
callback();
|
||||
}
|
||||
this.logger.log(
|
||||
`${Math.round(
|
||||
(100 * statModulesGenerated) /
|
||||
(statModulesGenerated + statModulesFromCache)
|
||||
)}% code generated (${statModulesGenerated} generated, ${statModulesFromCache} from cache)`
|
||||
);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
runIteration();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -3283,7 +3328,9 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
|
|||
moduleGraph,
|
||||
dependencyTemplates,
|
||||
runtimeTemplate,
|
||||
runtime
|
||||
runtime,
|
||||
codeGenerationResults: results,
|
||||
compilation: this
|
||||
});
|
||||
} catch (err) {
|
||||
errors.push(new CodeGenerationError(module, err));
|
||||
|
|
@ -3512,10 +3559,11 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
|
|||
}
|
||||
|
||||
/**
|
||||
* If `module` is passed, `loc` and `request` must also be passed.
|
||||
* @param {string | ChunkGroupOptions} groupOptions options for the chunk group
|
||||
* @param {Module} module the module the references the chunk group
|
||||
* @param {DependencyLocation} loc the location from with the chunk group is referenced (inside of module)
|
||||
* @param {string} request the request from which the the chunk group is referenced
|
||||
* @param {Module=} module the module the references the chunk group
|
||||
* @param {DependencyLocation=} loc the location from with the chunk group is referenced (inside of module)
|
||||
* @param {string=} request the request from which the the chunk group is referenced
|
||||
* @returns {ChunkGroup} the new or existing chunk group
|
||||
*/
|
||||
addChunkInGroup(groupOptions, module, loc, request) {
|
||||
|
|
@ -3838,6 +3886,7 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
|
|||
let statModulesFromCache = 0;
|
||||
const { chunkGraph, runtimeTemplate, moduleMemCaches2 } = this;
|
||||
const { hashFunction, hashDigest, hashDigestLength } = this.outputOptions;
|
||||
const errors = [];
|
||||
for (const module of this.modules) {
|
||||
const memCache = moduleMemCaches2 && moduleMemCaches2.get(module);
|
||||
for (const runtime of chunkGraph.getModuleRuntimes(module)) {
|
||||
|
|
@ -3848,7 +3897,7 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
|
|||
module,
|
||||
runtime,
|
||||
digest,
|
||||
digest.substr(0, hashDigestLength)
|
||||
digest.slice(0, hashDigestLength)
|
||||
);
|
||||
statModulesFromCache++;
|
||||
continue;
|
||||
|
|
@ -3862,13 +3911,20 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
|
|||
hashFunction,
|
||||
runtimeTemplate,
|
||||
hashDigest,
|
||||
hashDigestLength
|
||||
hashDigestLength,
|
||||
errors
|
||||
);
|
||||
if (memCache) {
|
||||
memCache.set(`moduleHash-${getRuntimeKey(runtime)}`, digest);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (errors.length > 0) {
|
||||
errors.sort(compareSelect(err => err.module, compareModulesByIdentifier));
|
||||
for (const error of errors) {
|
||||
this.errors.push(error);
|
||||
}
|
||||
}
|
||||
this.logger.log(
|
||||
`${statModulesHashed} modules hashed, ${statModulesFromCache} from cache (${
|
||||
Math.round(
|
||||
|
|
@ -3885,22 +3941,27 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
|
|||
hashFunction,
|
||||
runtimeTemplate,
|
||||
hashDigest,
|
||||
hashDigestLength
|
||||
hashDigestLength,
|
||||
errors
|
||||
) {
|
||||
const moduleHash = createHash(hashFunction);
|
||||
module.updateHash(moduleHash, {
|
||||
chunkGraph,
|
||||
runtime,
|
||||
runtimeTemplate
|
||||
});
|
||||
const moduleHashDigest = /** @type {string} */ (
|
||||
moduleHash.digest(hashDigest)
|
||||
);
|
||||
let moduleHashDigest;
|
||||
try {
|
||||
const moduleHash = createHash(hashFunction);
|
||||
module.updateHash(moduleHash, {
|
||||
chunkGraph,
|
||||
runtime,
|
||||
runtimeTemplate
|
||||
});
|
||||
moduleHashDigest = /** @type {string} */ (moduleHash.digest(hashDigest));
|
||||
} catch (err) {
|
||||
errors.push(new ModuleHashingError(module, err));
|
||||
moduleHashDigest = "XXXXXX";
|
||||
}
|
||||
chunkGraph.setModuleHashes(
|
||||
module,
|
||||
runtime,
|
||||
moduleHashDigest,
|
||||
moduleHashDigest.substr(0, hashDigestLength)
|
||||
moduleHashDigest.slice(0, hashDigestLength)
|
||||
);
|
||||
return moduleHashDigest;
|
||||
}
|
||||
|
|
@ -4046,6 +4107,7 @@ This prevents using hashes of each other and should be avoided.`);
|
|||
const codeGenerationJobs = [];
|
||||
/** @type {Map<string, Map<Module, {module: Module, hash: string, runtime: RuntimeSpec, runtimes: RuntimeSpec[]}>>} */
|
||||
const codeGenerationJobsMap = new Map();
|
||||
const errors = [];
|
||||
|
||||
const processChunk = chunk => {
|
||||
// Last minute module hash generation for modules that depend on chunk hashes
|
||||
|
|
@ -4060,7 +4122,8 @@ This prevents using hashes of each other and should be avoided.`);
|
|||
hashFunction,
|
||||
runtimeTemplate,
|
||||
hashDigest,
|
||||
hashDigestLength
|
||||
hashDigestLength,
|
||||
errors
|
||||
);
|
||||
let hashMap = codeGenerationJobsMap.get(hash);
|
||||
if (hashMap) {
|
||||
|
|
@ -4084,15 +4147,16 @@ This prevents using hashes of each other and should be avoided.`);
|
|||
}
|
||||
}
|
||||
this.logger.timeAggregate("hashing: hash runtime modules");
|
||||
this.logger.time("hashing: hash chunks");
|
||||
const chunkHash = createHash(hashFunction);
|
||||
try {
|
||||
this.logger.time("hashing: hash chunks");
|
||||
const chunkHash = createHash(hashFunction);
|
||||
if (outputOptions.hashSalt) {
|
||||
chunkHash.update(outputOptions.hashSalt);
|
||||
}
|
||||
chunk.updateHash(chunkHash, chunkGraph);
|
||||
this.hooks.chunkHash.call(chunk, chunkHash, {
|
||||
chunkGraph,
|
||||
codeGenerationResults: this.codeGenerationResults,
|
||||
moduleGraph: this.moduleGraph,
|
||||
runtimeTemplate: this.runtimeTemplate
|
||||
});
|
||||
|
|
@ -4101,7 +4165,7 @@ This prevents using hashes of each other and should be avoided.`);
|
|||
);
|
||||
hash.update(chunkHashDigest);
|
||||
chunk.hash = chunkHashDigest;
|
||||
chunk.renderedHash = chunk.hash.substr(0, hashDigestLength);
|
||||
chunk.renderedHash = chunk.hash.slice(0, hashDigestLength);
|
||||
const fullHashModules =
|
||||
chunkGraph.getChunkFullHashModulesIterable(chunk);
|
||||
if (fullHashModules) {
|
||||
|
|
@ -4116,13 +4180,19 @@ This prevents using hashes of each other and should be avoided.`);
|
|||
};
|
||||
otherChunks.forEach(processChunk);
|
||||
for (const chunk of runtimeChunks) processChunk(chunk);
|
||||
if (errors.length > 0) {
|
||||
errors.sort(compareSelect(err => err.module, compareModulesByIdentifier));
|
||||
for (const error of errors) {
|
||||
this.errors.push(error);
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.timeAggregateEnd("hashing: hash runtime modules");
|
||||
this.logger.timeAggregateEnd("hashing: hash chunks");
|
||||
this.logger.time("hashing: hash digest");
|
||||
this.hooks.fullHash.call(hash);
|
||||
this.fullHash = /** @type {string} */ (hash.digest(hashDigest));
|
||||
this.hash = this.fullHash.substr(0, hashDigestLength);
|
||||
this.hash = this.fullHash.slice(0, hashDigestLength);
|
||||
this.logger.timeEnd("hashing: hash digest");
|
||||
|
||||
this.logger.time("hashing: process full hash modules");
|
||||
|
|
@ -4142,7 +4212,7 @@ This prevents using hashes of each other and should be avoided.`);
|
|||
module,
|
||||
chunk.runtime,
|
||||
moduleHashDigest,
|
||||
moduleHashDigest.substr(0, hashDigestLength)
|
||||
moduleHashDigest.slice(0, hashDigestLength)
|
||||
);
|
||||
codeGenerationJobsMap.get(oldHash).get(module).hash = moduleHashDigest;
|
||||
}
|
||||
|
|
@ -4153,7 +4223,7 @@ This prevents using hashes of each other and should be avoided.`);
|
|||
chunkHash.digest(hashDigest)
|
||||
);
|
||||
chunk.hash = chunkHashDigest;
|
||||
chunk.renderedHash = chunk.hash.substr(0, hashDigestLength);
|
||||
chunk.renderedHash = chunk.hash.slice(0, hashDigestLength);
|
||||
this.hooks.contentHash.call(chunk);
|
||||
}
|
||||
this.logger.timeEnd("hashing: process full hash modules");
|
||||
|
|
@ -4755,6 +4825,9 @@ This prevents using hashes of each other and should be avoided.`);
|
|||
chunkGraph.connectChunkAndModule(chunk, module);
|
||||
}
|
||||
|
||||
/** @type {WebpackError[]} */
|
||||
const errors = [];
|
||||
|
||||
// Hash modules
|
||||
for (const module of modules) {
|
||||
this._createModuleHash(
|
||||
|
|
@ -4764,15 +4837,14 @@ This prevents using hashes of each other and should be avoided.`);
|
|||
hashFunction,
|
||||
runtimeTemplate,
|
||||
hashDigest,
|
||||
hashDigestLength
|
||||
hashDigestLength,
|
||||
errors
|
||||
);
|
||||
}
|
||||
|
||||
const codeGenerationResults = new CodeGenerationResults(
|
||||
this.outputOptions.hashFunction
|
||||
);
|
||||
/** @type {WebpackError[]} */
|
||||
const errors = [];
|
||||
/**
|
||||
* @param {Module} module the module
|
||||
* @param {Callback} callback callback
|
||||
|
|
|
|||
|
|
@ -58,13 +58,13 @@ const { isSourceEqual } = require("./util/source");
|
|||
/**
|
||||
* @template T
|
||||
* @callback Callback
|
||||
* @param {Error=} err
|
||||
* @param {(Error | null)=} err
|
||||
* @param {T=} result
|
||||
*/
|
||||
|
||||
/**
|
||||
* @callback RunAsChildCallback
|
||||
* @param {Error=} err
|
||||
* @param {(Error | null)=} err
|
||||
* @param {Chunk[]=} entries
|
||||
* @param {Compilation=} compilation
|
||||
*/
|
||||
|
|
@ -165,6 +165,11 @@ class Compiler {
|
|||
/** @type {AsyncSeriesHook<[Compilation]>} */
|
||||
afterCompile: new AsyncSeriesHook(["compilation"]),
|
||||
|
||||
/** @type {AsyncSeriesHook<[]>} */
|
||||
readRecords: new AsyncSeriesHook([]),
|
||||
/** @type {AsyncSeriesHook<[]>} */
|
||||
emitRecords: new AsyncSeriesHook([]),
|
||||
|
||||
/** @type {AsyncSeriesHook<[Compiler]>} */
|
||||
watchRun: new AsyncSeriesHook(["compiler"]),
|
||||
/** @type {SyncHook<[Error]>} */
|
||||
|
|
@ -540,8 +545,21 @@ class Compiler {
|
|||
*/
|
||||
runAsChild(callback) {
|
||||
const startTime = Date.now();
|
||||
|
||||
const finalCallback = (err, entries, compilation) => {
|
||||
try {
|
||||
callback(err, entries, compilation);
|
||||
} catch (e) {
|
||||
const err = new WebpackError(
|
||||
`compiler.runAsChild callback error: ${e}`
|
||||
);
|
||||
err.details = e.stack;
|
||||
this.parentCompilation.errors.push(err);
|
||||
}
|
||||
};
|
||||
|
||||
this.compile((err, compilation) => {
|
||||
if (err) return callback(err);
|
||||
if (err) return finalCallback(err);
|
||||
|
||||
this.parentCompilation.children.push(compilation);
|
||||
for (const { name, source, info } of compilation.getAssets()) {
|
||||
|
|
@ -556,7 +574,7 @@ class Compiler {
|
|||
compilation.startTime = startTime;
|
||||
compilation.endTime = Date.now();
|
||||
|
||||
return callback(null, entries, compilation);
|
||||
return finalCallback(null, entries, compilation);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -591,7 +609,7 @@ class Compiler {
|
|||
let immutable = info.immutable;
|
||||
const queryStringIdx = targetFile.indexOf("?");
|
||||
if (queryStringIdx >= 0) {
|
||||
targetFile = targetFile.substr(0, queryStringIdx);
|
||||
targetFile = targetFile.slice(0, queryStringIdx);
|
||||
// We may remove the hash, which is in the query string
|
||||
// So we recheck if the file is immutable
|
||||
// This doesn't cover all cases, but immutable is only a performance optimization anyway
|
||||
|
|
@ -882,8 +900,32 @@ ${other}`);
|
|||
* @returns {void}
|
||||
*/
|
||||
emitRecords(callback) {
|
||||
if (!this.recordsOutputPath) return callback();
|
||||
if (this.hooks.emitRecords.isUsed()) {
|
||||
if (this.recordsOutputPath) {
|
||||
asyncLib.parallel(
|
||||
[
|
||||
cb => this.hooks.emitRecords.callAsync(cb),
|
||||
this._emitRecords.bind(this)
|
||||
],
|
||||
err => callback(err)
|
||||
);
|
||||
} else {
|
||||
this.hooks.emitRecords.callAsync(callback);
|
||||
}
|
||||
} else {
|
||||
if (this.recordsOutputPath) {
|
||||
this._emitRecords(callback);
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Callback<void>} callback signals when the call finishes
|
||||
* @returns {void}
|
||||
*/
|
||||
_emitRecords(callback) {
|
||||
const writeFile = () => {
|
||||
this.outputFileSystem.writeFile(
|
||||
this.recordsOutputPath,
|
||||
|
|
@ -926,6 +968,31 @@ ${other}`);
|
|||
* @returns {void}
|
||||
*/
|
||||
readRecords(callback) {
|
||||
if (this.hooks.readRecords.isUsed()) {
|
||||
if (this.recordsInputPath) {
|
||||
asyncLib.parallel([
|
||||
cb => this.hooks.readRecords.callAsync(cb),
|
||||
this._readRecords.bind(this)
|
||||
]);
|
||||
} else {
|
||||
this.records = {};
|
||||
this.hooks.readRecords.callAsync(callback);
|
||||
}
|
||||
} else {
|
||||
if (this.recordsInputPath) {
|
||||
this._readRecords(callback);
|
||||
} else {
|
||||
this.records = {};
|
||||
callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Callback<void>} callback signals when the call finishes
|
||||
* @returns {void}
|
||||
*/
|
||||
_readRecords(callback) {
|
||||
if (!this.recordsInputPath) {
|
||||
this.records = {};
|
||||
return callback();
|
||||
|
|
|
|||
|
|
@ -324,7 +324,7 @@ class ConstPlugin {
|
|||
}
|
||||
} else if (expression.operator === "??") {
|
||||
const param = parser.evaluateExpression(expression.left);
|
||||
const keepRight = param && param.asNullish();
|
||||
const keepRight = param.asNullish();
|
||||
if (typeof keepRight === "boolean") {
|
||||
// ------------------------------------------
|
||||
//
|
||||
|
|
@ -407,7 +407,7 @@ class ConstPlugin {
|
|||
const expression = optionalExpressionsStack.pop();
|
||||
const evaluated = parser.evaluateExpression(expression);
|
||||
|
||||
if (evaluated && evaluated.asNullish()) {
|
||||
if (evaluated.asNullish()) {
|
||||
// ------------------------------------------
|
||||
//
|
||||
// Given the following code:
|
||||
|
|
|
|||
|
|
@ -19,7 +19,11 @@ const {
|
|||
keepOriginalOrder,
|
||||
compareModulesById
|
||||
} = require("./util/comparators");
|
||||
const { contextify, parseResource } = require("./util/identifier");
|
||||
const {
|
||||
contextify,
|
||||
parseResource,
|
||||
makePathsRelative
|
||||
} = require("./util/identifier");
|
||||
const makeSerializable = require("./util/makeSerializable");
|
||||
|
||||
/** @typedef {import("webpack-sources").Source} Source */
|
||||
|
|
@ -61,7 +65,7 @@ const makeSerializable = require("./util/makeSerializable");
|
|||
|
||||
/**
|
||||
* @typedef {Object} ContextModuleOptionsExtras
|
||||
* @property {string} resource
|
||||
* @property {false|string|string[]} resource
|
||||
* @property {string=} resourceQuery
|
||||
* @property {string=} resourceFragment
|
||||
* @property {TODO} resolveOptions
|
||||
|
|
@ -71,7 +75,7 @@ const makeSerializable = require("./util/makeSerializable");
|
|||
|
||||
/**
|
||||
* @callback ResolveDependenciesCallback
|
||||
* @param {Error=} err
|
||||
* @param {(Error | null)=} err
|
||||
* @param {ContextElementDependency[]=} dependencies
|
||||
*/
|
||||
|
||||
|
|
@ -92,23 +96,36 @@ class ContextModule extends Module {
|
|||
* @param {ContextModuleOptions} options options object
|
||||
*/
|
||||
constructor(resolveDependencies, options) {
|
||||
const parsed = parseResource(options ? options.resource : "");
|
||||
const resource = parsed.path;
|
||||
const resourceQuery = (options && options.resourceQuery) || parsed.query;
|
||||
const resourceFragment =
|
||||
(options && options.resourceFragment) || parsed.fragment;
|
||||
if (!options || typeof options.resource === "string") {
|
||||
const parsed = parseResource(
|
||||
options ? /** @type {string} */ (options.resource) : ""
|
||||
);
|
||||
const resource = parsed.path;
|
||||
const resourceQuery = (options && options.resourceQuery) || parsed.query;
|
||||
const resourceFragment =
|
||||
(options && options.resourceFragment) || parsed.fragment;
|
||||
|
||||
super("javascript/dynamic", resource);
|
||||
super("javascript/dynamic", resource);
|
||||
/** @type {ContextModuleOptions} */
|
||||
this.options = {
|
||||
...options,
|
||||
resource,
|
||||
resourceQuery,
|
||||
resourceFragment
|
||||
};
|
||||
} else {
|
||||
super("javascript/dynamic");
|
||||
/** @type {ContextModuleOptions} */
|
||||
this.options = {
|
||||
...options,
|
||||
resource: options.resource,
|
||||
resourceQuery: options.resourceQuery || "",
|
||||
resourceFragment: options.resourceFragment || ""
|
||||
};
|
||||
}
|
||||
|
||||
// Info from Factory
|
||||
this.resolveDependencies = resolveDependencies;
|
||||
/** @type {ContextModuleOptions} */
|
||||
this.options = {
|
||||
...options,
|
||||
resource,
|
||||
resourceQuery,
|
||||
resourceFragment
|
||||
};
|
||||
if (options && options.resolveOptions !== undefined) {
|
||||
this.resolveOptions = options.resolveOptions;
|
||||
}
|
||||
|
|
@ -149,16 +166,18 @@ class ContextModule extends Module {
|
|||
this.resolveDependencies = undefined;
|
||||
}
|
||||
|
||||
prettyRegExp(regexString) {
|
||||
// remove the "/" at the front and the beginning
|
||||
// "/foo/" -> "foo"
|
||||
return regexString
|
||||
.substring(1, regexString.length - 1)
|
||||
.replace(/!/g, "%21");
|
||||
_prettyRegExp(regexString, stripSlash = true) {
|
||||
const str = (regexString + "").replace(/!/g, "%21").replace(/\|/g, "%7C");
|
||||
return stripSlash ? str.substring(1, str.length - 1) : str;
|
||||
}
|
||||
|
||||
_createIdentifier() {
|
||||
let identifier = this.context;
|
||||
let identifier =
|
||||
this.context ||
|
||||
(typeof this.options.resource === "string" ||
|
||||
this.options.resource === false
|
||||
? `${this.options.resource}`
|
||||
: this.options.resource.join("|"));
|
||||
if (this.options.resourceQuery) {
|
||||
identifier += `|${this.options.resourceQuery}`;
|
||||
}
|
||||
|
|
@ -175,13 +194,19 @@ class ContextModule extends Module {
|
|||
identifier += `|${this.options.addon}`;
|
||||
}
|
||||
if (this.options.regExp) {
|
||||
identifier += `|${this.options.regExp}`;
|
||||
identifier += `|${this._prettyRegExp(this.options.regExp, false)}`;
|
||||
}
|
||||
if (this.options.include) {
|
||||
identifier += `|include: ${this.options.include}`;
|
||||
identifier += `|include: ${this._prettyRegExp(
|
||||
this.options.include,
|
||||
false
|
||||
)}`;
|
||||
}
|
||||
if (this.options.exclude) {
|
||||
identifier += `|exclude: ${this.options.exclude}`;
|
||||
identifier += `|exclude: ${this._prettyRegExp(
|
||||
this.options.exclude,
|
||||
false
|
||||
)}`;
|
||||
}
|
||||
if (this.options.referencedExports) {
|
||||
identifier += `|referencedExports: ${JSON.stringify(
|
||||
|
|
@ -217,7 +242,19 @@ class ContextModule extends Module {
|
|||
* @returns {string} a user readable identifier of the module
|
||||
*/
|
||||
readableIdentifier(requestShortener) {
|
||||
let identifier = requestShortener.shorten(this.context) + "/";
|
||||
let identifier;
|
||||
if (this.context) {
|
||||
identifier = requestShortener.shorten(this.context) + "/";
|
||||
} else if (
|
||||
typeof this.options.resource === "string" ||
|
||||
this.options.resource === false
|
||||
) {
|
||||
identifier = requestShortener.shorten(`${this.options.resource}`) + "/";
|
||||
} else {
|
||||
identifier = this.options.resource
|
||||
.map(r => requestShortener.shorten(r) + "/")
|
||||
.join(" ");
|
||||
}
|
||||
if (this.options.resourceQuery) {
|
||||
identifier += ` ${this.options.resourceQuery}`;
|
||||
}
|
||||
|
|
@ -231,13 +268,13 @@ class ContextModule extends Module {
|
|||
identifier += ` ${requestShortener.shorten(this.options.addon)}`;
|
||||
}
|
||||
if (this.options.regExp) {
|
||||
identifier += ` ${this.prettyRegExp(this.options.regExp + "")}`;
|
||||
identifier += ` ${this._prettyRegExp(this.options.regExp)}`;
|
||||
}
|
||||
if (this.options.include) {
|
||||
identifier += ` include: ${this.prettyRegExp(this.options.include + "")}`;
|
||||
identifier += ` include: ${this._prettyRegExp(this.options.include)}`;
|
||||
}
|
||||
if (this.options.exclude) {
|
||||
identifier += ` exclude: ${this.prettyRegExp(this.options.exclude + "")}`;
|
||||
identifier += ` exclude: ${this._prettyRegExp(this.options.exclude)}`;
|
||||
}
|
||||
if (this.options.referencedExports) {
|
||||
identifier += ` referencedExports: ${this.options.referencedExports
|
||||
|
|
@ -267,11 +304,31 @@ class ContextModule extends Module {
|
|||
* @returns {string | null} an identifier for library inclusion
|
||||
*/
|
||||
libIdent(options) {
|
||||
let identifier = contextify(
|
||||
options.context,
|
||||
this.context,
|
||||
options.associatedObjectForCache
|
||||
);
|
||||
let identifier;
|
||||
|
||||
if (this.context) {
|
||||
identifier = contextify(
|
||||
options.context,
|
||||
this.context,
|
||||
options.associatedObjectForCache
|
||||
);
|
||||
} else if (typeof this.options.resource === "string") {
|
||||
identifier = contextify(
|
||||
options.context,
|
||||
this.options.resource,
|
||||
options.associatedObjectForCache
|
||||
);
|
||||
} else if (this.options.resource === false) {
|
||||
identifier = "false";
|
||||
} else {
|
||||
identifier = this.options.resource
|
||||
.map(res =>
|
||||
contextify(options.context, res, options.associatedObjectForCache)
|
||||
)
|
||||
.join(" ");
|
||||
}
|
||||
|
||||
if (this.layer) identifier = `(${this.layer})/${identifier}`;
|
||||
if (this.options.mode) {
|
||||
identifier += ` ${this.options.mode}`;
|
||||
}
|
||||
|
|
@ -286,13 +343,13 @@ class ContextModule extends Module {
|
|||
)}`;
|
||||
}
|
||||
if (this.options.regExp) {
|
||||
identifier += ` ${this.prettyRegExp(this.options.regExp + "")}`;
|
||||
identifier += ` ${this._prettyRegExp(this.options.regExp)}`;
|
||||
}
|
||||
if (this.options.include) {
|
||||
identifier += ` include: ${this.prettyRegExp(this.options.include + "")}`;
|
||||
identifier += ` include: ${this._prettyRegExp(this.options.include)}`;
|
||||
}
|
||||
if (this.options.exclude) {
|
||||
identifier += ` exclude: ${this.prettyRegExp(this.options.exclude + "")}`;
|
||||
identifier += ` exclude: ${this._prettyRegExp(this.options.exclude)}`;
|
||||
}
|
||||
if (this.options.referencedExports) {
|
||||
identifier += ` referencedExports: ${this.options.referencedExports
|
||||
|
|
@ -312,15 +369,16 @@ class ContextModule extends Module {
|
|||
|
||||
/**
|
||||
* @param {NeedBuildContext} context context info
|
||||
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
||||
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
||||
* @returns {void}
|
||||
*/
|
||||
needBuild({ fileSystemInfo }, callback) {
|
||||
// build if enforced
|
||||
if (this._forceBuild) return callback(null, true);
|
||||
|
||||
// always build when we have no snapshot
|
||||
if (!this.buildInfo.snapshot) return callback(null, true);
|
||||
// always build when we have no snapshot and context
|
||||
if (!this.buildInfo.snapshot)
|
||||
return callback(null, Boolean(this.context || this.options.resource));
|
||||
|
||||
fileSystemInfo.checkSnapshotValid(this.buildInfo.snapshot, (err, valid) => {
|
||||
callback(err, !valid);
|
||||
|
|
@ -435,10 +493,16 @@ class ContextModule extends Module {
|
|||
);
|
||||
return;
|
||||
}
|
||||
if (!this.context && !this.options.resource) return callback();
|
||||
|
||||
compilation.fileSystemInfo.createSnapshot(
|
||||
startTime,
|
||||
null,
|
||||
[this.context],
|
||||
this.context
|
||||
? [this.context]
|
||||
: typeof this.options.resource === "string"
|
||||
? [this.options.resource]
|
||||
: /** @type {string[]} */ (this.options.resource),
|
||||
null,
|
||||
SNAPSHOT_OPTIONS,
|
||||
(err, snapshot) => {
|
||||
|
|
@ -462,7 +526,15 @@ class ContextModule extends Module {
|
|||
missingDependencies,
|
||||
buildDependencies
|
||||
) {
|
||||
contextDependencies.add(this.context);
|
||||
if (this.context) {
|
||||
contextDependencies.add(this.context);
|
||||
} else if (typeof this.options.resource === "string") {
|
||||
contextDependencies.add(this.options.resource);
|
||||
} else if (this.options.resource === false) {
|
||||
return;
|
||||
} else {
|
||||
for (const res of this.options.resource) contextDependencies.add(res);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -998,9 +1070,21 @@ module.exports = webpackEmptyAsyncContext;`;
|
|||
return this.getSourceForEmptyContext(id, runtimeTemplate);
|
||||
}
|
||||
|
||||
getSource(sourceString) {
|
||||
/**
|
||||
* @param {string} sourceString source content
|
||||
* @param {Compilation=} compilation the compilation
|
||||
* @returns {Source} generated source
|
||||
*/
|
||||
getSource(sourceString, compilation) {
|
||||
if (this.useSourceMap || this.useSimpleSourceMap) {
|
||||
return new OriginalSource(sourceString, this.identifier());
|
||||
return new OriginalSource(
|
||||
sourceString,
|
||||
`webpack://${makePathsRelative(
|
||||
(compilation && compilation.compiler.context) || "",
|
||||
this.identifier(),
|
||||
compilation && compilation.compiler.root
|
||||
)}`
|
||||
);
|
||||
}
|
||||
return new RawSource(sourceString);
|
||||
}
|
||||
|
|
@ -1010,16 +1094,23 @@ module.exports = webpackEmptyAsyncContext;`;
|
|||
* @returns {CodeGenerationResult} result
|
||||
*/
|
||||
codeGeneration(context) {
|
||||
const { chunkGraph } = context;
|
||||
const { chunkGraph, compilation } = context;
|
||||
const sources = new Map();
|
||||
sources.set(
|
||||
"javascript",
|
||||
this.getSource(this.getSourceString(this.options.mode, context))
|
||||
this.getSource(
|
||||
this.getSourceString(this.options.mode, context),
|
||||
compilation
|
||||
)
|
||||
);
|
||||
const set = new Set();
|
||||
const allDeps = /** @type {ContextElementDependency[]} */ (
|
||||
this.dependencies.concat(this.blocks.map(b => b.dependencies[0]))
|
||||
);
|
||||
const allDeps =
|
||||
this.dependencies.length > 0
|
||||
? /** @type {ContextElementDependency[]} */ (this.dependencies).slice()
|
||||
: [];
|
||||
for (const block of this.blocks)
|
||||
for (const dep of block.dependencies)
|
||||
allDeps.push(/** @type {ContextElementDependency} */ (dep));
|
||||
set.add(RuntimeGlobals.module);
|
||||
set.add(RuntimeGlobals.hasOwnProperty);
|
||||
if (allDeps.length > 0) {
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ module.exports = class ContextModuleFactory extends ModuleFactory {
|
|||
loadersPrefix = "";
|
||||
const idx = request.lastIndexOf("!");
|
||||
if (idx >= 0) {
|
||||
let loadersRequest = request.substr(0, idx + 1);
|
||||
let loadersRequest = request.slice(0, idx + 1);
|
||||
let i;
|
||||
for (
|
||||
i = 0;
|
||||
|
|
@ -138,7 +138,7 @@ module.exports = class ContextModuleFactory extends ModuleFactory {
|
|||
loadersPrefix += "!";
|
||||
}
|
||||
loadersRequest = loadersRequest
|
||||
.substr(i)
|
||||
.slice(i)
|
||||
.replace(/!+$/, "")
|
||||
.replace(/!!+/g, "!");
|
||||
if (loadersRequest === "") {
|
||||
|
|
@ -146,7 +146,7 @@ module.exports = class ContextModuleFactory extends ModuleFactory {
|
|||
} else {
|
||||
loaders = loadersRequest.split("!");
|
||||
}
|
||||
resource = request.substr(idx + 1);
|
||||
resource = request.slice(idx + 1);
|
||||
} else {
|
||||
loaders = [];
|
||||
resource = request;
|
||||
|
|
@ -167,6 +167,9 @@ module.exports = class ContextModuleFactory extends ModuleFactory {
|
|||
asyncLib.parallel(
|
||||
[
|
||||
callback => {
|
||||
const results = [];
|
||||
const yield_ = obj => results.push(obj);
|
||||
|
||||
contextResolver.resolve(
|
||||
{},
|
||||
context,
|
||||
|
|
@ -174,11 +177,12 @@ module.exports = class ContextModuleFactory extends ModuleFactory {
|
|||
{
|
||||
fileDependencies,
|
||||
missingDependencies,
|
||||
contextDependencies
|
||||
contextDependencies,
|
||||
yield: yield_
|
||||
},
|
||||
(err, result) => {
|
||||
err => {
|
||||
if (err) return callback(err);
|
||||
callback(null, result);
|
||||
callback(null, results);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
|
@ -213,15 +217,25 @@ module.exports = class ContextModuleFactory extends ModuleFactory {
|
|||
contextDependencies
|
||||
});
|
||||
}
|
||||
|
||||
let [contextResult, loaderResult] = result;
|
||||
if (contextResult.length > 1) {
|
||||
const first = contextResult[0];
|
||||
contextResult = contextResult.filter(r => r.path);
|
||||
if (contextResult.length === 0) contextResult.push(first);
|
||||
}
|
||||
this.hooks.afterResolve.callAsync(
|
||||
{
|
||||
addon:
|
||||
loadersPrefix +
|
||||
result[1].join("!") +
|
||||
(result[1].length > 0 ? "!" : ""),
|
||||
resource: result[0],
|
||||
loaderResult.join("!") +
|
||||
(loaderResult.length > 0 ? "!" : ""),
|
||||
resource:
|
||||
contextResult.length > 1
|
||||
? contextResult.map(r => r.path)
|
||||
: contextResult[0].path,
|
||||
resolveDependencies: this.resolveDependencies.bind(this),
|
||||
resourceQuery: contextResult[0].query,
|
||||
resourceFragment: contextResult[0].fragment,
|
||||
...beforeResolveResult
|
||||
},
|
||||
(err, result) => {
|
||||
|
|
@ -278,26 +292,27 @@ module.exports = class ContextModuleFactory extends ModuleFactory {
|
|||
} = options;
|
||||
if (!regExp || !resource) return callback(null, []);
|
||||
|
||||
const addDirectoryChecked = (directory, visited, callback) => {
|
||||
const addDirectoryChecked = (ctx, directory, visited, callback) => {
|
||||
fs.realpath(directory, (err, realPath) => {
|
||||
if (err) return callback(err);
|
||||
if (visited.has(realPath)) return callback(null, []);
|
||||
let recursionStack;
|
||||
addDirectory(
|
||||
ctx,
|
||||
directory,
|
||||
(dir, callback) => {
|
||||
(_, dir, callback) => {
|
||||
if (recursionStack === undefined) {
|
||||
recursionStack = new Set(visited);
|
||||
recursionStack.add(realPath);
|
||||
}
|
||||
addDirectoryChecked(dir, recursionStack, callback);
|
||||
addDirectoryChecked(ctx, dir, recursionStack, callback);
|
||||
},
|
||||
callback
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const addDirectory = (directory, addSubDirectory, callback) => {
|
||||
const addDirectory = (ctx, directory, addSubDirectory, callback) => {
|
||||
fs.readdir(directory, (err, files) => {
|
||||
if (err) return callback(err);
|
||||
const processedFiles = cmf.hooks.contextModuleFiles.call(
|
||||
|
|
@ -324,16 +339,15 @@ module.exports = class ContextModuleFactory extends ModuleFactory {
|
|||
|
||||
if (stat.isDirectory()) {
|
||||
if (!recursive) return callback();
|
||||
addSubDirectory(subResource, callback);
|
||||
addSubDirectory(ctx, subResource, callback);
|
||||
} else if (
|
||||
stat.isFile() &&
|
||||
(!include || subResource.match(include))
|
||||
) {
|
||||
const obj = {
|
||||
context: resource,
|
||||
context: ctx,
|
||||
request:
|
||||
"." +
|
||||
subResource.substr(resource.length).replace(/\\/g, "/")
|
||||
"." + subResource.slice(ctx.length).replace(/\\/g, "/")
|
||||
};
|
||||
|
||||
this.hooks.alternativeRequests.callAsync(
|
||||
|
|
@ -345,11 +359,12 @@ module.exports = class ContextModuleFactory extends ModuleFactory {
|
|||
.filter(obj => regExp.test(obj.request))
|
||||
.map(obj => {
|
||||
const dep = new ContextElementDependency(
|
||||
obj.request + resourceQuery + resourceFragment,
|
||||
`${obj.request}${resourceQuery}${resourceFragment}`,
|
||||
obj.request,
|
||||
typePrefix,
|
||||
category,
|
||||
referencedExports
|
||||
referencedExports,
|
||||
obj.context
|
||||
);
|
||||
dep.optional = true;
|
||||
return dep;
|
||||
|
|
@ -382,12 +397,37 @@ module.exports = class ContextModuleFactory extends ModuleFactory {
|
|||
});
|
||||
};
|
||||
|
||||
if (typeof fs.realpath === "function") {
|
||||
addDirectoryChecked(resource, new Set(), callback);
|
||||
const addSubDirectory = (ctx, dir, callback) =>
|
||||
addDirectory(ctx, dir, addSubDirectory, callback);
|
||||
|
||||
const visitResource = (resource, callback) => {
|
||||
if (typeof fs.realpath === "function") {
|
||||
addDirectoryChecked(resource, resource, new Set(), callback);
|
||||
} else {
|
||||
addDirectory(resource, resource, addSubDirectory, callback);
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof resource === "string") {
|
||||
visitResource(resource, callback);
|
||||
} else {
|
||||
const addSubDirectory = (dir, callback) =>
|
||||
addDirectory(dir, addSubDirectory, callback);
|
||||
addDirectory(resource, addSubDirectory, callback);
|
||||
asyncLib.map(resource, visitResource, (err, result) => {
|
||||
if (err) return callback(err);
|
||||
|
||||
// result dependencies should have unique userRequest
|
||||
// ordered by resolve result
|
||||
const temp = new Set();
|
||||
const res = [];
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
const inner = result[i];
|
||||
for (const el of inner) {
|
||||
if (temp.has(el.userRequest)) continue;
|
||||
res.push(el);
|
||||
temp.add(el.userRequest);
|
||||
}
|
||||
}
|
||||
callback(null, res);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ class DelegatedModule extends Module {
|
|||
|
||||
/**
|
||||
* @param {NeedBuildContext} context context info
|
||||
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
||||
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
||||
* @returns {void}
|
||||
*/
|
||||
needBuild(context, callback) {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class DelegatedModuleFactoryPlugin {
|
|||
const [dependency] = data.dependencies;
|
||||
const { request } = dependency;
|
||||
if (request && request.startsWith(`${scope}/`)) {
|
||||
const innerRequest = "." + request.substr(scope.length);
|
||||
const innerRequest = "." + request.slice(scope.length);
|
||||
let resolved;
|
||||
if (innerRequest in this.options.content) {
|
||||
resolved = this.options.content[innerRequest];
|
||||
|
|
|
|||
|
|
@ -172,6 +172,23 @@ class Dependency {
|
|||
this._loc = loc;
|
||||
}
|
||||
|
||||
setLoc(startLine, startColumn, endLine, endColumn) {
|
||||
this._locSL = startLine;
|
||||
this._locSC = startColumn;
|
||||
this._locEL = endLine;
|
||||
this._locEC = endColumn;
|
||||
this._locI = undefined;
|
||||
this._locN = undefined;
|
||||
this._loc = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string | undefined} a request context
|
||||
*/
|
||||
getContext() {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string | null} an identifier to merge equal requests
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
|
||||
/** @typedef {import("./ChunkGraph")} ChunkGraph */
|
||||
/** @typedef {import("./CodeGenerationResults")} CodeGenerationResults */
|
||||
/** @typedef {import("./ConcatenationScope")} ConcatenationScope */
|
||||
/** @typedef {import("./Dependency")} Dependency */
|
||||
/** @typedef {import("./Dependency").RuntimeSpec} RuntimeSpec */
|
||||
|
|
@ -28,9 +29,17 @@
|
|||
* @property {RuntimeSpec} runtime current runtimes, for which code is generated
|
||||
* @property {InitFragment<GenerateContext>[]} initFragments mutable array of init fragments for the current module
|
||||
* @property {ConcatenationScope=} concatenationScope when in a concatenated module, information about other concatenated modules
|
||||
* @property {CodeGenerationResults} codeGenerationResults the code generation results
|
||||
* @property {InitFragment<GenerateContext>[]} chunkInitFragments chunkInitFragments
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} CssDependencyTemplateContextExtras
|
||||
* @property {Map<string, string>} cssExports the css exports
|
||||
*/
|
||||
|
||||
/** @typedef {DependencyTemplateContext & CssDependencyTemplateContextExtras} CssDependencyTemplateContext */
|
||||
|
||||
class DependencyTemplate {
|
||||
/* istanbul ignore next */
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ class DependencyTemplates {
|
|||
}
|
||||
|
||||
clone() {
|
||||
const newInstance = new DependencyTemplates();
|
||||
const newInstance = new DependencyTemplates(this._hashFunction);
|
||||
newInstance._map = new Map(this._map);
|
||||
newInstance._hash = this._hash;
|
||||
return newInstance;
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ class DllModule extends Module {
|
|||
|
||||
/**
|
||||
* @param {NeedBuildContext} context context info
|
||||
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
||||
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
||||
* @returns {void}
|
||||
*/
|
||||
needBuild(context, callback) {
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ class EntryOptionPlugin {
|
|||
runtime: desc.runtime,
|
||||
layer: desc.layer,
|
||||
dependOn: desc.dependOn,
|
||||
baseUri: desc.baseUri,
|
||||
publicPath: desc.publicPath,
|
||||
chunkLoading: desc.chunkLoading,
|
||||
asyncChunks: desc.asyncChunks,
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ exports.cutOffMessage = (stack, message) => {
|
|||
if (nextLine === -1) {
|
||||
return stack === message ? "" : stack;
|
||||
} else {
|
||||
const firstLine = stack.substr(0, nextLine);
|
||||
return firstLine === message ? stack.substr(nextLine + 1) : stack;
|
||||
const firstLine = stack.slice(0, nextLine);
|
||||
return firstLine === message ? stack.slice(nextLine + 1) : stack;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
const { ConcatSource, RawSource } = require("webpack-sources");
|
||||
const ExternalModule = require("./ExternalModule");
|
||||
const ModuleFilenameHelpers = require("./ModuleFilenameHelpers");
|
||||
const RuntimeGlobals = require("./RuntimeGlobals");
|
||||
const JavascriptModulesPlugin = require("./javascript/JavascriptModulesPlugin");
|
||||
|
||||
/** @typedef {import("webpack-sources").Source} Source */
|
||||
|
|
@ -77,7 +78,13 @@ class EvalDevToolModulePlugin {
|
|||
.replace(/^\//, "")
|
||||
);
|
||||
const result = new RawSource(
|
||||
`eval(${JSON.stringify(content + footer)});`
|
||||
`eval(${
|
||||
compilation.outputOptions.trustedTypes
|
||||
? `${RuntimeGlobals.createScript}(${JSON.stringify(
|
||||
content + footer
|
||||
)})`
|
||||
: JSON.stringify(content + footer)
|
||||
});`
|
||||
);
|
||||
cache.set(source, result);
|
||||
return result;
|
||||
|
|
@ -95,6 +102,14 @@ class EvalDevToolModulePlugin {
|
|||
hash.update("EvalDevToolModulePlugin");
|
||||
hash.update("2");
|
||||
});
|
||||
if (compilation.outputOptions.trustedTypes) {
|
||||
compilation.hooks.additionalModuleRuntimeRequirements.tap(
|
||||
"EvalDevToolModulePlugin",
|
||||
(module, set, context) => {
|
||||
set.add(RuntimeGlobals.createScript);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
const { ConcatSource, RawSource } = require("webpack-sources");
|
||||
const ModuleFilenameHelpers = require("./ModuleFilenameHelpers");
|
||||
const NormalModule = require("./NormalModule");
|
||||
const RuntimeGlobals = require("./RuntimeGlobals");
|
||||
const SourceMapDevToolModuleOptionsPlugin = require("./SourceMapDevToolModuleOptionsPlugin");
|
||||
const JavascriptModulesPlugin = require("./javascript/JavascriptModulesPlugin");
|
||||
const ConcatenatedModule = require("./optimize/ConcatenatedModule");
|
||||
|
|
@ -165,7 +166,15 @@ class EvalSourceMapDevToolPlugin {
|
|||
) + `\n//# sourceURL=webpack-internal:///${moduleId}\n`; // workaround for chrome bug
|
||||
|
||||
return result(
|
||||
new RawSource(`eval(${JSON.stringify(content + footer)});`)
|
||||
new RawSource(
|
||||
`eval(${
|
||||
compilation.outputOptions.trustedTypes
|
||||
? `${RuntimeGlobals.createScript}(${JSON.stringify(
|
||||
content + footer
|
||||
)})`
|
||||
: JSON.stringify(content + footer)
|
||||
});`
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
|
@ -181,6 +190,14 @@ class EvalSourceMapDevToolPlugin {
|
|||
hash.update("EvalSourceMapDevToolPlugin");
|
||||
hash.update("2");
|
||||
});
|
||||
if (compilation.outputOptions.trustedTypes) {
|
||||
compilation.hooks.additionalModuleRuntimeRequirements.tap(
|
||||
"EvalSourceMapDevToolPlugin",
|
||||
(module, set, context) => {
|
||||
set.add(RuntimeGlobals.createScript);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -291,15 +291,15 @@ class ExportsInfo {
|
|||
}
|
||||
}
|
||||
for (const exportInfo of this._exports.values()) {
|
||||
if (!canMangle && exportInfo.canMangleProvide !== false) {
|
||||
exportInfo.canMangleProvide = false;
|
||||
changed = true;
|
||||
}
|
||||
if (excludeExports && excludeExports.has(exportInfo.name)) continue;
|
||||
if (exportInfo.provided !== true && exportInfo.provided !== null) {
|
||||
exportInfo.provided = null;
|
||||
changed = true;
|
||||
}
|
||||
if (!canMangle && exportInfo.canMangleProvide !== false) {
|
||||
exportInfo.canMangleProvide = false;
|
||||
changed = true;
|
||||
}
|
||||
if (targetKey) {
|
||||
exportInfo.setTarget(targetKey, targetModule, [exportInfo.name], -1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ const { register } = require("./util/serialization");
|
|||
*/
|
||||
|
||||
const TYPES = new Set(["javascript"]);
|
||||
const CSS_TYPES = new Set(["css-import"]);
|
||||
const RUNTIME_REQUIREMENTS = new Set([RuntimeGlobals.module]);
|
||||
const RUNTIME_REQUIREMENTS_FOR_SCRIPT = new Set([RuntimeGlobals.loadScript]);
|
||||
const RUNTIME_REQUIREMENTS_FOR_MODULE = new Set([
|
||||
|
|
@ -392,7 +393,7 @@ class ExternalModule extends Module {
|
|||
* @returns {Set<string>} types available (do not mutate)
|
||||
*/
|
||||
getSourceTypes() {
|
||||
return TYPES;
|
||||
return this.externalType === "css-import" ? CSS_TYPES : TYPES;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -409,7 +410,9 @@ class ExternalModule extends Module {
|
|||
* @returns {boolean} true, if the chunk is ok for the module
|
||||
*/
|
||||
chunkCondition(chunk, { chunkGraph }) {
|
||||
return chunkGraph.getNumberOfEntryModules(chunk) > 0;
|
||||
return this.externalType === "css-import"
|
||||
? true
|
||||
: chunkGraph.getNumberOfEntryModules(chunk) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -429,7 +432,7 @@ class ExternalModule extends Module {
|
|||
|
||||
/**
|
||||
* @param {NeedBuildContext} context context info
|
||||
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
||||
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
||||
* @returns {void}
|
||||
*/
|
||||
needBuild(context, callback) {
|
||||
|
|
@ -526,8 +529,14 @@ class ExternalModule extends Module {
|
|||
return { request, externalType };
|
||||
}
|
||||
|
||||
_getSourceData(runtimeTemplate, moduleGraph, chunkGraph, runtime) {
|
||||
const { request, externalType } = this._getRequestAndExternalType();
|
||||
_getSourceData(
|
||||
request,
|
||||
externalType,
|
||||
runtimeTemplate,
|
||||
moduleGraph,
|
||||
chunkGraph,
|
||||
runtime
|
||||
) {
|
||||
switch (externalType) {
|
||||
case "this":
|
||||
case "window":
|
||||
|
|
@ -541,6 +550,7 @@ class ExternalModule extends Module {
|
|||
case "commonjs":
|
||||
case "commonjs2":
|
||||
case "commonjs-module":
|
||||
case "commonjs-static":
|
||||
return getSourceForCommonJsExternal(request);
|
||||
case "node-commonjs":
|
||||
return this.buildInfo.module
|
||||
|
|
@ -613,60 +623,90 @@ class ExternalModule extends Module {
|
|||
runtime,
|
||||
concatenationScope
|
||||
}) {
|
||||
const sourceData = this._getSourceData(
|
||||
runtimeTemplate,
|
||||
moduleGraph,
|
||||
chunkGraph,
|
||||
runtime
|
||||
);
|
||||
const { request, externalType } = this._getRequestAndExternalType();
|
||||
switch (externalType) {
|
||||
case "asset": {
|
||||
const sources = new Map();
|
||||
sources.set(
|
||||
"javascript",
|
||||
new RawSource(`module.exports = ${JSON.stringify(request)};`)
|
||||
);
|
||||
const data = new Map();
|
||||
data.set("url", request);
|
||||
return { sources, runtimeRequirements: RUNTIME_REQUIREMENTS, data };
|
||||
}
|
||||
case "css-import": {
|
||||
const sources = new Map();
|
||||
sources.set(
|
||||
"css-import",
|
||||
new RawSource(`@import url(${JSON.stringify(request)});`)
|
||||
);
|
||||
return {
|
||||
sources,
|
||||
runtimeRequirements: EMPTY_RUNTIME_REQUIREMENTS
|
||||
};
|
||||
}
|
||||
default: {
|
||||
const sourceData = this._getSourceData(
|
||||
request,
|
||||
externalType,
|
||||
runtimeTemplate,
|
||||
moduleGraph,
|
||||
chunkGraph,
|
||||
runtime
|
||||
);
|
||||
|
||||
let sourceString = sourceData.expression;
|
||||
if (sourceData.iife)
|
||||
sourceString = `(function() { return ${sourceString}; }())`;
|
||||
if (concatenationScope) {
|
||||
sourceString = `${runtimeTemplate.supportsConst() ? "const" : "var"} ${
|
||||
ConcatenationScope.NAMESPACE_OBJECT_EXPORT
|
||||
} = ${sourceString};`;
|
||||
concatenationScope.registerNamespaceExport(
|
||||
ConcatenationScope.NAMESPACE_OBJECT_EXPORT
|
||||
);
|
||||
} else {
|
||||
sourceString = `module.exports = ${sourceString};`;
|
||||
}
|
||||
if (sourceData.init) sourceString = `${sourceData.init}\n${sourceString}`;
|
||||
let sourceString = sourceData.expression;
|
||||
if (sourceData.iife)
|
||||
sourceString = `(function() { return ${sourceString}; }())`;
|
||||
if (concatenationScope) {
|
||||
sourceString = `${
|
||||
runtimeTemplate.supportsConst() ? "const" : "var"
|
||||
} ${ConcatenationScope.NAMESPACE_OBJECT_EXPORT} = ${sourceString};`;
|
||||
concatenationScope.registerNamespaceExport(
|
||||
ConcatenationScope.NAMESPACE_OBJECT_EXPORT
|
||||
);
|
||||
} else {
|
||||
sourceString = `module.exports = ${sourceString};`;
|
||||
}
|
||||
if (sourceData.init)
|
||||
sourceString = `${sourceData.init}\n${sourceString}`;
|
||||
|
||||
let data = undefined;
|
||||
if (sourceData.chunkInitFragments) {
|
||||
data = new Map();
|
||||
data.set("chunkInitFragments", sourceData.chunkInitFragments);
|
||||
}
|
||||
let data = undefined;
|
||||
if (sourceData.chunkInitFragments) {
|
||||
data = new Map();
|
||||
data.set("chunkInitFragments", sourceData.chunkInitFragments);
|
||||
}
|
||||
|
||||
const sources = new Map();
|
||||
if (this.useSourceMap || this.useSimpleSourceMap) {
|
||||
sources.set(
|
||||
"javascript",
|
||||
new OriginalSource(sourceString, this.identifier())
|
||||
);
|
||||
} else {
|
||||
sources.set("javascript", new RawSource(sourceString));
|
||||
}
|
||||
const sources = new Map();
|
||||
if (this.useSourceMap || this.useSimpleSourceMap) {
|
||||
sources.set(
|
||||
"javascript",
|
||||
new OriginalSource(sourceString, this.identifier())
|
||||
);
|
||||
} else {
|
||||
sources.set("javascript", new RawSource(sourceString));
|
||||
}
|
||||
|
||||
let runtimeRequirements = sourceData.runtimeRequirements;
|
||||
if (!concatenationScope) {
|
||||
if (!runtimeRequirements) {
|
||||
runtimeRequirements = RUNTIME_REQUIREMENTS;
|
||||
} else {
|
||||
const set = new Set(runtimeRequirements);
|
||||
set.add(RuntimeGlobals.module);
|
||||
runtimeRequirements = set;
|
||||
let runtimeRequirements = sourceData.runtimeRequirements;
|
||||
if (!concatenationScope) {
|
||||
if (!runtimeRequirements) {
|
||||
runtimeRequirements = RUNTIME_REQUIREMENTS;
|
||||
} else {
|
||||
const set = new Set(runtimeRequirements);
|
||||
set.add(RuntimeGlobals.module);
|
||||
runtimeRequirements = set;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
sources,
|
||||
runtimeRequirements:
|
||||
runtimeRequirements || EMPTY_RUNTIME_REQUIREMENTS,
|
||||
data
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
sources,
|
||||
runtimeRequirements: runtimeRequirements || EMPTY_RUNTIME_REQUIREMENTS,
|
||||
data
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -89,8 +89,8 @@ class ExternalModuleFactoryPlugin {
|
|||
UNSPECIFIED_EXTERNAL_TYPE_REGEXP.test(externalConfig)
|
||||
) {
|
||||
const idx = externalConfig.indexOf(" ");
|
||||
type = externalConfig.substr(0, idx);
|
||||
externalConfig = externalConfig.substr(idx + 1);
|
||||
type = externalConfig.slice(0, idx);
|
||||
externalConfig = externalConfig.slice(idx + 1);
|
||||
} else if (
|
||||
Array.isArray(externalConfig) &&
|
||||
externalConfig.length > 0 &&
|
||||
|
|
@ -98,9 +98,9 @@ class ExternalModuleFactoryPlugin {
|
|||
) {
|
||||
const firstItem = externalConfig[0];
|
||||
const idx = firstItem.indexOf(" ");
|
||||
type = firstItem.substr(0, idx);
|
||||
type = firstItem.slice(0, idx);
|
||||
externalConfig = [
|
||||
firstItem.substr(idx + 1),
|
||||
firstItem.slice(idx + 1),
|
||||
...externalConfig.slice(1)
|
||||
];
|
||||
}
|
||||
|
|
@ -117,7 +117,7 @@ class ExternalModuleFactoryPlugin {
|
|||
|
||||
/**
|
||||
* @param {Externals} externals externals config
|
||||
* @param {function(Error=, ExternalModule=): void} callback callback
|
||||
* @param {function((Error | null)=, ExternalModule=): void} callback callback
|
||||
* @returns {void}
|
||||
*/
|
||||
const handleExternals = (externals, callback) => {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
"use strict";
|
||||
|
||||
const { create: createResolver } = require("enhanced-resolve");
|
||||
const nodeModule = require("module");
|
||||
const asyncLib = require("neo-async");
|
||||
const AsyncQueue = require("./util/AsyncQueue");
|
||||
const StackedCacheMap = require("./util/StackedCacheMap");
|
||||
|
|
@ -22,6 +23,8 @@ const processAsyncTree = require("./util/processAsyncTree");
|
|||
|
||||
const supportsEsm = +process.versions.modules >= 83;
|
||||
|
||||
const builtinModules = new Set(nodeModule.builtinModules);
|
||||
|
||||
let FS_ACCURACY = 2000;
|
||||
|
||||
const EMPTY_SET = new Set();
|
||||
|
|
@ -1185,7 +1188,7 @@ class FileSystemInfo {
|
|||
|
||||
/**
|
||||
* @param {string} path file path
|
||||
* @param {function(WebpackError=, (FileSystemInfoEntry | "ignore" | null)=): void} callback callback function
|
||||
* @param {function((WebpackError | null)=, (FileSystemInfoEntry | "ignore" | null)=): void} callback callback function
|
||||
* @returns {void}
|
||||
*/
|
||||
getFileTimestamp(path, callback) {
|
||||
|
|
@ -1196,7 +1199,7 @@ class FileSystemInfo {
|
|||
|
||||
/**
|
||||
* @param {string} path context path
|
||||
* @param {function(WebpackError=, (ResolvedContextFileSystemInfoEntry | "ignore" | null)=): void} callback callback function
|
||||
* @param {function((WebpackError | null)=, (ResolvedContextFileSystemInfoEntry | "ignore" | null)=): void} callback callback function
|
||||
* @returns {void}
|
||||
*/
|
||||
getContextTimestamp(path, callback) {
|
||||
|
|
@ -1217,7 +1220,7 @@ class FileSystemInfo {
|
|||
|
||||
/**
|
||||
* @param {string} path context path
|
||||
* @param {function(WebpackError=, (ContextFileSystemInfoEntry | "ignore" | null)=): void} callback callback function
|
||||
* @param {function((WebpackError | null)=, (ContextFileSystemInfoEntry | "ignore" | null)=): void} callback callback function
|
||||
* @returns {void}
|
||||
*/
|
||||
_getUnresolvedContextTimestamp(path, callback) {
|
||||
|
|
@ -1228,7 +1231,7 @@ class FileSystemInfo {
|
|||
|
||||
/**
|
||||
* @param {string} path file path
|
||||
* @param {function(WebpackError=, string=): void} callback callback function
|
||||
* @param {function((WebpackError | null)=, string=): void} callback callback function
|
||||
* @returns {void}
|
||||
*/
|
||||
getFileHash(path, callback) {
|
||||
|
|
@ -1239,7 +1242,7 @@ class FileSystemInfo {
|
|||
|
||||
/**
|
||||
* @param {string} path context path
|
||||
* @param {function(WebpackError=, string=): void} callback callback function
|
||||
* @param {function((WebpackError | null)=, string=): void} callback callback function
|
||||
* @returns {void}
|
||||
*/
|
||||
getContextHash(path, callback) {
|
||||
|
|
@ -1259,7 +1262,7 @@ class FileSystemInfo {
|
|||
|
||||
/**
|
||||
* @param {string} path context path
|
||||
* @param {function(WebpackError=, ContextHash=): void} callback callback function
|
||||
* @param {function((WebpackError | null)=, ContextHash=): void} callback callback function
|
||||
* @returns {void}
|
||||
*/
|
||||
_getUnresolvedContextHash(path, callback) {
|
||||
|
|
@ -1270,7 +1273,7 @@ class FileSystemInfo {
|
|||
|
||||
/**
|
||||
* @param {string} path context path
|
||||
* @param {function(WebpackError=, ResolvedContextTimestampAndHash=): void} callback callback function
|
||||
* @param {function((WebpackError | null)=, ResolvedContextTimestampAndHash=): void} callback callback function
|
||||
* @returns {void}
|
||||
*/
|
||||
getContextTsh(path, callback) {
|
||||
|
|
@ -1290,7 +1293,7 @@ class FileSystemInfo {
|
|||
|
||||
/**
|
||||
* @param {string} path context path
|
||||
* @param {function(WebpackError=, ContextTimestampAndHash=): void} callback callback function
|
||||
* @param {function((WebpackError | null)=, ContextTimestampAndHash=): void} callback callback function
|
||||
* @returns {void}
|
||||
*/
|
||||
_getUnresolvedContextTsh(path, callback) {
|
||||
|
|
@ -1330,7 +1333,7 @@ class FileSystemInfo {
|
|||
/**
|
||||
* @param {string} context context directory
|
||||
* @param {Iterable<string>} deps dependencies
|
||||
* @param {function(Error=, ResolveBuildDependenciesResult=): void} callback callback function
|
||||
* @param {function((Error | null)=, ResolveBuildDependenciesResult=): void} callback callback function
|
||||
* @returns {void}
|
||||
*/
|
||||
resolveBuildDependencies(context, deps, callback) {
|
||||
|
|
@ -1673,6 +1676,11 @@ class FileSystemInfo {
|
|||
// e.g. import.meta
|
||||
continue;
|
||||
}
|
||||
|
||||
// we should not track Node.js build dependencies
|
||||
if (dependency.startsWith("node:")) continue;
|
||||
if (builtinModules.has(dependency)) continue;
|
||||
|
||||
push({
|
||||
type: RBDT_RESOLVE_ESM_FILE,
|
||||
context,
|
||||
|
|
@ -1798,7 +1806,7 @@ class FileSystemInfo {
|
|||
|
||||
/**
|
||||
* @param {Map<string, string | false>} resolveResults results from resolving
|
||||
* @param {function(Error=, boolean=): void} callback callback with true when resolveResults resolve the same way
|
||||
* @param {function((Error | null)=, boolean=): void} callback callback with true when resolveResults resolve the same way
|
||||
* @returns {void}
|
||||
*/
|
||||
checkResolveResultsValid(resolveResults, callback) {
|
||||
|
|
@ -1880,7 +1888,7 @@ class FileSystemInfo {
|
|||
* @param {Object} options options object (for future extensions)
|
||||
* @param {boolean=} options.hash should use hash to snapshot
|
||||
* @param {boolean=} options.timestamp should use timestamp to snapshot
|
||||
* @param {function(WebpackError=, Snapshot=): void} callback callback function
|
||||
* @param {function((WebpackError | null)=, (Snapshot | null)=): void} callback callback function
|
||||
* @returns {void}
|
||||
*/
|
||||
createSnapshot(startTime, files, directories, missing, options, callback) {
|
||||
|
|
@ -2256,8 +2264,10 @@ class FileSystemInfo {
|
|||
for (const path of managedItems) {
|
||||
const cache = this._managedItems.get(path);
|
||||
if (cache !== undefined) {
|
||||
if (cache !== "missing") {
|
||||
if (!cache.startsWith("*")) {
|
||||
managedFiles.add(join(this.fs, path, "package.json"));
|
||||
} else if (cache === "*nested") {
|
||||
managedMissing.add(join(this.fs, path, "package.json"));
|
||||
}
|
||||
managedItemInfo.set(path, cache);
|
||||
} else {
|
||||
|
|
@ -2271,8 +2281,10 @@ class FileSystemInfo {
|
|||
}
|
||||
jobError();
|
||||
} else if (entry) {
|
||||
if (entry !== "missing") {
|
||||
if (!entry.startsWith("*")) {
|
||||
managedFiles.add(join(this.fs, path, "package.json"));
|
||||
} else if (cache === "*nested") {
|
||||
managedMissing.add(join(this.fs, path, "package.json"));
|
||||
}
|
||||
managedItemInfo.set(path, entry);
|
||||
jobDone();
|
||||
|
|
@ -2375,7 +2387,7 @@ class FileSystemInfo {
|
|||
|
||||
/**
|
||||
* @param {Snapshot} snapshot the snapshot made
|
||||
* @param {function(WebpackError=, boolean=): void} callback callback function
|
||||
* @param {function((WebpackError | null)=, boolean=): void} callback callback function
|
||||
* @returns {void}
|
||||
*/
|
||||
checkSnapshotValid(snapshot, callback) {
|
||||
|
|
@ -2395,7 +2407,7 @@ class FileSystemInfo {
|
|||
|
||||
/**
|
||||
* @param {Snapshot} snapshot the snapshot made
|
||||
* @param {function(WebpackError=, boolean=): void} callback callback function
|
||||
* @param {function((WebpackError | null)=, boolean=): void} callback callback function
|
||||
* @returns {void}
|
||||
*/
|
||||
_checkSnapshotValidNoCache(snapshot, callback) {
|
||||
|
|
@ -2944,7 +2956,7 @@ class FileSystemInfo {
|
|||
* @param {function(string, IStats, function(Error=, ItemType=): void): void} options.fromFile called when context item is a file
|
||||
* @param {function(string, IStats, function(Error=, ItemType=): void): void} options.fromDirectory called when context item is a directory
|
||||
* @param {function(string[], ItemType[]): T} options.reduce called from all context items
|
||||
* @param {function(Error=, (T)=): void} callback callback
|
||||
* @param {function((Error | null)=, (T)=): void} callback callback
|
||||
*/
|
||||
_readContext(
|
||||
{
|
||||
|
|
@ -3127,7 +3139,7 @@ class FileSystemInfo {
|
|||
|
||||
/**
|
||||
* @param {ContextFileSystemInfoEntry} entry entry
|
||||
* @param {function(Error=, ResolvedContextFileSystemInfoEntry=): void} callback callback
|
||||
* @param {function((Error | null)=, ResolvedContextFileSystemInfoEntry=): void} callback callback
|
||||
* @returns {void}
|
||||
*/
|
||||
_resolveContextTimestamp(entry, callback) {
|
||||
|
|
@ -3235,7 +3247,7 @@ class FileSystemInfo {
|
|||
|
||||
/**
|
||||
* @param {ContextHash} entry context hash
|
||||
* @param {function(Error=, string=): void} callback callback
|
||||
* @param {function((Error | null)=, string=): void} callback callback
|
||||
* @returns {void}
|
||||
*/
|
||||
_resolveContextHash(entry, callback) {
|
||||
|
|
@ -3391,7 +3403,7 @@ class FileSystemInfo {
|
|||
|
||||
/**
|
||||
* @param {ContextTimestampAndHash} entry entry
|
||||
* @param {function(Error=, ResolvedContextTimestampAndHash=): void} callback callback
|
||||
* @param {function((Error | null)=, ResolvedContextTimestampAndHash=): void} callback callback
|
||||
* @returns {void}
|
||||
*/
|
||||
_resolveContextTsh(entry, callback) {
|
||||
|
|
@ -3471,8 +3483,8 @@ class FileSystemInfo {
|
|||
}
|
||||
if (!elements.has(path)) {
|
||||
// file or directory doesn't exist
|
||||
this._managedItems.set(path, "missing");
|
||||
return callback(null, "missing");
|
||||
this._managedItems.set(path, "*missing");
|
||||
return callback(null, "*missing");
|
||||
}
|
||||
// something exists
|
||||
// it may be a file or directory
|
||||
|
|
@ -3481,8 +3493,8 @@ class FileSystemInfo {
|
|||
(path.endsWith("/node_modules") || path.endsWith("\\node_modules"))
|
||||
) {
|
||||
// we are only interested in existence of this special directory
|
||||
this._managedItems.set(path, "exists");
|
||||
return callback(null, "exists");
|
||||
this._managedItems.set(path, "*node_modules");
|
||||
return callback(null, "*node_modules");
|
||||
}
|
||||
|
||||
// we assume it's a directory, as files shouldn't occur in managed paths
|
||||
|
|
@ -3499,8 +3511,8 @@ class FileSystemInfo {
|
|||
) {
|
||||
// This is only a grouping folder e. g. used by yarn
|
||||
// we are only interested in existence of this special directory
|
||||
this._managedItems.set(path, "nested");
|
||||
return callback(null, "nested");
|
||||
this._managedItems.set(path, "*nested");
|
||||
return callback(null, "*nested");
|
||||
}
|
||||
this.logger.warn(
|
||||
`Managed item ${path} isn't a directory or doesn't contain a package.json (see snapshot.managedPaths option)`
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
/** @typedef {import("webpack-sources").Source} Source */
|
||||
/** @typedef {import("./ChunkGraph")} ChunkGraph */
|
||||
/** @typedef {import("./CodeGenerationResults")} CodeGenerationResults */
|
||||
/** @typedef {import("./Compilation")} Compilation */
|
||||
/** @typedef {import("./ConcatenationScope")} ConcatenationScope */
|
||||
/** @typedef {import("./DependencyTemplate")} DependencyTemplate */
|
||||
|
|
@ -27,6 +28,7 @@
|
|||
* @property {Set<string>} runtimeRequirements the requirements for runtime
|
||||
* @property {RuntimeSpec} runtime the runtime
|
||||
* @property {ConcatenationScope=} concatenationScope when in concatenated module, information about other concatenated modules
|
||||
* @property {CodeGenerationResults=} codeGenerationResults code generation results of other modules (need to have a codeGenerationDependency to use that)
|
||||
* @property {string} type which kind of code should be generated
|
||||
* @property {function(): Map<string, any>=} getData get access to the code generation data
|
||||
*/
|
||||
|
|
@ -36,6 +38,7 @@
|
|||
* @property {NormalModule} module the module
|
||||
* @property {ChunkGraph} chunkGraph
|
||||
* @property {RuntimeSpec} runtime
|
||||
* @property {RuntimeTemplate=} runtimeTemplate
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ module.exports.makeWebpackError = makeWebpackError;
|
|||
|
||||
/**
|
||||
* @template T
|
||||
* @param {function(WebpackError=, T=): void} callback webpack error callback
|
||||
* @param {function((WebpackError | null)=, T=): void} callback webpack error callback
|
||||
* @param {string} hook name of hook
|
||||
* @returns {Callback<T>} generic callback
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ class LoaderOptionsPlugin {
|
|||
if (
|
||||
ModuleFilenameHelpers.matchObject(
|
||||
options,
|
||||
i < 0 ? resource : resource.substr(0, i)
|
||||
i < 0 ? resource : resource.slice(0, i)
|
||||
)
|
||||
) {
|
||||
for (const key of Object.keys(options)) {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ const makeSerializable = require("./util/makeSerializable");
|
|||
/** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
|
||||
/** @typedef {import("./Chunk")} Chunk */
|
||||
/** @typedef {import("./ChunkGroup")} ChunkGroup */
|
||||
/** @typedef {import("./CodeGenerationResults")} CodeGenerationResults */
|
||||
/** @typedef {import("./Compilation")} Compilation */
|
||||
/** @typedef {import("./ConcatenationScope")} ConcatenationScope */
|
||||
/** @typedef {import("./Dependency")} Dependency */
|
||||
|
|
@ -48,6 +49,7 @@ const makeSerializable = require("./util/makeSerializable");
|
|||
* @property {string=} type the type of source that should be generated
|
||||
*/
|
||||
|
||||
// TODO webpack 6: compilation will be required in CodeGenerationContext
|
||||
/**
|
||||
* @typedef {Object} CodeGenerationContext
|
||||
* @property {DependencyTemplates} dependencyTemplates the dependency templates
|
||||
|
|
@ -56,6 +58,8 @@ const makeSerializable = require("./util/makeSerializable");
|
|||
* @property {ChunkGraph} chunkGraph the chunk graph
|
||||
* @property {RuntimeSpec} runtime the runtimes code should be generated for
|
||||
* @property {ConcatenationScope=} concatenationScope when in concatenated module, information about other concatenated modules
|
||||
* @property {CodeGenerationResults} codeGenerationResults code generation results of other modules (need to have a codeGenerationDependency to use that)
|
||||
* @property {Compilation=} compilation the compilation
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
@ -165,6 +169,8 @@ class Module extends DependenciesBlock {
|
|||
this.buildInfo = undefined;
|
||||
/** @type {Dependency[] | undefined} */
|
||||
this.presentationalDependencies = undefined;
|
||||
/** @type {Dependency[] | undefined} */
|
||||
this.codeGenerationDependencies = undefined;
|
||||
}
|
||||
|
||||
// TODO remove in webpack 6
|
||||
|
|
@ -396,7 +402,6 @@ class Module extends DependenciesBlock {
|
|||
// BACKWARD-COMPAT END
|
||||
|
||||
/**
|
||||
* @deprecated moved to .buildInfo.exportsArgument
|
||||
* @returns {string} name of the exports argument
|
||||
*/
|
||||
get exportsArgument() {
|
||||
|
|
@ -404,7 +409,6 @@ class Module extends DependenciesBlock {
|
|||
}
|
||||
|
||||
/**
|
||||
* @deprecated moved to .buildInfo.moduleArgument
|
||||
* @returns {string} name of the module argument
|
||||
*/
|
||||
get moduleArgument() {
|
||||
|
|
@ -493,6 +497,19 @@ class Module extends DependenciesBlock {
|
|||
this.presentationalDependencies.push(presentationalDependency);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Dependency} codeGenerationDependency dependency being tied to module.
|
||||
* This is a Dependency where the code generation result of the referenced module is needed during code generation.
|
||||
* The Dependency should also be added to normal dependencies via addDependency.
|
||||
* @returns {void}
|
||||
*/
|
||||
addCodeGenerationDependency(codeGenerationDependency) {
|
||||
if (this.codeGenerationDependencies === undefined) {
|
||||
this.codeGenerationDependencies = [];
|
||||
}
|
||||
this.codeGenerationDependencies.push(codeGenerationDependency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all dependencies and blocks
|
||||
* @returns {void}
|
||||
|
|
@ -501,6 +518,9 @@ class Module extends DependenciesBlock {
|
|||
if (this.presentationalDependencies !== undefined) {
|
||||
this.presentationalDependencies.length = 0;
|
||||
}
|
||||
if (this.codeGenerationDependencies !== undefined) {
|
||||
this.codeGenerationDependencies.length = 0;
|
||||
}
|
||||
super.clearDependenciesAndBlocks();
|
||||
}
|
||||
|
||||
|
|
@ -671,7 +691,7 @@ class Module extends DependenciesBlock {
|
|||
|
||||
/**
|
||||
* @param {NeedBuildContext} context context info
|
||||
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
||||
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
||||
* @returns {void}
|
||||
*/
|
||||
needBuild(context, callback) {
|
||||
|
|
@ -799,7 +819,8 @@ class Module extends DependenciesBlock {
|
|||
runtimeTemplate,
|
||||
moduleGraph: chunkGraph.moduleGraph,
|
||||
chunkGraph,
|
||||
runtime: undefined
|
||||
runtime: undefined,
|
||||
codeGenerationResults: undefined
|
||||
};
|
||||
const sources = this.codeGeneration(codeGenContext).sources;
|
||||
return type ? sources.get(type) : sources.get(first(this.getSourceTypes()));
|
||||
|
|
@ -976,6 +997,7 @@ class Module extends DependenciesBlock {
|
|||
write(this.buildMeta);
|
||||
write(this.buildInfo);
|
||||
write(this.presentationalDependencies);
|
||||
write(this.codeGenerationDependencies);
|
||||
super.serialize(context);
|
||||
}
|
||||
|
||||
|
|
@ -993,6 +1015,7 @@ class Module extends DependenciesBlock {
|
|||
this.buildMeta = read();
|
||||
this.buildInfo = read();
|
||||
this.presentationalDependencies = read();
|
||||
this.codeGenerationDependencies = read();
|
||||
super.deserialize(context);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const NormalModule = require("./NormalModule");
|
||||
const createHash = require("./util/createHash");
|
||||
const memoize = require("./util/memoize");
|
||||
|
||||
|
|
@ -46,7 +47,7 @@ const getAfter = (strFn, token) => {
|
|||
return () => {
|
||||
const str = strFn();
|
||||
const idx = str.indexOf(token);
|
||||
return idx < 0 ? "" : str.substr(idx);
|
||||
return idx < 0 ? "" : str.slice(idx);
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -54,7 +55,7 @@ const getBefore = (strFn, token) => {
|
|||
return () => {
|
||||
const str = strFn();
|
||||
const idx = str.lastIndexOf(token);
|
||||
return idx < 0 ? "" : str.substr(0, idx);
|
||||
return idx < 0 ? "" : str.slice(0, idx);
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -63,7 +64,7 @@ const getHash = (strFn, hashFunction) => {
|
|||
const hash = createHash(hashFunction);
|
||||
hash.update(strFn());
|
||||
const digest = /** @type {string} */ (hash.digest("hex"));
|
||||
return digest.substr(0, 4);
|
||||
return digest.slice(0, 4);
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -138,7 +139,10 @@ ModuleFilenameHelpers.createFilename = (
|
|||
);
|
||||
identifier = memoize(() => requestShortener.shorten(module.identifier()));
|
||||
moduleId = () => chunkGraph.getModuleId(module);
|
||||
absoluteResourcePath = () => module.identifier().split("!").pop();
|
||||
absoluteResourcePath = () =>
|
||||
module instanceof NormalModule
|
||||
? module.resource
|
||||
: module.identifier().split("!").pop();
|
||||
hash = getHash(identifier, hashFunction);
|
||||
}
|
||||
const resource = memoize(() => shortIdentifier().split("!").pop());
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const WebpackError = require("./WebpackError");
|
||||
|
||||
/** @typedef {import("./Module")} Module */
|
||||
|
||||
class ModuleHashingError extends WebpackError {
|
||||
/**
|
||||
* Create a new ModuleHashingError
|
||||
* @param {Module} module related module
|
||||
* @param {Error} error Original error
|
||||
*/
|
||||
constructor(module, error) {
|
||||
super();
|
||||
|
||||
this.name = "ModuleHashingError";
|
||||
this.error = error;
|
||||
this.message = error.message;
|
||||
this.details = error.stack;
|
||||
this.module = module;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ModuleHashingError;
|
||||
|
|
@ -27,7 +27,7 @@ const ArrayQueue = require("./util/ArrayQueue");
|
|||
/**
|
||||
* @template T
|
||||
* @callback Callback
|
||||
* @param {Error=} err
|
||||
* @param {(Error | null)=} err
|
||||
* @param {T=} result
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ const asyncLib = require("neo-async");
|
|||
/**
|
||||
* @template T
|
||||
* @callback Callback
|
||||
* @param {Error=} err
|
||||
* @param {(Error | null)=} err
|
||||
* @param {T=} result
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -81,6 +81,16 @@ class NodeStuffPlugin {
|
|||
);
|
||||
}
|
||||
});
|
||||
parser.hooks.rename.for("global").tap("NodeStuffPlugin", expr => {
|
||||
const dep = new ConstDependency(
|
||||
RuntimeGlobals.global,
|
||||
expr.range,
|
||||
[RuntimeGlobals.global]
|
||||
);
|
||||
dep.loc = expr.loc;
|
||||
parser.state.module.addPresentationalDependency(dep);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
const setModuleConstant = (expressionName, fn, warning) => {
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ const memoize = require("./util/memoize");
|
|||
/** @typedef {import("webpack-sources").Source} Source */
|
||||
/** @typedef {import("../declarations/LoaderContext").NormalModuleLoaderContext} NormalModuleLoaderContext */
|
||||
/** @typedef {import("../declarations/WebpackOptions").Mode} Mode */
|
||||
/** @typedef {import("../declarations/WebpackOptions").ResolveOptions} ResolveOptions */
|
||||
/** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
|
||||
/** @typedef {import("./ChunkGraph")} ChunkGraph */
|
||||
/** @typedef {import("./Compiler")} Compiler */
|
||||
|
|
@ -194,6 +195,25 @@ makeSerializable(
|
|||
* @property {AsyncSeriesBailHook<[NormalModule, NeedBuildContext], boolean>} needBuild
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} NormalModuleCreateData
|
||||
* @property {string=} layer an optional layer in which the module is
|
||||
* @property {string} type module type
|
||||
* @property {string} request request string
|
||||
* @property {string} userRequest request intended by user (without loaders from config)
|
||||
* @property {string} rawRequest request without resolving
|
||||
* @property {LoaderItem[]} loaders list of loaders
|
||||
* @property {string} resource path + query of the real resource
|
||||
* @property {Record<string, any>=} resourceResolveData resource resolve data
|
||||
* @property {string} context context directory for resolving
|
||||
* @property {string=} matchResource path + query of the matched resource (virtual)
|
||||
* @property {Parser} parser the parser used
|
||||
* @property {Record<string, any>=} parserOptions the options of the parser used
|
||||
* @property {Generator} generator the generator used
|
||||
* @property {Record<string, any>=} generatorOptions the options of the generator used
|
||||
* @property {ResolveOptions=} resolveOptions options used for resolving requests from this module
|
||||
*/
|
||||
|
||||
/** @type {WeakMap<Compilation, NormalModuleCompilationHooks>} */
|
||||
const compilationHooksMap = new WeakMap();
|
||||
|
||||
|
|
@ -246,22 +266,7 @@ class NormalModule extends Module {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {Object} options options object
|
||||
* @param {string=} options.layer an optional layer in which the module is
|
||||
* @param {string} options.type module type
|
||||
* @param {string} options.request request string
|
||||
* @param {string} options.userRequest request intended by user (without loaders from config)
|
||||
* @param {string} options.rawRequest request without resolving
|
||||
* @param {LoaderItem[]} options.loaders list of loaders
|
||||
* @param {string} options.resource path + query of the real resource
|
||||
* @param {Record<string, any>=} options.resourceResolveData resource resolve data
|
||||
* @param {string} options.context context directory for resolving
|
||||
* @param {string | undefined} options.matchResource path + query of the matched resource (virtual)
|
||||
* @param {Parser} options.parser the parser used
|
||||
* @param {object} options.parserOptions the options of the parser used
|
||||
* @param {Generator} options.generator the generator used
|
||||
* @param {object} options.generatorOptions the options of the generator used
|
||||
* @param {Object} options.resolveOptions options used for resolving requests from this module
|
||||
* @param {NormalModuleCreateData} options options object
|
||||
*/
|
||||
constructor({
|
||||
layer,
|
||||
|
|
@ -310,7 +315,7 @@ class NormalModule extends Module {
|
|||
}
|
||||
|
||||
// Info from Build
|
||||
/** @type {WebpackError=} */
|
||||
/** @type {(WebpackError | null)=} */
|
||||
this.error = null;
|
||||
/** @private @type {Source=} */
|
||||
this._source = null;
|
||||
|
|
@ -355,11 +360,13 @@ class NormalModule extends Module {
|
|||
* @returns {string | null} an identifier for library inclusion
|
||||
*/
|
||||
libIdent(options) {
|
||||
return contextify(
|
||||
let ident = contextify(
|
||||
options.context,
|
||||
this.userRequest,
|
||||
options.associatedObjectForCache
|
||||
);
|
||||
if (this.layer) ident = `(${this.layer})/${ident}`;
|
||||
return ident;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -368,7 +375,7 @@ class NormalModule extends Module {
|
|||
nameForCondition() {
|
||||
const resource = this.matchResource || this.resource;
|
||||
const idx = resource.indexOf("?");
|
||||
if (idx >= 0) return resource.substr(0, idx);
|
||||
if (idx >= 0) return resource.slice(0, idx);
|
||||
return resource;
|
||||
}
|
||||
|
||||
|
|
@ -551,7 +558,7 @@ class NormalModule extends Module {
|
|||
let { options } = loader;
|
||||
|
||||
if (typeof options === "string") {
|
||||
if (options.substr(0, 1) === "{" && options.substr(-1) === "}") {
|
||||
if (options.startsWith("{") && options.endsWith("}")) {
|
||||
try {
|
||||
options = parseJson(options);
|
||||
} catch (e) {
|
||||
|
|
@ -730,7 +737,7 @@ class NormalModule extends Module {
|
|||
* @param {ResolverWithOptions} resolver the resolver
|
||||
* @param {InputFileSystem} fs the file system
|
||||
* @param {NormalModuleCompilationHooks} hooks the hooks
|
||||
* @param {function(WebpackError=): void} callback callback function
|
||||
* @param {function((WebpackError | null)=): void} callback callback function
|
||||
* @returns {void}
|
||||
*/
|
||||
_doBuild(options, compilation, resolver, fs, hooks, callback) {
|
||||
|
|
@ -1168,7 +1175,8 @@ class NormalModule extends Module {
|
|||
moduleGraph,
|
||||
chunkGraph,
|
||||
runtime,
|
||||
concatenationScope
|
||||
concatenationScope,
|
||||
codeGenerationResults
|
||||
}) {
|
||||
/** @type {Set<string>} */
|
||||
const runtimeRequirements = new Set();
|
||||
|
|
@ -1200,6 +1208,7 @@ class NormalModule extends Module {
|
|||
runtimeRequirements,
|
||||
runtime,
|
||||
concatenationScope,
|
||||
codeGenerationResults,
|
||||
getData,
|
||||
type
|
||||
});
|
||||
|
|
@ -1234,7 +1243,7 @@ class NormalModule extends Module {
|
|||
|
||||
/**
|
||||
* @param {NeedBuildContext} context context info
|
||||
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
||||
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
||||
* @returns {void}
|
||||
*/
|
||||
needBuild(context, callback) {
|
||||
|
|
|
|||
|
|
@ -28,17 +28,25 @@ const LazySet = require("./util/LazySet");
|
|||
const { getScheme } = require("./util/URLAbsoluteSpecifier");
|
||||
const { cachedCleverMerge, cachedSetProperty } = require("./util/cleverMerge");
|
||||
const { join } = require("./util/fs");
|
||||
const { parseResource } = require("./util/identifier");
|
||||
const {
|
||||
parseResource,
|
||||
parseResourceWithoutFragment
|
||||
} = require("./util/identifier");
|
||||
|
||||
/** @typedef {import("../declarations/WebpackOptions").ModuleOptionsNormalized} ModuleOptions */
|
||||
/** @typedef {import("../declarations/WebpackOptions").RuleSetRule} RuleSetRule */
|
||||
/** @typedef {import("./Generator")} Generator */
|
||||
/** @typedef {import("./ModuleFactory").ModuleFactoryCreateData} ModuleFactoryCreateData */
|
||||
/** @typedef {import("./ModuleFactory").ModuleFactoryResult} ModuleFactoryResult */
|
||||
/** @typedef {import("./NormalModule").NormalModuleCreateData} NormalModuleCreateData */
|
||||
/** @typedef {import("./Parser")} Parser */
|
||||
/** @typedef {import("./ResolverFactory")} ResolverFactory */
|
||||
/** @typedef {import("./dependencies/ModuleDependency")} ModuleDependency */
|
||||
/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
|
||||
|
||||
/** @typedef {Pick<RuleSetRule, 'type'|'sideEffects'|'parser'|'generator'|'resolve'|'layer'>} ModuleSettings */
|
||||
/** @typedef {Partial<NormalModuleCreateData & {settings: ModuleSettings}>} CreateData */
|
||||
|
||||
/**
|
||||
* @typedef {Object} ResolveData
|
||||
* @property {ModuleFactoryCreateData["contextInfo"]} contextInfo
|
||||
|
|
@ -48,7 +56,7 @@ const { parseResource } = require("./util/identifier");
|
|||
* @property {Record<string, any> | undefined} assertions
|
||||
* @property {ModuleDependency[]} dependencies
|
||||
* @property {string} dependencyType
|
||||
* @property {Object} createData
|
||||
* @property {CreateData} createData
|
||||
* @property {LazySet<string>} fileDependencies
|
||||
* @property {LazySet<string>} missingDependencies
|
||||
* @property {LazySet<string>} contextDependencies
|
||||
|
|
@ -66,6 +74,11 @@ const { parseResource } = require("./util/identifier");
|
|||
|
||||
/** @typedef {ResourceData & { data: Record<string, any> }} ResourceDataWithData */
|
||||
|
||||
/** @typedef {Object} ParsedLoaderRequest
|
||||
* @property {string} loader loader
|
||||
* @property {string|undefined} options options
|
||||
*/
|
||||
|
||||
const EMPTY_RESOLVE_OPTIONS = {};
|
||||
const EMPTY_PARSER_OPTIONS = {};
|
||||
const EMPTY_GENERATOR_OPTIONS = {};
|
||||
|
|
@ -97,27 +110,6 @@ const stringifyLoadersAndResource = (loaders, resource) => {
|
|||
return str + resource;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} resultString resultString
|
||||
* @returns {{loader: string, options: string|undefined}} parsed loader request
|
||||
*/
|
||||
const identToLoaderRequest = resultString => {
|
||||
const idx = resultString.indexOf("?");
|
||||
if (idx >= 0) {
|
||||
const loader = resultString.substr(0, idx);
|
||||
const options = resultString.substr(idx + 1);
|
||||
return {
|
||||
loader,
|
||||
options
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
loader: resultString,
|
||||
options: undefined
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const needCalls = (times, callback) => {
|
||||
return err => {
|
||||
if (--times === 0) {
|
||||
|
|
@ -212,7 +204,7 @@ class NormalModuleFactory extends ModuleFactory {
|
|||
}) {
|
||||
super();
|
||||
this.hooks = Object.freeze({
|
||||
/** @type {AsyncSeriesBailHook<[ResolveData], TODO>} */
|
||||
/** @type {AsyncSeriesBailHook<[ResolveData], Module | false | void>} */
|
||||
resolve: new AsyncSeriesBailHook(["resolveData"]),
|
||||
/** @type {HookMap<AsyncSeriesBailHook<[ResourceDataWithData, ResolveData], true | void>>} */
|
||||
resolveForScheme: new HookMap(
|
||||
|
|
@ -222,15 +214,15 @@ class NormalModuleFactory extends ModuleFactory {
|
|||
resolveInScheme: new HookMap(
|
||||
() => new AsyncSeriesBailHook(["resourceData", "resolveData"])
|
||||
),
|
||||
/** @type {AsyncSeriesBailHook<[ResolveData], TODO>} */
|
||||
/** @type {AsyncSeriesBailHook<[ResolveData], Module>} */
|
||||
factorize: new AsyncSeriesBailHook(["resolveData"]),
|
||||
/** @type {AsyncSeriesBailHook<[ResolveData], TODO>} */
|
||||
/** @type {AsyncSeriesBailHook<[ResolveData], false | void>} */
|
||||
beforeResolve: new AsyncSeriesBailHook(["resolveData"]),
|
||||
/** @type {AsyncSeriesBailHook<[ResolveData], TODO>} */
|
||||
/** @type {AsyncSeriesBailHook<[ResolveData], false | void>} */
|
||||
afterResolve: new AsyncSeriesBailHook(["resolveData"]),
|
||||
/** @type {AsyncSeriesBailHook<[ResolveData["createData"], ResolveData], TODO>} */
|
||||
/** @type {AsyncSeriesBailHook<[ResolveData["createData"], ResolveData], Module | void>} */
|
||||
createModule: new AsyncSeriesBailHook(["createData", "resolveData"]),
|
||||
/** @type {SyncWaterfallHook<[Module, ResolveData["createData"], ResolveData], TODO>} */
|
||||
/** @type {SyncWaterfallHook<[Module, ResolveData["createData"], ResolveData], Module>} */
|
||||
module: new SyncWaterfallHook(["module", "createData", "resolveData"]),
|
||||
createParser: new HookMap(() => new SyncBailHook(["parserOptions"])),
|
||||
parser: new HookMap(() => new SyncHook(["parser", "parserOptions"])),
|
||||
|
|
@ -264,6 +256,9 @@ class NormalModuleFactory extends ModuleFactory {
|
|||
const cacheParseResource = parseResource.bindCache(
|
||||
associatedObjectForCache
|
||||
);
|
||||
const cachedParseResourceWithoutFragment =
|
||||
parseResourceWithoutFragment.bindCache(associatedObjectForCache);
|
||||
this._parseResourceWithoutFragment = cachedParseResourceWithoutFragment;
|
||||
|
||||
this.hooks.factorize.tapAsync(
|
||||
{
|
||||
|
|
@ -311,7 +306,9 @@ class NormalModuleFactory extends ModuleFactory {
|
|||
return callback(new Error("Empty dependency (no request)"));
|
||||
}
|
||||
|
||||
createdModule = new NormalModule(createData);
|
||||
createdModule = new NormalModule(
|
||||
/** @type {NormalModuleCreateData} */ (createData)
|
||||
);
|
||||
}
|
||||
|
||||
createdModule = this.hooks.module.call(
|
||||
|
|
@ -351,7 +348,7 @@ class NormalModuleFactory extends ModuleFactory {
|
|||
let matchResourceData = undefined;
|
||||
/** @type {string} */
|
||||
let unresolvedResource;
|
||||
/** @type {{loader: string, options: string|undefined}[]} */
|
||||
/** @type {ParsedLoaderRequest[]} */
|
||||
let elements;
|
||||
let noPreAutoLoaders = false;
|
||||
let noAutoLoaders = false;
|
||||
|
|
@ -382,7 +379,7 @@ class NormalModuleFactory extends ModuleFactory {
|
|||
resource: matchResource,
|
||||
...cacheParseResource(matchResource)
|
||||
};
|
||||
requestWithoutMatchResource = request.substr(
|
||||
requestWithoutMatchResource = request.slice(
|
||||
matchResourceMatch[0].length
|
||||
);
|
||||
}
|
||||
|
|
@ -405,7 +402,13 @@ class NormalModuleFactory extends ModuleFactory {
|
|||
)
|
||||
.split(/!+/);
|
||||
unresolvedResource = rawElements.pop();
|
||||
elements = rawElements.map(identToLoaderRequest);
|
||||
elements = rawElements.map(el => {
|
||||
const { path, query } = cachedParseResourceWithoutFragment(el);
|
||||
return {
|
||||
loader: path,
|
||||
options: query ? query.slice(1) : undefined
|
||||
};
|
||||
});
|
||||
scheme = getScheme(unresolvedResource);
|
||||
} else {
|
||||
unresolvedResource = requestWithoutMatchResource;
|
||||
|
|
@ -434,7 +437,7 @@ class NormalModuleFactory extends ModuleFactory {
|
|||
try {
|
||||
for (const item of loaders) {
|
||||
if (typeof item.options === "string" && item.options[0] === "?") {
|
||||
const ident = item.options.substr(1);
|
||||
const ident = item.options.slice(1);
|
||||
if (ident === "[[missing ident]]") {
|
||||
throw new Error(
|
||||
"No ident is provided by referenced loader. " +
|
||||
|
|
@ -1017,12 +1020,14 @@ If changing the source code is not an option there is also a resolve options cal
|
|||
}
|
||||
if (err) return callback(err);
|
||||
|
||||
const parsedResult = identToLoaderRequest(result);
|
||||
const parsedResult = this._parseResourceWithoutFragment(result);
|
||||
const resolved = {
|
||||
loader: parsedResult.loader,
|
||||
loader: parsedResult.path,
|
||||
options:
|
||||
item.options === undefined
|
||||
? parsedResult.options
|
||||
? parsedResult.query
|
||||
? parsedResult.query.slice(1)
|
||||
: undefined
|
||||
: item.options,
|
||||
ident: item.options === undefined ? undefined : item.ident
|
||||
};
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ const createDefaultHandler = (profile, logger) => {
|
|||
/**
|
||||
* @callback ReportProgress
|
||||
* @param {number} p
|
||||
* @param {...string[]} [args]
|
||||
* @param {...string} [args]
|
||||
* @returns {void}
|
||||
*/
|
||||
|
||||
|
|
@ -531,15 +531,14 @@ class ProgressPlugin {
|
|||
}
|
||||
});
|
||||
interceptHook(compiler.cache.hooks.endIdle, 0.01, "cache", "end idle");
|
||||
compiler.hooks.initialize.intercept({
|
||||
compiler.hooks.beforeRun.intercept({
|
||||
name: "ProgressPlugin",
|
||||
call() {
|
||||
handler(0, "");
|
||||
}
|
||||
});
|
||||
interceptHook(compiler.hooks.initialize, 0.01, "setup", "initialize");
|
||||
interceptHook(compiler.hooks.beforeRun, 0.02, "setup", "before run");
|
||||
interceptHook(compiler.hooks.run, 0.03, "setup", "run");
|
||||
interceptHook(compiler.hooks.beforeRun, 0.01, "setup", "before run");
|
||||
interceptHook(compiler.hooks.run, 0.02, "setup", "run");
|
||||
interceptHook(compiler.hooks.watchRun, 0.03, "setup", "watch run");
|
||||
interceptHook(
|
||||
compiler.hooks.normalModuleFactory,
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ class RawModule extends Module {
|
|||
|
||||
/**
|
||||
* @param {NeedBuildContext} context context info
|
||||
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
||||
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
||||
* @returns {void}
|
||||
*/
|
||||
needBuild(context, callback) {
|
||||
|
|
|
|||
|
|
@ -164,10 +164,17 @@ exports.scriptNonce = "__webpack_require__.nc";
|
|||
* function to load a script tag.
|
||||
* Arguments: (url: string, done: (event) => void), key?: string | number, chunkId?: string | number) => void
|
||||
* done function is called when loading has finished or timeout occurred.
|
||||
* It will attach to existing script tags with data-webpack == key or src == url.
|
||||
* It will attach to existing script tags with data-webpack == uniqueName + ":" + key or src == url.
|
||||
*/
|
||||
exports.loadScript = "__webpack_require__.l";
|
||||
|
||||
/**
|
||||
* function to promote a string to a TrustedScript using webpack's Trusted
|
||||
* Types policy
|
||||
* Arguments: (script: string) => TrustedScript
|
||||
*/
|
||||
exports.createScript = "__webpack_require__.ts";
|
||||
|
||||
/**
|
||||
* function to promote a string to a TrustedScriptURL using webpack's Trusted
|
||||
* Types policy
|
||||
|
|
@ -175,6 +182,12 @@ exports.loadScript = "__webpack_require__.l";
|
|||
*/
|
||||
exports.createScriptUrl = "__webpack_require__.tu";
|
||||
|
||||
/**
|
||||
* function to return webpack's Trusted Types policy
|
||||
* Arguments: () => TrustedTypePolicy
|
||||
*/
|
||||
exports.getTrustedTypesPolicy = "__webpack_require__.tt";
|
||||
|
||||
/**
|
||||
* the chunk name of the chunk with the runtime
|
||||
*/
|
||||
|
|
@ -190,11 +203,26 @@ exports.runtimeId = "__webpack_require__.j";
|
|||
*/
|
||||
exports.getChunkScriptFilename = "__webpack_require__.u";
|
||||
|
||||
/**
|
||||
* the filename of the css part of the chunk
|
||||
*/
|
||||
exports.getChunkCssFilename = "__webpack_require__.k";
|
||||
|
||||
/**
|
||||
* a flag when a module/chunk/tree has css modules
|
||||
*/
|
||||
exports.hasCssModules = "has css modules";
|
||||
|
||||
/**
|
||||
* the filename of the script part of the hot update chunk
|
||||
*/
|
||||
exports.getChunkUpdateScriptFilename = "__webpack_require__.hu";
|
||||
|
||||
/**
|
||||
* the filename of the css part of the hot update chunk
|
||||
*/
|
||||
exports.getChunkUpdateCssFilename = "__webpack_require__.hk";
|
||||
|
||||
/**
|
||||
* startup signal from runtime
|
||||
* This will be called when the runtime chunk has been loaded.
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ class RuntimeModule extends Module {
|
|||
|
||||
/**
|
||||
* @param {NeedBuildContext} context context info
|
||||
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
||||
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
||||
* @returns {void}
|
||||
*/
|
||||
needBuild(context, callback) {
|
||||
|
|
|
|||
|
|
@ -6,18 +6,22 @@
|
|||
"use strict";
|
||||
|
||||
const RuntimeGlobals = require("./RuntimeGlobals");
|
||||
const { getChunkFilenameTemplate } = require("./css/CssModulesPlugin");
|
||||
const RuntimeRequirementsDependency = require("./dependencies/RuntimeRequirementsDependency");
|
||||
const JavascriptModulesPlugin = require("./javascript/JavascriptModulesPlugin");
|
||||
const AsyncModuleRuntimeModule = require("./runtime/AsyncModuleRuntimeModule");
|
||||
const AutoPublicPathRuntimeModule = require("./runtime/AutoPublicPathRuntimeModule");
|
||||
const BaseUriRuntimeModule = require("./runtime/BaseUriRuntimeModule");
|
||||
const CompatGetDefaultExportRuntimeModule = require("./runtime/CompatGetDefaultExportRuntimeModule");
|
||||
const CompatRuntimeModule = require("./runtime/CompatRuntimeModule");
|
||||
const CreateFakeNamespaceObjectRuntimeModule = require("./runtime/CreateFakeNamespaceObjectRuntimeModule");
|
||||
const CreateScriptRuntimeModule = require("./runtime/CreateScriptRuntimeModule");
|
||||
const CreateScriptUrlRuntimeModule = require("./runtime/CreateScriptUrlRuntimeModule");
|
||||
const DefinePropertyGettersRuntimeModule = require("./runtime/DefinePropertyGettersRuntimeModule");
|
||||
const EnsureChunkRuntimeModule = require("./runtime/EnsureChunkRuntimeModule");
|
||||
const GetChunkFilenameRuntimeModule = require("./runtime/GetChunkFilenameRuntimeModule");
|
||||
const GetMainFilenameRuntimeModule = require("./runtime/GetMainFilenameRuntimeModule");
|
||||
const GetTrustedTypesPolicyRuntimeModule = require("./runtime/GetTrustedTypesPolicyRuntimeModule");
|
||||
const GlobalRuntimeModule = require("./runtime/GlobalRuntimeModule");
|
||||
const HasOwnPropertyRuntimeModule = require("./runtime/HasOwnPropertyRuntimeModule");
|
||||
const LoadScriptRuntimeModule = require("./runtime/LoadScriptRuntimeModule");
|
||||
|
|
@ -39,7 +43,9 @@ const GLOBALS_ON_REQUIRE = [
|
|||
RuntimeGlobals.runtimeId,
|
||||
RuntimeGlobals.compatGetDefaultExport,
|
||||
RuntimeGlobals.createFakeNamespaceObject,
|
||||
RuntimeGlobals.createScript,
|
||||
RuntimeGlobals.createScriptUrl,
|
||||
RuntimeGlobals.getTrustedTypesPolicy,
|
||||
RuntimeGlobals.definePropertyGetters,
|
||||
RuntimeGlobals.ensureChunk,
|
||||
RuntimeGlobals.entryModuleId,
|
||||
|
|
@ -91,6 +97,15 @@ class RuntimePlugin {
|
|||
*/
|
||||
apply(compiler) {
|
||||
compiler.hooks.compilation.tap("RuntimePlugin", compilation => {
|
||||
const globalChunkLoading = compilation.outputOptions.chunkLoading;
|
||||
const isChunkLoadingDisabledForChunk = chunk => {
|
||||
const options = chunk.getEntryOptions();
|
||||
const chunkLoading =
|
||||
options && options.chunkLoading !== undefined
|
||||
? options.chunkLoading
|
||||
: globalChunkLoading;
|
||||
return chunkLoading === false;
|
||||
};
|
||||
compilation.dependencyTemplates.set(
|
||||
RuntimeRequirementsDependency,
|
||||
new RuntimeRequirementsDependency.Template()
|
||||
|
|
@ -261,6 +276,30 @@ class RuntimePlugin {
|
|||
);
|
||||
return true;
|
||||
});
|
||||
compilation.hooks.runtimeRequirementInTree
|
||||
.for(RuntimeGlobals.getChunkCssFilename)
|
||||
.tap("RuntimePlugin", (chunk, set) => {
|
||||
if (
|
||||
typeof compilation.outputOptions.cssChunkFilename === "string" &&
|
||||
/\[(full)?hash(:\d+)?\]/.test(
|
||||
compilation.outputOptions.cssChunkFilename
|
||||
)
|
||||
) {
|
||||
set.add(RuntimeGlobals.getFullHash);
|
||||
}
|
||||
compilation.addRuntimeModule(
|
||||
chunk,
|
||||
new GetChunkFilenameRuntimeModule(
|
||||
"css",
|
||||
"css",
|
||||
RuntimeGlobals.getChunkCssFilename,
|
||||
chunk =>
|
||||
getChunkFilenameTemplate(chunk, compilation.outputOptions),
|
||||
set.has(RuntimeGlobals.hmrDownloadUpdateHandlers)
|
||||
)
|
||||
);
|
||||
return true;
|
||||
});
|
||||
compilation.hooks.runtimeRequirementInTree
|
||||
.for(RuntimeGlobals.getChunkUpdateScriptFilename)
|
||||
.tap("RuntimePlugin", (chunk, set) => {
|
||||
|
|
@ -339,15 +378,36 @@ class RuntimePlugin {
|
|||
);
|
||||
return true;
|
||||
});
|
||||
compilation.hooks.runtimeRequirementInTree
|
||||
.for(RuntimeGlobals.createScript)
|
||||
.tap("RuntimePlugin", (chunk, set) => {
|
||||
if (compilation.outputOptions.trustedTypes) {
|
||||
set.add(RuntimeGlobals.getTrustedTypesPolicy);
|
||||
}
|
||||
compilation.addRuntimeModule(chunk, new CreateScriptRuntimeModule());
|
||||
return true;
|
||||
});
|
||||
compilation.hooks.runtimeRequirementInTree
|
||||
.for(RuntimeGlobals.createScriptUrl)
|
||||
.tap("RuntimePlugin", (chunk, set) => {
|
||||
if (compilation.outputOptions.trustedTypes) {
|
||||
set.add(RuntimeGlobals.getTrustedTypesPolicy);
|
||||
}
|
||||
compilation.addRuntimeModule(
|
||||
chunk,
|
||||
new CreateScriptUrlRuntimeModule()
|
||||
);
|
||||
return true;
|
||||
});
|
||||
compilation.hooks.runtimeRequirementInTree
|
||||
.for(RuntimeGlobals.getTrustedTypesPolicy)
|
||||
.tap("RuntimePlugin", (chunk, set) => {
|
||||
compilation.addRuntimeModule(
|
||||
chunk,
|
||||
new GetTrustedTypesPolicyRuntimeModule(set)
|
||||
);
|
||||
return true;
|
||||
});
|
||||
compilation.hooks.runtimeRequirementInTree
|
||||
.for(RuntimeGlobals.relativeUrl)
|
||||
.tap("RuntimePlugin", (chunk, set) => {
|
||||
|
|
@ -363,6 +423,14 @@ class RuntimePlugin {
|
|||
);
|
||||
return true;
|
||||
});
|
||||
compilation.hooks.runtimeRequirementInTree
|
||||
.for(RuntimeGlobals.baseURI)
|
||||
.tap("RuntimePlugin", chunk => {
|
||||
if (isChunkLoadingDisabledForChunk(chunk)) {
|
||||
compilation.addRuntimeModule(chunk, new BaseUriRuntimeModule());
|
||||
return true;
|
||||
}
|
||||
});
|
||||
// TODO webpack 6: remove CompatRuntimeModule
|
||||
compilation.hooks.additionalTreeRuntimeRequirements.tap(
|
||||
"RuntimePlugin",
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ const { forEachRuntime, subtractRuntime } = require("./util/runtime");
|
|||
/** @typedef {import("../declarations/WebpackOptions").OutputNormalized} OutputOptions */
|
||||
/** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */
|
||||
/** @typedef {import("./ChunkGraph")} ChunkGraph */
|
||||
/** @typedef {import("./CodeGenerationResults")} CodeGenerationResults */
|
||||
/** @typedef {import("./Compilation")} Compilation */
|
||||
/** @typedef {import("./Dependency")} Dependency */
|
||||
/** @typedef {import("./Module")} Module */
|
||||
|
|
@ -82,6 +83,7 @@ class RuntimeTemplate {
|
|||
this.outputOptions = outputOptions || {};
|
||||
this.requestShortener = requestShortener;
|
||||
this.globalObject = getGlobalObject(outputOptions.globalObject);
|
||||
this.contentHashReplacement = "X".repeat(outputOptions.hashDigestLength);
|
||||
}
|
||||
|
||||
isIIFE() {
|
||||
|
|
@ -200,7 +202,7 @@ class RuntimeTemplate {
|
|||
|
||||
// when the first two args are expression, we need to prepend "" + to force string
|
||||
// concatenation instead of number addition.
|
||||
return typeof args[0] !== "string" && args[1] !== "string"
|
||||
return typeof args[0] !== "string" && typeof args[1] !== "string"
|
||||
? `"" + ${str}`
|
||||
: str;
|
||||
}
|
||||
|
|
@ -1014,6 +1016,26 @@ class RuntimeTemplate {
|
|||
runtimeRequirements.add(RuntimeGlobals.exports);
|
||||
return `${RuntimeGlobals.makeNamespaceObject}(${exportsArgument});\n`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} options options object
|
||||
* @param {Module} options.module the module
|
||||
* @param {string} options.publicPath the public path
|
||||
* @param {RuntimeSpec=} options.runtime runtime
|
||||
* @param {CodeGenerationResults} options.codeGenerationResults the code generation results
|
||||
* @returns {string} the url of the asset
|
||||
*/
|
||||
assetUrl({ publicPath, runtime, module, codeGenerationResults }) {
|
||||
if (!module) {
|
||||
return "data:,";
|
||||
}
|
||||
const codeGen = codeGenerationResults.get(module, runtime);
|
||||
const { data } = codeGen;
|
||||
const url = data.get("url");
|
||||
if (url) return url.toString();
|
||||
const filename = data.get("filename");
|
||||
return publicPath + filename;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = RuntimeTemplate;
|
||||
|
|
|
|||
|
|
@ -370,7 +370,8 @@ class Template {
|
|||
dependencyTemplates: renderContext.dependencyTemplates,
|
||||
moduleGraph: renderContext.moduleGraph,
|
||||
runtimeTemplate: renderContext.runtimeTemplate,
|
||||
runtime: renderContext.chunk.runtime
|
||||
runtime: renderContext.chunk.runtime,
|
||||
codeGenerationResults
|
||||
});
|
||||
if (!codeGenResult) continue;
|
||||
runtimeSource = codeGenResult.sources.get("runtime");
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const mime = require("mime-types");
|
||||
const { basename, extname } = require("path");
|
||||
const util = require("util");
|
||||
const Chunk = require("./Chunk");
|
||||
|
|
@ -117,29 +118,53 @@ const replacePathVariables = (path, data, assetInfo) => {
|
|||
// [name] - file
|
||||
// [ext] - .js
|
||||
if (typeof data.filename === "string") {
|
||||
const { path: file, query, fragment } = parseResource(data.filename);
|
||||
// check that filename is data uri
|
||||
let match = data.filename.match(/^data:([^;,]+)/);
|
||||
if (match) {
|
||||
const ext = mime.extension(match[1]);
|
||||
const emptyReplacer = replacer("", true);
|
||||
|
||||
const ext = extname(file);
|
||||
const base = basename(file);
|
||||
const name = base.slice(0, base.length - ext.length);
|
||||
const path = file.slice(0, file.length - base.length);
|
||||
replacements.set("file", emptyReplacer);
|
||||
replacements.set("query", emptyReplacer);
|
||||
replacements.set("fragment", emptyReplacer);
|
||||
replacements.set("path", emptyReplacer);
|
||||
replacements.set("base", emptyReplacer);
|
||||
replacements.set("name", emptyReplacer);
|
||||
replacements.set("ext", replacer(ext ? `.${ext}` : "", true));
|
||||
// Legacy
|
||||
replacements.set(
|
||||
"filebase",
|
||||
deprecated(
|
||||
emptyReplacer,
|
||||
"[filebase] is now [base]",
|
||||
"DEP_WEBPACK_TEMPLATE_PATH_PLUGIN_REPLACE_PATH_VARIABLES_FILENAME"
|
||||
)
|
||||
);
|
||||
} else {
|
||||
const { path: file, query, fragment } = parseResource(data.filename);
|
||||
|
||||
replacements.set("file", replacer(file));
|
||||
replacements.set("query", replacer(query, true));
|
||||
replacements.set("fragment", replacer(fragment, true));
|
||||
replacements.set("path", replacer(path, true));
|
||||
replacements.set("base", replacer(base));
|
||||
replacements.set("name", replacer(name));
|
||||
replacements.set("ext", replacer(ext, true));
|
||||
// Legacy
|
||||
replacements.set(
|
||||
"filebase",
|
||||
deprecated(
|
||||
replacer(base),
|
||||
"[filebase] is now [base]",
|
||||
"DEP_WEBPACK_TEMPLATE_PATH_PLUGIN_REPLACE_PATH_VARIABLES_FILENAME"
|
||||
)
|
||||
);
|
||||
const ext = extname(file);
|
||||
const base = basename(file);
|
||||
const name = base.slice(0, base.length - ext.length);
|
||||
const path = file.slice(0, file.length - base.length);
|
||||
|
||||
replacements.set("file", replacer(file));
|
||||
replacements.set("query", replacer(query, true));
|
||||
replacements.set("fragment", replacer(fragment, true));
|
||||
replacements.set("path", replacer(path, true));
|
||||
replacements.set("base", replacer(base));
|
||||
replacements.set("name", replacer(name));
|
||||
replacements.set("ext", replacer(ext, true));
|
||||
// Legacy
|
||||
replacements.set(
|
||||
"filebase",
|
||||
deprecated(
|
||||
replacer(base),
|
||||
"[filebase] is now [base]",
|
||||
"DEP_WEBPACK_TEMPLATE_PATH_PLUGIN_REPLACE_PATH_VARIABLES_FILENAME"
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Compilation context
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ const Stats = require("./Stats");
|
|||
/**
|
||||
* @template T
|
||||
* @callback Callback
|
||||
* @param {Error=} err
|
||||
* @param {(Error | null)=} err
|
||||
* @param {T=} result
|
||||
*/
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ class Watching {
|
|||
this.watchOptions = {};
|
||||
}
|
||||
if (typeof this.watchOptions.aggregateTimeout !== "number") {
|
||||
this.watchOptions.aggregateTimeout = 200;
|
||||
this.watchOptions.aggregateTimeout = 20;
|
||||
}
|
||||
this.compiler = compiler;
|
||||
this.running = false;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ const ResolverCachePlugin = require("./cache/ResolverCachePlugin");
|
|||
|
||||
const CommonJsPlugin = require("./dependencies/CommonJsPlugin");
|
||||
const HarmonyModulesPlugin = require("./dependencies/HarmonyModulesPlugin");
|
||||
const ImportMetaContextPlugin = require("./dependencies/ImportMetaContextPlugin");
|
||||
const ImportMetaPlugin = require("./dependencies/ImportMetaPlugin");
|
||||
const ImportPlugin = require("./dependencies/ImportPlugin");
|
||||
const LoaderPlugin = require("./dependencies/LoaderPlugin");
|
||||
|
|
@ -118,11 +119,47 @@ class WebpackOptionsApply extends OptionsApply {
|
|||
if (options.externalsPresets.webAsync) {
|
||||
//@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
|
||||
const ExternalsPlugin = require("./ExternalsPlugin");
|
||||
new ExternalsPlugin("import", /^(https?:\/\/|std:)/).apply(compiler);
|
||||
new ExternalsPlugin(
|
||||
"import",
|
||||
options.experiments.css
|
||||
? ({ request, dependencyType }, callback) => {
|
||||
if (dependencyType === "url") {
|
||||
if (/^(\/\/|https?:\/\/)/.test(request))
|
||||
return callback(null, `asset ${request}`);
|
||||
} else if (dependencyType === "css-import") {
|
||||
if (/^(\/\/|https?:\/\/)/.test(request))
|
||||
return callback(null, `css-import ${request}`);
|
||||
} else if (/^(\/\/|https?:\/\/|std:)/.test(request)) {
|
||||
if (/^\.css(\?|$)/.test(request))
|
||||
return callback(null, `css-import ${request}`);
|
||||
return callback(null, `import ${request}`);
|
||||
}
|
||||
callback();
|
||||
}
|
||||
: /^(\/\/|https?:\/\/|std:)/
|
||||
).apply(compiler);
|
||||
} else if (options.externalsPresets.web) {
|
||||
//@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
|
||||
const ExternalsPlugin = require("./ExternalsPlugin");
|
||||
new ExternalsPlugin("module", /^(https?:\/\/|std:)/).apply(compiler);
|
||||
new ExternalsPlugin(
|
||||
"module",
|
||||
options.experiments.css
|
||||
? ({ request, dependencyType }, callback) => {
|
||||
if (dependencyType === "url") {
|
||||
if (/^(\/\/|https?:\/\/)/.test(request))
|
||||
return callback(null, `asset ${request}`);
|
||||
} else if (dependencyType === "css-import") {
|
||||
if (/^(\/\/|https?:\/\/)/.test(request))
|
||||
return callback(null, `css-import ${request}`);
|
||||
} else if (/^(\/\/|https?:\/\/|std:)/.test(request)) {
|
||||
if (/^\.css(\?|$)/.test(request))
|
||||
return callback(null, `css-import ${request}`);
|
||||
return callback(null, `module ${request}`);
|
||||
}
|
||||
callback();
|
||||
}
|
||||
: /^(\/\/|https?:\/\/|std:)/
|
||||
).apply(compiler);
|
||||
}
|
||||
|
||||
new ChunkPrefetchPreloadPlugin().apply(compiler);
|
||||
|
|
@ -253,6 +290,11 @@ class WebpackOptionsApply extends OptionsApply {
|
|||
}).apply(compiler);
|
||||
}
|
||||
|
||||
if (options.experiments.css) {
|
||||
const CssModulesPlugin = require("./css/CssModulesPlugin");
|
||||
new CssModulesPlugin(options.experiments.css).apply(compiler);
|
||||
}
|
||||
|
||||
if (options.experiments.lazyCompilation) {
|
||||
const LazyCompilationPlugin = require("./hmr/LazyCompilationPlugin");
|
||||
const lazyOptions =
|
||||
|
|
@ -320,6 +362,7 @@ class WebpackOptionsApply extends OptionsApply {
|
|||
new RequireEnsurePlugin().apply(compiler);
|
||||
new RequireContextPlugin().apply(compiler);
|
||||
new ImportPlugin().apply(compiler);
|
||||
new ImportMetaContextPlugin().apply(compiler);
|
||||
new SystemPlugin().apply(compiler);
|
||||
new ImportMetaPlugin().apply(compiler);
|
||||
new URLPlugin().apply(compiler);
|
||||
|
|
|
|||
|
|
@ -12,9 +12,11 @@ const Generator = require("../Generator");
|
|||
const RuntimeGlobals = require("../RuntimeGlobals");
|
||||
const createHash = require("../util/createHash");
|
||||
const { makePathsRelative } = require("../util/identifier");
|
||||
const nonNumericOnlyHash = require("../util/nonNumericOnlyHash");
|
||||
|
||||
/** @typedef {import("webpack-sources").Source} Source */
|
||||
/** @typedef {import("../../declarations/WebpackOptions").AssetGeneratorOptions} AssetGeneratorOptions */
|
||||
/** @typedef {import("../../declarations/WebpackOptions").AssetModuleOutputPath} AssetModuleOutputPath */
|
||||
/** @typedef {import("../../declarations/WebpackOptions").RawPublicPath} RawPublicPath */
|
||||
/** @typedef {import("../Compilation")} Compilation */
|
||||
/** @typedef {import("../Compiler")} Compiler */
|
||||
|
|
@ -49,7 +51,7 @@ const mergeAssetInfo = (a, b) => {
|
|||
case "immutable":
|
||||
case "development":
|
||||
case "hotModuleReplacement":
|
||||
case "javascriptModule ":
|
||||
case "javascriptModule":
|
||||
result[key] = a[key] || b[key];
|
||||
break;
|
||||
case "related":
|
||||
|
|
@ -74,24 +76,121 @@ const mergeRelatedInfo = (a, b) => {
|
|||
return result;
|
||||
};
|
||||
|
||||
const encodeDataUri = (encoding, source) => {
|
||||
let encodedContent;
|
||||
|
||||
switch (encoding) {
|
||||
case "base64": {
|
||||
encodedContent = source.buffer().toString("base64");
|
||||
break;
|
||||
}
|
||||
case false: {
|
||||
const content = source.source();
|
||||
|
||||
if (typeof content !== "string") {
|
||||
encodedContent = content.toString("utf-8");
|
||||
}
|
||||
|
||||
encodedContent = encodeURIComponent(encodedContent).replace(
|
||||
/[!'()*]/g,
|
||||
character => "%" + character.codePointAt(0).toString(16)
|
||||
);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new Error(`Unsupported encoding '${encoding}'`);
|
||||
}
|
||||
|
||||
return encodedContent;
|
||||
};
|
||||
|
||||
const decodeDataUriContent = (encoding, content) => {
|
||||
const isBase64 = encoding === "base64";
|
||||
return isBase64
|
||||
? Buffer.from(content, "base64")
|
||||
: Buffer.from(decodeURIComponent(content), "ascii");
|
||||
};
|
||||
|
||||
const JS_TYPES = new Set(["javascript"]);
|
||||
const JS_AND_ASSET_TYPES = new Set(["javascript", "asset"]);
|
||||
const DEFAULT_ENCODING = "base64";
|
||||
|
||||
class AssetGenerator extends Generator {
|
||||
/**
|
||||
* @param {AssetGeneratorOptions["dataUrl"]=} dataUrlOptions the options for the data url
|
||||
* @param {string=} filename override for output.assetModuleFilename
|
||||
* @param {RawPublicPath=} publicPath override for output.assetModulePublicPath
|
||||
* @param {AssetModuleOutputPath=} outputPath the output path for the emitted file which is not included in the runtime import
|
||||
* @param {boolean=} emit generate output asset
|
||||
*/
|
||||
constructor(dataUrlOptions, filename, publicPath, emit) {
|
||||
constructor(dataUrlOptions, filename, publicPath, outputPath, emit) {
|
||||
super();
|
||||
this.dataUrlOptions = dataUrlOptions;
|
||||
this.filename = filename;
|
||||
this.publicPath = publicPath;
|
||||
this.outputPath = outputPath;
|
||||
this.emit = emit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {NormalModule} module module
|
||||
* @param {RuntimeTemplate} runtimeTemplate runtime template
|
||||
* @returns {string} source file name
|
||||
*/
|
||||
getSourceFileName(module, runtimeTemplate) {
|
||||
return makePathsRelative(
|
||||
runtimeTemplate.compilation.compiler.context,
|
||||
module.matchResource || module.resource,
|
||||
runtimeTemplate.compilation.compiler.root
|
||||
).replace(/^\.\//, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {NormalModule} module module
|
||||
* @returns {string} mime type
|
||||
*/
|
||||
getMimeType(module) {
|
||||
if (typeof this.dataUrlOptions === "function") {
|
||||
throw new Error(
|
||||
"This method must not be called when dataUrlOptions is a function"
|
||||
);
|
||||
}
|
||||
|
||||
let mimeType = this.dataUrlOptions.mimetype;
|
||||
if (mimeType === undefined) {
|
||||
const ext = path.extname(module.nameForCondition());
|
||||
if (
|
||||
module.resourceResolveData &&
|
||||
module.resourceResolveData.mimetype !== undefined
|
||||
) {
|
||||
mimeType =
|
||||
module.resourceResolveData.mimetype +
|
||||
module.resourceResolveData.parameters;
|
||||
} else if (ext) {
|
||||
mimeType = mimeTypes.lookup(ext);
|
||||
|
||||
if (typeof mimeType !== "string") {
|
||||
throw new Error(
|
||||
"DataUrl can't be generated automatically, " +
|
||||
`because there is no mimetype for "${ext}" in mimetype database. ` +
|
||||
'Either pass a mimetype via "generator.mimetype" or ' +
|
||||
'use type: "asset/resource" to create a resource file instead of a DataUrl'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof mimeType !== "string") {
|
||||
throw new Error(
|
||||
"DataUrl can't be generated automatically. " +
|
||||
'Either pass a mimetype via "generator.mimetype" or ' +
|
||||
'use type: "asset/resource" to create a resource file instead of a DataUrl'
|
||||
);
|
||||
}
|
||||
|
||||
return mimeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {NormalModule} module module for which the code should be generated
|
||||
* @param {GenerateContext} generateContext context for generate
|
||||
|
|
@ -131,66 +230,31 @@ class AssetGenerator extends Generator {
|
|||
}
|
||||
}
|
||||
if (encoding === undefined) {
|
||||
encoding = "base64";
|
||||
}
|
||||
let ext;
|
||||
let mimeType = this.dataUrlOptions.mimetype;
|
||||
if (mimeType === undefined) {
|
||||
ext = path.extname(module.nameForCondition());
|
||||
if (
|
||||
module.resourceResolveData &&
|
||||
module.resourceResolveData.mimetype !== undefined
|
||||
) {
|
||||
mimeType =
|
||||
module.resourceResolveData.mimetype +
|
||||
module.resourceResolveData.parameters;
|
||||
} else if (ext) {
|
||||
mimeType = mimeTypes.lookup(ext);
|
||||
}
|
||||
}
|
||||
if (typeof mimeType !== "string") {
|
||||
throw new Error(
|
||||
"DataUrl can't be generated automatically, " +
|
||||
`because there is no mimetype for "${ext}" in mimetype database. ` +
|
||||
'Either pass a mimetype via "generator.mimetype" or ' +
|
||||
'use type: "asset/resource" to create a resource file instead of a DataUrl'
|
||||
);
|
||||
encoding = DEFAULT_ENCODING;
|
||||
}
|
||||
const mimeType = this.getMimeType(module);
|
||||
|
||||
let encodedContent;
|
||||
|
||||
if (
|
||||
module.resourceResolveData &&
|
||||
module.resourceResolveData.encoding === encoding
|
||||
module.resourceResolveData.encoding === encoding &&
|
||||
decodeDataUriContent(
|
||||
module.resourceResolveData.encoding,
|
||||
module.resourceResolveData.encodedContent
|
||||
).equals(originalSource.buffer())
|
||||
) {
|
||||
encodedContent = module.resourceResolveData.encodedContent;
|
||||
} else {
|
||||
switch (encoding) {
|
||||
case "base64": {
|
||||
encodedContent = originalSource.buffer().toString("base64");
|
||||
break;
|
||||
}
|
||||
case false: {
|
||||
const content = originalSource.source();
|
||||
|
||||
if (typeof content !== "string") {
|
||||
encodedContent = content.toString("utf-8");
|
||||
}
|
||||
|
||||
encodedContent = encodeURIComponent(encodedContent).replace(
|
||||
/[!'()*]/g,
|
||||
character => "%" + character.codePointAt(0).toString(16)
|
||||
);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new Error(`Unsupported encoding '${encoding}'`);
|
||||
}
|
||||
encodedContent = encodeDataUri(encoding, originalSource);
|
||||
}
|
||||
|
||||
encodedSource = `data:${mimeType}${
|
||||
encoding ? `;${encoding}` : ""
|
||||
},${encodedContent}`;
|
||||
}
|
||||
const data = getData();
|
||||
data.set("url", Buffer.from(encodedSource));
|
||||
return new RawSource(
|
||||
`${RuntimeGlobals.module}.exports = ${JSON.stringify(
|
||||
encodedSource
|
||||
|
|
@ -207,16 +271,15 @@ class AssetGenerator extends Generator {
|
|||
const fullHash = /** @type {string} */ (
|
||||
hash.digest(runtimeTemplate.outputOptions.hashDigest)
|
||||
);
|
||||
const contentHash = fullHash.slice(
|
||||
0,
|
||||
const contentHash = nonNumericOnlyHash(
|
||||
fullHash,
|
||||
runtimeTemplate.outputOptions.hashDigestLength
|
||||
);
|
||||
module.buildInfo.fullContentHash = fullHash;
|
||||
const sourceFilename = makePathsRelative(
|
||||
runtimeTemplate.compilation.compiler.context,
|
||||
module.matchResource || module.resource,
|
||||
runtimeTemplate.compilation.compiler.root
|
||||
).replace(/^\.\//, "");
|
||||
const sourceFilename = this.getSourceFileName(
|
||||
module,
|
||||
runtimeTemplate
|
||||
);
|
||||
let { path: filename, info: assetInfo } =
|
||||
runtimeTemplate.compilation.getAssetPathWithInfo(
|
||||
assetModuleFilename,
|
||||
|
|
@ -254,6 +317,21 @@ class AssetGenerator extends Generator {
|
|||
sourceFilename,
|
||||
...assetInfo
|
||||
};
|
||||
if (this.outputPath) {
|
||||
const { path: outputPath, info } =
|
||||
runtimeTemplate.compilation.getAssetPathWithInfo(
|
||||
this.outputPath,
|
||||
{
|
||||
module,
|
||||
runtime,
|
||||
filename: sourceFilename,
|
||||
chunkGraph,
|
||||
contentHash
|
||||
}
|
||||
);
|
||||
assetInfo = mergeAssetInfo(assetInfo, info);
|
||||
filename = path.posix.join(outputPath, filename);
|
||||
}
|
||||
module.buildInfo.filename = filename;
|
||||
module.buildInfo.assetInfo = assetInfo;
|
||||
if (getData) {
|
||||
|
|
@ -327,8 +405,59 @@ class AssetGenerator extends Generator {
|
|||
* @param {Hash} hash hash that will be modified
|
||||
* @param {UpdateHashContext} updateHashContext context for updating hash
|
||||
*/
|
||||
updateHash(hash, { module }) {
|
||||
hash.update(module.buildInfo.dataUrl ? "data-url" : "resource");
|
||||
updateHash(hash, { module, runtime, runtimeTemplate, chunkGraph }) {
|
||||
if (module.buildInfo.dataUrl) {
|
||||
hash.update("data-url");
|
||||
// this.dataUrlOptions as function should be pure and only depend on input source and filename
|
||||
// therefore it doesn't need to be hashed
|
||||
if (typeof this.dataUrlOptions === "function") {
|
||||
const ident = /** @type {{ ident?: string }} */ (this.dataUrlOptions)
|
||||
.ident;
|
||||
if (ident) hash.update(ident);
|
||||
} else {
|
||||
if (
|
||||
this.dataUrlOptions.encoding &&
|
||||
this.dataUrlOptions.encoding !== DEFAULT_ENCODING
|
||||
) {
|
||||
hash.update(this.dataUrlOptions.encoding);
|
||||
}
|
||||
if (this.dataUrlOptions.mimetype)
|
||||
hash.update(this.dataUrlOptions.mimetype);
|
||||
// computed mimetype depends only on module filename which is already part of the hash
|
||||
}
|
||||
} else {
|
||||
hash.update("resource");
|
||||
|
||||
const pathData = {
|
||||
module,
|
||||
runtime,
|
||||
filename: this.getSourceFileName(module, runtimeTemplate),
|
||||
chunkGraph,
|
||||
contentHash: runtimeTemplate.contentHashReplacement
|
||||
};
|
||||
|
||||
if (typeof this.publicPath === "function") {
|
||||
hash.update("path");
|
||||
const assetInfo = {};
|
||||
hash.update(this.publicPath(pathData, assetInfo));
|
||||
hash.update(JSON.stringify(assetInfo));
|
||||
} else if (this.publicPath) {
|
||||
hash.update("path");
|
||||
hash.update(this.publicPath);
|
||||
} else {
|
||||
hash.update("no-path");
|
||||
}
|
||||
|
||||
const assetModuleFilename =
|
||||
this.filename || runtimeTemplate.outputOptions.assetModuleFilename;
|
||||
const { path: filename, info } =
|
||||
runtimeTemplate.compilation.getAssetPathWithInfo(
|
||||
assetModuleFilename,
|
||||
pathData
|
||||
);
|
||||
hash.update(filename);
|
||||
hash.update(JSON.stringify(info));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -137,9 +137,11 @@ class AssetModulesPlugin {
|
|||
|
||||
let filename = undefined;
|
||||
let publicPath = undefined;
|
||||
let outputPath = undefined;
|
||||
if (type !== "asset/inline") {
|
||||
filename = generatorOptions.filename;
|
||||
publicPath = generatorOptions.publicPath;
|
||||
outputPath = generatorOptions.outputPath;
|
||||
}
|
||||
|
||||
const AssetGenerator = getAssetGenerator();
|
||||
|
|
@ -148,6 +150,7 @@ class AssetModulesPlugin {
|
|||
dataUrl,
|
||||
filename,
|
||||
publicPath,
|
||||
outputPath,
|
||||
generatorOptions.emit !== false
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const { RawSource } = require("webpack-sources");
|
||||
const Module = require("../Module");
|
||||
const RuntimeGlobals = require("../RuntimeGlobals");
|
||||
const makeSerializable = require("../util/makeSerializable");
|
||||
|
||||
/** @typedef {import("../../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
|
||||
/** @typedef {import("../Compilation")} Compilation */
|
||||
/** @typedef {import("../Dependency").UpdateHashContext} UpdateHashContext */
|
||||
/** @typedef {import("../Module").CodeGenerationContext} CodeGenerationContext */
|
||||
/** @typedef {import("../Module").CodeGenerationResult} CodeGenerationResult */
|
||||
/** @typedef {import("../Module").NeedBuildContext} NeedBuildContext */
|
||||
/** @typedef {import("../RequestShortener")} RequestShortener */
|
||||
/** @typedef {import("../ResolverFactory").ResolverWithOptions} ResolverWithOptions */
|
||||
/** @typedef {import("../WebpackError")} WebpackError */
|
||||
/** @typedef {import("../util/Hash")} Hash */
|
||||
/** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */
|
||||
|
||||
const TYPES = new Set(["javascript"]);
|
||||
|
||||
class RawDataUrlModule extends Module {
|
||||
/**
|
||||
* @param {string} url raw url
|
||||
* @param {string} identifier unique identifier
|
||||
* @param {string=} readableIdentifier readable identifier
|
||||
*/
|
||||
constructor(url, identifier, readableIdentifier) {
|
||||
super("asset/raw-data-url", null);
|
||||
this.url = url;
|
||||
this.urlBuffer = url ? Buffer.from(url) : undefined;
|
||||
this.identifierStr = identifier || this.url;
|
||||
this.readableIdentifierStr = readableIdentifier || this.identifierStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Set<string>} types available (do not mutate)
|
||||
*/
|
||||
getSourceTypes() {
|
||||
return TYPES;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string} a unique identifier of the module
|
||||
*/
|
||||
identifier() {
|
||||
return this.identifierStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string=} type the source type for which the size should be estimated
|
||||
* @returns {number} the estimated size of the module (must be non-zero)
|
||||
*/
|
||||
size(type) {
|
||||
if (this.url === undefined) this.url = this.urlBuffer.toString();
|
||||
return Math.max(1, this.url.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {RequestShortener} requestShortener the request shortener
|
||||
* @returns {string} a user readable identifier of the module
|
||||
*/
|
||||
readableIdentifier(requestShortener) {
|
||||
return requestShortener.shorten(this.readableIdentifierStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {NeedBuildContext} context context info
|
||||
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
||||
* @returns {void}
|
||||
*/
|
||||
needBuild(context, callback) {
|
||||
return callback(null, !this.buildMeta);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {WebpackOptions} options webpack options
|
||||
* @param {Compilation} compilation the compilation
|
||||
* @param {ResolverWithOptions} resolver the resolver
|
||||
* @param {InputFileSystem} fs the file system
|
||||
* @param {function(WebpackError=): void} callback callback function
|
||||
* @returns {void}
|
||||
*/
|
||||
build(options, compilation, resolver, fs, callback) {
|
||||
this.buildMeta = {};
|
||||
this.buildInfo = {
|
||||
cacheable: true
|
||||
};
|
||||
callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {CodeGenerationContext} context context for code generation
|
||||
* @returns {CodeGenerationResult} result
|
||||
*/
|
||||
codeGeneration(context) {
|
||||
if (this.url === undefined) this.url = this.urlBuffer.toString();
|
||||
const sources = new Map();
|
||||
sources.set(
|
||||
"javascript",
|
||||
new RawSource(`module.exports = ${JSON.stringify(this.url)};`)
|
||||
);
|
||||
const data = new Map();
|
||||
data.set("url", this.urlBuffer);
|
||||
const runtimeRequirements = new Set();
|
||||
runtimeRequirements.add(RuntimeGlobals.module);
|
||||
return { sources, runtimeRequirements, data };
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Hash} hash the hash used to track dependencies
|
||||
* @param {UpdateHashContext} context context
|
||||
* @returns {void}
|
||||
*/
|
||||
updateHash(hash, context) {
|
||||
hash.update(this.urlBuffer);
|
||||
super.updateHash(hash, context);
|
||||
}
|
||||
|
||||
serialize(context) {
|
||||
const { write } = context;
|
||||
|
||||
write(this.urlBuffer);
|
||||
write(this.identifierStr);
|
||||
write(this.readableIdentifierStr);
|
||||
|
||||
super.serialize(context);
|
||||
}
|
||||
|
||||
deserialize(context) {
|
||||
const { read } = context;
|
||||
|
||||
this.urlBuffer = read();
|
||||
this.identifierStr = read();
|
||||
this.readableIdentifierStr = read();
|
||||
|
||||
super.deserialize(context);
|
||||
}
|
||||
}
|
||||
|
||||
makeSerializable(RawDataUrlModule, "webpack/lib/asset/RawDataUrlModule");
|
||||
|
||||
module.exports = RawDataUrlModule;
|
||||
|
|
@ -30,8 +30,8 @@ class AwaitDependenciesInitFragment extends InitFragment {
|
|||
}
|
||||
|
||||
merge(other) {
|
||||
const promises = new Set(this.promises);
|
||||
for (const p of other.promises) {
|
||||
const promises = new Set(other.promises);
|
||||
for (const p of this.promises) {
|
||||
promises.add(p);
|
||||
}
|
||||
return new AwaitDependenciesInitFragment(promises);
|
||||
|
|
@ -51,7 +51,7 @@ class AwaitDependenciesInitFragment extends InitFragment {
|
|||
for (const p of promises) {
|
||||
return Template.asString([
|
||||
`var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([${p}]);`,
|
||||
`${p} = (__webpack_async_dependencies__.then ? await __webpack_async_dependencies__ : __webpack_async_dependencies__)[0];`,
|
||||
`${p} = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];`,
|
||||
""
|
||||
]);
|
||||
}
|
||||
|
|
@ -60,7 +60,7 @@ class AwaitDependenciesInitFragment extends InitFragment {
|
|||
// TODO check if destructuring is supported
|
||||
return Template.asString([
|
||||
`var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([${sepPromises}]);`,
|
||||
`([${sepPromises}] = __webpack_async_dependencies__.then ? await __webpack_async_dependencies__ : __webpack_async_dependencies__);`,
|
||||
`([${sepPromises}] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__);`,
|
||||
""
|
||||
]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -905,7 +905,7 @@ const visitModules = (
|
|||
const module = it.value;
|
||||
if (
|
||||
availableModules.has(module) ||
|
||||
availableModules.plus.has(m)
|
||||
availableModules.plus.has(module)
|
||||
) {
|
||||
cachedMinAvailableModules.add(module);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -639,10 +639,14 @@ class PackContentItems {
|
|||
} catch (e) {
|
||||
rollback(s);
|
||||
if (e === NOT_SERIALIZABLE) continue;
|
||||
logger.warn(
|
||||
`Skipped not serializable cache item '${key}': ${e.message}`
|
||||
);
|
||||
logger.debug(e.stack);
|
||||
const msg = "Skipped not serializable cache item";
|
||||
if (e.message.includes("ModuleBuildError")) {
|
||||
logger.log(`${msg} (in build error): ${e.message}`);
|
||||
logger.debug(`${msg} '${key}' (in build error): ${e.stack}`);
|
||||
} else {
|
||||
logger.warn(`${msg}: ${e.message}`);
|
||||
logger.debug(`${msg} '${key}': ${e.stack}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
write(null);
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ class ResolverCachePlugin {
|
|||
* @param {Resolver} resolver the resolver
|
||||
* @param {Object} resolveContext context for resolving meta info
|
||||
* @param {Object} request the request info object
|
||||
* @param {function(Error=, Object=): void} callback callback function
|
||||
* @param {function((Error | null)=, Object=): void} callback callback function
|
||||
* @returns {void}
|
||||
*/
|
||||
const doRealResolve = (
|
||||
|
|
@ -128,6 +128,13 @@ class ResolverCachePlugin {
|
|||
fileDependencies: new LazySet(),
|
||||
contextDependencies: new LazySet()
|
||||
};
|
||||
let yieldResult;
|
||||
let withYield = false;
|
||||
if (typeof newResolveContext.yield === "function") {
|
||||
yieldResult = [];
|
||||
withYield = true;
|
||||
newResolveContext.yield = obj => yieldResult.push(obj);
|
||||
}
|
||||
const propagate = key => {
|
||||
if (resolveContext[key]) {
|
||||
addAllToSet(resolveContext[key], newResolveContext[key]);
|
||||
|
|
@ -155,15 +162,22 @@ class ResolverCachePlugin {
|
|||
snapshotOptions,
|
||||
(err, snapshot) => {
|
||||
if (err) return callback(err);
|
||||
const resolveResult = withYield ? yieldResult : result;
|
||||
// since we intercept resolve hook
|
||||
// we still can get result in callback
|
||||
if (withYield && result) yieldResult.push(result);
|
||||
if (!snapshot) {
|
||||
if (result) return callback(null, result);
|
||||
if (resolveResult) return callback(null, resolveResult);
|
||||
return callback();
|
||||
}
|
||||
itemCache.store(new CacheEntry(result, snapshot), storeErr => {
|
||||
if (storeErr) return callback(storeErr);
|
||||
if (result) return callback(null, result);
|
||||
callback();
|
||||
});
|
||||
itemCache.store(
|
||||
new CacheEntry(resolveResult, snapshot),
|
||||
storeErr => {
|
||||
if (storeErr) return callback(storeErr);
|
||||
if (resolveResult) return callback(null, resolveResult);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
@ -173,6 +187,8 @@ class ResolverCachePlugin {
|
|||
factory(type, hook) {
|
||||
/** @type {Map<string, (function(Error=, Object=): void)[]>} */
|
||||
const activeRequests = new Map();
|
||||
/** @type {Map<string, [function(Error=, Object=): void, function(Error=, Object=): void][]>} */
|
||||
const activeRequestsWithYield = new Map();
|
||||
hook.tap(
|
||||
"ResolverCachePlugin",
|
||||
/**
|
||||
|
|
@ -197,29 +213,67 @@ class ResolverCachePlugin {
|
|||
if (request._ResolverCachePluginCacheMiss || !fileSystemInfo) {
|
||||
return callback();
|
||||
}
|
||||
const identifier = `${type}${optionsIdent}${objectToString(
|
||||
request,
|
||||
!cacheWithContext
|
||||
)}`;
|
||||
const activeRequest = activeRequests.get(identifier);
|
||||
if (activeRequest) {
|
||||
activeRequest.push(callback);
|
||||
return;
|
||||
const withYield = typeof resolveContext.yield === "function";
|
||||
const identifier = `${type}${
|
||||
withYield ? "|yield" : "|default"
|
||||
}${optionsIdent}${objectToString(request, !cacheWithContext)}`;
|
||||
|
||||
if (withYield) {
|
||||
const activeRequest = activeRequestsWithYield.get(identifier);
|
||||
if (activeRequest) {
|
||||
activeRequest[0].push(callback);
|
||||
activeRequest[1].push(resolveContext.yield);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
const activeRequest = activeRequests.get(identifier);
|
||||
if (activeRequest) {
|
||||
activeRequest.push(callback);
|
||||
return;
|
||||
}
|
||||
}
|
||||
const itemCache = cache.getItemCache(identifier, null);
|
||||
let callbacks;
|
||||
const done = (err, result) => {
|
||||
if (callbacks === undefined) {
|
||||
callback(err, result);
|
||||
callbacks = false;
|
||||
} else {
|
||||
for (const callback of callbacks) {
|
||||
callback(err, result);
|
||||
}
|
||||
activeRequests.delete(identifier);
|
||||
callbacks = false;
|
||||
}
|
||||
};
|
||||
let callbacks, yields;
|
||||
const done = withYield
|
||||
? (err, result) => {
|
||||
if (callbacks === undefined) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
} else {
|
||||
if (result)
|
||||
for (const r of result) resolveContext.yield(r);
|
||||
callback(null, null);
|
||||
}
|
||||
yields = undefined;
|
||||
callbacks = false;
|
||||
} else {
|
||||
if (err) {
|
||||
for (const cb of callbacks) cb(err);
|
||||
} else {
|
||||
for (let i = 0; i < callbacks.length; i++) {
|
||||
const cb = callbacks[i];
|
||||
const yield_ = yields[i];
|
||||
if (result) for (const r of result) yield_(r);
|
||||
cb(null, null);
|
||||
}
|
||||
}
|
||||
activeRequestsWithYield.delete(identifier);
|
||||
yields = undefined;
|
||||
callbacks = false;
|
||||
}
|
||||
}
|
||||
: (err, result) => {
|
||||
if (callbacks === undefined) {
|
||||
callback(err, result);
|
||||
callbacks = false;
|
||||
} else {
|
||||
for (const callback of callbacks) {
|
||||
callback(err, result);
|
||||
}
|
||||
activeRequests.delete(identifier);
|
||||
callbacks = false;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @param {Error=} err error if any
|
||||
* @param {CacheEntry=} cacheEntry cache entry
|
||||
|
|
@ -276,7 +330,14 @@ class ResolverCachePlugin {
|
|||
}
|
||||
};
|
||||
itemCache.get(processCacheResult);
|
||||
if (callbacks === undefined) {
|
||||
if (withYield && callbacks === undefined) {
|
||||
callbacks = [callback];
|
||||
yields = [resolveContext.yield];
|
||||
activeRequestsWithYield.set(
|
||||
identifier,
|
||||
/** @type {[any, any]} */ ([callbacks, yields])
|
||||
);
|
||||
} else if (callbacks === undefined) {
|
||||
callbacks = [callback];
|
||||
activeRequests.set(identifier, callbacks);
|
||||
}
|
||||
|
|
|
|||
47
lib/cli.js
47
lib/cli.js
|
|
@ -37,6 +37,7 @@ const webpackSchema = require("../schemas/WebpackOptions.json");
|
|||
/**
|
||||
* @typedef {Object} ArgumentConfig
|
||||
* @property {string} description
|
||||
* @property {string} [negatedDescription]
|
||||
* @property {string} path
|
||||
* @property {boolean} multiple
|
||||
* @property {"enum"|"string"|"path"|"number"|"boolean"|"RegExp"|"reset"} type
|
||||
|
|
@ -96,11 +97,42 @@ const getArguments = (schema = webpackSchema) => {
|
|||
*/
|
||||
const getDescription = path => {
|
||||
for (const { schema } of path) {
|
||||
if (schema.cli && schema.cli.helper) continue;
|
||||
if (schema.cli) {
|
||||
if (schema.cli.helper) continue;
|
||||
if (schema.cli.description) return schema.cli.description;
|
||||
}
|
||||
if (schema.description) return schema.description;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {PathItem[]} path path in the schema
|
||||
* @returns {string | undefined} negative description
|
||||
*/
|
||||
const getNegatedDescription = path => {
|
||||
for (const { schema } of path) {
|
||||
if (schema.cli) {
|
||||
if (schema.cli.helper) continue;
|
||||
if (schema.cli.negatedDescription) return schema.cli.negatedDescription;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {PathItem[]} path path in the schema
|
||||
* @returns {string | undefined} reset description
|
||||
*/
|
||||
const getResetDescription = path => {
|
||||
for (const { schema } of path) {
|
||||
if (schema.cli) {
|
||||
if (schema.cli.helper) continue;
|
||||
if (schema.cli.resetDescription) return schema.cli.resetDescription;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {any} schemaPart schema
|
||||
|
|
@ -142,13 +174,17 @@ const getArguments = (schema = webpackSchema) => {
|
|||
const addResetFlag = path => {
|
||||
const schemaPath = path[0].path;
|
||||
const name = pathToArgumentName(`${schemaPath}.reset`);
|
||||
const description = getDescription(path);
|
||||
const description =
|
||||
getResetDescription(path) ||
|
||||
`Clear all items provided in '${schemaPath}' configuration. ${getDescription(
|
||||
path
|
||||
)}`;
|
||||
flags[name] = {
|
||||
configs: [
|
||||
{
|
||||
type: "reset",
|
||||
multiple: false,
|
||||
description: `Clear all items provided in '${schemaPath}' configuration. ${description}`,
|
||||
description,
|
||||
path: schemaPath
|
||||
}
|
||||
],
|
||||
|
|
@ -167,6 +203,7 @@ const getArguments = (schema = webpackSchema) => {
|
|||
const argConfigBase = schemaToArgumentConfig(path[0].schema);
|
||||
if (!argConfigBase) return 0;
|
||||
|
||||
const negatedDescription = getNegatedDescription(path);
|
||||
const name = pathToArgumentName(path[0].path);
|
||||
/** @type {ArgumentConfig} */
|
||||
const argConfig = {
|
||||
|
|
@ -176,6 +213,10 @@ const getArguments = (schema = webpackSchema) => {
|
|||
path: path[0].path
|
||||
};
|
||||
|
||||
if (negatedDescription) {
|
||||
argConfig.negatedDescription = negatedDescription;
|
||||
}
|
||||
|
||||
if (!flags[name]) {
|
||||
flags[name] = {
|
||||
configs: [],
|
||||
|
|
|
|||
|
|
@ -121,8 +121,7 @@ const resolve = browsers => {
|
|||
// baidu: Not supported
|
||||
// and_uc: Not supported
|
||||
// kaios: Not supported
|
||||
// Since Node.js 13.14.0 no warning about usage, but it was added 8.5.0 with some limitations and it was improved in 12.0.0 and 13.2.0
|
||||
node: [13, 14]
|
||||
node: [12, 17]
|
||||
});
|
||||
|
||||
return {
|
||||
|
|
@ -248,8 +247,7 @@ const resolve = browsers => {
|
|||
// baidu: Not supported
|
||||
// and_uc: Not supported
|
||||
// kaios: Not supported
|
||||
// Since Node.js 13.14.0 no warning about usage, but it was added 8.5.0 with some limitations and it was improved in 12.0.0 and 13.2.0
|
||||
node: [13, 14]
|
||||
node: [12, 17]
|
||||
}),
|
||||
dynamicImport: es6DynamicImport,
|
||||
dynamicImportInWorker: es6DynamicImport && !anyNode,
|
||||
|
|
@ -272,7 +270,7 @@ const resolve = browsers => {
|
|||
// baidu: Unknown support
|
||||
// and_uc: Unknown support
|
||||
// kaios: Unknown support
|
||||
node: [12, 0]
|
||||
node: 12
|
||||
}),
|
||||
optionalChaining: rawChecker({
|
||||
chrome: 80,
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ const {
|
|||
} = require("./target");
|
||||
|
||||
/** @typedef {import("../../declarations/WebpackOptions").CacheOptionsNormalized} CacheOptions */
|
||||
/** @typedef {import("../../declarations/WebpackOptions").CssExperimentOptions} CssExperimentOptions */
|
||||
/** @typedef {import("../../declarations/WebpackOptions").EntryDescription} EntryDescription */
|
||||
/** @typedef {import("../../declarations/WebpackOptions").EntryNormalized} Entry */
|
||||
/** @typedef {import("../../declarations/WebpackOptions").Experiments} Experiments */
|
||||
|
|
@ -160,7 +161,11 @@ const applyWebpackOptionsDefaults = options => {
|
|||
D(options, "recordsInputPath", false);
|
||||
D(options, "recordsOutputPath", false);
|
||||
|
||||
applyExperimentsDefaults(options.experiments, { production, development });
|
||||
applyExperimentsDefaults(options.experiments, {
|
||||
production,
|
||||
development,
|
||||
targetProperties
|
||||
});
|
||||
|
||||
const futureDefaults = options.experiments.futureDefaults;
|
||||
|
||||
|
|
@ -184,6 +189,7 @@ const applyWebpackOptionsDefaults = options => {
|
|||
cache,
|
||||
syncWebAssembly: options.experiments.syncWebAssembly,
|
||||
asyncWebAssembly: options.experiments.asyncWebAssembly,
|
||||
css: options.experiments.css,
|
||||
futureDefaults
|
||||
});
|
||||
|
||||
|
|
@ -240,6 +246,7 @@ const applyWebpackOptionsDefaults = options => {
|
|||
applyOptimizationDefaults(options.optimization, {
|
||||
development,
|
||||
production,
|
||||
css: options.experiments.css,
|
||||
records: !!(options.recordsInputPath || options.recordsOutputPath)
|
||||
});
|
||||
|
||||
|
|
@ -264,9 +271,13 @@ const applyWebpackOptionsDefaults = options => {
|
|||
* @param {Object} options options
|
||||
* @param {boolean} options.production is production
|
||||
* @param {boolean} options.development is development mode
|
||||
* @param {TargetProperties | false} options.targetProperties target properties
|
||||
* @returns {void}
|
||||
*/
|
||||
const applyExperimentsDefaults = (experiments, { production, development }) => {
|
||||
const applyExperimentsDefaults = (
|
||||
experiments,
|
||||
{ production, development, targetProperties }
|
||||
) => {
|
||||
D(experiments, "futureDefaults", false);
|
||||
D(experiments, "backCompat", !experiments.futureDefaults);
|
||||
D(experiments, "topLevelAwait", experiments.futureDefaults);
|
||||
|
|
@ -277,11 +288,20 @@ const applyExperimentsDefaults = (experiments, { production, development }) => {
|
|||
D(experiments, "lazyCompilation", undefined);
|
||||
D(experiments, "buildHttp", undefined);
|
||||
D(experiments, "cacheUnaffected", experiments.futureDefaults);
|
||||
F(experiments, "css", () => (experiments.futureDefaults ? {} : undefined));
|
||||
|
||||
if (typeof experiments.buildHttp === "object") {
|
||||
D(experiments.buildHttp, "frozen", production);
|
||||
D(experiments.buildHttp, "upgrade", false);
|
||||
}
|
||||
|
||||
if (typeof experiments.css === "object") {
|
||||
D(
|
||||
experiments.css,
|
||||
"exportsOnly",
|
||||
!targetProperties || !targetProperties.document
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -450,6 +470,7 @@ const applyJavascriptParserOptionsDefaults = (
|
|||
D(parserOptions, "wrappedContextRecursive", true);
|
||||
D(parserOptions, "wrappedContextCritical", false);
|
||||
D(parserOptions, "strictThisContextOnImports", false);
|
||||
D(parserOptions, "importMeta", true);
|
||||
if (futureDefaults) D(parserOptions, "exportsPresence", "error");
|
||||
};
|
||||
|
||||
|
|
@ -459,12 +480,13 @@ 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 {boolean} options.futureDefaults is future defaults enabled
|
||||
* @returns {void}
|
||||
*/
|
||||
const applyModuleDefaults = (
|
||||
module,
|
||||
{ cache, syncWebAssembly, asyncWebAssembly, futureDefaults }
|
||||
{ cache, syncWebAssembly, asyncWebAssembly, css, futureDefaults }
|
||||
) => {
|
||||
if (cache) {
|
||||
D(module, "unsafeCache", module => {
|
||||
|
|
@ -588,6 +610,41 @@ const applyModuleDefaults = (
|
|||
...wasm
|
||||
});
|
||||
}
|
||||
if (css) {
|
||||
const cssRule = {
|
||||
type: "css",
|
||||
resolve: {
|
||||
fullySpecified: true,
|
||||
preferRelative: true
|
||||
}
|
||||
};
|
||||
const cssModulesRule = {
|
||||
type: "css/module",
|
||||
resolve: {
|
||||
fullySpecified: true
|
||||
}
|
||||
};
|
||||
rules.push({
|
||||
test: /\.css$/i,
|
||||
oneOf: [
|
||||
{
|
||||
test: /\.module\.css$/i,
|
||||
...cssModulesRule
|
||||
},
|
||||
{
|
||||
...cssRule
|
||||
}
|
||||
]
|
||||
});
|
||||
rules.push({
|
||||
mimetype: "text/css+module",
|
||||
...cssModulesRule
|
||||
});
|
||||
rules.push({
|
||||
mimetype: "text/css",
|
||||
...cssRule
|
||||
});
|
||||
}
|
||||
rules.push(
|
||||
{
|
||||
dependency: "url",
|
||||
|
|
@ -659,7 +716,15 @@ const applyOutputDefaults = (
|
|||
};
|
||||
|
||||
F(output, "uniqueName", () => {
|
||||
const libraryName = getLibraryName(output.library);
|
||||
const libraryName = getLibraryName(output.library).replace(
|
||||
/^\[(\\*[\w:]+\\*)\](\.)|(\.)\[(\\*[\w:]+\\*)\](?=\.|$)|\[(\\*[\w:]+\\*)\]/g,
|
||||
(m, a, d1, d2, b, c) => {
|
||||
const content = a || b || c;
|
||||
return content.startsWith("\\") && content.endsWith("\\")
|
||||
? `${d2 || ""}[${content.slice(1, -1)}]${d1 || ""}`
|
||||
: "";
|
||||
}
|
||||
);
|
||||
if (libraryName) return libraryName;
|
||||
const pkgPath = path.resolve(context, "package.json");
|
||||
try {
|
||||
|
|
@ -693,6 +758,20 @@ const applyOutputDefaults = (
|
|||
}
|
||||
return output.module ? "[id].mjs" : "[id].js";
|
||||
});
|
||||
F(output, "cssFilename", () => {
|
||||
const filename = output.filename;
|
||||
if (typeof filename !== "function") {
|
||||
return filename.replace(/\.[mc]?js(\?|$)/, ".css$1");
|
||||
}
|
||||
return "[id].css";
|
||||
});
|
||||
F(output, "cssChunkFilename", () => {
|
||||
const chunkFilename = output.chunkFilename;
|
||||
if (typeof chunkFilename !== "function") {
|
||||
return chunkFilename.replace(/\.[mc]?js(\?|$)/, ".css$1");
|
||||
}
|
||||
return "[id].css";
|
||||
});
|
||||
D(output, "assetModuleFilename", "[hash][ext][query]");
|
||||
D(output, "webassemblyModuleFilename", "[hash].module.wasm");
|
||||
D(output, "compareBeforeEmit", true);
|
||||
|
|
@ -833,10 +912,11 @@ const applyOutputDefaults = (
|
|||
D(output, "chunkLoadTimeout", 120000);
|
||||
D(output, "hashFunction", futureDefaults ? "xxhash64" : "md4");
|
||||
D(output, "hashDigest", "hex");
|
||||
D(output, "hashDigestLength", 20);
|
||||
D(output, "hashDigestLength", futureDefaults ? 16 : 20);
|
||||
D(output, "strictModuleExceptionHandling", false);
|
||||
|
||||
const optimistic = v => v || v === undefined;
|
||||
const conditionallyOptimistic = (v, c) => (v === undefined && c) || v;
|
||||
F(
|
||||
output.environment,
|
||||
"arrowFunction",
|
||||
|
|
@ -850,8 +930,12 @@ const applyOutputDefaults = (
|
|||
);
|
||||
F(output.environment, "forOf", () => tp && optimistic(tp.forOf));
|
||||
F(output.environment, "bigIntLiteral", () => tp && tp.bigIntLiteral);
|
||||
F(output.environment, "dynamicImport", () => tp && tp.dynamicImport);
|
||||
F(output.environment, "module", () => tp && tp.module);
|
||||
F(output.environment, "dynamicImport", () =>
|
||||
conditionallyOptimistic(tp && tp.dynamicImport, output.module)
|
||||
);
|
||||
F(output.environment, "module", () =>
|
||||
conditionallyOptimistic(tp && tp.module, output.module)
|
||||
);
|
||||
|
||||
const { trustedTypes } = output;
|
||||
if (trustedTypes) {
|
||||
|
|
@ -1035,12 +1119,13 @@ 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 {boolean} options.records using records
|
||||
* @returns {void}
|
||||
*/
|
||||
const applyOptimizationDefaults = (
|
||||
optimization,
|
||||
{ production, development, records }
|
||||
{ production, development, css, records }
|
||||
) => {
|
||||
D(optimization, "removeAvailableModules", false);
|
||||
D(optimization, "removeEmptyChunks", true);
|
||||
|
|
@ -1091,7 +1176,9 @@ const applyOptimizationDefaults = (
|
|||
});
|
||||
const { splitChunks } = optimization;
|
||||
if (splitChunks) {
|
||||
A(splitChunks, "defaultSizeTypes", () => ["javascript", "unknown"]);
|
||||
A(splitChunks, "defaultSizeTypes", () =>
|
||||
css ? ["javascript", "css", "unknown"] : ["javascript", "unknown"]
|
||||
);
|
||||
D(splitChunks, "hidePathInfo", production);
|
||||
D(splitChunks, "chunks", "async");
|
||||
D(splitChunks, "usedExports", optimization.usedExports === true);
|
||||
|
|
|
|||
|
|
@ -180,6 +180,9 @@ const getNormalizedWebpackOptions = config => {
|
|||
experiments.lazyCompilation,
|
||||
options =>
|
||||
options === true ? {} : options === false ? undefined : options
|
||||
),
|
||||
css: optionalNestedConfig(experiments.css, options =>
|
||||
options === true ? {} : options === false ? undefined : options
|
||||
)
|
||||
})),
|
||||
externals: config.externals,
|
||||
|
|
@ -297,6 +300,8 @@ const getNormalizedWebpackOptions = config => {
|
|||
chunkLoading: output.chunkLoading,
|
||||
chunkLoadingGlobal: output.chunkLoadingGlobal,
|
||||
chunkLoadTimeout: output.chunkLoadTimeout,
|
||||
cssFilename: output.cssFilename,
|
||||
cssChunkFilename: output.cssChunkFilename,
|
||||
clean: output.clean,
|
||||
compareBeforeEmit: output.compareBeforeEmit,
|
||||
crossOriginLoading: output.crossOriginLoading,
|
||||
|
|
@ -483,6 +488,7 @@ const getNormalizedEntryStatic = entry => {
|
|||
filename: value.filename,
|
||||
layer: value.layer,
|
||||
runtime: value.runtime,
|
||||
baseUri: value.baseUri,
|
||||
publicPath: value.publicPath,
|
||||
chunkLoading: value.chunkLoading,
|
||||
asyncChunks: value.asyncChunks,
|
||||
|
|
|
|||
|
|
@ -79,12 +79,14 @@ class ContainerEntryModule extends Module {
|
|||
* @returns {string | null} an identifier for library inclusion
|
||||
*/
|
||||
libIdent(options) {
|
||||
return `webpack/container/entry/${this._name}`;
|
||||
return `${this.layer ? `(${this.layer})/` : ""}webpack/container/entry/${
|
||||
this._name
|
||||
}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {NeedBuildContext} context context info
|
||||
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
||||
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
||||
* @returns {void}
|
||||
*/
|
||||
needBuild(context, callback) {
|
||||
|
|
|
|||
|
|
@ -60,9 +60,9 @@ class FallbackModule extends Module {
|
|||
* @returns {string | null} an identifier for library inclusion
|
||||
*/
|
||||
libIdent(options) {
|
||||
return `webpack/container/fallback/${this.requests[0]}/and ${
|
||||
this.requests.length - 1
|
||||
} more`;
|
||||
return `${this.layer ? `(${this.layer})/` : ""}webpack/container/fallback/${
|
||||
this.requests[0]
|
||||
}/and ${this.requests.length - 1} more`;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -76,7 +76,7 @@ class FallbackModule extends Module {
|
|||
|
||||
/**
|
||||
* @param {NeedBuildContext} context context info
|
||||
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
||||
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
||||
* @returns {void}
|
||||
*/
|
||||
needBuild(context, callback) {
|
||||
|
|
|
|||
|
|
@ -67,12 +67,14 @@ class RemoteModule extends Module {
|
|||
* @returns {string | null} an identifier for library inclusion
|
||||
*/
|
||||
libIdent(options) {
|
||||
return `webpack/container/remote/${this.request}`;
|
||||
return `${this.layer ? `(${this.layer})/` : ""}webpack/container/remote/${
|
||||
this.request
|
||||
}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {NeedBuildContext} context context info
|
||||
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
||||
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
||||
* @returns {void}
|
||||
*/
|
||||
needBuild(context, callback) {
|
||||
|
|
|
|||
|
|
@ -73,9 +73,9 @@ class RemoteRuntimeModule extends RuntimeModule {
|
|||
Template.indent(
|
||||
`error.message += '\\nwhile loading "' + data[1] + '" from ' + data[2];`
|
||||
),
|
||||
`__webpack_modules__[id] = ${runtimeTemplate.basicFunction("", [
|
||||
"throw error;"
|
||||
])}`,
|
||||
`${
|
||||
RuntimeGlobals.moduleFactories
|
||||
}[id] = ${runtimeTemplate.basicFunction("", ["throw error;"])}`,
|
||||
"data.p = 0;"
|
||||
])};`,
|
||||
`var handleFunction = ${runtimeTemplate.basicFunction(
|
||||
|
|
@ -111,10 +111,11 @@ class RemoteRuntimeModule extends RuntimeModule {
|
|||
)};`,
|
||||
`var onFactory = ${runtimeTemplate.basicFunction("factory", [
|
||||
"data.p = 1;",
|
||||
`__webpack_modules__[id] = ${runtimeTemplate.basicFunction(
|
||||
"module",
|
||||
["module.exports = factory();"]
|
||||
)}`
|
||||
`${
|
||||
RuntimeGlobals.moduleFactories
|
||||
}[id] = ${runtimeTemplate.basicFunction("module", [
|
||||
"module.exports = factory();"
|
||||
])}`
|
||||
])};`,
|
||||
"handleFunction(__webpack_require__, data[2], 0, 0, onExternal, 1);"
|
||||
])});`
|
||||
|
|
|
|||
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Sergey Melyukov @smelukov
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const { ReplaceSource, RawSource, ConcatSource } = require("webpack-sources");
|
||||
const { UsageState } = require("../ExportsInfo");
|
||||
const Generator = require("../Generator");
|
||||
const RuntimeGlobals = require("../RuntimeGlobals");
|
||||
const Template = require("../Template");
|
||||
|
||||
/** @typedef {import("webpack-sources").Source} Source */
|
||||
/** @typedef {import("../Dependency")} Dependency */
|
||||
/** @typedef {import("../Generator").GenerateContext} GenerateContext */
|
||||
/** @typedef {import("../Generator").UpdateHashContext} UpdateHashContext */
|
||||
/** @typedef {import("../Module").ConcatenationBailoutReasonContext} ConcatenationBailoutReasonContext */
|
||||
/** @typedef {import("../NormalModule")} NormalModule */
|
||||
/** @typedef {import("../util/Hash")} Hash */
|
||||
|
||||
const TYPES = new Set(["javascript"]);
|
||||
|
||||
class CssExportsGenerator extends Generator {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
// TODO add getConcatenationBailoutReason to allow concatenation
|
||||
// but how to make it have a module id
|
||||
|
||||
/**
|
||||
* @param {NormalModule} module module for which the code should be generated
|
||||
* @param {GenerateContext} generateContext context for generate
|
||||
* @returns {Source} generated code
|
||||
*/
|
||||
generate(module, generateContext) {
|
||||
const source = new ReplaceSource(new RawSource(""));
|
||||
const initFragments = [];
|
||||
const cssExports = new Map();
|
||||
|
||||
generateContext.runtimeRequirements.add(RuntimeGlobals.module);
|
||||
|
||||
let chunkInitFragments;
|
||||
const runtimeRequirements = new Set();
|
||||
|
||||
const templateContext = {
|
||||
runtimeTemplate: generateContext.runtimeTemplate,
|
||||
dependencyTemplates: generateContext.dependencyTemplates,
|
||||
moduleGraph: generateContext.moduleGraph,
|
||||
chunkGraph: generateContext.chunkGraph,
|
||||
module,
|
||||
runtime: generateContext.runtime,
|
||||
runtimeRequirements: runtimeRequirements,
|
||||
concatenationScope: generateContext.concatenationScope,
|
||||
codeGenerationResults: generateContext.codeGenerationResults,
|
||||
initFragments,
|
||||
cssExports,
|
||||
get chunkInitFragments() {
|
||||
if (!chunkInitFragments) {
|
||||
const data = generateContext.getData();
|
||||
chunkInitFragments = data.get("chunkInitFragments");
|
||||
if (!chunkInitFragments) {
|
||||
chunkInitFragments = [];
|
||||
data.set("chunkInitFragments", chunkInitFragments);
|
||||
}
|
||||
}
|
||||
|
||||
return chunkInitFragments;
|
||||
}
|
||||
};
|
||||
|
||||
const handleDependency = dependency => {
|
||||
const constructor = /** @type {new (...args: any[]) => Dependency} */ (
|
||||
dependency.constructor
|
||||
);
|
||||
const template = generateContext.dependencyTemplates.get(constructor);
|
||||
if (!template) {
|
||||
throw new Error(
|
||||
"No template for dependency: " + dependency.constructor.name
|
||||
);
|
||||
}
|
||||
|
||||
template.apply(dependency, source, templateContext);
|
||||
};
|
||||
module.dependencies.forEach(handleDependency);
|
||||
|
||||
if (generateContext.concatenationScope) {
|
||||
const source = new ConcatSource();
|
||||
const usedIdentifiers = new Set();
|
||||
for (const [k, v] of cssExports) {
|
||||
let identifier = Template.toIdentifier(k);
|
||||
let i = 0;
|
||||
while (usedIdentifiers.has(identifier)) {
|
||||
identifier = Template.toIdentifier(k + i);
|
||||
}
|
||||
usedIdentifiers.add(identifier);
|
||||
generateContext.concatenationScope.registerExport(k, identifier);
|
||||
source.add(
|
||||
`${
|
||||
generateContext.runtimeTemplate.supportsConst ? "const" : "var"
|
||||
} ${identifier} = ${JSON.stringify(v)};\n`
|
||||
);
|
||||
}
|
||||
return source;
|
||||
} else {
|
||||
const otherUsed =
|
||||
generateContext.moduleGraph
|
||||
.getExportsInfo(module)
|
||||
.otherExportsInfo.getUsed(generateContext.runtime) !==
|
||||
UsageState.Unused;
|
||||
if (otherUsed) {
|
||||
generateContext.runtimeRequirements.add(
|
||||
RuntimeGlobals.makeNamespaceObject
|
||||
);
|
||||
}
|
||||
return new RawSource(
|
||||
`${otherUsed ? `${RuntimeGlobals.makeNamespaceObject}(` : ""}${
|
||||
module.moduleArgument
|
||||
}.exports = {\n${Array.from(
|
||||
cssExports,
|
||||
([k, v]) => `\t${JSON.stringify(k)}: ${JSON.stringify(v)}`
|
||||
).join(",\n")}\n}${otherUsed ? ")" : ""};`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {NormalModule} module fresh module
|
||||
* @returns {Set<string>} available types (do not mutate)
|
||||
*/
|
||||
getTypes(module) {
|
||||
return TYPES;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {NormalModule} module the module
|
||||
* @param {string=} type source type
|
||||
* @returns {number} estimate size of the module
|
||||
*/
|
||||
getSize(module, type) {
|
||||
return 42;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Hash} hash hash that will be modified
|
||||
* @param {UpdateHashContext} updateHashContext context for updating hash
|
||||
*/
|
||||
updateHash(hash, { module }) {}
|
||||
}
|
||||
|
||||
module.exports = CssExportsGenerator;
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Sergey Melyukov @smelukov
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const { ReplaceSource } = require("webpack-sources");
|
||||
const Generator = require("../Generator");
|
||||
const InitFragment = require("../InitFragment");
|
||||
const RuntimeGlobals = require("../RuntimeGlobals");
|
||||
|
||||
/** @typedef {import("webpack-sources").Source} Source */
|
||||
/** @typedef {import("../Dependency")} Dependency */
|
||||
/** @typedef {import("../Generator").GenerateContext} GenerateContext */
|
||||
/** @typedef {import("../Generator").UpdateHashContext} UpdateHashContext */
|
||||
/** @typedef {import("../NormalModule")} NormalModule */
|
||||
/** @typedef {import("../util/Hash")} Hash */
|
||||
|
||||
const TYPES = new Set(["css"]);
|
||||
|
||||
class CssGenerator extends Generator {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {NormalModule} module module for which the code should be generated
|
||||
* @param {GenerateContext} generateContext context for generate
|
||||
* @returns {Source} generated code
|
||||
*/
|
||||
generate(module, generateContext) {
|
||||
const originalSource = module.originalSource();
|
||||
const source = new ReplaceSource(originalSource);
|
||||
const initFragments = [];
|
||||
const cssExports = new Map();
|
||||
|
||||
generateContext.runtimeRequirements.add(RuntimeGlobals.hasCssModules);
|
||||
|
||||
let chunkInitFragments;
|
||||
const templateContext = {
|
||||
runtimeTemplate: generateContext.runtimeTemplate,
|
||||
dependencyTemplates: generateContext.dependencyTemplates,
|
||||
moduleGraph: generateContext.moduleGraph,
|
||||
chunkGraph: generateContext.chunkGraph,
|
||||
module,
|
||||
runtime: generateContext.runtime,
|
||||
runtimeRequirements: generateContext.runtimeRequirements,
|
||||
concatenationScope: generateContext.concatenationScope,
|
||||
codeGenerationResults: generateContext.codeGenerationResults,
|
||||
initFragments,
|
||||
cssExports,
|
||||
get chunkInitFragments() {
|
||||
if (!chunkInitFragments) {
|
||||
const data = generateContext.getData();
|
||||
chunkInitFragments = data.get("chunkInitFragments");
|
||||
if (!chunkInitFragments) {
|
||||
chunkInitFragments = [];
|
||||
data.set("chunkInitFragments", chunkInitFragments);
|
||||
}
|
||||
}
|
||||
|
||||
return chunkInitFragments;
|
||||
}
|
||||
};
|
||||
|
||||
const handleDependency = dependency => {
|
||||
const constructor = /** @type {new (...args: any[]) => Dependency} */ (
|
||||
dependency.constructor
|
||||
);
|
||||
const template = generateContext.dependencyTemplates.get(constructor);
|
||||
if (!template) {
|
||||
throw new Error(
|
||||
"No template for dependency: " + dependency.constructor.name
|
||||
);
|
||||
}
|
||||
|
||||
template.apply(dependency, source, templateContext);
|
||||
};
|
||||
module.dependencies.forEach(handleDependency);
|
||||
if (module.presentationalDependencies !== undefined)
|
||||
module.presentationalDependencies.forEach(handleDependency);
|
||||
|
||||
if (cssExports.size > 0) {
|
||||
const data = generateContext.getData();
|
||||
data.set("css-exports", cssExports);
|
||||
}
|
||||
|
||||
return InitFragment.addToSource(source, initFragments, generateContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {NormalModule} module fresh module
|
||||
* @returns {Set<string>} available types (do not mutate)
|
||||
*/
|
||||
getTypes(module) {
|
||||
return TYPES;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {NormalModule} module the module
|
||||
* @param {string=} type source type
|
||||
* @returns {number} estimate size of the module
|
||||
*/
|
||||
getSize(module, type) {
|
||||
const originalSource = module.originalSource();
|
||||
|
||||
if (!originalSource) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return originalSource.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Hash} hash hash that will be modified
|
||||
* @param {UpdateHashContext} updateHashContext context for updating hash
|
||||
*/
|
||||
updateHash(hash, { module }) {}
|
||||
}
|
||||
|
||||
module.exports = CssGenerator;
|
||||
|
|
@ -0,0 +1,440 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const { SyncWaterfallHook } = require("tapable");
|
||||
const Compilation = require("../Compilation");
|
||||
const RuntimeGlobals = require("../RuntimeGlobals");
|
||||
const RuntimeModule = require("../RuntimeModule");
|
||||
const Template = require("../Template");
|
||||
const compileBooleanMatcher = require("../util/compileBooleanMatcher");
|
||||
const { chunkHasCss } = require("./CssModulesPlugin");
|
||||
|
||||
/** @typedef {import("../Chunk")} Chunk */
|
||||
|
||||
/**
|
||||
* @typedef {Object} JsonpCompilationPluginHooks
|
||||
* @property {SyncWaterfallHook<[string, Chunk]>} createStylesheet
|
||||
*/
|
||||
|
||||
/** @type {WeakMap<Compilation, JsonpCompilationPluginHooks>} */
|
||||
const compilationHooksMap = new WeakMap();
|
||||
|
||||
class CssLoadingRuntimeModule extends RuntimeModule {
|
||||
/**
|
||||
* @param {Compilation} compilation the compilation
|
||||
* @returns {JsonpCompilationPluginHooks} hooks
|
||||
*/
|
||||
static getCompilationHooks(compilation) {
|
||||
if (!(compilation instanceof Compilation)) {
|
||||
throw new TypeError(
|
||||
"The 'compilation' argument must be an instance of Compilation"
|
||||
);
|
||||
}
|
||||
let hooks = compilationHooksMap.get(compilation);
|
||||
if (hooks === undefined) {
|
||||
hooks = {
|
||||
createStylesheet: new SyncWaterfallHook(["source", "chunk"])
|
||||
};
|
||||
compilationHooksMap.set(compilation, hooks);
|
||||
}
|
||||
return hooks;
|
||||
}
|
||||
|
||||
constructor(runtimeRequirements, runtimeOptions) {
|
||||
super("css loading", 10);
|
||||
|
||||
this._runtimeRequirements = runtimeRequirements;
|
||||
this.runtimeOptions = runtimeOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string} runtime code
|
||||
*/
|
||||
generate() {
|
||||
const { compilation, chunk, _runtimeRequirements } = this;
|
||||
const {
|
||||
chunkGraph,
|
||||
runtimeTemplate,
|
||||
outputOptions: {
|
||||
crossOriginLoading,
|
||||
uniqueName,
|
||||
chunkLoadTimeout: loadTimeout
|
||||
}
|
||||
} = compilation;
|
||||
const fn = RuntimeGlobals.ensureChunkHandlers;
|
||||
const conditionMap = chunkGraph.getChunkConditionMap(
|
||||
chunk,
|
||||
(chunk, chunkGraph) =>
|
||||
!!chunkGraph.getChunkModulesIterableBySourceType(chunk, "css")
|
||||
);
|
||||
const hasCssMatcher = compileBooleanMatcher(conditionMap);
|
||||
|
||||
const withLoading =
|
||||
_runtimeRequirements.has(RuntimeGlobals.ensureChunkHandlers) &&
|
||||
hasCssMatcher !== false;
|
||||
const withHmr = _runtimeRequirements.has(
|
||||
RuntimeGlobals.hmrDownloadUpdateHandlers
|
||||
);
|
||||
const initialChunkIdsWithCss = new Set();
|
||||
const initialChunkIdsWithoutCss = new Set();
|
||||
for (const c of chunk.getAllInitialChunks()) {
|
||||
(chunkHasCss(c, chunkGraph)
|
||||
? initialChunkIdsWithCss
|
||||
: initialChunkIdsWithoutCss
|
||||
).add(c.id);
|
||||
}
|
||||
|
||||
if (!withLoading && !withHmr && initialChunkIdsWithCss.size === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { createStylesheet } =
|
||||
CssLoadingRuntimeModule.getCompilationHooks(compilation);
|
||||
|
||||
const stateExpression = withHmr
|
||||
? `${RuntimeGlobals.hmrRuntimeStatePrefix}_css`
|
||||
: undefined;
|
||||
|
||||
const code = Template.asString([
|
||||
"link = document.createElement('link');",
|
||||
uniqueName
|
||||
? 'link.setAttribute("data-webpack", uniqueName + ":" + key);'
|
||||
: "",
|
||||
"link.setAttribute(loadingAttribute, 1);",
|
||||
'link.rel = "stylesheet";',
|
||||
"link.href = url;",
|
||||
crossOriginLoading
|
||||
? Template.asString([
|
||||
"if (link.src.indexOf(window.location.origin + '/') !== 0) {",
|
||||
Template.indent(
|
||||
`link.crossOrigin = ${JSON.stringify(crossOriginLoading)};`
|
||||
),
|
||||
"}"
|
||||
])
|
||||
: ""
|
||||
]);
|
||||
|
||||
const cc = str => str.charCodeAt(0);
|
||||
|
||||
return Template.asString([
|
||||
"// object to store loaded and loading chunks",
|
||||
"// undefined = chunk not loaded, null = chunk preloaded/prefetched",
|
||||
"// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded",
|
||||
`var installedChunks = ${
|
||||
stateExpression ? `${stateExpression} = ${stateExpression} || ` : ""
|
||||
}{${Array.from(
|
||||
initialChunkIdsWithoutCss,
|
||||
id => `${JSON.stringify(id)}:0`
|
||||
).join(",")}};`,
|
||||
"",
|
||||
uniqueName
|
||||
? `var uniqueName = ${JSON.stringify(
|
||||
runtimeTemplate.outputOptions.uniqueName
|
||||
)};`
|
||||
: "// data-webpack is not used as build has no uniqueName",
|
||||
`var loadCssChunkData = ${runtimeTemplate.basicFunction(
|
||||
"target, link, chunkId",
|
||||
[
|
||||
`var data, token = "", token2, exports = {}, exportsWithId = [], exportsWithDashes = [], ${
|
||||
withHmr ? "moduleIds = [], " : ""
|
||||
}i = 0, cc = 1;`,
|
||||
"try { if(!link) link = loadStylesheet(chunkId); data = link.sheet.cssRules; data = data[data.length - 1].style; } catch(e) { data = getComputedStyle(document.head); }",
|
||||
`data = data.getPropertyValue(${
|
||||
uniqueName
|
||||
? runtimeTemplate.concatenation(
|
||||
"--webpack-",
|
||||
{ expr: "uniqueName" },
|
||||
"-",
|
||||
{ expr: "chunkId" }
|
||||
)
|
||||
: runtimeTemplate.concatenation("--webpack-", { expr: "chunkId" })
|
||||
});`,
|
||||
"if(!data) return [];",
|
||||
"for(; cc; i++) {",
|
||||
Template.indent([
|
||||
"cc = data.charCodeAt(i);",
|
||||
`if(cc == ${cc("(")}) { token2 = token; token = ""; }`,
|
||||
`else if(cc == ${cc(
|
||||
")"
|
||||
)}) { exports[token2.replace(/^_/, "")] = token.replace(/^_/, ""); token = ""; }`,
|
||||
`else if(cc == ${cc("/")} || cc == ${cc(
|
||||
"%"
|
||||
)}) { token = token.replace(/^_/, ""); exports[token] = token; exportsWithId.push(token); if(cc == ${cc(
|
||||
"%"
|
||||
)}) exportsWithDashes.push(token); token = ""; }`,
|
||||
`else if(!cc || cc == ${cc(
|
||||
","
|
||||
)}) { token = token.replace(/^_/, ""); exportsWithId.forEach(${runtimeTemplate.expressionFunction(
|
||||
`exports[x] = ${
|
||||
uniqueName
|
||||
? runtimeTemplate.concatenation(
|
||||
{ expr: "uniqueName" },
|
||||
"-",
|
||||
{ expr: "token" },
|
||||
"-",
|
||||
{ expr: "exports[x]" }
|
||||
)
|
||||
: runtimeTemplate.concatenation({ expr: "token" }, "-", {
|
||||
expr: "exports[x]"
|
||||
})
|
||||
}`,
|
||||
"x"
|
||||
)}); exportsWithDashes.forEach(${runtimeTemplate.expressionFunction(
|
||||
`exports[x] = "--" + exports[x]`,
|
||||
"x"
|
||||
)}); ${
|
||||
RuntimeGlobals.makeNamespaceObject
|
||||
}(exports); target[token] = (${runtimeTemplate.basicFunction(
|
||||
"exports, module",
|
||||
`module.exports = exports;`
|
||||
)}).bind(null, exports); ${
|
||||
withHmr ? "moduleIds.push(token); " : ""
|
||||
}token = ""; exports = {}; exportsWithId.length = 0; }`,
|
||||
`else if(cc == ${cc("\\")}) { token += data[++i] }`,
|
||||
`else { token += data[i]; }`
|
||||
]),
|
||||
"}",
|
||||
`${
|
||||
withHmr ? `if(target == ${RuntimeGlobals.moduleFactories}) ` : ""
|
||||
}installedChunks[chunkId] = 0;`,
|
||||
withHmr ? "return moduleIds;" : ""
|
||||
]
|
||||
)}`,
|
||||
'var loadingAttribute = "data-webpack-loading";',
|
||||
`var loadStylesheet = ${runtimeTemplate.basicFunction(
|
||||
"chunkId, url, done" + (withHmr ? ", hmr" : ""),
|
||||
[
|
||||
'var link, needAttach, key = "chunk-" + chunkId;',
|
||||
withHmr ? "if(!hmr) {" : "",
|
||||
'var links = document.getElementsByTagName("link");',
|
||||
"for(var i = 0; i < links.length; i++) {",
|
||||
Template.indent([
|
||||
"var l = links[i];",
|
||||
`if(l.rel == "stylesheet" && (${
|
||||
withHmr
|
||||
? 'l.href.startsWith(url) || l.getAttribute("href").startsWith(url)'
|
||||
: 'l.href == url || l.getAttribute("href") == url'
|
||||
}${
|
||||
uniqueName
|
||||
? ' || l.getAttribute("data-webpack") == uniqueName + ":" + key'
|
||||
: ""
|
||||
})) { link = l; break; }`
|
||||
]),
|
||||
"}",
|
||||
"if(!done) return link;",
|
||||
withHmr ? "}" : "",
|
||||
"if(!link) {",
|
||||
Template.indent([
|
||||
"needAttach = true;",
|
||||
createStylesheet.call(code, this.chunk)
|
||||
]),
|
||||
"}",
|
||||
`var onLinkComplete = ${runtimeTemplate.basicFunction(
|
||||
"prev, event",
|
||||
Template.asString([
|
||||
"link.onerror = link.onload = null;",
|
||||
"link.removeAttribute(loadingAttribute);",
|
||||
"clearTimeout(timeout);",
|
||||
'if(event && event.type != "load") link.parentNode.removeChild(link)',
|
||||
"done(event);",
|
||||
"if(prev) return prev(event);"
|
||||
])
|
||||
)};`,
|
||||
"if(link.getAttribute(loadingAttribute)) {",
|
||||
Template.indent([
|
||||
`var timeout = setTimeout(onLinkComplete.bind(null, undefined, { type: 'timeout', target: link }), ${loadTimeout});`,
|
||||
"link.onerror = onLinkComplete.bind(null, link.onerror);",
|
||||
"link.onload = onLinkComplete.bind(null, link.onload);"
|
||||
]),
|
||||
"} else onLinkComplete(undefined, { type: 'load', target: link });", // We assume any existing stylesheet is render blocking
|
||||
withHmr ? "hmr ? document.head.insertBefore(link, hmr) :" : "",
|
||||
"needAttach && document.head.appendChild(link);",
|
||||
"return link;"
|
||||
]
|
||||
)};`,
|
||||
initialChunkIdsWithCss.size > 2
|
||||
? `${JSON.stringify(
|
||||
Array.from(initialChunkIdsWithCss)
|
||||
)}.forEach(loadCssChunkData.bind(null, ${
|
||||
RuntimeGlobals.moduleFactories
|
||||
}, 0));`
|
||||
: initialChunkIdsWithCss.size > 0
|
||||
? `${Array.from(
|
||||
initialChunkIdsWithCss,
|
||||
id =>
|
||||
`loadCssChunkData(${
|
||||
RuntimeGlobals.moduleFactories
|
||||
}, 0, ${JSON.stringify(id)});`
|
||||
).join("")}`
|
||||
: "// no initial css",
|
||||
"",
|
||||
withLoading
|
||||
? Template.asString([
|
||||
`${fn}.css = ${runtimeTemplate.basicFunction("chunkId, promises", [
|
||||
"// css chunk loading",
|
||||
`var installedChunkData = ${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;`,
|
||||
'if(installedChunkData !== 0) { // 0 means "already installed".',
|
||||
Template.indent([
|
||||
"",
|
||||
'// a Promise means "currently loading".',
|
||||
"if(installedChunkData) {",
|
||||
Template.indent(["promises.push(installedChunkData[2]);"]),
|
||||
"} else {",
|
||||
Template.indent([
|
||||
hasCssMatcher === true
|
||||
? "if(true) { // all chunks have CSS"
|
||||
: `if(${hasCssMatcher("chunkId")}) {`,
|
||||
Template.indent([
|
||||
"// setup Promise in chunk cache",
|
||||
`var promise = new Promise(${runtimeTemplate.expressionFunction(
|
||||
`installedChunkData = installedChunks[chunkId] = [resolve, reject]`,
|
||||
"resolve, reject"
|
||||
)});`,
|
||||
"promises.push(installedChunkData[2] = promise);",
|
||||
"",
|
||||
"// start chunk loading",
|
||||
`var url = ${RuntimeGlobals.publicPath} + ${RuntimeGlobals.getChunkCssFilename}(chunkId);`,
|
||||
"// create error before stack unwound to get useful stacktrace later",
|
||||
"var error = new Error();",
|
||||
`var loadingEnded = ${runtimeTemplate.basicFunction(
|
||||
"event",
|
||||
[
|
||||
`if(${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId)) {`,
|
||||
Template.indent([
|
||||
"installedChunkData = installedChunks[chunkId];",
|
||||
"if(installedChunkData !== 0) installedChunks[chunkId] = undefined;",
|
||||
"if(installedChunkData) {",
|
||||
Template.indent([
|
||||
'if(event.type !== "load") {',
|
||||
Template.indent([
|
||||
"var errorType = event && event.type;",
|
||||
"var realSrc = event && event.target && event.target.src;",
|
||||
"error.message = 'Loading css chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realSrc + ')';",
|
||||
"error.name = 'ChunkLoadError';",
|
||||
"error.type = errorType;",
|
||||
"error.request = realSrc;",
|
||||
"installedChunkData[1](error);"
|
||||
]),
|
||||
"} else {",
|
||||
Template.indent([
|
||||
`loadCssChunkData(${RuntimeGlobals.moduleFactories}, link, chunkId);`,
|
||||
"installedChunkData[0]();"
|
||||
]),
|
||||
"}"
|
||||
]),
|
||||
"}"
|
||||
]),
|
||||
"}"
|
||||
]
|
||||
)};`,
|
||||
"var link = loadStylesheet(chunkId, url, loadingEnded);"
|
||||
]),
|
||||
"} else installedChunks[chunkId] = 0;"
|
||||
]),
|
||||
"}"
|
||||
]),
|
||||
"}"
|
||||
])};`
|
||||
])
|
||||
: "// no chunk loading",
|
||||
"",
|
||||
withHmr
|
||||
? Template.asString([
|
||||
"var oldTags = [];",
|
||||
"var newTags = [];",
|
||||
`var applyHandler = ${runtimeTemplate.basicFunction("options", [
|
||||
`return { dispose: ${runtimeTemplate.basicFunction(
|
||||
"",
|
||||
[]
|
||||
)}, apply: ${runtimeTemplate.basicFunction("", [
|
||||
"var moduleIds = [];",
|
||||
`newTags.forEach(${runtimeTemplate.expressionFunction(
|
||||
"info[1].sheet.disabled = false",
|
||||
"info"
|
||||
)});`,
|
||||
"while(oldTags.length) {",
|
||||
Template.indent([
|
||||
"var oldTag = oldTags.pop();",
|
||||
"if(oldTag.parentNode) oldTag.parentNode.removeChild(oldTag);"
|
||||
]),
|
||||
"}",
|
||||
"while(newTags.length) {",
|
||||
Template.indent([
|
||||
`var info = newTags.pop();`,
|
||||
`var chunkModuleIds = loadCssChunkData(${RuntimeGlobals.moduleFactories}, info[1], info[0]);`,
|
||||
`chunkModuleIds.forEach(${runtimeTemplate.expressionFunction(
|
||||
"moduleIds.push(id)",
|
||||
"id"
|
||||
)});`
|
||||
]),
|
||||
"}",
|
||||
"return moduleIds;"
|
||||
])} };`
|
||||
])}`,
|
||||
`var cssTextKey = ${runtimeTemplate.returningFunction(
|
||||
`Array.from(link.sheet.cssRules, ${runtimeTemplate.returningFunction(
|
||||
"r.cssText",
|
||||
"r"
|
||||
)}).join()`,
|
||||
"link"
|
||||
)}`,
|
||||
`${
|
||||
RuntimeGlobals.hmrDownloadUpdateHandlers
|
||||
}.css = ${runtimeTemplate.basicFunction(
|
||||
"chunkIds, removedChunks, removedModules, promises, applyHandlers, updatedModulesList",
|
||||
[
|
||||
"applyHandlers.push(applyHandler);",
|
||||
`chunkIds.forEach(${runtimeTemplate.basicFunction("chunkId", [
|
||||
`var filename = ${RuntimeGlobals.getChunkCssFilename}(chunkId);`,
|
||||
`var url = ${RuntimeGlobals.publicPath} + filename;`,
|
||||
"var oldTag = loadStylesheet(chunkId, url);",
|
||||
"if(!oldTag) return;",
|
||||
`promises.push(new Promise(${runtimeTemplate.basicFunction(
|
||||
"resolve, reject",
|
||||
[
|
||||
`var link = loadStylesheet(chunkId, url + (url.indexOf("?") < 0 ? "?" : "&") + "hmr=" + Date.now(), ${runtimeTemplate.basicFunction(
|
||||
"event",
|
||||
[
|
||||
'if(event.type !== "load") {',
|
||||
Template.indent([
|
||||
"var errorType = event && event.type;",
|
||||
"var realSrc = event && event.target && event.target.src;",
|
||||
"error.message = 'Loading css hot update chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realSrc + ')';",
|
||||
"error.name = 'ChunkLoadError';",
|
||||
"error.type = errorType;",
|
||||
"error.request = realSrc;",
|
||||
"reject(error);"
|
||||
]),
|
||||
"} else {",
|
||||
Template.indent([
|
||||
"try { if(cssTextKey(oldTag) == cssTextKey(link)) { if(link.parentNode) link.parentNode.removeChild(link); return resolve(); } } catch(e) {}",
|
||||
"var factories = {};",
|
||||
"loadCssChunkData(factories, link, chunkId);",
|
||||
`Object.keys(factories).forEach(${runtimeTemplate.expressionFunction(
|
||||
"updatedModulesList.push(id)",
|
||||
"id"
|
||||
)})`,
|
||||
"link.sheet.disabled = true;",
|
||||
"oldTags.push(oldTag);",
|
||||
"newTags.push([chunkId, link]);",
|
||||
"resolve();"
|
||||
]),
|
||||
"}"
|
||||
]
|
||||
)}, oldTag);`
|
||||
]
|
||||
)}));`
|
||||
])});`
|
||||
]
|
||||
)}`
|
||||
])
|
||||
: "// no hmr"
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CssLoadingRuntimeModule;
|
||||
|
|
@ -0,0 +1,462 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const { ConcatSource } = require("webpack-sources");
|
||||
const HotUpdateChunk = require("../HotUpdateChunk");
|
||||
const RuntimeGlobals = require("../RuntimeGlobals");
|
||||
const SelfModuleFactory = require("../SelfModuleFactory");
|
||||
const CssExportDependency = require("../dependencies/CssExportDependency");
|
||||
const CssImportDependency = require("../dependencies/CssImportDependency");
|
||||
const CssLocalIdentifierDependency = require("../dependencies/CssLocalIdentifierDependency");
|
||||
const CssSelfLocalIdentifierDependency = require("../dependencies/CssSelfLocalIdentifierDependency");
|
||||
const CssUrlDependency = require("../dependencies/CssUrlDependency");
|
||||
const StaticExportsDependency = require("../dependencies/StaticExportsDependency");
|
||||
const { compareModulesByIdentifier } = require("../util/comparators");
|
||||
const createSchemaValidation = require("../util/create-schema-validation");
|
||||
const createHash = require("../util/createHash");
|
||||
const memoize = require("../util/memoize");
|
||||
const nonNumericOnlyHash = require("../util/nonNumericOnlyHash");
|
||||
const CssExportsGenerator = require("./CssExportsGenerator");
|
||||
const CssGenerator = require("./CssGenerator");
|
||||
const CssParser = require("./CssParser");
|
||||
|
||||
/** @typedef {import("webpack-sources").Source} Source */
|
||||
/** @typedef {import("../../declarations/WebpackOptions").CssExperimentOptions} CssExperimentOptions */
|
||||
/** @typedef {import("../Chunk")} Chunk */
|
||||
/** @typedef {import("../Compiler")} Compiler */
|
||||
/** @typedef {import("../Module")} Module */
|
||||
|
||||
const getCssLoadingRuntimeModule = memoize(() =>
|
||||
require("./CssLoadingRuntimeModule")
|
||||
);
|
||||
|
||||
const getSchema = name => {
|
||||
const { definitions } = require("../../schemas/WebpackOptions.json");
|
||||
return {
|
||||
definitions,
|
||||
oneOf: [{ $ref: `#/definitions/${name}` }]
|
||||
};
|
||||
};
|
||||
|
||||
const validateGeneratorOptions = createSchemaValidation(
|
||||
require("../../schemas/plugins/css/CssGeneratorOptions.check.js"),
|
||||
() => getSchema("CssGeneratorOptions"),
|
||||
{
|
||||
name: "Css Modules Plugin",
|
||||
baseDataPath: "parser"
|
||||
}
|
||||
);
|
||||
const validateParserOptions = createSchemaValidation(
|
||||
require("../../schemas/plugins/css/CssParserOptions.check.js"),
|
||||
() => getSchema("CssParserOptions"),
|
||||
{
|
||||
name: "Css Modules Plugin",
|
||||
baseDataPath: "parser"
|
||||
}
|
||||
);
|
||||
|
||||
const escapeCss = (str, omitOptionalUnderscore) => {
|
||||
const escaped = `${str}`.replace(
|
||||
// cspell:word uffff
|
||||
/[^a-zA-Z0-9_\u0081-\uffff-]/g,
|
||||
s => `\\${s}`
|
||||
);
|
||||
return !omitOptionalUnderscore && /^(?!--)[0-9_-]/.test(escaped)
|
||||
? `_${escaped}`
|
||||
: escaped;
|
||||
};
|
||||
|
||||
const plugin = "CssModulesPlugin";
|
||||
|
||||
class CssModulesPlugin {
|
||||
/**
|
||||
* @param {CssExperimentOptions} options options
|
||||
*/
|
||||
constructor({ exportsOnly = false }) {
|
||||
this._exportsOnly = exportsOnly;
|
||||
}
|
||||
/**
|
||||
* Apply the plugin
|
||||
* @param {Compiler} compiler the compiler instance
|
||||
* @returns {void}
|
||||
*/
|
||||
apply(compiler) {
|
||||
compiler.hooks.compilation.tap(
|
||||
plugin,
|
||||
(compilation, { normalModuleFactory }) => {
|
||||
const selfFactory = new SelfModuleFactory(compilation.moduleGraph);
|
||||
compilation.dependencyFactories.set(
|
||||
CssUrlDependency,
|
||||
normalModuleFactory
|
||||
);
|
||||
compilation.dependencyTemplates.set(
|
||||
CssUrlDependency,
|
||||
new CssUrlDependency.Template()
|
||||
);
|
||||
compilation.dependencyTemplates.set(
|
||||
CssLocalIdentifierDependency,
|
||||
new CssLocalIdentifierDependency.Template()
|
||||
);
|
||||
compilation.dependencyFactories.set(
|
||||
CssSelfLocalIdentifierDependency,
|
||||
selfFactory
|
||||
);
|
||||
compilation.dependencyTemplates.set(
|
||||
CssSelfLocalIdentifierDependency,
|
||||
new CssSelfLocalIdentifierDependency.Template()
|
||||
);
|
||||
compilation.dependencyTemplates.set(
|
||||
CssExportDependency,
|
||||
new CssExportDependency.Template()
|
||||
);
|
||||
compilation.dependencyFactories.set(
|
||||
CssImportDependency,
|
||||
normalModuleFactory
|
||||
);
|
||||
compilation.dependencyTemplates.set(
|
||||
CssImportDependency,
|
||||
new CssImportDependency.Template()
|
||||
);
|
||||
compilation.dependencyTemplates.set(
|
||||
StaticExportsDependency,
|
||||
new StaticExportsDependency.Template()
|
||||
);
|
||||
normalModuleFactory.hooks.createParser
|
||||
.for("css")
|
||||
.tap(plugin, parserOptions => {
|
||||
validateParserOptions(parserOptions);
|
||||
return new CssParser();
|
||||
});
|
||||
normalModuleFactory.hooks.createParser
|
||||
.for("css/global")
|
||||
.tap(plugin, parserOptions => {
|
||||
validateParserOptions(parserOptions);
|
||||
return new CssParser({
|
||||
allowPseudoBlocks: false,
|
||||
allowModeSwitch: false
|
||||
});
|
||||
});
|
||||
normalModuleFactory.hooks.createParser
|
||||
.for("css/module")
|
||||
.tap(plugin, parserOptions => {
|
||||
validateParserOptions(parserOptions);
|
||||
return new CssParser({
|
||||
defaultMode: "local"
|
||||
});
|
||||
});
|
||||
normalModuleFactory.hooks.createGenerator
|
||||
.for("css")
|
||||
.tap(plugin, generatorOptions => {
|
||||
validateGeneratorOptions(generatorOptions);
|
||||
return this._exportsOnly
|
||||
? new CssExportsGenerator()
|
||||
: new CssGenerator();
|
||||
});
|
||||
normalModuleFactory.hooks.createGenerator
|
||||
.for("css/global")
|
||||
.tap(plugin, generatorOptions => {
|
||||
validateGeneratorOptions(generatorOptions);
|
||||
return this._exportsOnly
|
||||
? new CssExportsGenerator()
|
||||
: new CssGenerator();
|
||||
});
|
||||
normalModuleFactory.hooks.createGenerator
|
||||
.for("css/module")
|
||||
.tap(plugin, generatorOptions => {
|
||||
validateGeneratorOptions(generatorOptions);
|
||||
return this._exportsOnly
|
||||
? new CssExportsGenerator()
|
||||
: new CssGenerator();
|
||||
});
|
||||
const orderedCssModulesPerChunk = new WeakMap();
|
||||
compilation.hooks.afterCodeGeneration.tap("CssModulesPlugin", () => {
|
||||
const { chunkGraph } = compilation;
|
||||
for (const chunk of compilation.chunks) {
|
||||
if (CssModulesPlugin.chunkHasCss(chunk, chunkGraph)) {
|
||||
orderedCssModulesPerChunk.set(
|
||||
chunk,
|
||||
this.getOrderedChunkCssModules(chunk, chunkGraph, compilation)
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
compilation.hooks.contentHash.tap("CssModulesPlugin", chunk => {
|
||||
const {
|
||||
chunkGraph,
|
||||
outputOptions: {
|
||||
hashSalt,
|
||||
hashDigest,
|
||||
hashDigestLength,
|
||||
hashFunction
|
||||
}
|
||||
} = compilation;
|
||||
const modules = orderedCssModulesPerChunk.get(chunk);
|
||||
if (modules === undefined) return;
|
||||
const hash = createHash(hashFunction);
|
||||
if (hashSalt) hash.update(hashSalt);
|
||||
for (const module of modules) {
|
||||
hash.update(chunkGraph.getModuleHash(module, chunk.runtime));
|
||||
}
|
||||
const digest = /** @type {string} */ (hash.digest(hashDigest));
|
||||
chunk.contentHash.css = nonNumericOnlyHash(digest, hashDigestLength);
|
||||
});
|
||||
compilation.hooks.renderManifest.tap(plugin, (result, options) => {
|
||||
const { chunkGraph } = compilation;
|
||||
const { hash, chunk, codeGenerationResults } = options;
|
||||
|
||||
if (chunk instanceof HotUpdateChunk) return result;
|
||||
|
||||
const modules = orderedCssModulesPerChunk.get(chunk);
|
||||
if (modules !== undefined) {
|
||||
result.push({
|
||||
render: () =>
|
||||
this.renderChunk({
|
||||
chunk,
|
||||
chunkGraph,
|
||||
codeGenerationResults,
|
||||
uniqueName: compilation.outputOptions.uniqueName,
|
||||
modules
|
||||
}),
|
||||
filenameTemplate: CssModulesPlugin.getChunkFilenameTemplate(
|
||||
chunk,
|
||||
compilation.outputOptions
|
||||
),
|
||||
pathOptions: {
|
||||
hash,
|
||||
runtime: chunk.runtime,
|
||||
chunk,
|
||||
contentHashType: "css"
|
||||
},
|
||||
identifier: `css${chunk.id}`,
|
||||
hash: chunk.contentHash.css
|
||||
});
|
||||
}
|
||||
return result;
|
||||
});
|
||||
const enabledChunks = new WeakSet();
|
||||
const handler = (chunk, set) => {
|
||||
if (enabledChunks.has(chunk)) {
|
||||
return;
|
||||
}
|
||||
enabledChunks.add(chunk);
|
||||
|
||||
set.add(RuntimeGlobals.publicPath);
|
||||
set.add(RuntimeGlobals.getChunkCssFilename);
|
||||
set.add(RuntimeGlobals.hasOwnProperty);
|
||||
set.add(RuntimeGlobals.moduleFactoriesAddOnly);
|
||||
set.add(RuntimeGlobals.makeNamespaceObject);
|
||||
|
||||
const CssLoadingRuntimeModule = getCssLoadingRuntimeModule();
|
||||
compilation.addRuntimeModule(chunk, new CssLoadingRuntimeModule(set));
|
||||
};
|
||||
compilation.hooks.runtimeRequirementInTree
|
||||
.for(RuntimeGlobals.hasCssModules)
|
||||
.tap(plugin, handler);
|
||||
compilation.hooks.runtimeRequirementInTree
|
||||
.for(RuntimeGlobals.ensureChunkHandlers)
|
||||
.tap(plugin, handler);
|
||||
compilation.hooks.runtimeRequirementInTree
|
||||
.for(RuntimeGlobals.hmrDownloadUpdateHandlers)
|
||||
.tap(plugin, handler);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
getModulesInOrder(chunk, modules, compilation) {
|
||||
if (!modules) return [];
|
||||
|
||||
const modulesList = [...modules];
|
||||
|
||||
// Get ordered list of modules per chunk group
|
||||
// Lists are in reverse order to allow to use Array.pop()
|
||||
const modulesByChunkGroup = Array.from(chunk.groupsIterable, chunkGroup => {
|
||||
const sortedModules = modulesList
|
||||
.map(module => {
|
||||
return {
|
||||
module,
|
||||
index: chunkGroup.getModulePostOrderIndex(module)
|
||||
};
|
||||
})
|
||||
.filter(item => item.index !== undefined)
|
||||
.sort((a, b) => b.index - a.index)
|
||||
.map(item => item.module);
|
||||
|
||||
return { list: sortedModules, set: new Set(sortedModules) };
|
||||
});
|
||||
|
||||
if (modulesByChunkGroup.length === 1)
|
||||
return modulesByChunkGroup[0].list.reverse();
|
||||
|
||||
const compareModuleLists = ({ list: a }, { list: b }) => {
|
||||
if (a.length === 0) {
|
||||
return b.length === 0 ? 0 : 1;
|
||||
} else {
|
||||
if (b.length === 0) return -1;
|
||||
return compareModulesByIdentifier(a[a.length - 1], b[b.length - 1]);
|
||||
}
|
||||
};
|
||||
|
||||
modulesByChunkGroup.sort(compareModuleLists);
|
||||
|
||||
const finalModules = [];
|
||||
|
||||
for (;;) {
|
||||
const failedModules = new Set();
|
||||
const list = modulesByChunkGroup[0].list;
|
||||
if (list.length === 0) {
|
||||
// done, everything empty
|
||||
break;
|
||||
}
|
||||
let selectedModule = list[list.length - 1];
|
||||
let hasFailed = undefined;
|
||||
outer: for (;;) {
|
||||
for (const { list, set } of modulesByChunkGroup) {
|
||||
if (list.length === 0) continue;
|
||||
const lastModule = list[list.length - 1];
|
||||
if (lastModule === selectedModule) continue;
|
||||
if (!set.has(selectedModule)) continue;
|
||||
failedModules.add(selectedModule);
|
||||
if (failedModules.has(lastModule)) {
|
||||
// There is a conflict, try other alternatives
|
||||
hasFailed = lastModule;
|
||||
continue;
|
||||
}
|
||||
selectedModule = lastModule;
|
||||
hasFailed = false;
|
||||
continue outer; // restart
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (hasFailed) {
|
||||
// There is a not resolve-able conflict with the selectedModule
|
||||
if (compilation) {
|
||||
// TODO print better warning
|
||||
compilation.warnings.push(
|
||||
new Error(
|
||||
`chunk ${
|
||||
chunk.name || chunk.id
|
||||
}\nConflicting order between ${hasFailed.readableIdentifier(
|
||||
compilation.requestShortener
|
||||
)} and ${selectedModule.readableIdentifier(
|
||||
compilation.requestShortener
|
||||
)}`
|
||||
)
|
||||
);
|
||||
}
|
||||
selectedModule = hasFailed;
|
||||
}
|
||||
// Insert the selected module into the final modules list
|
||||
finalModules.push(selectedModule);
|
||||
// Remove the selected module from all lists
|
||||
for (const { list, set } of modulesByChunkGroup) {
|
||||
const lastModule = list[list.length - 1];
|
||||
if (lastModule === selectedModule) list.pop();
|
||||
else if (hasFailed && set.has(selectedModule)) {
|
||||
const idx = list.indexOf(selectedModule);
|
||||
if (idx >= 0) list.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
modulesByChunkGroup.sort(compareModuleLists);
|
||||
}
|
||||
return finalModules;
|
||||
}
|
||||
|
||||
getOrderedChunkCssModules(chunk, chunkGraph, compilation) {
|
||||
return [
|
||||
...this.getModulesInOrder(
|
||||
chunk,
|
||||
chunkGraph.getOrderedChunkModulesIterableBySourceType(
|
||||
chunk,
|
||||
"css-import",
|
||||
compareModulesByIdentifier
|
||||
),
|
||||
compilation
|
||||
),
|
||||
...this.getModulesInOrder(
|
||||
chunk,
|
||||
chunkGraph.getOrderedChunkModulesIterableBySourceType(
|
||||
chunk,
|
||||
"css",
|
||||
compareModulesByIdentifier
|
||||
),
|
||||
compilation
|
||||
)
|
||||
];
|
||||
}
|
||||
|
||||
renderChunk({
|
||||
uniqueName,
|
||||
chunk,
|
||||
chunkGraph,
|
||||
codeGenerationResults,
|
||||
modules
|
||||
}) {
|
||||
const source = new ConcatSource();
|
||||
const metaData = [];
|
||||
for (const module of modules) {
|
||||
try {
|
||||
const codeGenResult = codeGenerationResults.get(module, chunk.runtime);
|
||||
|
||||
const s =
|
||||
codeGenResult.sources.get("css") ||
|
||||
codeGenResult.sources.get("css-import");
|
||||
if (s) {
|
||||
source.add(s);
|
||||
source.add("\n");
|
||||
}
|
||||
const exports =
|
||||
codeGenResult.data && codeGenResult.data.get("css-exports");
|
||||
const moduleId = chunkGraph.getModuleId(module) + "";
|
||||
metaData.push(
|
||||
`${
|
||||
exports
|
||||
? Array.from(exports, ([n, v]) => {
|
||||
const shortcutValue = `${
|
||||
uniqueName ? uniqueName + "-" : ""
|
||||
}${moduleId}-${n}`;
|
||||
return v === shortcutValue
|
||||
? `${escapeCss(n)}/`
|
||||
: v === "--" + shortcutValue
|
||||
? `${escapeCss(n)}%`
|
||||
: `${escapeCss(n)}(${escapeCss(v)})`;
|
||||
}).join("")
|
||||
: ""
|
||||
}${escapeCss(moduleId)}`
|
||||
);
|
||||
} catch (e) {
|
||||
e.message += `\nduring rendering of css ${module.identifier()}`;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
source.add(
|
||||
`head{--webpack-${escapeCss(
|
||||
(uniqueName ? uniqueName + "-" : "") + chunk.id,
|
||||
true
|
||||
)}:${metaData.join(",")};}`
|
||||
);
|
||||
return source;
|
||||
}
|
||||
|
||||
static getChunkFilenameTemplate(chunk, outputOptions) {
|
||||
if (chunk.cssFilenameTemplate) {
|
||||
return chunk.cssFilenameTemplate;
|
||||
} else if (chunk.canBeInitial()) {
|
||||
return outputOptions.cssFilename;
|
||||
} else {
|
||||
return outputOptions.cssChunkFilename;
|
||||
}
|
||||
}
|
||||
|
||||
static chunkHasCss(chunk, chunkGraph) {
|
||||
return (
|
||||
!!chunkGraph.getChunkModulesIterableBySourceType(chunk, "css") ||
|
||||
!!chunkGraph.getChunkModulesIterableBySourceType(chunk, "css-import")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CssModulesPlugin;
|
||||
|
|
@ -0,0 +1,618 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const Parser = require("../Parser");
|
||||
const ConstDependency = require("../dependencies/ConstDependency");
|
||||
const CssExportDependency = require("../dependencies/CssExportDependency");
|
||||
const CssImportDependency = require("../dependencies/CssImportDependency");
|
||||
const CssLocalIdentifierDependency = require("../dependencies/CssLocalIdentifierDependency");
|
||||
const CssSelfLocalIdentifierDependency = require("../dependencies/CssSelfLocalIdentifierDependency");
|
||||
const CssUrlDependency = require("../dependencies/CssUrlDependency");
|
||||
const StaticExportsDependency = require("../dependencies/StaticExportsDependency");
|
||||
const walkCssTokens = require("./walkCssTokens");
|
||||
|
||||
/** @typedef {import("../Parser").ParserState} ParserState */
|
||||
/** @typedef {import("../Parser").PreparsedAst} PreparsedAst */
|
||||
|
||||
const CC_LEFT_CURLY = "{".charCodeAt(0);
|
||||
const CC_RIGHT_CURLY = "}".charCodeAt(0);
|
||||
const CC_COLON = ":".charCodeAt(0);
|
||||
const CC_SLASH = "/".charCodeAt(0);
|
||||
const CC_SEMICOLON = ";".charCodeAt(0);
|
||||
|
||||
const cssUnescape = str => {
|
||||
return str.replace(/\\([0-9a-fA-F]{1,6}[ \t\n\r\f]?|[\s\S])/g, match => {
|
||||
if (match.length > 2) {
|
||||
return String.fromCharCode(parseInt(match.slice(1).trim(), 16));
|
||||
} else {
|
||||
return match[1];
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
class LocConverter {
|
||||
constructor(input) {
|
||||
this._input = input;
|
||||
this.line = 1;
|
||||
this.column = 0;
|
||||
this.pos = 0;
|
||||
}
|
||||
|
||||
get(pos) {
|
||||
if (this.pos !== pos) {
|
||||
if (this.pos < pos) {
|
||||
const str = this._input.slice(this.pos, pos);
|
||||
let i = str.lastIndexOf("\n");
|
||||
if (i === -1) {
|
||||
this.column += str.length;
|
||||
} else {
|
||||
this.column = str.length - i - 1;
|
||||
this.line++;
|
||||
while (i > 0 && (i = str.lastIndexOf("\n", i - 1)) !== -1)
|
||||
this.line++;
|
||||
}
|
||||
} else {
|
||||
let i = this._input.lastIndexOf("\n", this.pos);
|
||||
while (i >= pos) {
|
||||
this.line--;
|
||||
i = i > 0 ? this._input.lastIndexOf("\n", i - 1) : -1;
|
||||
}
|
||||
this.column = pos - i;
|
||||
}
|
||||
this.pos = pos;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
const CSS_MODE_TOP_LEVEL = 0;
|
||||
const CSS_MODE_IN_RULE = 1;
|
||||
const CSS_MODE_IN_LOCAL_RULE = 2;
|
||||
const CSS_MODE_AT_IMPORT_EXPECT_URL = 3;
|
||||
// TODO implement layer and supports for @import
|
||||
const CSS_MODE_AT_IMPORT_EXPECT_SUPPORTS = 4;
|
||||
const CSS_MODE_AT_IMPORT_EXPECT_MEDIA = 5;
|
||||
const CSS_MODE_AT_OTHER = 6;
|
||||
|
||||
const explainMode = mode => {
|
||||
switch (mode) {
|
||||
case CSS_MODE_TOP_LEVEL:
|
||||
return "parsing top level css";
|
||||
case CSS_MODE_IN_RULE:
|
||||
return "parsing css rule content (global)";
|
||||
case CSS_MODE_IN_LOCAL_RULE:
|
||||
return "parsing css rule content (local)";
|
||||
case CSS_MODE_AT_IMPORT_EXPECT_URL:
|
||||
return "parsing @import (expecting url)";
|
||||
case CSS_MODE_AT_IMPORT_EXPECT_SUPPORTS:
|
||||
return "parsing @import (expecting optionally supports or media query)";
|
||||
case CSS_MODE_AT_IMPORT_EXPECT_MEDIA:
|
||||
return "parsing @import (expecting optionally media query)";
|
||||
case CSS_MODE_AT_OTHER:
|
||||
return "parsing at-rule";
|
||||
default:
|
||||
return mode;
|
||||
}
|
||||
};
|
||||
|
||||
class CssParser extends Parser {
|
||||
constructor({
|
||||
allowPseudoBlocks = true,
|
||||
allowModeSwitch = true,
|
||||
defaultMode = "global"
|
||||
} = {}) {
|
||||
super();
|
||||
this.allowPseudoBlocks = allowPseudoBlocks;
|
||||
this.allowModeSwitch = allowModeSwitch;
|
||||
this.defaultMode = defaultMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string | Buffer | PreparsedAst} source the source to parse
|
||||
* @param {ParserState} state the parser state
|
||||
* @returns {ParserState} the parser state
|
||||
*/
|
||||
parse(source, state) {
|
||||
if (Buffer.isBuffer(source)) {
|
||||
source = source.toString("utf-8");
|
||||
} else if (typeof source === "object") {
|
||||
throw new Error("webpackAst is unexpected for the CssParser");
|
||||
}
|
||||
if (source[0] === "\ufeff") {
|
||||
source = source.slice(1);
|
||||
}
|
||||
|
||||
const module = state.module;
|
||||
|
||||
const declaredCssVariables = new Set();
|
||||
|
||||
const locConverter = new LocConverter(source);
|
||||
let mode = CSS_MODE_TOP_LEVEL;
|
||||
let modePos = 0;
|
||||
let modeNestingLevel = 0;
|
||||
let modeData = undefined;
|
||||
let singleClassSelector = undefined;
|
||||
let lastIdentifier = undefined;
|
||||
const modeStack = [];
|
||||
const isTopLevelLocal = () =>
|
||||
modeData === "local" ||
|
||||
(this.defaultMode === "local" && modeData === undefined);
|
||||
const eatWhiteLine = (input, pos) => {
|
||||
for (;;) {
|
||||
const cc = input.charCodeAt(pos);
|
||||
if (cc === 32 || cc === 9) {
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
if (cc === 10) pos++;
|
||||
break;
|
||||
}
|
||||
return pos;
|
||||
};
|
||||
const eatUntil = chars => {
|
||||
const charCodes = Array.from({ length: chars.length }, (_, i) =>
|
||||
chars.charCodeAt(i)
|
||||
);
|
||||
const arr = Array.from(
|
||||
{ length: charCodes.reduce((a, b) => Math.max(a, b), 0) + 1 },
|
||||
() => false
|
||||
);
|
||||
charCodes.forEach(cc => (arr[cc] = true));
|
||||
return (input, pos) => {
|
||||
for (;;) {
|
||||
const cc = input.charCodeAt(pos);
|
||||
if (cc < arr.length && arr[cc]) {
|
||||
return pos;
|
||||
}
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
}
|
||||
};
|
||||
};
|
||||
const eatText = (input, pos, eater) => {
|
||||
let text = "";
|
||||
for (;;) {
|
||||
if (input.charCodeAt(pos) === CC_SLASH) {
|
||||
const newPos = walkCssTokens.eatComments(input, pos);
|
||||
if (pos !== newPos) {
|
||||
pos = newPos;
|
||||
if (pos === input.length) break;
|
||||
} else {
|
||||
text += "/";
|
||||
pos++;
|
||||
if (pos === input.length) break;
|
||||
}
|
||||
}
|
||||
const newPos = eater(input, pos);
|
||||
if (pos !== newPos) {
|
||||
text += input.slice(pos, newPos);
|
||||
pos = newPos;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if (pos === input.length) break;
|
||||
}
|
||||
return [pos, text.trimRight()];
|
||||
};
|
||||
const eatExportName = eatUntil(":};/");
|
||||
const eatExportValue = eatUntil("};/");
|
||||
const parseExports = (input, pos) => {
|
||||
pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
|
||||
const cc = input.charCodeAt(pos);
|
||||
if (cc !== CC_LEFT_CURLY)
|
||||
throw new Error(
|
||||
`Unexpected ${input[pos]} at ${pos} during parsing of ':export' (expected '{')`
|
||||
);
|
||||
pos++;
|
||||
pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
|
||||
for (;;) {
|
||||
if (input.charCodeAt(pos) === CC_RIGHT_CURLY) break;
|
||||
pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
|
||||
if (pos === input.length) return pos;
|
||||
let start = pos;
|
||||
let name;
|
||||
[pos, name] = eatText(input, pos, eatExportName);
|
||||
if (pos === input.length) return pos;
|
||||
if (input.charCodeAt(pos) !== CC_COLON) {
|
||||
throw new Error(
|
||||
`Unexpected ${input[pos]} at ${pos} during parsing of export name in ':export' (expected ':')`
|
||||
);
|
||||
}
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
|
||||
if (pos === input.length) return pos;
|
||||
let value;
|
||||
[pos, value] = eatText(input, pos, eatExportValue);
|
||||
if (pos === input.length) return pos;
|
||||
const cc = input.charCodeAt(pos);
|
||||
if (cc === CC_SEMICOLON) {
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
|
||||
if (pos === input.length) return pos;
|
||||
} else if (cc !== CC_RIGHT_CURLY) {
|
||||
throw new Error(
|
||||
`Unexpected ${input[pos]} at ${pos} during parsing of export value in ':export' (expected ';' or '}')`
|
||||
);
|
||||
}
|
||||
const dep = new CssExportDependency(name, value);
|
||||
const { line: sl, column: sc } = locConverter.get(start);
|
||||
const { line: el, column: ec } = locConverter.get(pos);
|
||||
dep.setLoc(sl, sc, el, ec);
|
||||
module.addDependency(dep);
|
||||
}
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
pos = eatWhiteLine(input, pos);
|
||||
return pos;
|
||||
};
|
||||
const eatPropertyName = eatUntil(":{};");
|
||||
const processLocalDeclaration = (input, pos) => {
|
||||
modeData = undefined;
|
||||
const start = pos;
|
||||
pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
|
||||
const propertyNameStart = pos;
|
||||
const [propertyNameEnd, propertyName] = eatText(
|
||||
input,
|
||||
pos,
|
||||
eatPropertyName
|
||||
);
|
||||
if (input.charCodeAt(propertyNameEnd) !== CC_COLON) return start;
|
||||
pos = propertyNameEnd + 1;
|
||||
if (propertyName.startsWith("--")) {
|
||||
// CSS Variable
|
||||
const { line: sl, column: sc } = locConverter.get(propertyNameStart);
|
||||
const { line: el, column: ec } = locConverter.get(propertyNameEnd);
|
||||
const name = propertyName.slice(2);
|
||||
const dep = new CssLocalIdentifierDependency(
|
||||
name,
|
||||
[propertyNameStart, propertyNameEnd],
|
||||
"--"
|
||||
);
|
||||
dep.setLoc(sl, sc, el, ec);
|
||||
module.addDependency(dep);
|
||||
declaredCssVariables.add(name);
|
||||
} else if (
|
||||
propertyName === "animation-name" ||
|
||||
propertyName === "animation"
|
||||
) {
|
||||
modeData = "animation";
|
||||
lastIdentifier = undefined;
|
||||
}
|
||||
return pos;
|
||||
};
|
||||
const processDeclarationValueDone = (input, pos) => {
|
||||
if (modeData === "animation" && lastIdentifier) {
|
||||
const { line: sl, column: sc } = locConverter.get(lastIdentifier[0]);
|
||||
const { line: el, column: ec } = locConverter.get(lastIdentifier[1]);
|
||||
const name = input.slice(lastIdentifier[0], lastIdentifier[1]);
|
||||
const dep = new CssSelfLocalIdentifierDependency(name, lastIdentifier);
|
||||
dep.setLoc(sl, sc, el, ec);
|
||||
module.addDependency(dep);
|
||||
}
|
||||
};
|
||||
const eatKeyframes = eatUntil("{};/");
|
||||
const eatNameInVar = eatUntil(",)};/");
|
||||
walkCssTokens(source, {
|
||||
isSelector: () => {
|
||||
return mode !== CSS_MODE_IN_RULE && mode !== CSS_MODE_IN_LOCAL_RULE;
|
||||
},
|
||||
url: (input, start, end, contentStart, contentEnd) => {
|
||||
const value = cssUnescape(input.slice(contentStart, contentEnd));
|
||||
switch (mode) {
|
||||
case CSS_MODE_AT_IMPORT_EXPECT_URL: {
|
||||
modeData.url = value;
|
||||
mode = CSS_MODE_AT_IMPORT_EXPECT_SUPPORTS;
|
||||
break;
|
||||
}
|
||||
case CSS_MODE_AT_IMPORT_EXPECT_SUPPORTS:
|
||||
case CSS_MODE_AT_IMPORT_EXPECT_MEDIA:
|
||||
throw new Error(
|
||||
`Unexpected ${input.slice(
|
||||
start,
|
||||
end
|
||||
)} at ${start} during ${explainMode(mode)}`
|
||||
);
|
||||
default: {
|
||||
const dep = new CssUrlDependency(value, [start, end], "url");
|
||||
const { line: sl, column: sc } = locConverter.get(start);
|
||||
const { line: el, column: ec } = locConverter.get(end);
|
||||
dep.setLoc(sl, sc, el, ec);
|
||||
module.addDependency(dep);
|
||||
module.addCodeGenerationDependency(dep);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return end;
|
||||
},
|
||||
string: (input, start, end) => {
|
||||
switch (mode) {
|
||||
case CSS_MODE_AT_IMPORT_EXPECT_URL: {
|
||||
modeData.url = cssUnescape(input.slice(start + 1, end - 1));
|
||||
mode = CSS_MODE_AT_IMPORT_EXPECT_SUPPORTS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return end;
|
||||
},
|
||||
atKeyword: (input, start, end) => {
|
||||
const name = input.slice(start, end);
|
||||
if (name === "@namespace") {
|
||||
throw new Error("@namespace is not supported in bundled CSS");
|
||||
}
|
||||
if (name === "@import") {
|
||||
if (mode !== CSS_MODE_TOP_LEVEL) {
|
||||
throw new Error(
|
||||
`Unexpected @import at ${start} during ${explainMode(mode)}`
|
||||
);
|
||||
}
|
||||
mode = CSS_MODE_AT_IMPORT_EXPECT_URL;
|
||||
modePos = end;
|
||||
modeData = {
|
||||
start: start,
|
||||
url: undefined,
|
||||
supports: undefined
|
||||
};
|
||||
}
|
||||
if (name === "@keyframes") {
|
||||
let pos = end;
|
||||
pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
|
||||
if (pos === input.length) return pos;
|
||||
const [newPos, name] = eatText(input, pos, eatKeyframes);
|
||||
const { line: sl, column: sc } = locConverter.get(pos);
|
||||
const { line: el, column: ec } = locConverter.get(newPos);
|
||||
const dep = new CssLocalIdentifierDependency(name, [pos, newPos]);
|
||||
dep.setLoc(sl, sc, el, ec);
|
||||
module.addDependency(dep);
|
||||
pos = newPos;
|
||||
if (pos === input.length) return pos;
|
||||
if (input.charCodeAt(pos) !== CC_LEFT_CURLY) {
|
||||
throw new Error(
|
||||
`Unexpected ${input[pos]} at ${pos} during parsing of @keyframes (expected '{')`
|
||||
);
|
||||
}
|
||||
mode = CSS_MODE_IN_LOCAL_RULE;
|
||||
modeNestingLevel = 1;
|
||||
return pos + 1;
|
||||
}
|
||||
return end;
|
||||
},
|
||||
semicolon: (input, start, end) => {
|
||||
switch (mode) {
|
||||
case CSS_MODE_AT_IMPORT_EXPECT_URL:
|
||||
throw new Error(`Expected URL for @import at ${start}`);
|
||||
case CSS_MODE_AT_IMPORT_EXPECT_MEDIA:
|
||||
case CSS_MODE_AT_IMPORT_EXPECT_SUPPORTS: {
|
||||
const { line: sl, column: sc } = locConverter.get(modeData.start);
|
||||
const { line: el, column: ec } = locConverter.get(end);
|
||||
end = eatWhiteLine(input, end);
|
||||
const media = input.slice(modePos, start).trim();
|
||||
const dep = new CssImportDependency(
|
||||
modeData.url,
|
||||
[modeData.start, end],
|
||||
modeData.supports,
|
||||
media
|
||||
);
|
||||
dep.setLoc(sl, sc, el, ec);
|
||||
module.addDependency(dep);
|
||||
break;
|
||||
}
|
||||
case CSS_MODE_IN_LOCAL_RULE: {
|
||||
processDeclarationValueDone(input, start);
|
||||
return processLocalDeclaration(input, end);
|
||||
}
|
||||
case CSS_MODE_IN_RULE: {
|
||||
return end;
|
||||
}
|
||||
}
|
||||
mode = CSS_MODE_TOP_LEVEL;
|
||||
modeData = undefined;
|
||||
singleClassSelector = undefined;
|
||||
return end;
|
||||
},
|
||||
leftCurlyBracket: (input, start, end) => {
|
||||
switch (mode) {
|
||||
case CSS_MODE_TOP_LEVEL:
|
||||
mode = isTopLevelLocal()
|
||||
? CSS_MODE_IN_LOCAL_RULE
|
||||
: CSS_MODE_IN_RULE;
|
||||
modeNestingLevel = 1;
|
||||
if (mode === CSS_MODE_IN_LOCAL_RULE)
|
||||
return processLocalDeclaration(input, end);
|
||||
break;
|
||||
case CSS_MODE_IN_RULE:
|
||||
case CSS_MODE_IN_LOCAL_RULE:
|
||||
modeNestingLevel++;
|
||||
break;
|
||||
}
|
||||
return end;
|
||||
},
|
||||
rightCurlyBracket: (input, start, end) => {
|
||||
switch (mode) {
|
||||
case CSS_MODE_IN_LOCAL_RULE:
|
||||
processDeclarationValueDone(input, start);
|
||||
/* falls through */
|
||||
case CSS_MODE_IN_RULE:
|
||||
if (--modeNestingLevel === 0) {
|
||||
mode = CSS_MODE_TOP_LEVEL;
|
||||
modeData = undefined;
|
||||
singleClassSelector = undefined;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return end;
|
||||
},
|
||||
id: (input, start, end) => {
|
||||
singleClassSelector = false;
|
||||
switch (mode) {
|
||||
case CSS_MODE_TOP_LEVEL:
|
||||
if (isTopLevelLocal()) {
|
||||
const name = input.slice(start + 1, end);
|
||||
const dep = new CssLocalIdentifierDependency(name, [
|
||||
start + 1,
|
||||
end
|
||||
]);
|
||||
const { line: sl, column: sc } = locConverter.get(start);
|
||||
const { line: el, column: ec } = locConverter.get(end);
|
||||
dep.setLoc(sl, sc, el, ec);
|
||||
module.addDependency(dep);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return end;
|
||||
},
|
||||
identifier: (input, start, end) => {
|
||||
singleClassSelector = false;
|
||||
switch (mode) {
|
||||
case CSS_MODE_IN_LOCAL_RULE:
|
||||
if (modeData === "animation") {
|
||||
lastIdentifier = [start, end];
|
||||
}
|
||||
break;
|
||||
}
|
||||
return end;
|
||||
},
|
||||
class: (input, start, end) => {
|
||||
switch (mode) {
|
||||
case CSS_MODE_TOP_LEVEL: {
|
||||
if (isTopLevelLocal()) {
|
||||
const name = input.slice(start + 1, end);
|
||||
const dep = new CssLocalIdentifierDependency(name, [
|
||||
start + 1,
|
||||
end
|
||||
]);
|
||||
const { line: sl, column: sc } = locConverter.get(start);
|
||||
const { line: el, column: ec } = locConverter.get(end);
|
||||
dep.setLoc(sl, sc, el, ec);
|
||||
module.addDependency(dep);
|
||||
if (singleClassSelector === undefined) singleClassSelector = name;
|
||||
} else {
|
||||
singleClassSelector = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return end;
|
||||
},
|
||||
leftParenthesis: (input, start, end) => {
|
||||
switch (mode) {
|
||||
case CSS_MODE_TOP_LEVEL: {
|
||||
modeStack.push(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return end;
|
||||
},
|
||||
rightParenthesis: (input, start, end) => {
|
||||
switch (mode) {
|
||||
case CSS_MODE_TOP_LEVEL: {
|
||||
const newModeData = modeStack.pop();
|
||||
if (newModeData !== false) {
|
||||
modeData = newModeData;
|
||||
const dep = new ConstDependency("", [start, end]);
|
||||
module.addPresentationalDependency(dep);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return end;
|
||||
},
|
||||
pseudoClass: (input, start, end) => {
|
||||
singleClassSelector = false;
|
||||
switch (mode) {
|
||||
case CSS_MODE_TOP_LEVEL: {
|
||||
const name = input.slice(start, end);
|
||||
if (this.allowModeSwitch && name === ":global") {
|
||||
modeData = "global";
|
||||
const dep = new ConstDependency("", [start, end]);
|
||||
module.addPresentationalDependency(dep);
|
||||
} else if (this.allowModeSwitch && name === ":local") {
|
||||
modeData = "local";
|
||||
const dep = new ConstDependency("", [start, end]);
|
||||
module.addPresentationalDependency(dep);
|
||||
} else if (this.allowPseudoBlocks && name === ":export") {
|
||||
const pos = parseExports(input, end);
|
||||
const dep = new ConstDependency("", [start, pos]);
|
||||
module.addPresentationalDependency(dep);
|
||||
return pos;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return end;
|
||||
},
|
||||
pseudoFunction: (input, start, end) => {
|
||||
switch (mode) {
|
||||
case CSS_MODE_TOP_LEVEL: {
|
||||
const name = input.slice(start, end - 1);
|
||||
if (this.allowModeSwitch && name === ":global") {
|
||||
modeStack.push(modeData);
|
||||
modeData = "global";
|
||||
const dep = new ConstDependency("", [start, end]);
|
||||
module.addPresentationalDependency(dep);
|
||||
} else if (this.allowModeSwitch && name === ":local") {
|
||||
modeStack.push(modeData);
|
||||
modeData = "local";
|
||||
const dep = new ConstDependency("", [start, end]);
|
||||
module.addPresentationalDependency(dep);
|
||||
} else {
|
||||
modeStack.push(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return end;
|
||||
},
|
||||
function: (input, start, end) => {
|
||||
switch (mode) {
|
||||
case CSS_MODE_IN_LOCAL_RULE: {
|
||||
const name = input.slice(start, end - 1);
|
||||
if (name === "var") {
|
||||
let pos = walkCssTokens.eatWhitespaceAndComments(input, end);
|
||||
if (pos === input.length) return pos;
|
||||
const [newPos, name] = eatText(input, pos, eatNameInVar);
|
||||
if (!name.startsWith("--")) return end;
|
||||
const { line: sl, column: sc } = locConverter.get(pos);
|
||||
const { line: el, column: ec } = locConverter.get(newPos);
|
||||
const dep = new CssSelfLocalIdentifierDependency(
|
||||
name.slice(2),
|
||||
[pos, newPos],
|
||||
"--",
|
||||
declaredCssVariables
|
||||
);
|
||||
dep.setLoc(sl, sc, el, ec);
|
||||
module.addDependency(dep);
|
||||
return newPos;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return end;
|
||||
},
|
||||
comma: (input, start, end) => {
|
||||
switch (mode) {
|
||||
case CSS_MODE_TOP_LEVEL:
|
||||
modeData = undefined;
|
||||
modeStack.length = 0;
|
||||
break;
|
||||
case CSS_MODE_IN_LOCAL_RULE:
|
||||
processDeclarationValueDone(input, start);
|
||||
break;
|
||||
}
|
||||
return end;
|
||||
}
|
||||
});
|
||||
|
||||
module.buildInfo.strict = true;
|
||||
module.buildMeta.exportsType = "namespace";
|
||||
module.addDependency(new StaticExportsDependency([], true));
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CssParser;
|
||||
|
|
@ -0,0 +1,659 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* @typedef {Object} CssTokenCallbacks
|
||||
* @property {function(string, number): boolean} isSelector
|
||||
* @property {function(string, number, number, number, number): number=} url
|
||||
* @property {function(string, number, number): number=} string
|
||||
* @property {function(string, number, number): number=} leftParenthesis
|
||||
* @property {function(string, number, number): number=} rightParenthesis
|
||||
* @property {function(string, number, number): number=} pseudoFunction
|
||||
* @property {function(string, number, number): number=} function
|
||||
* @property {function(string, number, number): number=} pseudoClass
|
||||
* @property {function(string, number, number): number=} atKeyword
|
||||
* @property {function(string, number, number): number=} class
|
||||
* @property {function(string, number, number): number=} identifier
|
||||
* @property {function(string, number, number): number=} id
|
||||
* @property {function(string, number, number): number=} leftCurlyBracket
|
||||
* @property {function(string, number, number): number=} rightCurlyBracket
|
||||
* @property {function(string, number, number): number=} semicolon
|
||||
* @property {function(string, number, number): number=} comma
|
||||
*/
|
||||
|
||||
/** @typedef {function(string, number, CssTokenCallbacks): number} CharHandler */
|
||||
|
||||
// spec: https://drafts.csswg.org/css-syntax/
|
||||
|
||||
const CC_LINE_FEED = "\n".charCodeAt(0);
|
||||
const CC_CARRIAGE_RETURN = "\r".charCodeAt(0);
|
||||
const CC_FORM_FEED = "\f".charCodeAt(0);
|
||||
|
||||
const CC_TAB = "\t".charCodeAt(0);
|
||||
const CC_SPACE = " ".charCodeAt(0);
|
||||
|
||||
const CC_SLASH = "/".charCodeAt(0);
|
||||
const CC_BACK_SLASH = "\\".charCodeAt(0);
|
||||
const CC_ASTERISK = "*".charCodeAt(0);
|
||||
|
||||
const CC_LEFT_PARENTHESIS = "(".charCodeAt(0);
|
||||
const CC_RIGHT_PARENTHESIS = ")".charCodeAt(0);
|
||||
const CC_LEFT_CURLY = "{".charCodeAt(0);
|
||||
const CC_RIGHT_CURLY = "}".charCodeAt(0);
|
||||
|
||||
const CC_QUOTATION_MARK = '"'.charCodeAt(0);
|
||||
const CC_APOSTROPHE = "'".charCodeAt(0);
|
||||
|
||||
const CC_FULL_STOP = ".".charCodeAt(0);
|
||||
const CC_COLON = ":".charCodeAt(0);
|
||||
const CC_SEMICOLON = ";".charCodeAt(0);
|
||||
const CC_COMMA = ",".charCodeAt(0);
|
||||
const CC_PERCENTAGE = "%".charCodeAt(0);
|
||||
const CC_AT_SIGN = "@".charCodeAt(0);
|
||||
|
||||
const CC_LOW_LINE = "_".charCodeAt(0);
|
||||
const CC_LOWER_A = "a".charCodeAt(0);
|
||||
const CC_LOWER_U = "u".charCodeAt(0);
|
||||
const CC_LOWER_E = "e".charCodeAt(0);
|
||||
const CC_LOWER_Z = "z".charCodeAt(0);
|
||||
const CC_UPPER_A = "A".charCodeAt(0);
|
||||
const CC_UPPER_E = "E".charCodeAt(0);
|
||||
const CC_UPPER_Z = "Z".charCodeAt(0);
|
||||
const CC_0 = "0".charCodeAt(0);
|
||||
const CC_9 = "9".charCodeAt(0);
|
||||
|
||||
const CC_NUMBER_SIGN = "#".charCodeAt(0);
|
||||
const CC_PLUS_SIGN = "+".charCodeAt(0);
|
||||
const CC_HYPHEN_MINUS = "-".charCodeAt(0);
|
||||
|
||||
const CC_LESS_THAN_SIGN = "<".charCodeAt(0);
|
||||
const CC_GREATER_THAN_SIGN = ">".charCodeAt(0);
|
||||
|
||||
const _isNewLine = cc => {
|
||||
return (
|
||||
cc === CC_LINE_FEED || cc === CC_CARRIAGE_RETURN || cc === CC_FORM_FEED
|
||||
);
|
||||
};
|
||||
|
||||
/** @type {CharHandler} */
|
||||
const consumeSpace = (input, pos, callbacks) => {
|
||||
let cc;
|
||||
do {
|
||||
pos++;
|
||||
cc = input.charCodeAt(pos);
|
||||
} while (_isWhiteSpace(cc));
|
||||
return pos;
|
||||
};
|
||||
|
||||
const _isWhiteSpace = cc => {
|
||||
return (
|
||||
cc === CC_LINE_FEED ||
|
||||
cc === CC_CARRIAGE_RETURN ||
|
||||
cc === CC_FORM_FEED ||
|
||||
cc === CC_TAB ||
|
||||
cc === CC_SPACE
|
||||
);
|
||||
};
|
||||
|
||||
/** @type {CharHandler} */
|
||||
const consumeSingleCharToken = (input, pos, callbacks) => {
|
||||
return pos + 1;
|
||||
};
|
||||
|
||||
/** @type {CharHandler} */
|
||||
const consumePotentialComment = (input, pos, callbacks) => {
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
let cc = input.charCodeAt(pos);
|
||||
if (cc !== CC_ASTERISK) return pos;
|
||||
for (;;) {
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
cc = input.charCodeAt(pos);
|
||||
while (cc === CC_ASTERISK) {
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
cc = input.charCodeAt(pos);
|
||||
if (cc === CC_SLASH) return pos + 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** @type {function(number): CharHandler} */
|
||||
const consumeString = end => (input, pos, callbacks) => {
|
||||
const start = pos;
|
||||
pos = _consumeString(input, pos, end);
|
||||
if (callbacks.string !== undefined) {
|
||||
pos = callbacks.string(input, start, pos);
|
||||
}
|
||||
return pos;
|
||||
};
|
||||
|
||||
const _consumeString = (input, pos, end) => {
|
||||
pos++;
|
||||
for (;;) {
|
||||
if (pos === input.length) return pos;
|
||||
const cc = input.charCodeAt(pos);
|
||||
if (cc === end) return pos + 1;
|
||||
if (_isNewLine(cc)) {
|
||||
// bad string
|
||||
return pos;
|
||||
}
|
||||
if (cc === CC_BACK_SLASH) {
|
||||
// we don't need to fully parse the escaped code point
|
||||
// just skip over a potential new line
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
pos++;
|
||||
} else {
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const _isIdentifierStartCode = cc => {
|
||||
return (
|
||||
cc === CC_LOW_LINE ||
|
||||
(cc >= CC_LOWER_A && cc <= CC_LOWER_Z) ||
|
||||
(cc >= CC_UPPER_A && cc <= CC_UPPER_Z) ||
|
||||
cc > 0x80
|
||||
);
|
||||
};
|
||||
|
||||
const _isDigit = cc => {
|
||||
return cc >= CC_0 && cc <= CC_9;
|
||||
};
|
||||
|
||||
const _startsIdentifier = (input, pos) => {
|
||||
const cc = input.charCodeAt(pos);
|
||||
if (cc === CC_HYPHEN_MINUS) {
|
||||
if (pos === input.length) return false;
|
||||
const cc = input.charCodeAt(pos + 1);
|
||||
if (cc === CC_HYPHEN_MINUS) return true;
|
||||
if (cc === CC_BACK_SLASH) {
|
||||
const cc = input.charCodeAt(pos + 2);
|
||||
return !_isNewLine(cc);
|
||||
}
|
||||
return _isIdentifierStartCode(cc);
|
||||
}
|
||||
if (cc === CC_BACK_SLASH) {
|
||||
const cc = input.charCodeAt(pos + 1);
|
||||
return !_isNewLine(cc);
|
||||
}
|
||||
return _isIdentifierStartCode(cc);
|
||||
};
|
||||
|
||||
/** @type {CharHandler} */
|
||||
const consumeNumberSign = (input, pos, callbacks) => {
|
||||
const start = pos;
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
if (callbacks.isSelector(input, pos) && _startsIdentifier(input, pos)) {
|
||||
pos = _consumeIdentifier(input, pos);
|
||||
if (callbacks.id !== undefined) {
|
||||
return callbacks.id(input, start, pos);
|
||||
}
|
||||
}
|
||||
return pos;
|
||||
};
|
||||
|
||||
/** @type {CharHandler} */
|
||||
const consumeMinus = (input, pos, callbacks) => {
|
||||
const start = pos;
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
const cc = input.charCodeAt(pos);
|
||||
if (cc === CC_FULL_STOP || _isDigit(cc)) {
|
||||
return consumeNumericToken(input, pos, callbacks);
|
||||
} else if (cc === CC_HYPHEN_MINUS) {
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
const cc = input.charCodeAt(pos);
|
||||
if (cc === CC_GREATER_THAN_SIGN) {
|
||||
return pos + 1;
|
||||
} else {
|
||||
pos = _consumeIdentifier(input, pos);
|
||||
if (callbacks.identifier !== undefined) {
|
||||
return callbacks.identifier(input, start, pos);
|
||||
}
|
||||
}
|
||||
} else if (cc === CC_BACK_SLASH) {
|
||||
if (pos + 1 === input.length) return pos;
|
||||
const cc = input.charCodeAt(pos + 1);
|
||||
if (_isNewLine(cc)) return pos;
|
||||
pos = _consumeIdentifier(input, pos);
|
||||
if (callbacks.identifier !== undefined) {
|
||||
return callbacks.identifier(input, start, pos);
|
||||
}
|
||||
} else if (_isIdentifierStartCode(cc)) {
|
||||
pos++;
|
||||
pos = _consumeIdentifier(input, pos);
|
||||
if (callbacks.identifier !== undefined) {
|
||||
return callbacks.identifier(input, start, pos);
|
||||
}
|
||||
}
|
||||
return pos;
|
||||
};
|
||||
|
||||
/** @type {CharHandler} */
|
||||
const consumeDot = (input, pos, callbacks) => {
|
||||
const start = pos;
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
const cc = input.charCodeAt(pos);
|
||||
if (_isDigit(cc)) return consumeNumericToken(input, pos - 2, callbacks);
|
||||
if (!callbacks.isSelector(input, pos) || !_startsIdentifier(input, pos))
|
||||
return pos;
|
||||
pos = _consumeIdentifier(input, pos);
|
||||
if (callbacks.class !== undefined) return callbacks.class(input, start, pos);
|
||||
return pos;
|
||||
};
|
||||
|
||||
/** @type {CharHandler} */
|
||||
const consumeNumericToken = (input, pos, callbacks) => {
|
||||
pos = _consumeNumber(input, pos);
|
||||
if (pos === input.length) return pos;
|
||||
if (_startsIdentifier(input, pos)) return _consumeIdentifier(input, pos);
|
||||
const cc = input.charCodeAt(pos);
|
||||
if (cc === CC_PERCENTAGE) return pos + 1;
|
||||
return pos;
|
||||
};
|
||||
|
||||
/** @type {CharHandler} */
|
||||
const consumeOtherIdentifier = (input, pos, callbacks) => {
|
||||
const start = pos;
|
||||
pos = _consumeIdentifier(input, pos);
|
||||
if (
|
||||
pos !== input.length &&
|
||||
!callbacks.isSelector(input, pos) &&
|
||||
input.charCodeAt(pos) === CC_LEFT_PARENTHESIS
|
||||
) {
|
||||
pos++;
|
||||
if (callbacks.function !== undefined) {
|
||||
return callbacks.function(input, start, pos);
|
||||
}
|
||||
} else {
|
||||
if (callbacks.identifier !== undefined) {
|
||||
return callbacks.identifier(input, start, pos);
|
||||
}
|
||||
}
|
||||
return pos;
|
||||
};
|
||||
|
||||
/** @type {CharHandler} */
|
||||
const consumePotentialUrl = (input, pos, callbacks) => {
|
||||
const start = pos;
|
||||
pos = _consumeIdentifier(input, pos);
|
||||
if (pos === start + 3 && input.slice(start, pos + 1) === "url(") {
|
||||
pos++;
|
||||
let cc = input.charCodeAt(pos);
|
||||
while (_isWhiteSpace(cc)) {
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
cc = input.charCodeAt(pos);
|
||||
}
|
||||
if (cc === CC_QUOTATION_MARK || cc === CC_APOSTROPHE) {
|
||||
pos++;
|
||||
const contentStart = pos;
|
||||
pos = _consumeString(input, pos, cc);
|
||||
const contentEnd = pos - 1;
|
||||
cc = input.charCodeAt(pos);
|
||||
while (_isWhiteSpace(cc)) {
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
cc = input.charCodeAt(pos);
|
||||
}
|
||||
if (cc !== CC_RIGHT_PARENTHESIS) return pos;
|
||||
pos++;
|
||||
if (callbacks.url !== undefined)
|
||||
return callbacks.url(input, start, pos, contentStart, contentEnd);
|
||||
return pos;
|
||||
} else {
|
||||
const contentStart = pos;
|
||||
let contentEnd;
|
||||
for (;;) {
|
||||
if (cc === CC_BACK_SLASH) {
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
pos++;
|
||||
} else if (_isWhiteSpace(cc)) {
|
||||
contentEnd = pos;
|
||||
do {
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
cc = input.charCodeAt(pos);
|
||||
} while (_isWhiteSpace(cc));
|
||||
if (cc !== CC_RIGHT_PARENTHESIS) return pos;
|
||||
pos++;
|
||||
if (callbacks.url !== undefined) {
|
||||
return callbacks.url(input, start, pos, contentStart, contentEnd);
|
||||
}
|
||||
return pos;
|
||||
} else if (cc === CC_RIGHT_PARENTHESIS) {
|
||||
contentEnd = pos;
|
||||
pos++;
|
||||
if (callbacks.url !== undefined) {
|
||||
return callbacks.url(input, start, pos, contentStart, contentEnd);
|
||||
}
|
||||
return pos;
|
||||
} else if (cc === CC_LEFT_PARENTHESIS) {
|
||||
return pos;
|
||||
} else {
|
||||
pos++;
|
||||
}
|
||||
if (pos === input.length) return pos;
|
||||
cc = input.charCodeAt(pos);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (callbacks.identifier !== undefined) {
|
||||
return callbacks.identifier(input, start, pos);
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
};
|
||||
|
||||
/** @type {CharHandler} */
|
||||
const consumePotentialPseudo = (input, pos, callbacks) => {
|
||||
const start = pos;
|
||||
pos++;
|
||||
if (!callbacks.isSelector(input, pos) || !_startsIdentifier(input, pos))
|
||||
return pos;
|
||||
pos = _consumeIdentifier(input, pos);
|
||||
let cc = input.charCodeAt(pos);
|
||||
if (cc === CC_LEFT_PARENTHESIS) {
|
||||
pos++;
|
||||
if (callbacks.pseudoFunction !== undefined) {
|
||||
return callbacks.pseudoFunction(input, start, pos);
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
if (callbacks.pseudoClass !== undefined) {
|
||||
return callbacks.pseudoClass(input, start, pos);
|
||||
}
|
||||
return pos;
|
||||
};
|
||||
|
||||
/** @type {CharHandler} */
|
||||
const consumeLeftParenthesis = (input, pos, callbacks) => {
|
||||
pos++;
|
||||
if (callbacks.leftParenthesis !== undefined) {
|
||||
return callbacks.leftParenthesis(input, pos - 1, pos);
|
||||
}
|
||||
return pos;
|
||||
};
|
||||
|
||||
/** @type {CharHandler} */
|
||||
const consumeRightParenthesis = (input, pos, callbacks) => {
|
||||
pos++;
|
||||
if (callbacks.rightParenthesis !== undefined) {
|
||||
return callbacks.rightParenthesis(input, pos - 1, pos);
|
||||
}
|
||||
return pos;
|
||||
};
|
||||
|
||||
/** @type {CharHandler} */
|
||||
const consumeLeftCurlyBracket = (input, pos, callbacks) => {
|
||||
pos++;
|
||||
if (callbacks.leftCurlyBracket !== undefined) {
|
||||
return callbacks.leftCurlyBracket(input, pos - 1, pos);
|
||||
}
|
||||
return pos;
|
||||
};
|
||||
|
||||
/** @type {CharHandler} */
|
||||
const consumeRightCurlyBracket = (input, pos, callbacks) => {
|
||||
pos++;
|
||||
if (callbacks.rightCurlyBracket !== undefined) {
|
||||
return callbacks.rightCurlyBracket(input, pos - 1, pos);
|
||||
}
|
||||
return pos;
|
||||
};
|
||||
|
||||
/** @type {CharHandler} */
|
||||
const consumeSemicolon = (input, pos, callbacks) => {
|
||||
pos++;
|
||||
if (callbacks.semicolon !== undefined) {
|
||||
return callbacks.semicolon(input, pos - 1, pos);
|
||||
}
|
||||
return pos;
|
||||
};
|
||||
|
||||
/** @type {CharHandler} */
|
||||
const consumeComma = (input, pos, callbacks) => {
|
||||
pos++;
|
||||
if (callbacks.comma !== undefined) {
|
||||
return callbacks.comma(input, pos - 1, pos);
|
||||
}
|
||||
return pos;
|
||||
};
|
||||
|
||||
const _consumeIdentifier = (input, pos) => {
|
||||
for (;;) {
|
||||
const cc = input.charCodeAt(pos);
|
||||
if (cc === CC_BACK_SLASH) {
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
pos++;
|
||||
} else if (
|
||||
_isIdentifierStartCode(cc) ||
|
||||
_isDigit(cc) ||
|
||||
cc === CC_HYPHEN_MINUS
|
||||
) {
|
||||
pos++;
|
||||
} else {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const _consumeNumber = (input, pos) => {
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
let cc = input.charCodeAt(pos);
|
||||
while (_isDigit(cc)) {
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
cc = input.charCodeAt(pos);
|
||||
}
|
||||
if (cc === CC_FULL_STOP && pos + 1 !== input.length) {
|
||||
const next = input.charCodeAt(pos + 1);
|
||||
if (_isDigit(next)) {
|
||||
pos += 2;
|
||||
cc = input.charCodeAt(pos);
|
||||
while (_isDigit(cc)) {
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
cc = input.charCodeAt(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cc === CC_LOWER_E || cc === CC_UPPER_E) {
|
||||
if (pos + 1 !== input.length) {
|
||||
const next = input.charCodeAt(pos + 2);
|
||||
if (_isDigit(next)) {
|
||||
pos += 2;
|
||||
} else if (
|
||||
(next === CC_HYPHEN_MINUS || next === CC_PLUS_SIGN) &&
|
||||
pos + 2 !== input.length
|
||||
) {
|
||||
const next = input.charCodeAt(pos + 2);
|
||||
if (_isDigit(next)) {
|
||||
pos += 3;
|
||||
} else {
|
||||
return pos;
|
||||
}
|
||||
} else {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return pos;
|
||||
}
|
||||
cc = input.charCodeAt(pos);
|
||||
while (_isDigit(cc)) {
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
cc = input.charCodeAt(pos);
|
||||
}
|
||||
return pos;
|
||||
};
|
||||
|
||||
/** @type {CharHandler} */
|
||||
const consumeLessThan = (input, pos, callbacks) => {
|
||||
if (input.slice(pos + 1, pos + 4) === "!--") return pos + 4;
|
||||
return pos + 1;
|
||||
};
|
||||
|
||||
/** @type {CharHandler} */
|
||||
const consumeAt = (input, pos, callbacks) => {
|
||||
const start = pos;
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
if (_startsIdentifier(input, pos)) {
|
||||
pos = _consumeIdentifier(input, pos);
|
||||
if (callbacks.atKeyword !== undefined) {
|
||||
pos = callbacks.atKeyword(input, start, pos);
|
||||
}
|
||||
}
|
||||
return pos;
|
||||
};
|
||||
|
||||
const CHAR_MAP = Array.from({ length: 0x80 }, (_, cc) => {
|
||||
// https://drafts.csswg.org/css-syntax/#consume-token
|
||||
switch (cc) {
|
||||
case CC_LINE_FEED:
|
||||
case CC_CARRIAGE_RETURN:
|
||||
case CC_FORM_FEED:
|
||||
case CC_TAB:
|
||||
case CC_SPACE:
|
||||
return consumeSpace;
|
||||
case CC_QUOTATION_MARK:
|
||||
case CC_APOSTROPHE:
|
||||
return consumeString(cc);
|
||||
case CC_NUMBER_SIGN:
|
||||
return consumeNumberSign;
|
||||
case CC_SLASH:
|
||||
return consumePotentialComment;
|
||||
// case CC_LEFT_SQUARE:
|
||||
// case CC_RIGHT_SQUARE:
|
||||
// case CC_COMMA:
|
||||
// case CC_COLON:
|
||||
// return consumeSingleCharToken;
|
||||
case CC_COMMA:
|
||||
return consumeComma;
|
||||
case CC_SEMICOLON:
|
||||
return consumeSemicolon;
|
||||
case CC_LEFT_PARENTHESIS:
|
||||
return consumeLeftParenthesis;
|
||||
case CC_RIGHT_PARENTHESIS:
|
||||
return consumeRightParenthesis;
|
||||
case CC_LEFT_CURLY:
|
||||
return consumeLeftCurlyBracket;
|
||||
case CC_RIGHT_CURLY:
|
||||
return consumeRightCurlyBracket;
|
||||
case CC_COLON:
|
||||
return consumePotentialPseudo;
|
||||
case CC_PLUS_SIGN:
|
||||
return consumeNumericToken;
|
||||
case CC_FULL_STOP:
|
||||
return consumeDot;
|
||||
case CC_HYPHEN_MINUS:
|
||||
return consumeMinus;
|
||||
case CC_LESS_THAN_SIGN:
|
||||
return consumeLessThan;
|
||||
case CC_AT_SIGN:
|
||||
return consumeAt;
|
||||
case CC_LOWER_U:
|
||||
return consumePotentialUrl;
|
||||
case CC_LOW_LINE:
|
||||
return consumeOtherIdentifier;
|
||||
default:
|
||||
if (_isDigit(cc)) return consumeNumericToken;
|
||||
if (
|
||||
(cc >= CC_LOWER_A && cc <= CC_LOWER_Z) ||
|
||||
(cc >= CC_UPPER_A && cc <= CC_UPPER_Z)
|
||||
) {
|
||||
return consumeOtherIdentifier;
|
||||
}
|
||||
return consumeSingleCharToken;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {string} input input css
|
||||
* @param {CssTokenCallbacks} callbacks callbacks
|
||||
* @returns {void}
|
||||
*/
|
||||
module.exports = (input, callbacks) => {
|
||||
let pos = 0;
|
||||
while (pos < input.length) {
|
||||
const cc = input.charCodeAt(pos);
|
||||
if (cc < 0x80) {
|
||||
pos = CHAR_MAP[cc](input, pos, callbacks);
|
||||
} else {
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.eatComments = (input, pos) => {
|
||||
loop: for (;;) {
|
||||
const cc = input.charCodeAt(pos);
|
||||
if (cc === CC_SLASH) {
|
||||
if (pos === input.length) return pos;
|
||||
let cc = input.charCodeAt(pos + 1);
|
||||
if (cc !== CC_ASTERISK) return pos;
|
||||
pos++;
|
||||
for (;;) {
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
cc = input.charCodeAt(pos);
|
||||
while (cc === CC_ASTERISK) {
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
cc = input.charCodeAt(pos);
|
||||
if (cc === CC_SLASH) {
|
||||
pos++;
|
||||
continue loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.eatWhitespaceAndComments = (input, pos) => {
|
||||
loop: for (;;) {
|
||||
const cc = input.charCodeAt(pos);
|
||||
if (cc === CC_SLASH) {
|
||||
if (pos === input.length) return pos;
|
||||
let cc = input.charCodeAt(pos + 1);
|
||||
if (cc !== CC_ASTERISK) return pos;
|
||||
pos++;
|
||||
for (;;) {
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
cc = input.charCodeAt(pos);
|
||||
while (cc === CC_ASTERISK) {
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
cc = input.charCodeAt(pos);
|
||||
if (cc === CC_SLASH) {
|
||||
pos++;
|
||||
continue loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (_isWhiteSpace(cc)) {
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
};
|
||||
|
|
@ -123,9 +123,7 @@ class Profiler {
|
|||
* @returns {Trace} The trace object
|
||||
*/
|
||||
const createTrace = (fs, outputPath) => {
|
||||
const trace = new Tracer({
|
||||
noStream: true
|
||||
});
|
||||
const trace = new Tracer();
|
||||
const profiler = new Profiler(inspector);
|
||||
if (/\/|\\/.test(outputPath)) {
|
||||
const dirPath = dirname(fs, outputPath);
|
||||
|
|
@ -173,6 +171,7 @@ const createTrace = (fs, outputPath) => {
|
|||
counter,
|
||||
profiler,
|
||||
end: callback => {
|
||||
trace.push("]");
|
||||
// Wait until the write stream finishes.
|
||||
fsStream.on("close", () => {
|
||||
callback();
|
||||
|
|
@ -242,10 +241,10 @@ class ProfilingPlugin {
|
|||
stage: Infinity
|
||||
},
|
||||
(stats, callback) => {
|
||||
if (compiler.watchMode) return callback();
|
||||
tracer.profiler.stopProfiling().then(parsedResults => {
|
||||
if (parsedResults === undefined) {
|
||||
tracer.profiler.destroy();
|
||||
tracer.trace.flush();
|
||||
tracer.end(callback);
|
||||
return;
|
||||
}
|
||||
|
|
@ -293,7 +292,6 @@ class ProfilingPlugin {
|
|||
});
|
||||
|
||||
tracer.profiler.destroy();
|
||||
tracer.trace.flush();
|
||||
tracer.end(callback);
|
||||
});
|
||||
}
|
||||
|
|
@ -345,16 +343,19 @@ const interceptAllJavascriptModulesPluginHooks = (compilation, tracer) => {
|
|||
};
|
||||
|
||||
const makeInterceptorFor = (instance, tracer) => hookName => ({
|
||||
register: ({ name, type, context, fn }) => {
|
||||
const newFn = makeNewProfiledTapFn(hookName, tracer, {
|
||||
name,
|
||||
type,
|
||||
fn
|
||||
});
|
||||
register: tapInfo => {
|
||||
const { name, type, fn } = tapInfo;
|
||||
const newFn =
|
||||
// Don't tap our own hooks to ensure stream can close cleanly
|
||||
name === pluginName
|
||||
? fn
|
||||
: makeNewProfiledTapFn(hookName, tracer, {
|
||||
name,
|
||||
type,
|
||||
fn
|
||||
});
|
||||
return {
|
||||
name,
|
||||
type,
|
||||
context,
|
||||
...tapInfo,
|
||||
fn: newFn
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ class CommonJsExportsParserPlugin {
|
|||
if (expr.arguments[1].type === "SpreadElement") return;
|
||||
if (expr.arguments[2].type === "SpreadElement") return;
|
||||
const exportsArg = parser.evaluateExpression(expr.arguments[0]);
|
||||
if (!exportsArg || !exportsArg.isIdentifier()) return;
|
||||
if (!exportsArg.isIdentifier()) return;
|
||||
if (
|
||||
exportsArg.identifier !== "exports" &&
|
||||
exportsArg.identifier !== "module.exports" &&
|
||||
|
|
@ -210,7 +210,6 @@ class CommonJsExportsParserPlugin {
|
|||
return;
|
||||
}
|
||||
const propertyArg = parser.evaluateExpression(expr.arguments[1]);
|
||||
if (!propertyArg) return;
|
||||
const property = propertyArg.asString();
|
||||
if (typeof property !== "string") return;
|
||||
enableStructuredExports();
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ const splitContextFromPrefix = prefix => {
|
|||
const idx = prefix.lastIndexOf("/");
|
||||
let context = ".";
|
||||
if (idx >= 0) {
|
||||
context = prefix.substr(0, idx);
|
||||
prefix = `.${prefix.substr(idx)}`;
|
||||
context = prefix.slice(0, idx);
|
||||
prefix = `.${prefix.slice(idx)}`;
|
||||
}
|
||||
return {
|
||||
context,
|
||||
|
|
@ -37,7 +37,7 @@ const splitContextFromPrefix = prefix => {
|
|||
};
|
||||
};
|
||||
|
||||
/** @typedef {Partial<Omit<ContextDependencyOptions, "resource"|"recursive"|"regExp">>} PartialContextDependencyOptions */
|
||||
/** @typedef {Partial<Omit<ContextDependencyOptions, "resource">>} PartialContextDependencyOptions */
|
||||
|
||||
/** @typedef {{ new(options: ContextDependencyOptions, range: [number, number], valueRange: [number, number]): ContextDependency }} ContextDependencyConstructor */
|
||||
|
||||
|
|
|
|||
|
|
@ -14,11 +14,27 @@ const ModuleDependency = require("./ModuleDependency");
|
|||
/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
|
||||
|
||||
class ContextElementDependency extends ModuleDependency {
|
||||
constructor(request, userRequest, typePrefix, category, referencedExports) {
|
||||
/**
|
||||
* @param {string} request request
|
||||
* @param {string|undefined} userRequest user request
|
||||
* @param {string} typePrefix type prefix
|
||||
* @param {string} category category
|
||||
* @param {string[][]=} referencedExports referenced exports
|
||||
* @param {string=} context context
|
||||
*/
|
||||
constructor(
|
||||
request,
|
||||
userRequest,
|
||||
typePrefix,
|
||||
category,
|
||||
referencedExports,
|
||||
context
|
||||
) {
|
||||
super(request);
|
||||
this.referencedExports = referencedExports;
|
||||
this._typePrefix = typePrefix;
|
||||
this._category = category;
|
||||
this._context = context || undefined;
|
||||
|
||||
if (userRequest) {
|
||||
this.userRequest = userRequest;
|
||||
|
|
@ -33,6 +49,20 @@ 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;
|
||||
}
|
||||
|
|
@ -53,12 +83,20 @@ class ContextElementDependency extends ModuleDependency {
|
|||
}
|
||||
|
||||
serialize(context) {
|
||||
context.write(this.referencedExports);
|
||||
const { write } = context;
|
||||
write(this._typePrefix);
|
||||
write(this._category);
|
||||
write(this._context);
|
||||
write(this.referencedExports);
|
||||
super.serialize(context);
|
||||
}
|
||||
|
||||
deserialize(context) {
|
||||
this.referencedExports = context.read();
|
||||
const { read } = context;
|
||||
this._typePrefix = read();
|
||||
this._category = read();
|
||||
this._context = read();
|
||||
this.referencedExports = read();
|
||||
super.deserialize(context);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue