webpack 4.15.0 → 4.16.2
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/LICENSE +20 -20
- package/README.md +761 -758
- package/SECURITY.md +9 -9
- package/buildin/amd-define.js +3 -3
- package/buildin/amd-options.js +2 -2
- package/buildin/global.js +20 -20
- package/buildin/harmony-module.js +24 -24
- package/buildin/module.js +22 -22
- package/buildin/system.js +7 -7
- package/hot/dev-server.js +61 -61
- package/hot/emitter.js +2 -2
- package/hot/log-apply-result.js +44 -44
- package/hot/log.js +45 -45
- package/hot/only-dev-server.js +105 -105
- package/hot/poll.js +40 -37
- package/hot/signal.js +62 -62
- package/lib/APIPlugin.js +84 -84
- package/lib/AmdMainTemplatePlugin.js +87 -87
- package/lib/AsyncDependencyToInitialChunkError.js +31 -31
- package/lib/AutomaticPrefetchPlugin.js +1 -1
- package/lib/BannerPlugin.js +117 -117
- package/lib/BasicEvaluatedExpression.js +211 -211
- package/lib/CachePlugin.js +102 -102
- package/lib/CaseSensitiveModulesWarning.js +67 -67
- package/lib/Chunk.js +833 -811
- package/lib/ChunkGroup.js +4 -4
- package/lib/ChunkRenderError.js +32 -32
- package/lib/CommentCompilationWarning.js +2 -2
- package/lib/CompatibilityPlugin.js +70 -70
- package/lib/Compilation.js +46 -15
- package/lib/ConcurrentCompilationError.js +19 -19
- package/lib/ConstPlugin.js +258 -258
- package/lib/ContextExclusionPlugin.js +28 -17
- package/lib/ContextModule.js +844 -739
- package/lib/ContextModuleFactory.js +262 -256
- package/lib/ContextReplacementPlugin.js +133 -133
- package/lib/DefinePlugin.js +49 -0
- package/lib/DelegatedModule.js +5 -0
- package/lib/DelegatedModuleFactoryPlugin.js +95 -89
- package/lib/DelegatedPlugin.js +39 -39
- package/lib/DependenciesBlock.js +1 -1
- package/lib/Dependency.js +10 -4
- package/lib/DllModule.js +60 -54
- package/lib/DllModuleFactory.js +29 -29
- package/lib/DllPlugin.js +44 -44
- package/lib/DllReferencePlugin.js +132 -84
- package/lib/EntryModuleNotFoundError.js +21 -21
- package/lib/Entrypoint.js +54 -54
- package/lib/EnvironmentPlugin.js +72 -65
- package/lib/ErrorHelpers.js +60 -60
- package/lib/EvalDevToolModulePlugin.js +27 -27
- package/lib/EvalSourceMapDevToolModuleTemplatePlugin.js +115 -115
- package/lib/EvalSourceMapDevToolPlugin.js +41 -41
- package/lib/ExportPropertyMainTemplatePlugin.js +53 -53
- package/lib/ExternalModule.js +165 -159
- package/lib/ExternalsPlugin.js +23 -23
- package/lib/FlagDependencyExportsPlugin.js +146 -146
- package/lib/FlagInitialModulesAsUsedPlugin.js +36 -36
- package/lib/FunctionModuleTemplatePlugin.js +100 -100
- package/lib/Generator.js +60 -52
- package/lib/HarmonyLinkingError.js +17 -17
- package/lib/HashedModuleIdsPlugin.js +53 -53
- package/lib/HotModuleReplacementPlugin.js +411 -413
- package/lib/IgnorePlugin.js +90 -90
- package/lib/JavascriptGenerator.js +229 -229
- package/lib/JavascriptModulesPlugin.js +179 -179
- package/lib/JsonGenerator.js +55 -55
- package/lib/JsonModulesPlugin.js +30 -30
- package/lib/JsonParser.js +27 -27
- package/lib/LibManifestPlugin.js +86 -86
- package/lib/LibraryTemplatePlugin.js +153 -153
- package/lib/LoaderOptionsPlugin.js +53 -53
- package/lib/LoaderTargetPlugin.js +24 -24
- package/lib/MemoryOutputFileSystem.js +5 -5
- package/lib/Module.js +431 -391
- package/lib/ModuleBuildError.js +52 -52
- package/lib/ModuleDependencyError.js +35 -35
- package/lib/ModuleDependencyWarning.js +25 -25
- package/lib/ModuleError.js +36 -36
- package/lib/ModuleFilenameHelpers.js +178 -178
- package/lib/ModuleNotFoundError.js +23 -23
- package/lib/ModuleParseError.js +57 -57
- package/lib/ModuleTemplate.js +93 -93
- package/lib/ModuleWarning.js +36 -36
- package/lib/MultiCompiler.js +283 -283
- package/lib/MultiModule.js +87 -81
- package/lib/MultiModuleFactory.js +23 -23
- package/lib/MultiStats.js +92 -92
- package/lib/MultiWatching.js +38 -38
- package/lib/NamedChunksPlugin.js +29 -29
- package/lib/NamedModulesPlugin.js +57 -57
- package/lib/NoEmitOnErrorsPlugin.js +20 -20
- package/lib/NoModeWarning.js +23 -23
- package/lib/NodeStuffPlugin.js +197 -179
- package/lib/NormalModule.js +542 -536
- package/lib/NormalModuleFactory.js +526 -526
- package/lib/NormalModuleReplacementPlugin.js +51 -51
- package/lib/NullFactory.js +12 -12
- package/lib/OptionsApply.js +10 -10
- package/lib/OptionsDefaulter.js +84 -84
- package/lib/Parser.js +2202 -2193
- package/lib/ParserHelpers.js +103 -103
- package/lib/PrefetchPlugin.js +37 -37
- package/lib/ProgressPlugin.js +246 -246
- package/lib/ProvidePlugin.js +86 -86
- package/lib/RawModule.js +56 -56
- package/lib/RecordIdsPlugin.js +230 -230
- package/lib/RemovedPluginError.js +11 -11
- package/lib/RequestShortener.js +83 -83
- package/lib/RequireJsStuffPlugin.js +69 -69
- package/lib/ResolverFactory.js +64 -64
- package/lib/RuntimeTemplate.js +12 -0
- package/lib/SetVarMainTemplatePlugin.js +69 -69
- package/lib/SingleEntryPlugin.js +6 -1
- package/lib/SizeFormatHelpers.js +24 -24
- package/lib/SourceMapDevToolModuleOptionsPlugin.js +49 -49
- package/lib/SourceMapDevToolPlugin.js +301 -301
- package/lib/Stats.js +28 -5
- package/lib/TemplatedPathPlugin.js +173 -173
- package/lib/UnsupportedFeatureWarning.js +22 -22
- package/lib/UseStrictPlugin.js +54 -54
- package/lib/WarnCaseSensitiveModulesPlugin.js +37 -37
- package/lib/WarnNoModeSetPlugin.js +17 -17
- package/lib/WatchIgnorePlugin.js +100 -100
- package/lib/Watching.js +194 -194
- package/lib/WebpackOptionsApply.js +92 -10
- package/lib/WebpackOptionsDefaulter.js +368 -354
- package/lib/debug/ProfilingPlugin.js +430 -430
- package/lib/dependencies/AMDPlugin.js +250 -250
- package/lib/dependencies/AMDRequireArrayDependency.js +49 -49
- package/lib/dependencies/AMDRequireContextDependency.js +20 -20
- package/lib/dependencies/AMDRequireDependency.js +135 -135
- package/lib/dependencies/AMDRequireItemDependency.js +22 -22
- package/lib/dependencies/CommonJsPlugin.js +161 -161
- package/lib/dependencies/CommonJsRequireContextDependency.js +23 -23
- package/lib/dependencies/CommonJsRequireDependency.js +22 -22
- package/lib/dependencies/CommonJsRequireDependencyParserPlugin.js +6 -0
- package/lib/dependencies/ConstDependency.js +33 -33
- package/lib/dependencies/ContextDependency.js +68 -68
- package/lib/dependencies/ContextDependencyHelpers.js +142 -142
- package/lib/dependencies/ContextDependencyTemplateAsId.js +42 -42
- package/lib/dependencies/ContextDependencyTemplateAsRequireCall.js +38 -38
- package/lib/dependencies/ContextElementDependency.js +21 -21
- package/lib/dependencies/CriticalDependencyWarning.js +20 -20
- package/lib/dependencies/DelegatedSourceDependency.js +18 -18
- package/lib/dependencies/DllEntryDependency.js +20 -20
- package/lib/dependencies/HarmonyAcceptDependency.js +45 -45
- package/lib/dependencies/HarmonyCompatibilityDependency.js +31 -31
- package/lib/dependencies/HarmonyDetectionParserPlugin.js +92 -92
- package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +139 -139
- package/lib/dependencies/HarmonyExportHeaderDependency.js +30 -30
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +2 -1
- package/lib/dependencies/HarmonyImportDependency.js +109 -109
- package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +222 -222
- package/lib/dependencies/HarmonyImportSideEffectDependency.js +31 -31
- package/lib/dependencies/HarmonyImportSpecifierDependency.js +167 -167
- package/lib/dependencies/HarmonyInitDependency.js +60 -60
- package/lib/dependencies/HarmonyModulesPlugin.js +146 -146
- package/lib/dependencies/HarmonyTopLevelThisParserPlugin.js +26 -26
- package/lib/dependencies/ImportContextDependency.js +23 -23
- package/lib/dependencies/ImportDependenciesBlock.js +18 -18
- package/lib/dependencies/ImportDependency.js +34 -34
- package/lib/dependencies/ImportEagerDependency.js +32 -32
- package/lib/dependencies/ImportParserPlugin.js +263 -263
- package/lib/dependencies/ImportPlugin.js +82 -82
- package/lib/dependencies/ImportWeakDependency.js +34 -34
- package/lib/dependencies/LoaderPlugin.js +18 -1
- package/lib/dependencies/LocalModule.js +23 -23
- package/lib/dependencies/LocalModulesHelpers.js +52 -52
- package/lib/dependencies/ModuleDependencyTemplateAsId.js +17 -17
- package/lib/dependencies/ModuleDependencyTemplateAsRequireId.js +17 -17
- package/lib/dependencies/ModuleHotAcceptDependency.js +23 -23
- package/lib/dependencies/ModuleHotDeclineDependency.js +23 -23
- package/lib/dependencies/NullDependency.js +20 -20
- package/lib/dependencies/PrefetchDependency.js +18 -18
- package/lib/dependencies/RequireContextDependency.js +22 -22
- package/lib/dependencies/RequireContextDependencyParserPlugin.js +56 -56
- package/lib/dependencies/RequireContextPlugin.js +143 -143
- package/lib/dependencies/RequireEnsureDependenciesBlock.js +33 -33
- package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +116 -116
- package/lib/dependencies/RequireEnsureDependency.js +58 -58
- package/lib/dependencies/RequireEnsureItemDependency.js +21 -21
- package/lib/dependencies/RequireEnsurePlugin.js +74 -74
- package/lib/dependencies/RequireHeaderDependency.js +26 -26
- package/lib/dependencies/RequireIncludeDependencyParserPlugin.js +23 -23
- package/lib/dependencies/RequireIncludePlugin.js +61 -61
- package/lib/dependencies/RequireResolveContextDependency.js +23 -23
- package/lib/dependencies/RequireResolveDependency.js +22 -22
- package/lib/dependencies/RequireResolveDependencyParserPlugin.js +85 -85
- package/lib/dependencies/RequireResolveHeaderDependency.js +26 -26
- package/lib/dependencies/SystemPlugin.js +125 -125
- package/lib/dependencies/UnsupportedDependency.js +27 -27
- package/lib/dependencies/WebAssemblyExportImportedDependency.js +29 -29
- package/lib/dependencies/WebAssemblyImportDependency.js +48 -48
- package/lib/dependencies/WebpackMissingModule.js +20 -20
- package/lib/formatLocation.js +75 -61
- package/lib/node/NodeChunkTemplatePlugin.js +31 -31
- package/lib/node/NodeEnvironmentPlugin.js +28 -28
- package/lib/node/NodeHotUpdateChunkTemplatePlugin.js +36 -36
- package/lib/node/NodeMainTemplate.runtime.js +27 -27
- package/lib/node/NodeMainTemplatePlugin.js +323 -323
- package/lib/node/NodeOutputFileSystem.js +22 -22
- package/lib/node/NodeSourcePlugin.js +144 -144
- package/lib/node/NodeTargetPlugin.js +18 -18
- package/lib/node/NodeTemplatePlugin.js +31 -31
- package/lib/node/NodeWatchFileSystem.js +99 -99
- package/lib/node/ReadFileCompileWasmTemplatePlugin.js +61 -61
- package/lib/optimize/AggressiveMergingPlugin.js +87 -87
- package/lib/optimize/AggressiveSplittingPlugin.js +287 -287
- package/lib/optimize/ConcatenatedModule.js +5 -0
- package/lib/optimize/EnsureChunkConditionsPlugin.js +70 -70
- package/lib/optimize/FlagIncludedChunksPlugin.js +99 -99
- package/lib/optimize/LimitChunkCountPlugin.js +66 -66
- package/lib/optimize/MergeDuplicateChunksPlugin.js +78 -78
- package/lib/optimize/MinChunkSizePlugin.js +77 -77
- package/lib/optimize/NaturalChunkOrderPlugin.js +41 -0
- package/lib/optimize/OccurrenceChunkOrderPlugin.js +61 -0
- package/lib/optimize/OccurrenceModuleOrderPlugin.js +103 -0
- package/lib/optimize/OccurrenceOrderPlugin.js +135 -133
- package/lib/optimize/RemoveEmptyChunksPlugin.js +42 -42
- package/lib/optimize/RemoveParentModulesPlugin.js +127 -127
- package/lib/optimize/RuntimeChunkPlugin.js +41 -41
- package/lib/optimize/SideEffectsFlagPlugin.js +168 -168
- package/lib/optimize/SplitChunksPlugin.js +866 -850
- package/lib/performance/AssetsOverSizeLimitWarning.js +30 -30
- package/lib/performance/EntrypointsOverSizeLimitWarning.js +30 -30
- package/lib/performance/NoAsyncChunksWarning.js +21 -21
- package/lib/performance/SizeLimitsPlugin.js +105 -105
- package/lib/util/SortableSet.js +1 -0
- package/lib/util/StackedSetMap.js +144 -135
- package/lib/util/TrackingSet.js +35 -35
- package/lib/util/cachedMerge.js +35 -35
- package/lib/util/deterministicGrouping.js +251 -251
- package/lib/util/identifier.js +103 -103
- package/lib/util/objectToMap.js +16 -16
- package/lib/validateSchema.js +67 -67
- package/lib/wasm/UnsupportedWebAssemblyFeatureError.js +17 -17
- package/lib/wasm/WasmFinalizeExportsPlugin.js +1 -1
- package/lib/wasm/WebAssemblyGenerator.js +16 -2
- package/lib/wasm/WebAssemblyJavascriptGenerator.js +147 -133
- package/lib/wasm/WebAssemblyParser.js +174 -174
- package/lib/wasm/WebAssemblyUtils.js +59 -59
- package/lib/web/FetchCompileWasmTemplatePlugin.js +37 -37
- package/lib/web/JsonpExportMainTemplatePlugin.js +47 -47
- package/lib/web/JsonpHotUpdateChunkTemplatePlugin.js +39 -39
- package/lib/web/JsonpMainTemplate.runtime.js +65 -65
- package/lib/web/JsonpMainTemplatePlugin.js +1 -1
- package/lib/web/JsonpTemplatePlugin.js +23 -23
- package/lib/web/WebEnvironmentPlugin.js +18 -18
- package/lib/webpack.js +5 -0
- package/lib/webworker/WebWorkerChunkTemplatePlugin.js +35 -35
- package/lib/webworker/WebWorkerHotUpdateChunkTemplatePlugin.js +40 -40
- package/lib/webworker/WebWorkerMainTemplate.runtime.js +65 -65
- package/lib/webworker/WebWorkerMainTemplatePlugin.js +196 -196
- package/lib/webworker/WebWorkerTemplatePlugin.js +25 -25
- package/package.json +22 -13
- package/schemas/WebpackOptions.json +2062 -2036
- package/schemas/ajv.absolutePath.js +55 -55
- package/schemas/plugins/BannerPlugin.json +96 -96
- package/schemas/plugins/DllPlugin.json +32 -32
- package/schemas/plugins/DllReferencePlugin.json +99 -99
- package/schemas/plugins/HashedModuleIdsPlugin.json +24 -24
- package/schemas/plugins/LoaderOptionsPlugin.json +26 -26
- package/schemas/plugins/SourceMapDevToolPlugin.json +187 -187
- package/schemas/plugins/WatchIgnorePlugin.json +16 -16
- package/schemas/plugins/debug/ProfilingPlugin.json +12 -12
- package/schemas/plugins/optimize/AggressiveSplittingPlugin.json +22 -22
- package/schemas/plugins/optimize/LimitChunkCountPlugin.json +15 -15
- package/schemas/plugins/optimize/MinChunkSizePlugin.json +13 -13
- package/schemas/plugins/optimize/OccurrenceOrderChunkIdsPlugin.json +10 -0
- package/schemas/plugins/optimize/OccurrenceOrderModuleIdsPlugin.json +10 -0
package/lib/util/TrackingSet.js
CHANGED
@@ -1,35 +1,35 @@
|
|
1
|
-
/*
|
2
|
-
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
-
Author Tobias Koppers @sokra
|
4
|
-
*/
|
5
|
-
"use strict";
|
6
|
-
|
7
|
-
module.exports = class TrackingSet {
|
8
|
-
constructor(set) {
|
9
|
-
this.set = set;
|
10
|
-
this.set2 = new Set();
|
11
|
-
this.stack = set.stack;
|
12
|
-
}
|
13
|
-
|
14
|
-
add(item) {
|
15
|
-
this.set2.add(item);
|
16
|
-
return this.set.add(item);
|
17
|
-
}
|
18
|
-
|
19
|
-
delete(item) {
|
20
|
-
this.set2.delete(item);
|
21
|
-
return this.set.delete(item);
|
22
|
-
}
|
23
|
-
|
24
|
-
has(item) {
|
25
|
-
return this.set.has(item);
|
26
|
-
}
|
27
|
-
|
28
|
-
createChild() {
|
29
|
-
return this.set.createChild();
|
30
|
-
}
|
31
|
-
|
32
|
-
getAddedItems() {
|
33
|
-
return this.set2;
|
34
|
-
}
|
35
|
-
};
|
1
|
+
/*
|
2
|
+
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
+
Author Tobias Koppers @sokra
|
4
|
+
*/
|
5
|
+
"use strict";
|
6
|
+
|
7
|
+
module.exports = class TrackingSet {
|
8
|
+
constructor(set) {
|
9
|
+
this.set = set;
|
10
|
+
this.set2 = new Set();
|
11
|
+
this.stack = set.stack;
|
12
|
+
}
|
13
|
+
|
14
|
+
add(item) {
|
15
|
+
this.set2.add(item);
|
16
|
+
return this.set.add(item);
|
17
|
+
}
|
18
|
+
|
19
|
+
delete(item) {
|
20
|
+
this.set2.delete(item);
|
21
|
+
return this.set.delete(item);
|
22
|
+
}
|
23
|
+
|
24
|
+
has(item) {
|
25
|
+
return this.set.has(item);
|
26
|
+
}
|
27
|
+
|
28
|
+
createChild() {
|
29
|
+
return this.set.createChild();
|
30
|
+
}
|
31
|
+
|
32
|
+
getAddedItems() {
|
33
|
+
return this.set2;
|
34
|
+
}
|
35
|
+
};
|
package/lib/util/cachedMerge.js
CHANGED
@@ -1,35 +1,35 @@
|
|
1
|
-
/*
|
2
|
-
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
-
Author Tobias Koppers @sokra
|
4
|
-
*/
|
5
|
-
"use strict";
|
6
|
-
|
7
|
-
const mergeCache = new WeakMap();
|
8
|
-
|
9
|
-
/**
|
10
|
-
* Merges two given objects and caches the result to avoid computation if same objects passed as
|
11
|
-
* @example
|
12
|
-
* // performs Object.assign(first, second), stores the result in WeakMap and returns result
|
13
|
-
* cachedMerge({a: 1}, {a: 2})
|
14
|
-
* {a: 2}
|
15
|
-
* // when same arguments passed, gets the result from WeakMap and returns it.
|
16
|
-
* cachedMerge({a: 1}, {a: 2})
|
17
|
-
* {a: 2}
|
18
|
-
* @param {object} first first object
|
19
|
-
* @param {object} second second object
|
20
|
-
* @returns {object} merged object of first and second object
|
21
|
-
*/
|
22
|
-
const cachedMerge = (first, second) => {
|
23
|
-
let innerCache = mergeCache.get(first);
|
24
|
-
if (innerCache === undefined) {
|
25
|
-
innerCache = new WeakMap();
|
26
|
-
mergeCache.set(first, innerCache);
|
27
|
-
}
|
28
|
-
const prevMerge = innerCache.get(second);
|
29
|
-
if (prevMerge !== undefined) return prevMerge;
|
30
|
-
const newMerge = Object.assign({}, first, second);
|
31
|
-
innerCache.set(second, newMerge);
|
32
|
-
return newMerge;
|
33
|
-
};
|
34
|
-
|
35
|
-
module.exports = cachedMerge;
|
1
|
+
/*
|
2
|
+
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
+
Author Tobias Koppers @sokra
|
4
|
+
*/
|
5
|
+
"use strict";
|
6
|
+
|
7
|
+
const mergeCache = new WeakMap();
|
8
|
+
|
9
|
+
/**
|
10
|
+
* Merges two given objects and caches the result to avoid computation if same objects passed as arguments again.
|
11
|
+
* @example
|
12
|
+
* // performs Object.assign(first, second), stores the result in WeakMap and returns result
|
13
|
+
* cachedMerge({a: 1}, {a: 2})
|
14
|
+
* {a: 2}
|
15
|
+
* // when same arguments passed, gets the result from WeakMap and returns it.
|
16
|
+
* cachedMerge({a: 1}, {a: 2})
|
17
|
+
* {a: 2}
|
18
|
+
* @param {object} first first object
|
19
|
+
* @param {object} second second object
|
20
|
+
* @returns {object} merged object of first and second object
|
21
|
+
*/
|
22
|
+
const cachedMerge = (first, second) => {
|
23
|
+
let innerCache = mergeCache.get(first);
|
24
|
+
if (innerCache === undefined) {
|
25
|
+
innerCache = new WeakMap();
|
26
|
+
mergeCache.set(first, innerCache);
|
27
|
+
}
|
28
|
+
const prevMerge = innerCache.get(second);
|
29
|
+
if (prevMerge !== undefined) return prevMerge;
|
30
|
+
const newMerge = Object.assign({}, first, second);
|
31
|
+
innerCache.set(second, newMerge);
|
32
|
+
return newMerge;
|
33
|
+
};
|
34
|
+
|
35
|
+
module.exports = cachedMerge;
|
@@ -1,251 +1,251 @@
|
|
1
|
-
"use strict";
|
2
|
-
|
3
|
-
// Simulations show these probabilities for a single change
|
4
|
-
// 93.1% that one group is invalidated
|
5
|
-
// 4.8% that two groups are invalidated
|
6
|
-
// 1.1% that 3 groups are invalidated
|
7
|
-
// 0.1% that 4 or more groups are invalidated
|
8
|
-
//
|
9
|
-
// And these for removing/adding 10 lexically adjacent files
|
10
|
-
// 64.5% that one group is invalidated
|
11
|
-
// 24.8% that two groups are invalidated
|
12
|
-
// 7.8% that 3 groups are invalidated
|
13
|
-
// 2.7% that 4 or more groups are invalidated
|
14
|
-
//
|
15
|
-
// And these for removing/adding 3 random files
|
16
|
-
// 0% that one group is invalidated
|
17
|
-
// 3.7% that two groups are invalidated
|
18
|
-
// 80.8% that 3 groups are invalidated
|
19
|
-
// 12.3% that 4 groups are invalidated
|
20
|
-
// 3.2% that 5 or more groups are invalidated
|
21
|
-
|
22
|
-
/**
|
23
|
-
*
|
24
|
-
* @param {string} a key
|
25
|
-
* @param {string} b key
|
26
|
-
* @returns {number} the similarity as number
|
27
|
-
*/
|
28
|
-
const similarity = (a, b) => {
|
29
|
-
const l = Math.min(a.length, b.length);
|
30
|
-
let dist = 0;
|
31
|
-
for (let i = 0; i < l; i++) {
|
32
|
-
const ca = a.charCodeAt(i);
|
33
|
-
const cb = b.charCodeAt(i);
|
34
|
-
dist += Math.max(0, 10 - Math.abs(ca - cb));
|
35
|
-
}
|
36
|
-
return dist;
|
37
|
-
};
|
38
|
-
|
39
|
-
/**
|
40
|
-
* @param {string} a key
|
41
|
-
* @param {string} b key
|
42
|
-
* @returns {string} the common part and a single char for the difference
|
43
|
-
*/
|
44
|
-
const getName = (a, b) => {
|
45
|
-
const l = Math.min(a.length, b.length);
|
46
|
-
let r = "";
|
47
|
-
for (let i = 0; i < l; i++) {
|
48
|
-
const ca = a.charAt(i);
|
49
|
-
const cb = b.charAt(i);
|
50
|
-
r += ca;
|
51
|
-
if (ca === cb) {
|
52
|
-
continue;
|
53
|
-
}
|
54
|
-
return r;
|
55
|
-
}
|
56
|
-
return a;
|
57
|
-
};
|
58
|
-
|
59
|
-
/**
|
60
|
-
* @template T
|
61
|
-
*/
|
62
|
-
class Node {
|
63
|
-
/**
|
64
|
-
* @param {T} item item
|
65
|
-
* @param {string} key key
|
66
|
-
* @param {number} size size
|
67
|
-
*/
|
68
|
-
constructor(item, key, size) {
|
69
|
-
this.item = item;
|
70
|
-
this.key = key;
|
71
|
-
this.size = size;
|
72
|
-
}
|
73
|
-
}
|
74
|
-
|
75
|
-
/**
|
76
|
-
* @template T
|
77
|
-
*/
|
78
|
-
class Group {
|
79
|
-
/**
|
80
|
-
* @param {Node<T>[]} nodes nodes
|
81
|
-
* @param {number[]} similarities similarities between the nodes (length = nodes.length - 1)
|
82
|
-
*/
|
83
|
-
constructor(nodes, similarities) {
|
84
|
-
this.nodes = nodes;
|
85
|
-
this.similarities = similarities;
|
86
|
-
this.size = nodes.reduce((size, node) => size + node.size, 0);
|
87
|
-
/** @type {string} */
|
88
|
-
this.key = undefined;
|
89
|
-
}
|
90
|
-
}
|
91
|
-
|
92
|
-
/**
|
93
|
-
* @template T
|
94
|
-
* @typedef {Object} GroupedItems<T>
|
95
|
-
* @property {string} key
|
96
|
-
* @property {T[]} items
|
97
|
-
* @property {number} size
|
98
|
-
*/
|
99
|
-
|
100
|
-
/**
|
101
|
-
* @template T
|
102
|
-
* @typedef {Object} Options
|
103
|
-
* @property {number} maxSize maximum size of a group
|
104
|
-
* @property {number} minSize minimum size of a group (preferred over maximum size)
|
105
|
-
* @property {Iterable<T>} items a list of items
|
106
|
-
* @property {function(T): number} getSize function to get size of an item
|
107
|
-
* @property {function(T): string} getKey function to get the key of an item
|
108
|
-
*/
|
109
|
-
|
110
|
-
/**
|
111
|
-
* @template T
|
112
|
-
* @param {Options<T>} options options object
|
113
|
-
* @returns {GroupedItems<T>[]} grouped items
|
114
|
-
*/
|
115
|
-
module.exports = ({ maxSize, minSize, items, getSize, getKey }) => {
|
116
|
-
/** @type {Group<T>[]} */
|
117
|
-
const result = [];
|
118
|
-
|
119
|
-
const nodes = Array.from(
|
120
|
-
items,
|
121
|
-
item => new Node(item, getKey(item), getSize(item))
|
122
|
-
);
|
123
|
-
|
124
|
-
/** @type {Node<T>[]} */
|
125
|
-
const initialNodes = [];
|
126
|
-
|
127
|
-
// return nodes bigger than maxSize directly as group
|
128
|
-
for (const node of nodes) {
|
129
|
-
if (node.size >= maxSize) {
|
130
|
-
result.push(new Group([node], []));
|
131
|
-
} else {
|
132
|
-
initialNodes.push(node);
|
133
|
-
}
|
134
|
-
}
|
135
|
-
|
136
|
-
if (initialNodes.length > 0) {
|
137
|
-
// lexically ordering of keys
|
138
|
-
initialNodes.sort((a, b) => {
|
139
|
-
if (a.key < b.key) return -1;
|
140
|
-
if (a.key > b.key) return 1;
|
141
|
-
return 0;
|
142
|
-
});
|
143
|
-
|
144
|
-
// calculate similarities between lexically adjacent nodes
|
145
|
-
/** @type {number[]} */
|
146
|
-
const similarities = [];
|
147
|
-
for (let i = 1; i < initialNodes.length; i++) {
|
148
|
-
const a = initialNodes[i - 1];
|
149
|
-
const b = initialNodes[i];
|
150
|
-
similarities.push(similarity(a.key, b.key));
|
151
|
-
}
|
152
|
-
|
153
|
-
const queue = [new Group(initialNodes, similarities)];
|
154
|
-
|
155
|
-
while (queue.length) {
|
156
|
-
const group = queue.pop();
|
157
|
-
// only groups bigger than maxSize need to be splitted
|
158
|
-
if (group.size < maxSize) {
|
159
|
-
result.push(group);
|
160
|
-
continue;
|
161
|
-
}
|
162
|
-
|
163
|
-
// find unsplittable area from left and right
|
164
|
-
// going minSize from left and right
|
165
|
-
let left = 0;
|
166
|
-
let leftSize = 0;
|
167
|
-
while (leftSize < minSize) {
|
168
|
-
leftSize += group.nodes[left].size;
|
169
|
-
left++;
|
170
|
-
}
|
171
|
-
let right = group.nodes.length - 1;
|
172
|
-
let rightSize = 0;
|
173
|
-
while (rightSize < minSize) {
|
174
|
-
rightSize += group.nodes[right].size;
|
175
|
-
right--;
|
176
|
-
}
|
177
|
-
|
178
|
-
if (left - 1 > right) {
|
179
|
-
// can't split group while holding minSize
|
180
|
-
// because minSize is preferred of maxSize we return
|
181
|
-
// the group here even while it's too big
|
182
|
-
// To avoid this make sure maxSize > minSize * 3
|
183
|
-
result.push(group);
|
184
|
-
continue;
|
185
|
-
}
|
186
|
-
if (left <= right) {
|
187
|
-
// when there is a area between left and right
|
188
|
-
// we look for best split point
|
189
|
-
// we split at the minimum
|
190
|
-
// here key space is separated the most
|
191
|
-
let best = left - 1;
|
192
|
-
let bestSimilarity = group.similarities[best];
|
193
|
-
for (let i = left; i <= right; i++) {
|
194
|
-
const similarity = group.similarities[i];
|
195
|
-
if (similarity < bestSimilarity) {
|
196
|
-
best = i;
|
197
|
-
bestSimilarity = similarity;
|
198
|
-
}
|
199
|
-
}
|
200
|
-
left = best + 1;
|
201
|
-
right = best;
|
202
|
-
}
|
203
|
-
|
204
|
-
// create two new groups for left and right area
|
205
|
-
// and queue them up
|
206
|
-
const rightNodes = [group.nodes[right + 1]];
|
207
|
-
/** @type {number[]} */
|
208
|
-
const rightSimilaries = [];
|
209
|
-
for (let i = right + 2; i < group.nodes.length; i++) {
|
210
|
-
rightSimilaries.push(group.similarities[i - 1]);
|
211
|
-
rightNodes.push(group.nodes[i]);
|
212
|
-
}
|
213
|
-
queue.push(new Group(rightNodes, rightSimilaries));
|
214
|
-
|
215
|
-
const leftNodes = [group.nodes[0]];
|
216
|
-
/** @type {number[]} */
|
217
|
-
const leftSimilaries = [];
|
218
|
-
for (let i = 1; i < left; i++) {
|
219
|
-
leftSimilaries.push(group.similarities[i - 1]);
|
220
|
-
leftNodes.push(group.nodes[i]);
|
221
|
-
}
|
222
|
-
queue.push(new Group(leftNodes, leftSimilaries));
|
223
|
-
}
|
224
|
-
}
|
225
|
-
|
226
|
-
// lexically ordering
|
227
|
-
result.sort((a, b) => {
|
228
|
-
if (a.nodes[0].key < b.nodes[0].key) return -1;
|
229
|
-
if (a.nodes[0].key > b.nodes[0].key) return 1;
|
230
|
-
return 0;
|
231
|
-
});
|
232
|
-
|
233
|
-
// give every group a name
|
234
|
-
for (let i = 0; i < result.length; i++) {
|
235
|
-
const group = result[i];
|
236
|
-
const first = group.nodes[0];
|
237
|
-
const last = group.nodes[group.nodes.length - 1];
|
238
|
-
let name = getName(first.key, last.key);
|
239
|
-
group.key = name;
|
240
|
-
}
|
241
|
-
|
242
|
-
// return the results
|
243
|
-
return result.map(group => {
|
244
|
-
/** @type {GroupedItems} */
|
245
|
-
return {
|
246
|
-
key: group.key,
|
247
|
-
items: group.nodes.map(node => node.item),
|
248
|
-
size: group.size
|
249
|
-
};
|
250
|
-
});
|
251
|
-
};
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
// Simulations show these probabilities for a single change
|
4
|
+
// 93.1% that one group is invalidated
|
5
|
+
// 4.8% that two groups are invalidated
|
6
|
+
// 1.1% that 3 groups are invalidated
|
7
|
+
// 0.1% that 4 or more groups are invalidated
|
8
|
+
//
|
9
|
+
// And these for removing/adding 10 lexically adjacent files
|
10
|
+
// 64.5% that one group is invalidated
|
11
|
+
// 24.8% that two groups are invalidated
|
12
|
+
// 7.8% that 3 groups are invalidated
|
13
|
+
// 2.7% that 4 or more groups are invalidated
|
14
|
+
//
|
15
|
+
// And these for removing/adding 3 random files
|
16
|
+
// 0% that one group is invalidated
|
17
|
+
// 3.7% that two groups are invalidated
|
18
|
+
// 80.8% that 3 groups are invalidated
|
19
|
+
// 12.3% that 4 groups are invalidated
|
20
|
+
// 3.2% that 5 or more groups are invalidated
|
21
|
+
|
22
|
+
/**
|
23
|
+
*
|
24
|
+
* @param {string} a key
|
25
|
+
* @param {string} b key
|
26
|
+
* @returns {number} the similarity as number
|
27
|
+
*/
|
28
|
+
const similarity = (a, b) => {
|
29
|
+
const l = Math.min(a.length, b.length);
|
30
|
+
let dist = 0;
|
31
|
+
for (let i = 0; i < l; i++) {
|
32
|
+
const ca = a.charCodeAt(i);
|
33
|
+
const cb = b.charCodeAt(i);
|
34
|
+
dist += Math.max(0, 10 - Math.abs(ca - cb));
|
35
|
+
}
|
36
|
+
return dist;
|
37
|
+
};
|
38
|
+
|
39
|
+
/**
|
40
|
+
* @param {string} a key
|
41
|
+
* @param {string} b key
|
42
|
+
* @returns {string} the common part and a single char for the difference
|
43
|
+
*/
|
44
|
+
const getName = (a, b) => {
|
45
|
+
const l = Math.min(a.length, b.length);
|
46
|
+
let r = "";
|
47
|
+
for (let i = 0; i < l; i++) {
|
48
|
+
const ca = a.charAt(i);
|
49
|
+
const cb = b.charAt(i);
|
50
|
+
r += ca;
|
51
|
+
if (ca === cb) {
|
52
|
+
continue;
|
53
|
+
}
|
54
|
+
return r;
|
55
|
+
}
|
56
|
+
return a;
|
57
|
+
};
|
58
|
+
|
59
|
+
/**
|
60
|
+
* @template T
|
61
|
+
*/
|
62
|
+
class Node {
|
63
|
+
/**
|
64
|
+
* @param {T} item item
|
65
|
+
* @param {string} key key
|
66
|
+
* @param {number} size size
|
67
|
+
*/
|
68
|
+
constructor(item, key, size) {
|
69
|
+
this.item = item;
|
70
|
+
this.key = key;
|
71
|
+
this.size = size;
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
/**
|
76
|
+
* @template T
|
77
|
+
*/
|
78
|
+
class Group {
|
79
|
+
/**
|
80
|
+
* @param {Node<T>[]} nodes nodes
|
81
|
+
* @param {number[]} similarities similarities between the nodes (length = nodes.length - 1)
|
82
|
+
*/
|
83
|
+
constructor(nodes, similarities) {
|
84
|
+
this.nodes = nodes;
|
85
|
+
this.similarities = similarities;
|
86
|
+
this.size = nodes.reduce((size, node) => size + node.size, 0);
|
87
|
+
/** @type {string} */
|
88
|
+
this.key = undefined;
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
/**
|
93
|
+
* @template T
|
94
|
+
* @typedef {Object} GroupedItems<T>
|
95
|
+
* @property {string} key
|
96
|
+
* @property {T[]} items
|
97
|
+
* @property {number} size
|
98
|
+
*/
|
99
|
+
|
100
|
+
/**
|
101
|
+
* @template T
|
102
|
+
* @typedef {Object} Options
|
103
|
+
* @property {number} maxSize maximum size of a group
|
104
|
+
* @property {number} minSize minimum size of a group (preferred over maximum size)
|
105
|
+
* @property {Iterable<T>} items a list of items
|
106
|
+
* @property {function(T): number} getSize function to get size of an item
|
107
|
+
* @property {function(T): string} getKey function to get the key of an item
|
108
|
+
*/
|
109
|
+
|
110
|
+
/**
|
111
|
+
* @template T
|
112
|
+
* @param {Options<T>} options options object
|
113
|
+
* @returns {GroupedItems<T>[]} grouped items
|
114
|
+
*/
|
115
|
+
module.exports = ({ maxSize, minSize, items, getSize, getKey }) => {
|
116
|
+
/** @type {Group<T>[]} */
|
117
|
+
const result = [];
|
118
|
+
|
119
|
+
const nodes = Array.from(
|
120
|
+
items,
|
121
|
+
item => new Node(item, getKey(item), getSize(item))
|
122
|
+
);
|
123
|
+
|
124
|
+
/** @type {Node<T>[]} */
|
125
|
+
const initialNodes = [];
|
126
|
+
|
127
|
+
// return nodes bigger than maxSize directly as group
|
128
|
+
for (const node of nodes) {
|
129
|
+
if (node.size >= maxSize) {
|
130
|
+
result.push(new Group([node], []));
|
131
|
+
} else {
|
132
|
+
initialNodes.push(node);
|
133
|
+
}
|
134
|
+
}
|
135
|
+
|
136
|
+
if (initialNodes.length > 0) {
|
137
|
+
// lexically ordering of keys
|
138
|
+
initialNodes.sort((a, b) => {
|
139
|
+
if (a.key < b.key) return -1;
|
140
|
+
if (a.key > b.key) return 1;
|
141
|
+
return 0;
|
142
|
+
});
|
143
|
+
|
144
|
+
// calculate similarities between lexically adjacent nodes
|
145
|
+
/** @type {number[]} */
|
146
|
+
const similarities = [];
|
147
|
+
for (let i = 1; i < initialNodes.length; i++) {
|
148
|
+
const a = initialNodes[i - 1];
|
149
|
+
const b = initialNodes[i];
|
150
|
+
similarities.push(similarity(a.key, b.key));
|
151
|
+
}
|
152
|
+
|
153
|
+
const queue = [new Group(initialNodes, similarities)];
|
154
|
+
|
155
|
+
while (queue.length) {
|
156
|
+
const group = queue.pop();
|
157
|
+
// only groups bigger than maxSize need to be splitted
|
158
|
+
if (group.size < maxSize) {
|
159
|
+
result.push(group);
|
160
|
+
continue;
|
161
|
+
}
|
162
|
+
|
163
|
+
// find unsplittable area from left and right
|
164
|
+
// going minSize from left and right
|
165
|
+
let left = 0;
|
166
|
+
let leftSize = 0;
|
167
|
+
while (leftSize < minSize) {
|
168
|
+
leftSize += group.nodes[left].size;
|
169
|
+
left++;
|
170
|
+
}
|
171
|
+
let right = group.nodes.length - 1;
|
172
|
+
let rightSize = 0;
|
173
|
+
while (rightSize < minSize) {
|
174
|
+
rightSize += group.nodes[right].size;
|
175
|
+
right--;
|
176
|
+
}
|
177
|
+
|
178
|
+
if (left - 1 > right) {
|
179
|
+
// can't split group while holding minSize
|
180
|
+
// because minSize is preferred of maxSize we return
|
181
|
+
// the group here even while it's too big
|
182
|
+
// To avoid this make sure maxSize > minSize * 3
|
183
|
+
result.push(group);
|
184
|
+
continue;
|
185
|
+
}
|
186
|
+
if (left <= right) {
|
187
|
+
// when there is a area between left and right
|
188
|
+
// we look for best split point
|
189
|
+
// we split at the minimum similarity
|
190
|
+
// here key space is separated the most
|
191
|
+
let best = left - 1;
|
192
|
+
let bestSimilarity = group.similarities[best];
|
193
|
+
for (let i = left; i <= right; i++) {
|
194
|
+
const similarity = group.similarities[i];
|
195
|
+
if (similarity < bestSimilarity) {
|
196
|
+
best = i;
|
197
|
+
bestSimilarity = similarity;
|
198
|
+
}
|
199
|
+
}
|
200
|
+
left = best + 1;
|
201
|
+
right = best;
|
202
|
+
}
|
203
|
+
|
204
|
+
// create two new groups for left and right area
|
205
|
+
// and queue them up
|
206
|
+
const rightNodes = [group.nodes[right + 1]];
|
207
|
+
/** @type {number[]} */
|
208
|
+
const rightSimilaries = [];
|
209
|
+
for (let i = right + 2; i < group.nodes.length; i++) {
|
210
|
+
rightSimilaries.push(group.similarities[i - 1]);
|
211
|
+
rightNodes.push(group.nodes[i]);
|
212
|
+
}
|
213
|
+
queue.push(new Group(rightNodes, rightSimilaries));
|
214
|
+
|
215
|
+
const leftNodes = [group.nodes[0]];
|
216
|
+
/** @type {number[]} */
|
217
|
+
const leftSimilaries = [];
|
218
|
+
for (let i = 1; i < left; i++) {
|
219
|
+
leftSimilaries.push(group.similarities[i - 1]);
|
220
|
+
leftNodes.push(group.nodes[i]);
|
221
|
+
}
|
222
|
+
queue.push(new Group(leftNodes, leftSimilaries));
|
223
|
+
}
|
224
|
+
}
|
225
|
+
|
226
|
+
// lexically ordering
|
227
|
+
result.sort((a, b) => {
|
228
|
+
if (a.nodes[0].key < b.nodes[0].key) return -1;
|
229
|
+
if (a.nodes[0].key > b.nodes[0].key) return 1;
|
230
|
+
return 0;
|
231
|
+
});
|
232
|
+
|
233
|
+
// give every group a name
|
234
|
+
for (let i = 0; i < result.length; i++) {
|
235
|
+
const group = result[i];
|
236
|
+
const first = group.nodes[0];
|
237
|
+
const last = group.nodes[group.nodes.length - 1];
|
238
|
+
let name = getName(first.key, last.key);
|
239
|
+
group.key = name;
|
240
|
+
}
|
241
|
+
|
242
|
+
// return the results
|
243
|
+
return result.map(group => {
|
244
|
+
/** @type {GroupedItems} */
|
245
|
+
return {
|
246
|
+
key: group.key,
|
247
|
+
items: group.nodes.map(node => node.item),
|
248
|
+
size: group.size
|
249
|
+
};
|
250
|
+
});
|
251
|
+
};
|