webpack 5.106.2 → 5.107.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/lib/APIPlugin.js +1 -1
- package/lib/Cache.js +3 -6
- package/lib/CompatibilityPlugin.js +8 -7
- package/lib/Compilation.js +34 -26
- package/lib/Compiler.js +4 -13
- package/lib/ContextModule.js +2 -2
- package/lib/DefinePlugin.js +2 -2
- package/lib/Dependency.js +22 -1
- package/lib/DependencyTemplate.js +2 -1
- package/lib/EnvironmentPlugin.js +1 -1
- package/lib/EvalSourceMapDevToolPlugin.js +8 -9
- package/lib/ExternalModule.js +76 -15
- package/lib/ExternalModuleFactoryPlugin.js +5 -0
- package/lib/FileSystemInfo.js +187 -72
- package/lib/Generator.js +3 -3
- package/lib/HotModuleReplacementPlugin.js +26 -8
- package/lib/IgnorePlugin.js +2 -1
- package/lib/Module.js +19 -18
- package/lib/ModuleFactory.js +1 -1
- package/lib/ModuleSourceTypeConstants.js +31 -1
- package/lib/ModuleTypeConstants.js +12 -3
- package/lib/MultiCompiler.js +2 -2
- package/lib/NodeStuffPlugin.js +1 -1
- package/lib/NormalModule.js +13 -31
- package/lib/NormalModuleFactory.js +10 -2
- package/lib/Parser.js +1 -1
- package/lib/ProgressPlugin.js +129 -56
- package/lib/RuntimeGlobals.js +5 -5
- package/lib/RuntimeModule.js +9 -7
- package/lib/RuntimePlugin.js +11 -0
- package/lib/WarnCaseSensitiveModulesPlugin.js +70 -2
- package/lib/WarnDeprecatedOptionPlugin.js +1 -1
- package/lib/WarnNoModeSetPlugin.js +16 -1
- package/lib/Watching.js +2 -3
- package/lib/WebpackError.js +3 -77
- package/lib/WebpackIsIncludedPlugin.js +1 -1
- package/lib/WebpackOptionsApply.js +13 -1
- package/lib/asset/AssetBytesGenerator.js +6 -2
- package/lib/asset/AssetGenerator.js +22 -8
- package/lib/asset/AssetModulesPlugin.js +3 -1
- package/lib/asset/AssetSourceGenerator.js +6 -2
- package/lib/buildChunkGraph.js +4 -6
- package/lib/cache/PackFileCacheStrategy.js +4 -4
- package/lib/cli.js +3 -1
- package/lib/config/defaults.js +197 -10
- package/lib/config/normalization.js +3 -1
- package/lib/css/CssGenerator.js +320 -105
- package/lib/css/CssInjectStyleRuntimeModule.js +44 -42
- package/lib/css/CssLoadingRuntimeModule.js +22 -4
- package/lib/{CssModule.js → css/CssModule.js} +15 -15
- package/lib/css/CssModulesPlugin.js +166 -86
- package/lib/css/CssParser.js +566 -269
- package/lib/css/walkCssTokens.js +148 -2
- package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +1 -1
- package/lib/dependencies/CommonJsDependencyHelpers.js +63 -0
- package/lib/dependencies/CommonJsExportRequireDependency.js +54 -10
- package/lib/dependencies/CommonJsExportsParserPlugin.js +1 -1
- package/lib/dependencies/CommonJsFullRequireDependency.js +32 -9
- package/lib/dependencies/CommonJsImportsParserPlugin.js +4 -3
- package/lib/dependencies/CommonJsRequireDependency.js +67 -4
- package/lib/dependencies/ContextDependency.js +1 -1
- package/lib/dependencies/ContextDependencyHelpers.js +1 -1
- package/lib/dependencies/CreateRequireParserPlugin.js +1 -1
- package/lib/dependencies/CriticalDependencyWarning.js +1 -1
- package/lib/dependencies/CssIcssExportDependency.js +332 -67
- package/lib/dependencies/CssIcssImportDependency.js +49 -7
- package/lib/dependencies/CssIcssSymbolDependency.js +11 -3
- package/lib/dependencies/CssImportDependency.js +8 -0
- package/lib/dependencies/CssUrlDependency.js +25 -0
- package/lib/dependencies/HarmonyDetectionParserPlugin.js +1 -1
- package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +8 -7
- package/lib/dependencies/HarmonyExportExpressionDependency.js +22 -14
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +110 -3
- package/lib/dependencies/HarmonyImportDependency.js +10 -2
- package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +22 -1
- package/lib/dependencies/HarmonyImportSpecifierDependency.js +1 -1
- package/lib/{HarmonyLinkingError.js → dependencies/HarmonyLinkingError.js} +5 -3
- package/lib/dependencies/HtmlInlineScriptDependency.js +133 -0
- package/lib/dependencies/HtmlInlineStyleDependency.js +101 -0
- package/lib/dependencies/HtmlScriptSrcDependency.js +318 -0
- package/lib/dependencies/HtmlSourceDependency.js +127 -0
- package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +1 -1
- package/lib/dependencies/ImportParserPlugin.js +2 -2
- package/lib/dependencies/ImportPhase.js +1 -1
- package/lib/dependencies/RequireIncludeDependencyParserPlugin.js +1 -1
- package/lib/{RequireJsStuffPlugin.js → dependencies/RequireJsStuffPlugin.js} +7 -7
- package/lib/dependencies/SystemPlugin.js +1 -1
- package/lib/dependencies/WebAssemblyImportDependency.js +1 -1
- package/lib/dependencies/WorkerPlugin.js +2 -2
- package/lib/{DelegatedModule.js → dll/DelegatedModule.js} +31 -31
- package/lib/{DelegatedModuleFactoryPlugin.js → dll/DelegatedModuleFactoryPlugin.js} +4 -4
- package/lib/{DelegatedPlugin.js → dll/DelegatedPlugin.js} +2 -2
- package/lib/{DllEntryPlugin.js → dll/DllEntryPlugin.js} +4 -4
- package/lib/{DllModule.js → dll/DllModule.js} +24 -24
- package/lib/{DllModuleFactory.js → dll/DllModuleFactory.js} +4 -4
- package/lib/{DllPlugin.js → dll/DllPlugin.js} +6 -5
- package/lib/{DllReferencePlugin.js → dll/DllReferencePlugin.js} +14 -14
- package/lib/{LibManifestPlugin.js → dll/LibManifestPlugin.js} +9 -9
- package/lib/{AsyncDependencyToInitialChunkError.js → errors/AsyncDependencyToInitialChunkError.js} +2 -2
- package/lib/errors/BuildCycleError.js +1 -1
- package/lib/{ChunkRenderError.js → errors/ChunkRenderError.js} +1 -1
- package/lib/{CodeGenerationError.js → errors/CodeGenerationError.js} +1 -1
- package/lib/{CommentCompilationWarning.js → errors/CommentCompilationWarning.js} +3 -3
- package/lib/{ConcurrentCompilationError.js → errors/ConcurrentCompilationError.js} +4 -2
- package/lib/{EnvironmentNotSupportAsyncWarning.js → errors/EnvironmentNotSupportAsyncWarning.js} +4 -4
- package/lib/{HookWebpackError.js → errors/HookWebpackError.js} +5 -5
- package/lib/{IgnoreErrorModuleFactory.js → errors/IgnoreErrorModuleFactory.js} +4 -4
- package/lib/{InvalidDependenciesModuleWarning.js → errors/InvalidDependenciesModuleWarning.js} +3 -3
- package/lib/errors/JSONParseError.js +114 -0
- package/lib/{ModuleBuildError.js → errors/ModuleBuildError.js} +5 -5
- package/lib/{ModuleDependencyError.js → errors/ModuleDependencyError.js} +2 -2
- package/lib/{ModuleDependencyWarning.js → errors/ModuleDependencyWarning.js} +4 -4
- package/lib/{ModuleError.js → errors/ModuleError.js} +5 -5
- package/lib/{ModuleHashingError.js → errors/ModuleHashingError.js} +1 -1
- package/lib/{ModuleNotFoundError.js → errors/ModuleNotFoundError.js} +2 -2
- package/lib/{ModuleParseError.js → errors/ModuleParseError.js} +8 -6
- package/lib/{ModuleRestoreError.js → errors/ModuleRestoreError.js} +1 -1
- package/lib/{ModuleStoreError.js → errors/ModuleStoreError.js} +1 -1
- package/lib/{ModuleWarning.js → errors/ModuleWarning.js} +5 -5
- package/lib/{NodeStuffInWebError.js → errors/NodeStuffInWebError.js} +4 -4
- package/lib/errors/NonErrorEmittedError.js +28 -0
- package/lib/{UnhandledSchemeError.js → errors/UnhandledSchemeError.js} +2 -2
- package/lib/{UnsupportedFeatureWarning.js → errors/UnsupportedFeatureWarning.js} +3 -3
- package/lib/errors/WebpackError.js +84 -0
- package/lib/html/HtmlGenerator.js +379 -0
- package/lib/html/HtmlModulesPlugin.js +433 -0
- package/lib/html/HtmlParser.js +1489 -0
- package/lib/html/walkHtmlTokens.js +2733 -0
- package/lib/ids/IdHelpers.js +2 -1
- package/lib/index.js +34 -15
- package/lib/javascript/JavascriptModulesPlugin.js +89 -8
- package/lib/javascript/JavascriptParser.js +197 -16
- package/lib/javascript/JavascriptParserHelpers.js +1 -1
- package/lib/json/JsonParser.js +7 -16
- package/lib/library/AbstractLibraryPlugin.js +1 -1
- package/lib/library/EnableLibraryPlugin.js +1 -1
- package/lib/{FalseIIFEUmdWarning.js → library/FalseIIFEUmdWarning.js} +1 -1
- package/lib/library/ModuleLibraryPlugin.js +74 -0
- package/lib/node/NodeEnvironmentPlugin.js +4 -2
- package/lib/node/nodeConsole.js +113 -64
- package/lib/optimize/ConcatenatedModule.js +51 -6
- package/lib/optimize/InnerGraph.js +1 -1
- package/lib/optimize/InnerGraphPlugin.js +11 -1
- package/lib/optimize/MinMaxSizeWarning.js +4 -4
- package/lib/optimize/ModuleConcatenationPlugin.js +15 -7
- package/lib/optimize/RealContentHashPlugin.js +89 -26
- package/lib/optimize/SideEffectsFlagPlugin.js +111 -3
- package/lib/optimize/SplitChunksPlugin.js +1 -1
- package/lib/performance/AssetsOverSizeLimitWarning.js +2 -2
- package/lib/performance/EntrypointsOverSizeLimitWarning.js +2 -2
- package/lib/performance/NoAsyncChunksWarning.js +5 -3
- package/lib/performance/SizeLimitsPlugin.js +1 -1
- package/lib/prefetch/ChunkPrefetchTriggerRuntimeModule.js +4 -1
- package/lib/rules/UseEffectRulePlugin.js +4 -3
- package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +119 -13
- package/lib/runtime/SetAnonymousDefaultNameRuntimeModule.js +35 -0
- package/lib/schemes/DataUriPlugin.js +13 -1
- package/lib/schemes/VirtualUrlPlugin.js +1 -1
- package/lib/serialization/SerializerMiddleware.js +2 -2
- package/lib/sharing/ConsumeSharedPlugin.js +2 -2
- package/lib/sharing/ConsumeSharedRuntimeModule.js +8 -4
- package/lib/sharing/ProvideSharedModule.js +1 -1
- package/lib/sharing/ProvideSharedPlugin.js +1 -1
- package/lib/sharing/resolveMatchedConfigs.js +1 -1
- package/lib/stats/DefaultStatsFactoryPlugin.js +2 -2
- package/lib/stats/DefaultStatsPresetPlugin.js +1 -1
- package/lib/stats/DefaultStatsPrinterPlugin.js +1 -1
- package/lib/stats/StatsFactory.js +1 -1
- package/lib/typescript/TypeScriptPlugin.js +210 -0
- package/lib/url/URLParserPlugin.js +2 -2
- package/lib/util/AsyncQueue.js +2 -2
- package/lib/util/Hash.js +2 -2
- package/lib/util/LocConverter.js +53 -0
- package/lib/util/SortableSet.js +1 -1
- package/lib/util/cleverMerge.js +2 -2
- package/lib/util/comparators.js +3 -3
- package/lib/util/concatenate.js +3 -3
- package/lib/util/conventions.js +42 -1
- package/lib/util/createMappings.js +118 -0
- package/lib/{formatLocation.js → util/formatLocation.js} +2 -2
- package/lib/{SizeFormatHelpers.js → util/formatSize.js} +3 -1
- package/lib/util/fs.js +8 -8
- package/lib/util/hash/md4.js +1 -1
- package/lib/util/hash/xxhash64.js +1 -1
- package/lib/util/identifier.js +48 -0
- package/lib/util/internalSerializables.js +35 -19
- package/lib/util/magicComment.js +10 -7
- package/lib/util/parseJson.js +2 -73
- package/lib/util/source.js +21 -0
- package/lib/util/topologicalSort.js +69 -0
- package/lib/wasm-async/AsyncWebAssemblyModulesPlugin.js +2 -2
- package/lib/wasm-async/AsyncWebAssemblyParser.js +1 -1
- package/lib/wasm-sync/UnsupportedWebAssemblyFeatureError.js +5 -3
- package/lib/wasm-sync/WasmFinalizeExportsPlugin.js +1 -1
- package/lib/wasm-sync/WebAssemblyInInitialChunkError.js +5 -3
- package/lib/webpack.js +3 -1
- package/package.json +22 -20
- package/schemas/WebpackOptions.check.js +1 -1
- package/schemas/WebpackOptions.json +118 -3
- package/schemas/plugins/{DllPlugin.check.d.ts → HtmlGeneratorOptions.check.d.ts} +1 -1
- package/schemas/plugins/HtmlGeneratorOptions.check.js +6 -0
- package/schemas/plugins/HtmlGeneratorOptions.json +3 -0
- package/schemas/plugins/ProgressPlugin.check.js +1 -1
- package/schemas/plugins/ProgressPlugin.json +22 -0
- package/schemas/plugins/{DllReferencePlugin.check.d.ts → css/CssAutoOrModuleParserOptions.check.d.ts} +1 -1
- package/schemas/plugins/css/CssAutoOrModuleParserOptions.check.js +6 -0
- package/schemas/plugins/css/CssAutoOrModuleParserOptions.json +3 -0
- package/schemas/plugins/dll/DllPlugin.check.d.ts +7 -0
- package/schemas/plugins/dll/DllReferencePlugin.check.d.ts +7 -0
- package/types.d.ts +810 -101
- package/lib/CaseSensitiveModulesWarning.js +0 -80
- package/lib/GraphHelpers.js +0 -49
- package/lib/NoModeWarning.js +0 -23
- package/lib/css/CssMergeStyleSheetsRuntimeModule.js +0 -57
- /package/lib/{AbstractMethodError.js → errors/AbstractMethodError.js} +0 -0
- /package/schemas/plugins/{DllPlugin.check.js → dll/DllPlugin.check.js} +0 -0
- /package/schemas/plugins/{DllPlugin.json → dll/DllPlugin.json} +0 -0
- /package/schemas/plugins/{DllReferencePlugin.check.js → dll/DllReferencePlugin.check.js} +0 -0
- /package/schemas/plugins/{DllReferencePlugin.json → dll/DllReferencePlugin.json} +0 -0
package/lib/css/CssParser.js
CHANGED
|
@@ -5,13 +5,10 @@
|
|
|
5
5
|
|
|
6
6
|
"use strict";
|
|
7
7
|
|
|
8
|
+
const path = require("path");
|
|
8
9
|
const vm = require("vm");
|
|
9
|
-
const CommentCompilationWarning = require("../CommentCompilationWarning");
|
|
10
|
-
const ModuleDependencyWarning = require("../ModuleDependencyWarning");
|
|
11
10
|
const { CSS_MODULE_TYPE_AUTO } = require("../ModuleTypeConstants");
|
|
12
11
|
const Parser = require("../Parser");
|
|
13
|
-
const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning");
|
|
14
|
-
const WebpackError = require("../WebpackError");
|
|
15
12
|
const ConstDependency = require("../dependencies/ConstDependency");
|
|
16
13
|
const CssIcssExportDependency = require("../dependencies/CssIcssExportDependency");
|
|
17
14
|
const CssIcssImportDependency = require("../dependencies/CssIcssImportDependency");
|
|
@@ -19,12 +16,18 @@ const CssIcssSymbolDependency = require("../dependencies/CssIcssSymbolDependency
|
|
|
19
16
|
const CssImportDependency = require("../dependencies/CssImportDependency");
|
|
20
17
|
const CssUrlDependency = require("../dependencies/CssUrlDependency");
|
|
21
18
|
const StaticExportsDependency = require("../dependencies/StaticExportsDependency");
|
|
19
|
+
const CommentCompilationWarning = require("../errors/CommentCompilationWarning");
|
|
20
|
+
const ModuleDependencyWarning = require("../errors/ModuleDependencyWarning");
|
|
21
|
+
const UnsupportedFeatureWarning = require("../errors/UnsupportedFeatureWarning");
|
|
22
|
+
const WebpackError = require("../errors/WebpackError");
|
|
23
|
+
const LocConverter = require("../util/LocConverter");
|
|
22
24
|
const binarySearchBounds = require("../util/binarySearchBounds");
|
|
23
25
|
const { parseResource } = require("../util/identifier");
|
|
24
26
|
const {
|
|
25
27
|
createMagicCommentContext,
|
|
26
28
|
webpackCommentRegExp
|
|
27
29
|
} = require("../util/magicComment");
|
|
30
|
+
const topologicalSort = require("../util/topologicalSort");
|
|
28
31
|
const walkCssTokens = require("./walkCssTokens");
|
|
29
32
|
|
|
30
33
|
/** @typedef {import("../Module").BuildInfo} BuildInfo */
|
|
@@ -32,8 +35,9 @@ const walkCssTokens = require("./walkCssTokens");
|
|
|
32
35
|
/** @typedef {import("../Parser").ParserState} ParserState */
|
|
33
36
|
/** @typedef {import("../Parser").PreparsedAst} PreparsedAst */
|
|
34
37
|
/** @typedef {import("./walkCssTokens").CssTokenCallbacks} CssTokenCallbacks */
|
|
38
|
+
/** @typedef {import("../../declarations/WebpackOptions").CssAutoOrModuleParserOptions} CssAutoOrModuleParserOptions */
|
|
35
39
|
/** @typedef {import("../../declarations/WebpackOptions").CssModuleParserOptions} CssModuleParserOptions */
|
|
36
|
-
/** @typedef {import("
|
|
40
|
+
/** @typedef {import("./CssModule")} CssModule */
|
|
37
41
|
|
|
38
42
|
/** @typedef {[number, number]} Range */
|
|
39
43
|
/** @typedef {{ line: number, column: number }} Position */
|
|
@@ -52,6 +56,7 @@ const CC_TILDE = "~".charCodeAt(0);
|
|
|
52
56
|
const CC_EQUAL = "=".charCodeAt(0);
|
|
53
57
|
const CC_FULL_STOP = ".".charCodeAt(0);
|
|
54
58
|
const CC_EXCLAMATION = "!".charCodeAt(0);
|
|
59
|
+
const CC_AMPERSAND = "&".charCodeAt(0);
|
|
55
60
|
|
|
56
61
|
// https://www.w3.org/TR/css-syntax-3/#newline
|
|
57
62
|
// We don't have `preprocessing` stage, so we need specify all of them
|
|
@@ -128,138 +133,7 @@ const normalizeUrl = (str, isString) => {
|
|
|
128
133
|
return str;
|
|
129
134
|
};
|
|
130
135
|
|
|
131
|
-
const
|
|
132
|
-
const regexExcessiveSpaces =
|
|
133
|
-
/(^|\\+)?(\\[A-F0-9]{1,6})\u0020(?![a-fA-F0-9\u0020])/g;
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Returns escaped identifier.
|
|
137
|
-
* @param {string} str string
|
|
138
|
-
* @returns {string} escaped identifier
|
|
139
|
-
*/
|
|
140
|
-
const escapeIdentifier = (str) => {
|
|
141
|
-
let output = "";
|
|
142
|
-
let counter = 0;
|
|
143
|
-
|
|
144
|
-
while (counter < str.length) {
|
|
145
|
-
const character = str.charAt(counter++);
|
|
146
|
-
|
|
147
|
-
/** @type {string} */
|
|
148
|
-
let value;
|
|
149
|
-
|
|
150
|
-
if (/[\t\n\f\r\v]/.test(character)) {
|
|
151
|
-
const codePoint = character.charCodeAt(0);
|
|
152
|
-
|
|
153
|
-
value = `\\${codePoint.toString(16).toUpperCase()} `;
|
|
154
|
-
} else if (character === "\\" || regexSingleEscape.test(character)) {
|
|
155
|
-
value = `\\${character}`;
|
|
156
|
-
} else {
|
|
157
|
-
value = character;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
output += value;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const firstChar = str.charAt(0);
|
|
164
|
-
|
|
165
|
-
if (/^-[-\d]/.test(output)) {
|
|
166
|
-
output = `\\-${output.slice(1)}`;
|
|
167
|
-
} else if (/\d/.test(firstChar)) {
|
|
168
|
-
output = `\\3${firstChar} ${output.slice(1)}`;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// Remove spaces after `\HEX` escapes that are not followed by a hex digit,
|
|
172
|
-
// since they’re redundant. Note that this is only possible if the escape
|
|
173
|
-
// sequence isn’t preceded by an odd number of backslashes.
|
|
174
|
-
output = output.replace(regexExcessiveSpaces, ($0, $1, $2) => {
|
|
175
|
-
if ($1 && $1.length % 2) {
|
|
176
|
-
// It’s not safe to remove the space, so don’t.
|
|
177
|
-
return $0;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// Strip the space.
|
|
181
|
-
return ($1 || "") + $2;
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
return output;
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
const CONTAINS_ESCAPE = /\\/;
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Returns hex.
|
|
191
|
-
* @param {string} str string
|
|
192
|
-
* @returns {[string, number] | undefined} hex
|
|
193
|
-
*/
|
|
194
|
-
const gobbleHex = (str) => {
|
|
195
|
-
const lower = str.toLowerCase();
|
|
196
|
-
let hex = "";
|
|
197
|
-
let spaceTerminated = false;
|
|
198
|
-
|
|
199
|
-
for (let i = 0; i < 6 && lower[i] !== undefined; i++) {
|
|
200
|
-
const code = lower.charCodeAt(i);
|
|
201
|
-
// check to see if we are dealing with a valid hex char [a-f|0-9]
|
|
202
|
-
const valid = (code >= 97 && code <= 102) || (code >= 48 && code <= 57);
|
|
203
|
-
// https://drafts.csswg.org/css-syntax/#consume-escaped-code-point
|
|
204
|
-
spaceTerminated = code === 32;
|
|
205
|
-
if (!valid) break;
|
|
206
|
-
hex += lower[i];
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
if (hex.length === 0) return undefined;
|
|
210
|
-
|
|
211
|
-
const codePoint = Number.parseInt(hex, 16);
|
|
212
|
-
const isSurrogate = codePoint >= 0xd800 && codePoint <= 0xdfff;
|
|
213
|
-
|
|
214
|
-
// Add special case for
|
|
215
|
-
// "If this number is zero, or is for a surrogate, or is greater than the maximum allowed code point"
|
|
216
|
-
// https://drafts.csswg.org/css-syntax/#maximum-allowed-code-point
|
|
217
|
-
if (isSurrogate || codePoint === 0x0000 || codePoint > 0x10ffff) {
|
|
218
|
-
return ["\uFFFD", hex.length + (spaceTerminated ? 1 : 0)];
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
return [
|
|
222
|
-
String.fromCodePoint(codePoint),
|
|
223
|
-
hex.length + (spaceTerminated ? 1 : 0)
|
|
224
|
-
];
|
|
225
|
-
};
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Unescape identifier.
|
|
229
|
-
* @param {string} str string
|
|
230
|
-
* @returns {string} unescaped string
|
|
231
|
-
*/
|
|
232
|
-
const unescapeIdentifier = (str) => {
|
|
233
|
-
const needToProcess = CONTAINS_ESCAPE.test(str);
|
|
234
|
-
if (!needToProcess) return str;
|
|
235
|
-
let ret = "";
|
|
236
|
-
for (let i = 0; i < str.length; i++) {
|
|
237
|
-
if (str[i] === "\\") {
|
|
238
|
-
const gobbled = gobbleHex(str.slice(i + 1, i + 7));
|
|
239
|
-
if (gobbled !== undefined) {
|
|
240
|
-
ret += gobbled[0];
|
|
241
|
-
i += gobbled[1];
|
|
242
|
-
continue;
|
|
243
|
-
}
|
|
244
|
-
// Retain a pair of \\ if double escaped `\\\\`
|
|
245
|
-
// https://github.com/postcss/postcss-selector-parser/commit/268c9a7656fb53f543dc620aa5b73a30ec3ff20e
|
|
246
|
-
if (str[i + 1] === "\\") {
|
|
247
|
-
ret += "\\";
|
|
248
|
-
i += 1;
|
|
249
|
-
continue;
|
|
250
|
-
}
|
|
251
|
-
// if \\ is at the end of the string retain it
|
|
252
|
-
// https://github.com/postcss/postcss-selector-parser/commit/01a6b346e3612ce1ab20219acc26abdc259ccefb
|
|
253
|
-
if (str.length === i + 1) {
|
|
254
|
-
ret += str[i];
|
|
255
|
-
}
|
|
256
|
-
continue;
|
|
257
|
-
}
|
|
258
|
-
ret += str[i];
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
return ret;
|
|
262
|
-
};
|
|
136
|
+
const { escapeIdentifier, unescapeIdentifier } = walkCssTokens;
|
|
263
137
|
|
|
264
138
|
/**
|
|
265
139
|
* A custom property is any property whose name starts with two dashes (U+002D HYPHEN-MINUS), like --foo.
|
|
@@ -531,51 +405,6 @@ const getKnownProperties = (options = {}) => {
|
|
|
531
405
|
return knownProperties;
|
|
532
406
|
};
|
|
533
407
|
|
|
534
|
-
class LocConverter {
|
|
535
|
-
/**
|
|
536
|
-
* Creates an instance of LocConverter.
|
|
537
|
-
* @param {string} input input
|
|
538
|
-
*/
|
|
539
|
-
constructor(input) {
|
|
540
|
-
this._input = input;
|
|
541
|
-
this.line = 1;
|
|
542
|
-
this.column = 0;
|
|
543
|
-
this.pos = 0;
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
/**
|
|
547
|
-
* Returns location converter.
|
|
548
|
-
* @param {number} pos position
|
|
549
|
-
* @returns {LocConverter} location converter
|
|
550
|
-
*/
|
|
551
|
-
get(pos) {
|
|
552
|
-
if (this.pos !== pos) {
|
|
553
|
-
if (this.pos < pos) {
|
|
554
|
-
const str = this._input.slice(this.pos, pos);
|
|
555
|
-
let i = str.lastIndexOf("\n");
|
|
556
|
-
if (i === -1) {
|
|
557
|
-
this.column += str.length;
|
|
558
|
-
} else {
|
|
559
|
-
this.column = str.length - i - 1;
|
|
560
|
-
this.line++;
|
|
561
|
-
while (i > 0 && (i = str.lastIndexOf("\n", i - 1)) !== -1) {
|
|
562
|
-
this.line++;
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
} else {
|
|
566
|
-
let i = this._input.lastIndexOf("\n", this.pos);
|
|
567
|
-
while (i >= pos) {
|
|
568
|
-
this.line--;
|
|
569
|
-
i = i > 0 ? this._input.lastIndexOf("\n", i - 1) : -1;
|
|
570
|
-
}
|
|
571
|
-
this.column = pos - i;
|
|
572
|
-
}
|
|
573
|
-
this.pos = pos;
|
|
574
|
-
}
|
|
575
|
-
return this;
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
|
|
579
408
|
const EMPTY_COMMENT_OPTIONS = {
|
|
580
409
|
options: null,
|
|
581
410
|
errors: null
|
|
@@ -596,7 +425,7 @@ const eatUntilLeftCurly = walkCssTokens.eatUntil("{");
|
|
|
596
425
|
* @property {("pure" | "global" | "local" | "auto")=} defaultMode default mode
|
|
597
426
|
*/
|
|
598
427
|
|
|
599
|
-
/** @typedef {
|
|
428
|
+
/** @typedef {CssAutoOrModuleParserOptions & CssParserOwnOptions} CssParserOptions */
|
|
600
429
|
|
|
601
430
|
class CssParser extends Parser {
|
|
602
431
|
/**
|
|
@@ -644,6 +473,27 @@ class CssParser extends Parser {
|
|
|
644
473
|
);
|
|
645
474
|
}
|
|
646
475
|
|
|
476
|
+
/**
|
|
477
|
+
* Emits a build error for the provided range.
|
|
478
|
+
* @param {ParserState} state parser state
|
|
479
|
+
* @param {string} message error message
|
|
480
|
+
* @param {LocConverter} locConverter location converter
|
|
481
|
+
* @param {number} start start offset
|
|
482
|
+
* @param {number} end end offset
|
|
483
|
+
*/
|
|
484
|
+
_emitError(state, message, locConverter, start, end) {
|
|
485
|
+
const { line: sl, column: sc } = locConverter.get(start);
|
|
486
|
+
const { line: el, column: ec } = locConverter.get(end);
|
|
487
|
+
|
|
488
|
+
const err = new WebpackError(message);
|
|
489
|
+
err.module = state.module;
|
|
490
|
+
err.loc = {
|
|
491
|
+
start: { line: sl, column: sc },
|
|
492
|
+
end: { line: el, column: ec }
|
|
493
|
+
};
|
|
494
|
+
state.module.addError(err);
|
|
495
|
+
}
|
|
496
|
+
|
|
647
497
|
/**
|
|
648
498
|
* Parses the provided source and updates the parser state.
|
|
649
499
|
* @param {string | Buffer | PreparsedAst} source the source to parse
|
|
@@ -660,6 +510,10 @@ class CssParser extends Parser {
|
|
|
660
510
|
source = source.slice(1);
|
|
661
511
|
}
|
|
662
512
|
|
|
513
|
+
const unescapeIdentifierCached = unescapeIdentifier.bindCache(
|
|
514
|
+
state.compilation.compiler.root
|
|
515
|
+
);
|
|
516
|
+
|
|
663
517
|
let mode = this.defaultMode;
|
|
664
518
|
|
|
665
519
|
const module = state.module;
|
|
@@ -675,6 +529,40 @@ class CssParser extends Parser {
|
|
|
675
529
|
}
|
|
676
530
|
|
|
677
531
|
const isModules = mode === "global" || mode === "local";
|
|
532
|
+
|
|
533
|
+
const parsedModuleResource = parseResource(
|
|
534
|
+
/** @type {string} */ (module.getResource())
|
|
535
|
+
);
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* Check whether a request points back to the current module
|
|
539
|
+
* (e.g. `composes: foo from "./self.module.css"` inside `self.module.css`).
|
|
540
|
+
* Only relative requests are checked — aliases / package / absolute requests
|
|
541
|
+
* fall through to the normal import path. Requests with a `?query` or
|
|
542
|
+
* `#fragment` are only treated as self when the parent module's resource
|
|
543
|
+
* has the same query/fragment, since `NormalModuleFactory` keys modules
|
|
544
|
+
* on the full resource string.
|
|
545
|
+
* @param {string} request request string from `from "<request>"`
|
|
546
|
+
* @returns {boolean} true if request resolves to the current module
|
|
547
|
+
*/
|
|
548
|
+
const isSelfReferenceRequest = (request) => {
|
|
549
|
+
if (!/^\.{1,2}\//.test(request)) return false;
|
|
550
|
+
if (!module.context) return false;
|
|
551
|
+
const parsedRequest = parseResource(request);
|
|
552
|
+
if (parsedRequest.query !== parsedModuleResource.query) return false;
|
|
553
|
+
if (parsedRequest.fragment !== parsedModuleResource.fragment) {
|
|
554
|
+
return false;
|
|
555
|
+
}
|
|
556
|
+
try {
|
|
557
|
+
return (
|
|
558
|
+
path.resolve(module.context, parsedRequest.path) ===
|
|
559
|
+
parsedModuleResource.path
|
|
560
|
+
);
|
|
561
|
+
} catch (_err) {
|
|
562
|
+
return false;
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
|
|
678
566
|
const knownProperties = getKnownProperties({
|
|
679
567
|
animation: this.options.animation,
|
|
680
568
|
container: this.options.container,
|
|
@@ -683,7 +571,11 @@ class CssParser extends Parser {
|
|
|
683
571
|
});
|
|
684
572
|
|
|
685
573
|
/** @type {BuildMeta} */
|
|
686
|
-
(module.buildMeta).
|
|
574
|
+
(module.buildMeta).isCssModule = isModules;
|
|
575
|
+
if (/** @type {CssModule} */ (module).exportType === "style") {
|
|
576
|
+
/** @type {BuildMeta} */
|
|
577
|
+
(module.buildMeta).needIdInConcatenation = true;
|
|
578
|
+
}
|
|
687
579
|
|
|
688
580
|
const locConverter = new LocConverter(source);
|
|
689
581
|
|
|
@@ -707,10 +599,121 @@ class CssParser extends Parser {
|
|
|
707
599
|
/** @type {string[]} */
|
|
708
600
|
let lastLocalIdentifiers = [];
|
|
709
601
|
|
|
710
|
-
|
|
602
|
+
const pureMode = isModules && Boolean(this.options.pure);
|
|
603
|
+
/** @type {boolean} */
|
|
604
|
+
let currentSelectorHasLocal = false;
|
|
605
|
+
/** Whether any comma-separated selector in the current rule's prelude was impure. */
|
|
606
|
+
let currentRuleHasImpureSelector = false;
|
|
607
|
+
/** Offset just after the previous `}` (or 0) — used as the prelude start. */
|
|
608
|
+
let currentRulePreludeStart = 0;
|
|
609
|
+
/** Pure-mode flags (only meaningful when `pureMode` is true). */
|
|
610
|
+
let pureNoCheck = false;
|
|
611
|
+
let pureIgnorePending = false;
|
|
612
|
+
let nextBlockChildrenSkip = false;
|
|
613
|
+
let nextBlockTreatAsLeaf = false;
|
|
614
|
+
let seenTopLevelRule = false;
|
|
615
|
+
// True after an at-rule keyword and before the next `{` or `;`. Used so
|
|
616
|
+
// identifiers inside the at-rule prelude (e.g. `min-width` inside
|
|
617
|
+
// `@media (min-width: 768px)`) don't get counted as declarations.
|
|
618
|
+
let inAtRulePrelude = false;
|
|
619
|
+
/**
|
|
620
|
+
* One entry per open block. `skipOwn` skips this rule's own check (set
|
|
621
|
+
* when the parent passed down `skipChildren`, e.g. `from`/`to` inside
|
|
622
|
+
* `@keyframes`). `skipChildren` is propagated to descendants. `ignored`
|
|
623
|
+
* is per-rule only (PCSL semantics for `cssmodules-pure-ignore`).
|
|
624
|
+
* `ancestorHadLocal` lets nested rules inherit purity from a
|
|
625
|
+
* local-bearing ancestor.
|
|
626
|
+
* @type {{
|
|
627
|
+
* ignored: boolean,
|
|
628
|
+
* skipOwn: boolean,
|
|
629
|
+
* skipChildren: boolean,
|
|
630
|
+
* treatAsLeaf: boolean,
|
|
631
|
+
* ancestorHadLocal: boolean,
|
|
632
|
+
* impure: boolean,
|
|
633
|
+
* hasDirectDecl: boolean,
|
|
634
|
+
* hasNestedBlock: boolean,
|
|
635
|
+
* isRulePrelude: boolean,
|
|
636
|
+
* preludeStart: number,
|
|
637
|
+
* preludeEnd: number,
|
|
638
|
+
* }[]}
|
|
639
|
+
*/
|
|
640
|
+
const pureBlockStack = [];
|
|
641
|
+
|
|
642
|
+
const PURE_IGNORE_RE = /^\s*cssmodules-pure-ignore(?:\s|$)/;
|
|
643
|
+
const PURE_NO_CHECK_RE = /^\s*cssmodules-pure-no-check(?:\s|$)/;
|
|
644
|
+
|
|
645
|
+
/**
|
|
646
|
+
* @returns {(typeof pureBlockStack)[number] | undefined} top of stack
|
|
647
|
+
*/
|
|
648
|
+
const pureTop = () => pureBlockStack[pureBlockStack.length - 1];
|
|
649
|
+
|
|
650
|
+
/**
|
|
651
|
+
* Was the parent rule pure overall (its own selectors pure or any
|
|
652
|
+
* ancestor pure)? Used both for ancestor-inheritance and `&`-resolution.
|
|
653
|
+
* @returns {boolean} true if any ancestor (self inclusive) provided a local
|
|
654
|
+
*/
|
|
655
|
+
const parentEffectivePure = () => {
|
|
656
|
+
const top = pureTop();
|
|
657
|
+
return top ? top.ancestorHadLocal : false;
|
|
658
|
+
};
|
|
659
|
+
|
|
660
|
+
/**
|
|
661
|
+
* Marks the just-finished comma-separated selector (or whole prelude
|
|
662
|
+
* at `{`) as impure if it lacks a local and no ancestor compensates.
|
|
663
|
+
*/
|
|
664
|
+
const finalizeSelector = () => {
|
|
665
|
+
if (!currentSelectorHasLocal && !parentEffectivePure()) {
|
|
666
|
+
currentRuleHasImpureSelector = true;
|
|
667
|
+
}
|
|
668
|
+
currentSelectorHasLocal = false;
|
|
669
|
+
};
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* Reports a pure-mode violation covering the entire rule prelude.
|
|
673
|
+
* @param {number} start prelude start offset
|
|
674
|
+
* @param {number} end prelude end offset (`{` position)
|
|
675
|
+
*/
|
|
676
|
+
const reportPureRule = (start, end) => {
|
|
677
|
+
const slice = source.slice(start, end);
|
|
678
|
+
const lead = /** @type {RegExpExecArray} */ (
|
|
679
|
+
/^(?:\s|\/\*[\s\S]*?\*\/)*/.exec(slice)
|
|
680
|
+
)[0].length;
|
|
681
|
+
const trail = /** @type {RegExpExecArray} */ (/\s*$/.exec(slice))[0]
|
|
682
|
+
.length;
|
|
683
|
+
const from = start + lead;
|
|
684
|
+
const to = end - trail;
|
|
685
|
+
if (to <= from) return;
|
|
686
|
+
this._emitError(
|
|
687
|
+
state,
|
|
688
|
+
`Selector "${source.slice(from, to)}" is not pure (pure selectors must contain at least one local class or id)`,
|
|
689
|
+
locConverter,
|
|
690
|
+
from,
|
|
691
|
+
to
|
|
692
|
+
);
|
|
693
|
+
};
|
|
694
|
+
|
|
695
|
+
/** @typedef {{ value?: string, importName?: string, localName?: string, request?: string }} IcssDefinition */
|
|
711
696
|
/** @type {Map<string, IcssDefinition>} */
|
|
712
697
|
const icssDefinitions = new Map();
|
|
713
698
|
|
|
699
|
+
// Tracks `composes: <name> from "<file>"` declarations to enforce a
|
|
700
|
+
// predictable file load order across rules (port of
|
|
701
|
+
// postcss-modules-extract-imports#138). Each rule's composes order
|
|
702
|
+
// is a partial ordering: if `.x` composes `b from "./b"` before
|
|
703
|
+
// `c from "./c"`, then `b.css` must load before `c.css` so `c` can
|
|
704
|
+
// override `b` in the cascade. Edges are added inline as the rule
|
|
705
|
+
// is parsed; at end-of-parse the first composes-import dep of each
|
|
706
|
+
// file is tagged with `sourceOrder` according to a topological
|
|
707
|
+
// sort (`NormalModule#build` reorders by `sourceOrder` for us).
|
|
708
|
+
/** @type {Map<string, Set<string>>} */
|
|
709
|
+
const composesGraph = new Map();
|
|
710
|
+
/** @type {Map<string, CssIcssImportDependency>} */
|
|
711
|
+
const composesFirstFileImport = new Map();
|
|
712
|
+
/** @type {string | undefined} */
|
|
713
|
+
let currentRulePrevComposesFile;
|
|
714
|
+
/** @type {Set<string>} */
|
|
715
|
+
const currentRuleComposesFiles = new Set();
|
|
716
|
+
|
|
714
717
|
/**
|
|
715
718
|
* Checks whether this css parser is next nested syntax.
|
|
716
719
|
* @param {string} input input
|
|
@@ -762,9 +765,11 @@ class CssParser extends Parser {
|
|
|
762
765
|
const { line: sl, column: sc } = locConverter.get(start);
|
|
763
766
|
const { line: el, column: ec } = locConverter.get(end);
|
|
764
767
|
|
|
768
|
+
const value = input.slice(start + 2, end - 2);
|
|
769
|
+
|
|
765
770
|
/** @type {Comment} */
|
|
766
771
|
const comment = {
|
|
767
|
-
value
|
|
772
|
+
value,
|
|
768
773
|
range: [start, end],
|
|
769
774
|
loc: {
|
|
770
775
|
start: { line: sl, column: sc },
|
|
@@ -772,6 +777,19 @@ class CssParser extends Parser {
|
|
|
772
777
|
}
|
|
773
778
|
};
|
|
774
779
|
this.comments.push(comment);
|
|
780
|
+
|
|
781
|
+
if (pureMode) {
|
|
782
|
+
if (PURE_IGNORE_RE.test(value)) {
|
|
783
|
+
pureIgnorePending = true;
|
|
784
|
+
} else if (
|
|
785
|
+
PURE_NO_CHECK_RE.test(value) &&
|
|
786
|
+
scope === CSS_MODE_TOP_LEVEL &&
|
|
787
|
+
!seenTopLevelRule
|
|
788
|
+
) {
|
|
789
|
+
pureNoCheck = true;
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
|
|
775
793
|
return end;
|
|
776
794
|
};
|
|
777
795
|
|
|
@@ -790,7 +808,7 @@ class CssParser extends Parser {
|
|
|
790
808
|
});
|
|
791
809
|
if (!tokens[3]) return end;
|
|
792
810
|
const semi = tokens[3][1];
|
|
793
|
-
if (!tokens[0]) {
|
|
811
|
+
if (!tokens[0] || (tokens[0][4] && !isModules)) {
|
|
794
812
|
this._emitWarning(
|
|
795
813
|
state,
|
|
796
814
|
`Expected URL in '${input.slice(start, semi)}'`,
|
|
@@ -802,7 +820,48 @@ class CssParser extends Parser {
|
|
|
802
820
|
}
|
|
803
821
|
|
|
804
822
|
const urlToken = tokens[0];
|
|
805
|
-
|
|
823
|
+
/** @type {string} */
|
|
824
|
+
let url;
|
|
825
|
+
if (urlToken[4]) {
|
|
826
|
+
// URL given as identifier — resolve via CSS Modules @value.
|
|
827
|
+
const name = input.slice(urlToken[2], urlToken[3]);
|
|
828
|
+
const def = icssDefinitions.get(name);
|
|
829
|
+
if (!def) {
|
|
830
|
+
this._emitWarning(
|
|
831
|
+
state,
|
|
832
|
+
`Unknown '@value' identifier '${name}' in '${input.slice(start, semi)}'`,
|
|
833
|
+
locConverter,
|
|
834
|
+
start,
|
|
835
|
+
semi
|
|
836
|
+
);
|
|
837
|
+
// Consume the whole at-rule so the unresolved identifier
|
|
838
|
+
// doesn't get re-tokenized and accidentally substituted
|
|
839
|
+
// into a malformed `@import` in the output.
|
|
840
|
+
const dep = new ConstDependency("", [start, semi]);
|
|
841
|
+
module.addPresentationalDependency(dep);
|
|
842
|
+
return semi;
|
|
843
|
+
}
|
|
844
|
+
if (def.value === undefined) {
|
|
845
|
+
this._emitWarning(
|
|
846
|
+
state,
|
|
847
|
+
`'@value' identifier '${name}' was imported from another module and cannot be used as the URL of '@import' — only locally defined values are supported here`,
|
|
848
|
+
locConverter,
|
|
849
|
+
start,
|
|
850
|
+
semi
|
|
851
|
+
);
|
|
852
|
+
const dep = new ConstDependency("", [start, semi]);
|
|
853
|
+
module.addPresentationalDependency(dep);
|
|
854
|
+
return semi;
|
|
855
|
+
}
|
|
856
|
+
const raw = def.value.trim();
|
|
857
|
+
url =
|
|
858
|
+
(raw.startsWith('"') && raw.endsWith('"')) ||
|
|
859
|
+
(raw.startsWith("'") && raw.endsWith("'"))
|
|
860
|
+
? normalizeUrl(raw.slice(1, -1), true)
|
|
861
|
+
: normalizeUrl(raw, false);
|
|
862
|
+
} else {
|
|
863
|
+
url = normalizeUrl(input.slice(urlToken[2], urlToken[3]), true);
|
|
864
|
+
}
|
|
806
865
|
const newline = walkCssTokens.eatWhiteLine(input, semi);
|
|
807
866
|
const { options, errors: commentErrors } = this.parseCommentOptions([
|
|
808
867
|
end,
|
|
@@ -886,6 +945,17 @@ class CssParser extends Parser {
|
|
|
886
945
|
);
|
|
887
946
|
dep.setLoc(sl, sc, el, ec);
|
|
888
947
|
module.addDependency(dep);
|
|
948
|
+
// `text` and `css-style-sheet` parents inline the imported
|
|
949
|
+
// module's rendered CSS at build time, which means we read the
|
|
950
|
+
// imported module's `codeGenerationResults` (and through it the
|
|
951
|
+
// results of any assets the import references). Registering this
|
|
952
|
+
// as a code-generation dependency tells the compilation scheduler
|
|
953
|
+
// to generate the imported subtree before us.
|
|
954
|
+
const exportType = /** @type {import("./CssModule")} */ (module)
|
|
955
|
+
.exportType;
|
|
956
|
+
if (exportType === "text" || exportType === "css-style-sheet") {
|
|
957
|
+
module.addCodeGenerationDependency(dep);
|
|
958
|
+
}
|
|
889
959
|
|
|
890
960
|
return newline;
|
|
891
961
|
};
|
|
@@ -1004,9 +1074,32 @@ class CssParser extends Parser {
|
|
|
1004
1074
|
return end;
|
|
1005
1075
|
}
|
|
1006
1076
|
}
|
|
1007
|
-
|
|
1077
|
+
let value = normalizeUrl(input.slice(contentStart, contentEnd), false);
|
|
1008
1078
|
// Ignore `url()`, `url('')` and `url("")`, they are valid by spec
|
|
1009
1079
|
if (value.length === 0) return end;
|
|
1080
|
+
if (isModules) {
|
|
1081
|
+
const def = icssDefinitions.get(value);
|
|
1082
|
+
if (def) {
|
|
1083
|
+
if (def.value !== undefined) {
|
|
1084
|
+
const raw = def.value.trim();
|
|
1085
|
+
value =
|
|
1086
|
+
(raw.startsWith('"') && raw.endsWith('"')) ||
|
|
1087
|
+
(raw.startsWith("'") && raw.endsWith("'"))
|
|
1088
|
+
? normalizeUrl(raw.slice(1, -1), true)
|
|
1089
|
+
: normalizeUrl(raw, false);
|
|
1090
|
+
if (value.length === 0) return end;
|
|
1091
|
+
} else {
|
|
1092
|
+
this._emitWarning(
|
|
1093
|
+
state,
|
|
1094
|
+
`'@value' identifier '${value}' was imported from another module and cannot be used inside 'url()' — only locally defined values are supported here`,
|
|
1095
|
+
locConverter,
|
|
1096
|
+
start,
|
|
1097
|
+
end
|
|
1098
|
+
);
|
|
1099
|
+
return end;
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1010
1103
|
const dep = new CssUrlDependency(value, [start, end], "url");
|
|
1011
1104
|
const { line: sl, column: sc } = locConverter.get(start);
|
|
1012
1105
|
const { line: el, column: ec } = locConverter.get(end);
|
|
@@ -1086,7 +1179,7 @@ class CssParser extends Parser {
|
|
|
1086
1179
|
* @param {string} value value to resolve
|
|
1087
1180
|
* @param {string=} localName override local name
|
|
1088
1181
|
* @param {boolean=} isCustomProperty true when it is custom property, otherwise false
|
|
1089
|
-
* @returns {string | [string, string]} resolved reexport (`localName` and `
|
|
1182
|
+
* @returns {string | [string, string] | [string, string, string]} resolved reexport (`localName`, `importName` and optional `request` of the active `@value` import)
|
|
1090
1183
|
*/
|
|
1091
1184
|
const getReexport = (value, localName, isCustomProperty) => {
|
|
1092
1185
|
const reexport = icssDefinitions.get(
|
|
@@ -1095,10 +1188,11 @@ class CssParser extends Parser {
|
|
|
1095
1188
|
|
|
1096
1189
|
if (reexport) {
|
|
1097
1190
|
if (reexport.importName) {
|
|
1098
|
-
|
|
1099
|
-
reexport.localName || (isCustomProperty ? `--${value}` : value)
|
|
1100
|
-
|
|
1101
|
-
|
|
1191
|
+
const resolvedLocalName =
|
|
1192
|
+
reexport.localName || (isCustomProperty ? `--${value}` : value);
|
|
1193
|
+
return reexport.request
|
|
1194
|
+
? [resolvedLocalName, reexport.importName, reexport.request]
|
|
1195
|
+
: [resolvedLocalName, reexport.importName];
|
|
1102
1196
|
}
|
|
1103
1197
|
|
|
1104
1198
|
if (isCustomProperty) {
|
|
@@ -1192,7 +1286,10 @@ class CssParser extends Parser {
|
|
|
1192
1286
|
dep.setLoc(sl, sc, el, ec);
|
|
1193
1287
|
module.addDependency(dep);
|
|
1194
1288
|
|
|
1195
|
-
icssDefinitions.set(name, {
|
|
1289
|
+
icssDefinitions.set(name, {
|
|
1290
|
+
importName: value,
|
|
1291
|
+
request: /** @type {string} */ (request)
|
|
1292
|
+
});
|
|
1196
1293
|
} else if (type === 1) {
|
|
1197
1294
|
const dep = new CssIcssExportDependency(name, getReexport(value));
|
|
1198
1295
|
const { line: sl, column: sc } = locConverter.get(start);
|
|
@@ -1409,7 +1506,7 @@ class CssParser extends Parser {
|
|
|
1409
1506
|
dep.setLoc(sl, sc, el, ec);
|
|
1410
1507
|
module.addDependency(dep);
|
|
1411
1508
|
|
|
1412
|
-
icssDefinitions.set(localName, { importName });
|
|
1509
|
+
icssDefinitions.set(localName, { importName, request: from });
|
|
1413
1510
|
}
|
|
1414
1511
|
|
|
1415
1512
|
{
|
|
@@ -1491,7 +1588,8 @@ class CssParser extends Parser {
|
|
|
1491
1588
|
def.localName || name,
|
|
1492
1589
|
[start, end],
|
|
1493
1590
|
def.value,
|
|
1494
|
-
def.importName
|
|
1591
|
+
def.importName,
|
|
1592
|
+
def.request
|
|
1495
1593
|
);
|
|
1496
1594
|
dep.setLoc(sl, sc, el, ec);
|
|
1497
1595
|
module.addDependency(dep);
|
|
@@ -1520,7 +1618,9 @@ class CssParser extends Parser {
|
|
|
1520
1618
|
{
|
|
1521
1619
|
identifier(input, start, end) {
|
|
1522
1620
|
if (type === 1) {
|
|
1523
|
-
let identifier =
|
|
1621
|
+
let identifier = unescapeIdentifierCached(
|
|
1622
|
+
input.slice(start, end)
|
|
1623
|
+
);
|
|
1524
1624
|
const { line: sl, column: sc } = locConverter.get(start);
|
|
1525
1625
|
const { line: el, column: ec } = locConverter.get(end);
|
|
1526
1626
|
const isDashedIdent = isDashedIdentifier(identifier);
|
|
@@ -1576,7 +1676,9 @@ class CssParser extends Parser {
|
|
|
1576
1676
|
{
|
|
1577
1677
|
string(_input, start, end) {
|
|
1578
1678
|
if (!found && options.string) {
|
|
1579
|
-
const value =
|
|
1679
|
+
const value = unescapeIdentifierCached(
|
|
1680
|
+
input.slice(start + 1, end - 1)
|
|
1681
|
+
);
|
|
1580
1682
|
const { line: sl, column: sc } = locConverter.get(start);
|
|
1581
1683
|
const { line: el, column: ec } = locConverter.get(end);
|
|
1582
1684
|
const dep = new CssIcssExportDependency(
|
|
@@ -1589,6 +1691,7 @@ class CssParser extends Parser {
|
|
|
1589
1691
|
dep.setLoc(sl, sc, el, ec);
|
|
1590
1692
|
module.addDependency(dep);
|
|
1591
1693
|
found = true;
|
|
1694
|
+
if (pureMode) currentSelectorHasLocal = true;
|
|
1592
1695
|
}
|
|
1593
1696
|
return end;
|
|
1594
1697
|
},
|
|
@@ -1597,7 +1700,7 @@ class CssParser extends Parser {
|
|
|
1597
1700
|
const value = input.slice(start, end);
|
|
1598
1701
|
|
|
1599
1702
|
if (options.identifier) {
|
|
1600
|
-
const identifier =
|
|
1703
|
+
const identifier = unescapeIdentifierCached(value);
|
|
1601
1704
|
|
|
1602
1705
|
if (
|
|
1603
1706
|
options.identifier instanceof RegExp &&
|
|
@@ -1620,6 +1723,7 @@ class CssParser extends Parser {
|
|
|
1620
1723
|
dep.setLoc(sl, sc, el, ec);
|
|
1621
1724
|
module.addDependency(dep);
|
|
1622
1725
|
found = true;
|
|
1726
|
+
if (pureMode) currentSelectorHasLocal = true;
|
|
1623
1727
|
}
|
|
1624
1728
|
}
|
|
1625
1729
|
return end;
|
|
@@ -1638,6 +1742,7 @@ class CssParser extends Parser {
|
|
|
1638
1742
|
|
|
1639
1743
|
if (!found && type) {
|
|
1640
1744
|
found = true;
|
|
1745
|
+
if (type === 1 && pureMode) currentSelectorHasLocal = true;
|
|
1641
1746
|
return processLocalOrGlobalFunction(input, type, start, end);
|
|
1642
1747
|
}
|
|
1643
1748
|
|
|
@@ -1665,7 +1770,7 @@ class CssParser extends Parser {
|
|
|
1665
1770
|
const processDashedIdent = (input, start, end) => {
|
|
1666
1771
|
const customIdent = walkCssTokens.eatIdentSequence(input, start);
|
|
1667
1772
|
if (!customIdent) return end;
|
|
1668
|
-
const identifier =
|
|
1773
|
+
const identifier = unescapeIdentifierCached(
|
|
1669
1774
|
input.slice(customIdent[0] + 2, customIdent[1])
|
|
1670
1775
|
);
|
|
1671
1776
|
const afterCustomIdent = walkCssTokens.eatWhitespaceAndComments(
|
|
@@ -1842,7 +1947,7 @@ class CssParser extends Parser {
|
|
|
1842
1947
|
propertyName === "grid-template" ||
|
|
1843
1948
|
propertyName === "grid-template-areas"
|
|
1844
1949
|
) {
|
|
1845
|
-
const areas =
|
|
1950
|
+
const areas = unescapeIdentifierCached(
|
|
1846
1951
|
input.slice(start + 1, end - 1)
|
|
1847
1952
|
);
|
|
1848
1953
|
const matches = matchAll(/\b\w+\b/g, areas);
|
|
@@ -1936,7 +2041,7 @@ class CssParser extends Parser {
|
|
|
1936
2041
|
const { line: sl, column: sc } = locConverter.get(value[0]);
|
|
1937
2042
|
const { line: el, column: ec } = locConverter.get(value[1]);
|
|
1938
2043
|
const [start, end, isString] = value;
|
|
1939
|
-
const name =
|
|
2044
|
+
const name = unescapeIdentifierCached(
|
|
1940
2045
|
isString
|
|
1941
2046
|
? input.slice(start + 1, end - 1)
|
|
1942
2047
|
: input.slice(start, end)
|
|
@@ -1976,7 +2081,7 @@ class CssParser extends Parser {
|
|
|
1976
2081
|
const lastLocalIdentifier = lastLocalIdentifiers[0];
|
|
1977
2082
|
let end = pos;
|
|
1978
2083
|
|
|
1979
|
-
/** @type {Set<[number, number]>} */
|
|
2084
|
+
/** @type {Set<[number, number, boolean]>} */
|
|
1980
2085
|
const classNames = new Set();
|
|
1981
2086
|
|
|
1982
2087
|
while (true) {
|
|
@@ -2022,18 +2127,20 @@ class CssParser extends Parser {
|
|
|
2022
2127
|
|
|
2023
2128
|
if (isComma || isSemicolon || isRightCurly) {
|
|
2024
2129
|
if (className) {
|
|
2025
|
-
classNames.add(className);
|
|
2130
|
+
classNames.add([className[0], className[1], isGlobalFunction]);
|
|
2026
2131
|
}
|
|
2027
2132
|
|
|
2028
|
-
for (const
|
|
2029
|
-
const [start, end] =
|
|
2030
|
-
const identifier =
|
|
2133
|
+
for (const entry of classNames) {
|
|
2134
|
+
const [start, end, isGlobal] = entry;
|
|
2135
|
+
const identifier = unescapeIdentifierCached(
|
|
2136
|
+
input.slice(start, end)
|
|
2137
|
+
);
|
|
2031
2138
|
const dep = new CssIcssExportDependency(
|
|
2032
2139
|
lastLocalIdentifier,
|
|
2033
2140
|
getReexport(identifier),
|
|
2034
2141
|
[start, end],
|
|
2035
|
-
!
|
|
2036
|
-
|
|
2142
|
+
!isGlobal,
|
|
2143
|
+
isGlobal
|
|
2037
2144
|
? CssIcssExportDependency.EXPORT_MODE.APPEND
|
|
2038
2145
|
: CssIcssExportDependency.EXPORT_MODE.SELF_REFERENCE,
|
|
2039
2146
|
CssIcssExportDependency.EXPORT_TYPE.COMPOSES
|
|
@@ -2063,12 +2170,53 @@ class CssParser extends Parser {
|
|
|
2063
2170
|
|
|
2064
2171
|
if (from) {
|
|
2065
2172
|
const request = input.slice(from[0] + 1, from[1] - 1);
|
|
2173
|
+
const selfReference = isSelfReferenceRequest(request);
|
|
2066
2174
|
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2175
|
+
if (!selfReference && !currentRuleComposesFiles.has(request)) {
|
|
2176
|
+
currentRuleComposesFiles.add(request);
|
|
2177
|
+
if (
|
|
2178
|
+
currentRulePrevComposesFile !== undefined &&
|
|
2179
|
+
currentRulePrevComposesFile !== request
|
|
2180
|
+
) {
|
|
2181
|
+
let successors = composesGraph.get(
|
|
2182
|
+
currentRulePrevComposesFile
|
|
2183
|
+
);
|
|
2184
|
+
if (!successors) {
|
|
2185
|
+
successors = new Set();
|
|
2186
|
+
composesGraph.set(currentRulePrevComposesFile, successors);
|
|
2187
|
+
}
|
|
2188
|
+
successors.add(request);
|
|
2189
|
+
}
|
|
2190
|
+
currentRulePrevComposesFile = request;
|
|
2191
|
+
}
|
|
2192
|
+
|
|
2193
|
+
for (const entry of classNames) {
|
|
2194
|
+
const [start, end] = entry;
|
|
2195
|
+
const identifier = unescapeIdentifierCached(
|
|
2196
|
+
input.slice(start, end)
|
|
2197
|
+
);
|
|
2070
2198
|
const { line: sl, column: sc } = locConverter.get(start);
|
|
2071
2199
|
const { line: el, column: ec } = locConverter.get(end);
|
|
2200
|
+
|
|
2201
|
+
if (selfReference) {
|
|
2202
|
+
// `composes: foo from "./self.module.css"` from inside
|
|
2203
|
+
// `self.module.css` — collapse to a self-reference, like
|
|
2204
|
+
// `composes: foo` without `from`. When the composed name
|
|
2205
|
+
// equals the local class name, it's a true no-op.
|
|
2206
|
+
if (identifier === lastLocalIdentifier) continue;
|
|
2207
|
+
const dep = new CssIcssExportDependency(
|
|
2208
|
+
lastLocalIdentifier,
|
|
2209
|
+
getReexport(identifier),
|
|
2210
|
+
[start, end],
|
|
2211
|
+
true,
|
|
2212
|
+
CssIcssExportDependency.EXPORT_MODE.SELF_REFERENCE,
|
|
2213
|
+
CssIcssExportDependency.EXPORT_TYPE.COMPOSES
|
|
2214
|
+
);
|
|
2215
|
+
dep.setLoc(sl, sc, el, ec);
|
|
2216
|
+
module.addDependency(dep);
|
|
2217
|
+
continue;
|
|
2218
|
+
}
|
|
2219
|
+
|
|
2072
2220
|
const localName = `__ICSS_IMPORT_${counter++}__`;
|
|
2073
2221
|
|
|
2074
2222
|
{
|
|
@@ -2082,6 +2230,9 @@ class CssParser extends Parser {
|
|
|
2082
2230
|
);
|
|
2083
2231
|
dep.setLoc(sl, sc, el, ec);
|
|
2084
2232
|
module.addDependency(dep);
|
|
2233
|
+
if (!composesFirstFileImport.has(request)) {
|
|
2234
|
+
composesFirstFileImport.set(request, dep);
|
|
2235
|
+
}
|
|
2085
2236
|
}
|
|
2086
2237
|
|
|
2087
2238
|
{
|
|
@@ -2104,9 +2255,9 @@ class CssParser extends Parser {
|
|
|
2104
2255
|
from = walkCssTokens.eatIdentSequence(input, pos);
|
|
2105
2256
|
|
|
2106
2257
|
if (from && input.slice(from[0], from[1]) === "global") {
|
|
2107
|
-
for (const
|
|
2108
|
-
const [start, end] =
|
|
2109
|
-
const identifier =
|
|
2258
|
+
for (const entry of classNames) {
|
|
2259
|
+
const [start, end] = entry;
|
|
2260
|
+
const identifier = unescapeIdentifierCached(
|
|
2110
2261
|
input.slice(start, end)
|
|
2111
2262
|
);
|
|
2112
2263
|
const dep = new CssIcssExportDependency(
|
|
@@ -2139,7 +2290,7 @@ class CssParser extends Parser {
|
|
|
2139
2290
|
}
|
|
2140
2291
|
}
|
|
2141
2292
|
} else if (className) {
|
|
2142
|
-
classNames.add(className);
|
|
2293
|
+
classNames.add([className[0], className[1], isGlobalFunction]);
|
|
2143
2294
|
} else {
|
|
2144
2295
|
const end = eatUntilSemi(input, pos);
|
|
2145
2296
|
this._emitWarning(
|
|
@@ -2170,7 +2321,7 @@ class CssParser extends Parser {
|
|
|
2170
2321
|
*/
|
|
2171
2322
|
const processIdSelector = (input, start, end) => {
|
|
2172
2323
|
const valueStart = start + 1;
|
|
2173
|
-
const name =
|
|
2324
|
+
const name = unescapeIdentifierCached(input.slice(valueStart, end));
|
|
2174
2325
|
const dep = new CssIcssExportDependency(
|
|
2175
2326
|
name,
|
|
2176
2327
|
getReexport(name),
|
|
@@ -2182,6 +2333,7 @@ class CssParser extends Parser {
|
|
|
2182
2333
|
const { line: el, column: ec } = locConverter.get(end);
|
|
2183
2334
|
dep.setLoc(sl, sc, el, ec);
|
|
2184
2335
|
module.addDependency(dep);
|
|
2336
|
+
if (pureMode) currentSelectorHasLocal = true;
|
|
2185
2337
|
return end;
|
|
2186
2338
|
};
|
|
2187
2339
|
|
|
@@ -2195,7 +2347,7 @@ class CssParser extends Parser {
|
|
|
2195
2347
|
const processClassSelector = (input, start, end) => {
|
|
2196
2348
|
const ident = walkCssTokens.skipCommentsAndEatIdentSequence(input, end);
|
|
2197
2349
|
if (!ident) return end;
|
|
2198
|
-
const name =
|
|
2350
|
+
const name = unescapeIdentifierCached(input.slice(ident[0], ident[1]));
|
|
2199
2351
|
lastLocalIdentifiers.push(name);
|
|
2200
2352
|
const dep = new CssIcssExportDependency(
|
|
2201
2353
|
name,
|
|
@@ -2208,6 +2360,7 @@ class CssParser extends Parser {
|
|
|
2208
2360
|
const { line: el, column: ec } = locConverter.get(ident[1]);
|
|
2209
2361
|
dep.setLoc(sl, sc, el, ec);
|
|
2210
2362
|
module.addDependency(dep);
|
|
2363
|
+
if (pureMode) currentSelectorHasLocal = true;
|
|
2211
2364
|
return ident[1];
|
|
2212
2365
|
};
|
|
2213
2366
|
|
|
@@ -2222,7 +2375,7 @@ class CssParser extends Parser {
|
|
|
2222
2375
|
end = walkCssTokens.eatWhitespaceAndComments(input, end)[0];
|
|
2223
2376
|
const identifier = walkCssTokens.eatIdentSequence(input, end);
|
|
2224
2377
|
if (!identifier) return end;
|
|
2225
|
-
const name =
|
|
2378
|
+
const name = unescapeIdentifierCached(
|
|
2226
2379
|
input.slice(identifier[0], identifier[1])
|
|
2227
2380
|
);
|
|
2228
2381
|
if (name.toLowerCase() !== "class") {
|
|
@@ -2258,7 +2411,7 @@ class CssParser extends Parser {
|
|
|
2258
2411
|
|
|
2259
2412
|
const classNameStart = value[2] ? value[0] : value[0] + 1;
|
|
2260
2413
|
const classNameEnd = value[2] ? value[1] : value[1] - 1;
|
|
2261
|
-
const className =
|
|
2414
|
+
const className = unescapeIdentifierCached(
|
|
2262
2415
|
input.slice(classNameStart, classNameEnd)
|
|
2263
2416
|
);
|
|
2264
2417
|
const dep = new CssIcssExportDependency(
|
|
@@ -2278,44 +2431,97 @@ class CssParser extends Parser {
|
|
|
2278
2431
|
walkCssTokens(source, 0, {
|
|
2279
2432
|
comment,
|
|
2280
2433
|
leftCurlyBracket: (input, start, end) => {
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2434
|
+
const wasTopLevel = scope === CSS_MODE_TOP_LEVEL;
|
|
2435
|
+
if (wasTopLevel) {
|
|
2436
|
+
allowImportAtRule = false;
|
|
2437
|
+
scope = CSS_MODE_IN_BLOCK;
|
|
2438
|
+
} else if (scope !== CSS_MODE_IN_BLOCK) {
|
|
2439
|
+
return end;
|
|
2440
|
+
}
|
|
2441
|
+
if (!isModules) return end;
|
|
2442
|
+
if (pureMode) {
|
|
2443
|
+
inAtRulePrelude = false;
|
|
2444
|
+
if (wasTopLevel) seenTopLevelRule = true;
|
|
2445
|
+
const isRulePrelude = isNextRulePrelude;
|
|
2446
|
+
if (isRulePrelude) finalizeSelector();
|
|
2447
|
+
const top = pureTop();
|
|
2448
|
+
if (top) top.hasNestedBlock = true;
|
|
2449
|
+
const inheritedSkip = top ? top.skipChildren : false;
|
|
2450
|
+
pureBlockStack.push({
|
|
2451
|
+
ignored: pureIgnorePending,
|
|
2452
|
+
skipOwn: inheritedSkip,
|
|
2453
|
+
skipChildren: nextBlockChildrenSkip || inheritedSkip,
|
|
2454
|
+
treatAsLeaf: nextBlockTreatAsLeaf,
|
|
2455
|
+
// "this rule is fully pure" (no impure comma-segment) OR any
|
|
2456
|
+
// ancestor pure. Matches PCSL's `[isPureSelectorSymbol]`.
|
|
2457
|
+
ancestorHadLocal:
|
|
2458
|
+
parentEffectivePure() ||
|
|
2459
|
+
(isRulePrelude && !currentRuleHasImpureSelector),
|
|
2460
|
+
impure: isRulePrelude && currentRuleHasImpureSelector,
|
|
2461
|
+
hasDirectDecl: false,
|
|
2462
|
+
hasNestedBlock: false,
|
|
2463
|
+
isRulePrelude,
|
|
2464
|
+
preludeStart: currentRulePreludeStart,
|
|
2465
|
+
preludeEnd: start
|
|
2466
|
+
});
|
|
2467
|
+
pureIgnorePending = false;
|
|
2468
|
+
nextBlockChildrenSkip = false;
|
|
2469
|
+
nextBlockTreatAsLeaf = false;
|
|
2470
|
+
currentRuleHasImpureSelector = false;
|
|
2471
|
+
currentSelectorHasLocal = false;
|
|
2472
|
+
currentRulePreludeStart = end;
|
|
2300
2473
|
}
|
|
2474
|
+
blockNestingLevel = wasTopLevel ? 1 : blockNestingLevel + 1;
|
|
2475
|
+
isNextRulePrelude = isNextNestedSyntax(input, end);
|
|
2301
2476
|
return end;
|
|
2302
2477
|
},
|
|
2303
2478
|
rightCurlyBracket: (input, start, end) => {
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2479
|
+
if (scope !== CSS_MODE_IN_BLOCK) return end;
|
|
2480
|
+
const closing = blockNestingLevel === 1;
|
|
2481
|
+
if (closing) {
|
|
2482
|
+
scope = CSS_MODE_TOP_LEVEL;
|
|
2483
|
+
blockNestingLevel = 0;
|
|
2484
|
+
if (!isModules) return end;
|
|
2485
|
+
isNextRulePrelude = true;
|
|
2486
|
+
modeData = undefined;
|
|
2487
|
+
lastLocalIdentifiers = [];
|
|
2488
|
+
currentRulePrevComposesFile = undefined;
|
|
2489
|
+
currentRuleComposesFiles.clear();
|
|
2490
|
+
} else {
|
|
2491
|
+
blockNestingLevel--;
|
|
2492
|
+
if (!isModules) return end;
|
|
2493
|
+
isNextRulePrelude = isNextNestedSyntax(input, end);
|
|
2494
|
+
}
|
|
2495
|
+
if (pureMode) {
|
|
2496
|
+
const frame = pureBlockStack.pop();
|
|
2497
|
+
if (frame) {
|
|
2498
|
+
// PCSL throws on impure rules whose body has any non-rule
|
|
2499
|
+
// content (declaration, empty body). Rules whose body is
|
|
2500
|
+
// only nested rules are skipped — child rules carry the
|
|
2501
|
+
// check themselves.
|
|
2502
|
+
if (
|
|
2503
|
+
!pureNoCheck &&
|
|
2504
|
+
!frame.ignored &&
|
|
2505
|
+
!frame.skipOwn &&
|
|
2506
|
+
frame.isRulePrelude &&
|
|
2507
|
+
frame.impure &&
|
|
2508
|
+
(frame.hasDirectDecl ||
|
|
2509
|
+
!frame.hasNestedBlock ||
|
|
2510
|
+
frame.treatAsLeaf)
|
|
2511
|
+
) {
|
|
2512
|
+
reportPureRule(frame.preludeStart, frame.preludeEnd);
|
|
2513
|
+
}
|
|
2514
|
+
// Propagate "has direct declaration" through at-rule frames
|
|
2515
|
+
// so a parent rule containing only e.g. `@media { decl }` is
|
|
2516
|
+
// still treated as "rule with declarations".
|
|
2517
|
+
if (!frame.isRulePrelude && frame.hasDirectDecl) {
|
|
2518
|
+
const parent = pureTop();
|
|
2519
|
+
if (parent) parent.hasDirectDecl = true;
|
|
2316
2520
|
}
|
|
2317
|
-
break;
|
|
2318
2521
|
}
|
|
2522
|
+
currentRuleHasImpureSelector = false;
|
|
2523
|
+
currentSelectorHasLocal = false;
|
|
2524
|
+
currentRulePreludeStart = end;
|
|
2319
2525
|
}
|
|
2320
2526
|
return end;
|
|
2321
2527
|
},
|
|
@@ -2334,7 +2540,16 @@ class CssParser extends Parser {
|
|
|
2334
2540
|
},
|
|
2335
2541
|
atKeyword: (input, start, end) => {
|
|
2336
2542
|
const name = input.slice(start, end).toLowerCase();
|
|
2543
|
+
const wasTopLevel = scope === CSS_MODE_TOP_LEVEL;
|
|
2544
|
+
if (pureMode) {
|
|
2545
|
+
inAtRulePrelude = true;
|
|
2546
|
+
// Match PCSL's `isPureCheckDisabled`: any non-comment top-level
|
|
2547
|
+
// node (including `;`-terminated at-rules like `@import`) seals
|
|
2548
|
+
// the leading-comments window.
|
|
2549
|
+
if (wasTopLevel) seenTopLevelRule = true;
|
|
2550
|
+
}
|
|
2337
2551
|
|
|
2552
|
+
let pos = end;
|
|
2338
2553
|
switch (name) {
|
|
2339
2554
|
case "@namespace": {
|
|
2340
2555
|
this._emitWarning(
|
|
@@ -2345,13 +2560,15 @@ class CssParser extends Parser {
|
|
|
2345
2560
|
end
|
|
2346
2561
|
);
|
|
2347
2562
|
|
|
2348
|
-
|
|
2563
|
+
pos = eatUntilSemi(input, start);
|
|
2564
|
+
break;
|
|
2349
2565
|
}
|
|
2350
2566
|
case "@charset": {
|
|
2351
2567
|
const atRuleEnd = eatUntilSemi(input, start);
|
|
2352
2568
|
|
|
2353
2569
|
if (/** @type {CssModule} */ (module).exportType === "style") {
|
|
2354
|
-
|
|
2570
|
+
pos = atRuleEnd;
|
|
2571
|
+
break;
|
|
2355
2572
|
}
|
|
2356
2573
|
|
|
2357
2574
|
const dep = new ConstDependency("", [start, atRuleEnd + 1]);
|
|
@@ -2360,7 +2577,8 @@ class CssParser extends Parser {
|
|
|
2360
2577
|
const value = walkCssTokens.eatString(input, end);
|
|
2361
2578
|
|
|
2362
2579
|
if (!value) {
|
|
2363
|
-
|
|
2580
|
+
pos = atRuleEnd;
|
|
2581
|
+
break;
|
|
2364
2582
|
}
|
|
2365
2583
|
|
|
2366
2584
|
/** @type {BuildInfo} */
|
|
@@ -2368,11 +2586,13 @@ class CssParser extends Parser {
|
|
|
2368
2586
|
.slice(value[0] + 1, value[1] - 1)
|
|
2369
2587
|
.toUpperCase();
|
|
2370
2588
|
|
|
2371
|
-
|
|
2589
|
+
pos = atRuleEnd;
|
|
2590
|
+
break;
|
|
2372
2591
|
}
|
|
2373
2592
|
case "@import": {
|
|
2374
2593
|
if (!this.options.import) {
|
|
2375
|
-
|
|
2594
|
+
pos = eatUntilSemi(input, end);
|
|
2595
|
+
break;
|
|
2376
2596
|
}
|
|
2377
2597
|
|
|
2378
2598
|
if (!allowImportAtRule) {
|
|
@@ -2383,43 +2603,57 @@ class CssParser extends Parser {
|
|
|
2383
2603
|
start,
|
|
2384
2604
|
end
|
|
2385
2605
|
);
|
|
2386
|
-
|
|
2606
|
+
pos = eatUntilSemi(input, end);
|
|
2607
|
+
break;
|
|
2387
2608
|
}
|
|
2388
2609
|
|
|
2389
|
-
|
|
2610
|
+
pos = processAtImport(input, start, end);
|
|
2611
|
+
break;
|
|
2390
2612
|
}
|
|
2391
2613
|
default: {
|
|
2392
2614
|
if (isModules) {
|
|
2393
2615
|
if (name === "@value") {
|
|
2394
|
-
|
|
2616
|
+
pos = processAtValue(input, start, end);
|
|
2617
|
+
break;
|
|
2395
2618
|
} else if (
|
|
2396
2619
|
this.options.animation &&
|
|
2397
2620
|
OPTIONALLY_VENDOR_PREFIXED_KEYFRAMES_AT_RULE.test(name) &&
|
|
2398
2621
|
isLocalMode()
|
|
2399
2622
|
) {
|
|
2400
|
-
|
|
2623
|
+
if (pureMode) {
|
|
2624
|
+
nextBlockChildrenSkip = true;
|
|
2625
|
+
nextBlockTreatAsLeaf = true;
|
|
2626
|
+
}
|
|
2627
|
+
pos = processLocalAtRule(input, end, {
|
|
2401
2628
|
string: true,
|
|
2402
2629
|
identifier: true
|
|
2403
2630
|
});
|
|
2631
|
+
break;
|
|
2404
2632
|
} else if (
|
|
2405
2633
|
this.options.customIdents &&
|
|
2406
2634
|
name === "@counter-style" &&
|
|
2407
2635
|
isLocalMode()
|
|
2408
2636
|
) {
|
|
2409
|
-
|
|
2637
|
+
if (pureMode) {
|
|
2638
|
+
nextBlockChildrenSkip = true;
|
|
2639
|
+
nextBlockTreatAsLeaf = true;
|
|
2640
|
+
}
|
|
2641
|
+
pos = processLocalAtRule(input, end, {
|
|
2410
2642
|
identifier: true
|
|
2411
2643
|
});
|
|
2644
|
+
break;
|
|
2412
2645
|
} else if (
|
|
2413
2646
|
this.options.container &&
|
|
2414
2647
|
name === "@container" &&
|
|
2415
2648
|
isLocalMode()
|
|
2416
2649
|
) {
|
|
2417
|
-
|
|
2650
|
+
pos = processLocalAtRule(input, end, {
|
|
2418
2651
|
identifier: /^(none|and|or|not)$/
|
|
2419
2652
|
});
|
|
2653
|
+
break;
|
|
2420
2654
|
} else if (name === "@scope") {
|
|
2421
2655
|
isNextRulePrelude = true;
|
|
2422
|
-
|
|
2656
|
+
break;
|
|
2423
2657
|
}
|
|
2424
2658
|
|
|
2425
2659
|
isNextRulePrelude = false;
|
|
@@ -2427,12 +2661,48 @@ class CssParser extends Parser {
|
|
|
2427
2661
|
}
|
|
2428
2662
|
}
|
|
2429
2663
|
|
|
2430
|
-
|
|
2664
|
+
// If the at-rule consumed its own `;` (for `@import`/`@value`/
|
|
2665
|
+
// `@charset`/`@namespace`), advance the prelude pointer so a
|
|
2666
|
+
// later impure rule's reported selector doesn't include this
|
|
2667
|
+
// at-rule's text. Body-bearing at-rules return at `{` — let
|
|
2668
|
+
// `leftCurlyBracket` handle those.
|
|
2669
|
+
if (pureMode && wasTopLevel && pos > end) {
|
|
2670
|
+
let probe = pos - 1;
|
|
2671
|
+
while (
|
|
2672
|
+
probe > end &&
|
|
2673
|
+
walkCssTokens.isWhiteSpace(input.charCodeAt(probe))
|
|
2674
|
+
) {
|
|
2675
|
+
probe--;
|
|
2676
|
+
}
|
|
2677
|
+
if (input.charCodeAt(probe) === CC_SEMICOLON) {
|
|
2678
|
+
currentRulePreludeStart = pos;
|
|
2679
|
+
}
|
|
2680
|
+
}
|
|
2681
|
+
|
|
2682
|
+
return pos;
|
|
2431
2683
|
},
|
|
2432
2684
|
semicolon: (input, start, end) => {
|
|
2433
2685
|
if (isModules && scope === CSS_MODE_IN_BLOCK) {
|
|
2434
2686
|
isNextRulePrelude = isNextNestedSyntax(input, end);
|
|
2435
2687
|
}
|
|
2688
|
+
if (pureMode) {
|
|
2689
|
+
if (scope === CSS_MODE_IN_BLOCK) {
|
|
2690
|
+
if (
|
|
2691
|
+
balanced.length === 0 &&
|
|
2692
|
+
!isNextRulePrelude &&
|
|
2693
|
+
!inAtRulePrelude
|
|
2694
|
+
) {
|
|
2695
|
+
const top = pureTop();
|
|
2696
|
+
if (top) top.hasDirectDecl = true;
|
|
2697
|
+
}
|
|
2698
|
+
} else if (scope === CSS_MODE_TOP_LEVEL && balanced.length === 0) {
|
|
2699
|
+
// Top-level `;` ends a statement (e.g. `@import "x";`).
|
|
2700
|
+
// Advance the prelude pointer so a later impure rule's
|
|
2701
|
+
// reported selector doesn't include the preceding text.
|
|
2702
|
+
currentRulePreludeStart = end;
|
|
2703
|
+
}
|
|
2704
|
+
inAtRulePrelude = false;
|
|
2705
|
+
}
|
|
2436
2706
|
return end;
|
|
2437
2707
|
},
|
|
2438
2708
|
identifier: (input, start, end) => {
|
|
@@ -2454,6 +2724,10 @@ class CssParser extends Parser {
|
|
|
2454
2724
|
switch (scope) {
|
|
2455
2725
|
case CSS_MODE_IN_BLOCK: {
|
|
2456
2726
|
if (isModules && !isNextRulePrelude) {
|
|
2727
|
+
if (balanced.length === 0 && !inAtRulePrelude) {
|
|
2728
|
+
const top = pureTop();
|
|
2729
|
+
if (top) top.hasDirectDecl = true;
|
|
2730
|
+
}
|
|
2457
2731
|
// Handle only top level values and not inside functions
|
|
2458
2732
|
return processLocalDeclaration(input, start, end);
|
|
2459
2733
|
}
|
|
@@ -2465,12 +2739,17 @@ class CssParser extends Parser {
|
|
|
2465
2739
|
return end;
|
|
2466
2740
|
},
|
|
2467
2741
|
delim: (input, start, end) => {
|
|
2742
|
+
const ch = input.charCodeAt(start);
|
|
2743
|
+
if (ch === CC_FULL_STOP && isNextRulePrelude && isLocalMode()) {
|
|
2744
|
+
return processClassSelector(input, start, end);
|
|
2745
|
+
}
|
|
2468
2746
|
if (
|
|
2469
|
-
|
|
2747
|
+
ch === CC_AMPERSAND &&
|
|
2470
2748
|
isNextRulePrelude &&
|
|
2471
|
-
|
|
2749
|
+
parentEffectivePure() &&
|
|
2750
|
+
pureMode
|
|
2472
2751
|
) {
|
|
2473
|
-
|
|
2752
|
+
currentSelectorHasLocal = true;
|
|
2474
2753
|
}
|
|
2475
2754
|
|
|
2476
2755
|
return end;
|
|
@@ -2677,6 +2956,7 @@ class CssParser extends Parser {
|
|
|
2677
2956
|
if (isModules && balanced.length === 0) {
|
|
2678
2957
|
// Reset stack for `:global .class :local .class-other` selector after
|
|
2679
2958
|
modeData = undefined;
|
|
2959
|
+
if (pureMode && isNextRulePrelude) finalizeSelector();
|
|
2680
2960
|
}
|
|
2681
2961
|
|
|
2682
2962
|
lastTokenEndForComments = start;
|
|
@@ -2688,6 +2968,23 @@ class CssParser extends Parser {
|
|
|
2688
2968
|
/** @type {BuildInfo} */
|
|
2689
2969
|
(module.buildInfo).strict = true;
|
|
2690
2970
|
|
|
2971
|
+
// Topologically sort the files referenced by `composes ... from`
|
|
2972
|
+
// declarations and tag each file's first import dep with the
|
|
2973
|
+
// resulting `sourceOrder`. `NormalModule#build` then reorders the
|
|
2974
|
+
// deps via `sortWithSourceOrder` so the bundle loads them in
|
|
2975
|
+
// cascade-correct order. Files stuck in a cycle are not visited
|
|
2976
|
+
// and keep their natural loc-based position.
|
|
2977
|
+
if (composesFirstFileImport.size > 1) {
|
|
2978
|
+
topologicalSort(
|
|
2979
|
+
composesGraph,
|
|
2980
|
+
[...composesFirstFileImport.keys()],
|
|
2981
|
+
(file, i) => {
|
|
2982
|
+
/** @type {CssIcssImportDependency} */
|
|
2983
|
+
(composesFirstFileImport.get(file)).sourceOrder = i;
|
|
2984
|
+
}
|
|
2985
|
+
);
|
|
2986
|
+
}
|
|
2987
|
+
|
|
2691
2988
|
const buildMeta = /** @type {BuildMeta} */ (state.module.buildMeta);
|
|
2692
2989
|
|
|
2693
2990
|
buildMeta.exportsType = this.options.namedExports ? "namespace" : "default";
|