From bbff7403fbf46f9ad92240ac213df8d30ef31b64 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 20 Sep 2018 02:56:13 +0200 Subject: update packages --- node_modules/webpack/lib/APIPlugin.js | 129 +- node_modules/webpack/lib/AmdMainTemplatePlugin.js | 143 +- node_modules/webpack/lib/AsyncDependenciesBlock.js | 153 +- .../lib/AsyncDependencyToInitialChunkWarning.js | 21 - .../webpack/lib/AutomaticPrefetchPlugin.js | 93 +- node_modules/webpack/lib/BannerPlugin.js | 190 +- .../webpack/lib/BasicEvaluatedExpression.js | 414 +- node_modules/webpack/lib/CachePlugin.js | 197 +- .../webpack/lib/CaseSensitiveModulesWarning.js | 116 +- node_modules/webpack/lib/Chunk.js | 1312 ++++--- node_modules/webpack/lib/ChunkRenderError.js | 56 +- node_modules/webpack/lib/ChunkTemplate.js | 123 +- node_modules/webpack/lib/CompatibilityPlugin.js | 127 +- node_modules/webpack/lib/Compilation.js | 3968 +++++++++++++------- node_modules/webpack/lib/Compiler.js | 1080 +++--- node_modules/webpack/lib/ConstPlugin.js | 318 +- node_modules/webpack/lib/ContextExclusionPlugin.js | 45 +- node_modules/webpack/lib/ContextModule.js | 1275 ++++--- node_modules/webpack/lib/ContextModuleFactory.js | 431 ++- .../webpack/lib/ContextReplacementPlugin.js | 244 +- node_modules/webpack/lib/DefinePlugin.js | 406 +- node_modules/webpack/lib/DelegatedModule.js | 212 +- .../webpack/lib/DelegatedModuleFactoryPlugin.js | 154 +- node_modules/webpack/lib/DelegatedPlugin.js | 69 +- node_modules/webpack/lib/DependenciesBlock.js | 205 +- .../webpack/lib/DependenciesBlockVariable.js | 123 +- node_modules/webpack/lib/Dependency.js | 143 +- node_modules/webpack/lib/DllEntryPlugin.js | 91 +- node_modules/webpack/lib/DllModule.js | 118 +- node_modules/webpack/lib/DllModuleFactory.js | 49 +- node_modules/webpack/lib/DllPlugin.js | 82 +- node_modules/webpack/lib/DllReferencePlugin.js | 194 +- node_modules/webpack/lib/DynamicEntryPlugin.js | 152 +- .../webpack/lib/EntryModuleNotFoundError.js | 43 +- node_modules/webpack/lib/EntryOptionPlugin.js | 76 +- node_modules/webpack/lib/Entrypoint.js | 97 +- node_modules/webpack/lib/EnvironmentPlugin.js | 122 +- node_modules/webpack/lib/ErrorHelpers.js | 91 +- .../webpack/lib/EvalDevToolModulePlugin.js | 49 +- .../webpack/lib/EvalDevToolModuleTemplatePlugin.js | 94 +- .../EvalSourceMapDevToolModuleTemplatePlugin.js | 190 +- .../webpack/lib/EvalSourceMapDevToolPlugin.js | 73 +- .../lib/ExportPropertyMainTemplatePlugin.js | 84 +- node_modules/webpack/lib/ExtendedAPIPlugin.js | 135 +- node_modules/webpack/lib/ExternalModule.js | 305 +- .../webpack/lib/ExternalModuleFactoryPlugin.js | 201 +- node_modules/webpack/lib/ExternalsPlugin.js | 44 +- .../webpack/lib/FlagDependencyExportsPlugin.js | 247 +- .../webpack/lib/FlagDependencyUsagePlugin.js | 197 +- .../webpack/lib/FlagInitialModulesAsUsedPlugin.js | 60 +- node_modules/webpack/lib/FunctionModulePlugin.js | 43 +- .../webpack/lib/FunctionModuleTemplatePlugin.js | 161 +- node_modules/webpack/lib/HashedModuleIdsPlugin.js | 95 +- .../webpack/lib/HotModuleReplacement.runtime.js | 1247 +++--- .../webpack/lib/HotModuleReplacementPlugin.js | 658 ++-- node_modules/webpack/lib/HotUpdateChunkTemplate.js | 109 +- node_modules/webpack/lib/IgnorePlugin.js | 178 +- .../webpack/lib/JsonpChunkTemplatePlugin.js | 31 - .../webpack/lib/JsonpExportMainTemplatePlugin.js | 37 - .../lib/JsonpHotUpdateChunkTemplatePlugin.js | 27 - .../webpack/lib/JsonpMainTemplate.runtime.js | 60 - .../webpack/lib/JsonpMainTemplatePlugin.js | 211 -- node_modules/webpack/lib/JsonpTemplatePlugin.js | 21 - node_modules/webpack/lib/LibManifestPlugin.js | 149 +- node_modules/webpack/lib/LibraryTemplatePlugin.js | 245 +- node_modules/webpack/lib/LoaderOptionsPlugin.js | 89 +- node_modules/webpack/lib/LoaderTargetPlugin.js | 43 +- node_modules/webpack/lib/MainTemplate.js | 766 ++-- node_modules/webpack/lib/MemoryOutputFileSystem.js | 10 +- node_modules/webpack/lib/Module.js | 681 ++-- node_modules/webpack/lib/ModuleBuildError.js | 94 +- node_modules/webpack/lib/ModuleDependencyError.js | 57 +- .../webpack/lib/ModuleDependencyWarning.js | 47 +- node_modules/webpack/lib/ModuleError.js | 60 +- node_modules/webpack/lib/ModuleFilenameHelpers.js | 340 +- node_modules/webpack/lib/ModuleNotFoundError.js | 49 +- node_modules/webpack/lib/ModuleParseError.js | 91 +- node_modules/webpack/lib/ModuleReason.js | 98 +- node_modules/webpack/lib/ModuleTemplate.js | 116 +- node_modules/webpack/lib/ModuleWarning.js | 60 +- .../webpack/lib/MovedToPluginWarningPlugin.js | 21 - node_modules/webpack/lib/MultiCompiler.js | 447 ++- node_modules/webpack/lib/MultiEntryPlugin.js | 119 +- node_modules/webpack/lib/MultiModule.js | 162 +- node_modules/webpack/lib/MultiModuleFactory.js | 42 +- node_modules/webpack/lib/MultiStats.js | 171 +- node_modules/webpack/lib/MultiWatching.js | 70 +- node_modules/webpack/lib/NamedChunksPlugin.js | 59 +- node_modules/webpack/lib/NamedModulesPlugin.js | 84 +- node_modules/webpack/lib/NewWatchingPlugin.js | 15 - node_modules/webpack/lib/NoEmitOnErrorsPlugin.js | 42 +- node_modules/webpack/lib/NoErrorsPlugin.js | 29 - node_modules/webpack/lib/NodeStuffPlugin.js | 294 +- node_modules/webpack/lib/NormalModule.js | 1098 +++--- node_modules/webpack/lib/NormalModuleFactory.js | 818 ++-- .../webpack/lib/NormalModuleReplacementPlugin.js | 96 +- node_modules/webpack/lib/NullFactory.js | 24 +- node_modules/webpack/lib/OptionsApply.js | 20 +- node_modules/webpack/lib/OptionsDefaulter.js | 156 +- node_modules/webpack/lib/Parser.js | 3664 ++++++++++-------- node_modules/webpack/lib/ParserHelpers.js | 188 +- node_modules/webpack/lib/PrefetchPlugin.js | 68 +- node_modules/webpack/lib/ProgressPlugin.js | 438 ++- node_modules/webpack/lib/ProvidePlugin.js | 141 +- node_modules/webpack/lib/RawModule.js | 110 +- node_modules/webpack/lib/RecordIdsPlugin.js | 347 +- node_modules/webpack/lib/RequestShortener.js | 146 +- node_modules/webpack/lib/RequireJsStuffPlugin.js | 97 +- node_modules/webpack/lib/RuleSet.js | 1011 ++--- .../webpack/lib/SetVarMainTemplatePlugin.js | 110 +- node_modules/webpack/lib/SingleEntryPlugin.js | 98 +- node_modules/webpack/lib/SizeFormatHelpers.js | 42 +- .../lib/SourceMapDevToolModuleOptionsPlugin.js | 86 +- node_modules/webpack/lib/SourceMapDevToolPlugin.js | 510 +-- node_modules/webpack/lib/Stats.js | 2418 +++++++----- node_modules/webpack/lib/Template.js | 466 ++- node_modules/webpack/lib/TemplatedPathPlugin.js | 285 +- node_modules/webpack/lib/UmdMainTemplatePlugin.js | 495 ++- .../webpack/lib/UnsupportedFeatureWarning.js | 51 +- node_modules/webpack/lib/UseStrictPlugin.js | 88 +- .../webpack/lib/WarnCaseSensitiveModulesPlugin.js | 68 +- node_modules/webpack/lib/WatchIgnorePlugin.js | 149 +- node_modules/webpack/lib/WebpackError.js | 40 +- node_modules/webpack/lib/WebpackOptionsApply.js | 817 ++-- .../webpack/lib/WebpackOptionsDefaulter.js | 501 ++- .../webpack/lib/WebpackOptionsValidationError.js | 563 +-- node_modules/webpack/lib/compareLocations.js | 88 +- .../lib/dependencies/AMDDefineDependency.js | 279 +- .../AMDDefineDependencyParserPlugin.js | 600 +-- node_modules/webpack/lib/dependencies/AMDPlugin.js | 368 +- .../lib/dependencies/AMDRequireArrayDependency.js | 107 +- .../dependencies/AMDRequireContextDependency.js | 40 +- .../dependencies/AMDRequireDependenciesBlock.js | 76 +- .../AMDRequireDependenciesBlockParserPlugin.js | 449 ++- .../lib/dependencies/AMDRequireDependency.js | 202 +- .../lib/dependencies/AMDRequireItemDependency.js | 44 +- .../webpack/lib/dependencies/CommonJsPlugin.js | 247 +- .../CommonJsRequireContextDependency.js | 47 +- .../lib/dependencies/CommonJsRequireDependency.js | 44 +- .../CommonJsRequireDependencyParserPlugin.js | 225 +- .../webpack/lib/dependencies/ConstDependency.js | 65 +- .../webpack/lib/dependencies/ContextDependency.js | 117 +- .../lib/dependencies/ContextDependencyHelpers.js | 248 +- .../dependencies/ContextDependencyTemplateAsId.js | 75 +- .../ContextDependencyTemplateAsRequireCall.js | 73 +- .../lib/dependencies/ContextElementDependency.js | 42 +- .../lib/dependencies/CriticalDependencyWarning.js | 40 +- .../lib/dependencies/DelegatedExportsDependency.js | 66 +- .../lib/dependencies/DelegatedSourceDependency.js | 36 +- .../webpack/lib/dependencies/DepBlockHelpers.js | 39 - .../webpack/lib/dependencies/DllEntryDependency.js | 40 +- .../lib/dependencies/HarmonyAcceptDependency.js | 87 +- .../dependencies/HarmonyAcceptImportDependency.js | 45 +- .../dependencies/HarmonyCompatibilityDependency.js | 61 +- .../dependencies/HarmonyDetectionParserPlugin.js | 148 +- .../HarmonyExportDependencyParserPlugin.js | 241 +- .../HarmonyExportExpressionDependency.js | 108 +- .../dependencies/HarmonyExportHeaderDependency.js | 58 +- .../HarmonyExportImportedSpecifierDependency.js | 930 +++-- .../HarmonyExportSpecifierDependency.js | 108 +- .../lib/dependencies/HarmonyImportDependency.js | 181 +- .../HarmonyImportDependencyParserPlugin.js | 346 +- .../HarmonyImportSpecifierDependency.js | 296 +- .../lib/dependencies/HarmonyModulesHelpers.js | 32 - .../lib/dependencies/HarmonyModulesPlugin.js | 215 +- .../lib/dependencies/ImportContextDependency.js | 48 +- .../lib/dependencies/ImportDependenciesBlock.js | 35 +- .../webpack/lib/dependencies/ImportDependency.js | 88 +- .../dependencies/ImportEagerContextDependency.js | 22 - .../lib/dependencies/ImportEagerDependency.js | 78 +- .../dependencies/ImportLazyContextDependency.js | 22 - .../ImportLazyOnceContextDependency.js | 22 - .../webpack/lib/dependencies/ImportParserPlugin.js | 352 +- .../webpack/lib/dependencies/ImportPlugin.js | 139 +- .../dependencies/ImportWeakContextDependency.js | 22 - .../lib/dependencies/ImportWeakDependency.js | 81 +- .../webpack/lib/dependencies/LoaderDependency.js | 39 +- .../webpack/lib/dependencies/LoaderPlugin.js | 177 +- .../webpack/lib/dependencies/LocalModule.js | 46 +- .../lib/dependencies/LocalModuleDependency.js | 52 +- .../lib/dependencies/LocalModulesHelpers.js | 98 +- .../webpack/lib/dependencies/ModuleDependency.js | 46 +- .../dependencies/ModuleDependencyTemplateAsId.js | 38 +- .../ModuleDependencyTemplateAsRequireId.js | 38 +- .../lib/dependencies/ModuleHotAcceptDependency.js | 46 +- .../lib/dependencies/ModuleHotDeclineDependency.js | 46 +- .../lib/dependencies/MultiEntryDependency.js | 45 +- .../webpack/lib/dependencies/NullDependency.js | 44 +- .../webpack/lib/dependencies/PrefetchDependency.js | 36 +- .../lib/dependencies/RequireContextDependency.js | 48 +- .../RequireContextDependencyParserPlugin.js | 106 +- .../lib/dependencies/RequireContextPlugin.js | 239 +- .../dependencies/RequireEnsureDependenciesBlock.js | 55 +- .../RequireEnsureDependenciesBlockParserPlugin.js | 218 +- .../lib/dependencies/RequireEnsureDependency.js | 96 +- .../dependencies/RequireEnsureItemDependency.js | 42 +- .../lib/dependencies/RequireEnsurePlugin.js | 114 +- .../lib/dependencies/RequireHeaderDependency.js | 52 +- .../lib/dependencies/RequireIncludeDependency.js | 80 +- .../RequireIncludeDependencyParserPlugin.js | 44 +- .../lib/dependencies/RequireIncludePlugin.js | 94 +- .../RequireResolveContextDependency.js | 47 +- .../lib/dependencies/RequireResolveDependency.js | 44 +- .../RequireResolveDependencyParserPlugin.js | 156 +- .../dependencies/RequireResolveHeaderDependency.js | 52 +- .../lib/dependencies/SingleEntryDependency.js | 39 +- .../webpack/lib/dependencies/SystemPlugin.js | 166 +- .../lib/dependencies/UnsupportedDependency.js | 50 +- .../lib/dependencies/WebpackMissingModule.js | 38 +- .../lib/dependencies/getFunctionExpression.js | 96 +- node_modules/webpack/lib/formatLocation.js | 129 +- .../webpack/lib/node/NodeChunkTemplatePlugin.js | 58 +- .../webpack/lib/node/NodeEnvironmentPlugin.js | 53 +- .../lib/node/NodeHotUpdateChunkTemplatePlugin.js | 63 +- .../webpack/lib/node/NodeMainTemplate.runtime.js | 51 +- .../lib/node/NodeMainTemplateAsync.runtime.js | 84 +- .../webpack/lib/node/NodeMainTemplatePlugin.js | 504 ++- .../webpack/lib/node/NodeOutputFileSystem.js | 44 +- node_modules/webpack/lib/node/NodeSourcePlugin.js | 232 +- node_modules/webpack/lib/node/NodeTargetPlugin.js | 34 +- .../webpack/lib/node/NodeTemplatePlugin.js | 58 +- .../webpack/lib/node/NodeWatchFileSystem.js | 171 +- .../lib/optimize/AggressiveMergingPlugin.js | 202 +- .../lib/optimize/AggressiveSplittingPlugin.js | 482 ++- .../lib/optimize/ChunkModuleIdRangePlugin.js | 121 +- .../webpack/lib/optimize/CommonsChunkPlugin.js | 404 -- .../webpack/lib/optimize/ConcatenatedModule.js | 2322 ++++++++---- node_modules/webpack/lib/optimize/DedupePlugin.js | 15 - .../lib/optimize/EnsureChunkConditionsPlugin.js | 110 +- .../lib/optimize/FlagIncludedChunksPlugin.js | 134 +- .../webpack/lib/optimize/LimitChunkCountPlugin.js | 125 +- .../lib/optimize/MergeDuplicateChunksPlugin.js | 106 +- .../webpack/lib/optimize/MinChunkSizePlugin.js | 142 +- .../lib/optimize/ModuleConcatenationPlugin.js | 791 ++-- .../webpack/lib/optimize/OccurrenceOrderPlugin.js | 237 +- .../lib/optimize/RemoveEmptyChunksPlugin.js | 63 +- .../lib/optimize/RemoveParentModulesPlugin.js | 192 +- .../webpack/lib/optimize/UglifyJsPlugin.js | 9 - .../lib/performance/AssetsOverSizeLimitWarning.js | 53 +- .../performance/EntrypointsOverSizeLimitWarning.js | 58 +- .../lib/performance/NoAsyncChunksWarning.js | 41 +- .../webpack/lib/performance/SizeLimitsPlugin.js | 207 +- node_modules/webpack/lib/prepareOptions.js | 29 - node_modules/webpack/lib/removeAndDo.js | 15 - node_modules/webpack/lib/util/Queue.js | 88 +- node_modules/webpack/lib/util/Semaphore.js | 85 +- node_modules/webpack/lib/util/SortableSet.js | 185 +- node_modules/webpack/lib/util/identifier.js | 141 +- node_modules/webpack/lib/validateSchema.js | 133 +- .../webpack/lib/web/WebEnvironmentPlugin.js | 36 +- node_modules/webpack/lib/webpack.js | 311 +- node_modules/webpack/lib/webpack.web.js | 60 +- .../lib/webworker/WebWorkerChunkTemplatePlugin.js | 64 +- .../WebWorkerHotUpdateChunkTemplatePlugin.js | 68 +- .../lib/webworker/WebWorkerMainTemplate.runtime.js | 123 +- .../lib/webworker/WebWorkerMainTemplatePlugin.js | 296 +- .../lib/webworker/WebWorkerTemplatePlugin.js | 45 +- 257 files changed, 33248 insertions(+), 22953 deletions(-) delete mode 100644 node_modules/webpack/lib/AsyncDependencyToInitialChunkWarning.js delete mode 100644 node_modules/webpack/lib/JsonpChunkTemplatePlugin.js delete mode 100644 node_modules/webpack/lib/JsonpExportMainTemplatePlugin.js delete mode 100644 node_modules/webpack/lib/JsonpHotUpdateChunkTemplatePlugin.js delete mode 100644 node_modules/webpack/lib/JsonpMainTemplate.runtime.js delete mode 100644 node_modules/webpack/lib/JsonpMainTemplatePlugin.js delete mode 100644 node_modules/webpack/lib/JsonpTemplatePlugin.js delete mode 100644 node_modules/webpack/lib/MovedToPluginWarningPlugin.js delete mode 100644 node_modules/webpack/lib/NewWatchingPlugin.js delete mode 100644 node_modules/webpack/lib/NoErrorsPlugin.js delete mode 100644 node_modules/webpack/lib/dependencies/DepBlockHelpers.js delete mode 100644 node_modules/webpack/lib/dependencies/HarmonyModulesHelpers.js delete mode 100644 node_modules/webpack/lib/dependencies/ImportEagerContextDependency.js delete mode 100644 node_modules/webpack/lib/dependencies/ImportLazyContextDependency.js delete mode 100644 node_modules/webpack/lib/dependencies/ImportLazyOnceContextDependency.js delete mode 100644 node_modules/webpack/lib/dependencies/ImportWeakContextDependency.js delete mode 100644 node_modules/webpack/lib/optimize/CommonsChunkPlugin.js delete mode 100644 node_modules/webpack/lib/optimize/DedupePlugin.js delete mode 100644 node_modules/webpack/lib/optimize/UglifyJsPlugin.js delete mode 100644 node_modules/webpack/lib/prepareOptions.js delete mode 100644 node_modules/webpack/lib/removeAndDo.js (limited to 'node_modules/webpack/lib') diff --git a/node_modules/webpack/lib/APIPlugin.js b/node_modules/webpack/lib/APIPlugin.js index 19a5be424..6cd80646d 100644 --- a/node_modules/webpack/lib/APIPlugin.js +++ b/node_modules/webpack/lib/APIPlugin.js @@ -1,45 +1,84 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ConstDependency = require("./dependencies/ConstDependency"); -const ParserHelpers = require("./ParserHelpers"); - -const NullFactory = require("./NullFactory"); - -const REPLACEMENTS = { - __webpack_require__: "__webpack_require__", // eslint-disable-line camelcase - __webpack_public_path__: "__webpack_require__.p", // eslint-disable-line camelcase - __webpack_modules__: "__webpack_require__.m", // eslint-disable-line camelcase - __webpack_chunk_load__: "__webpack_require__.e", // eslint-disable-line camelcase - __non_webpack_require__: "require", // eslint-disable-line camelcase - __webpack_nonce__: "__webpack_require__.nc", // eslint-disable-line camelcase - "require.onError": "__webpack_require__.oe" // eslint-disable-line camelcase -}; -const REPLACEMENT_TYPES = { - __webpack_public_path__: "string", // eslint-disable-line camelcase - __webpack_require__: "function", // eslint-disable-line camelcase - __webpack_modules__: "object", // eslint-disable-line camelcase - __webpack_chunk_load__: "function", // eslint-disable-line camelcase - __webpack_nonce__: "string" // eslint-disable-line camelcase -}; - -class APIPlugin { - apply(compiler) { - compiler.plugin("compilation", (compilation, params) => { - compilation.dependencyFactories.set(ConstDependency, new NullFactory()); - compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template()); - - params.normalModuleFactory.plugin("parser", parser => { - Object.keys(REPLACEMENTS).forEach(key => { - parser.plugin(`expression ${key}`, ParserHelpers.toConstantDependency(REPLACEMENTS[key])); - parser.plugin(`evaluate typeof ${key}`, ParserHelpers.evaluateToString(REPLACEMENT_TYPES[key])); - }); - }); - }); - } -} - -module.exports = APIPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const ConstDependency = require("./dependencies/ConstDependency"); +const ParserHelpers = require("./ParserHelpers"); + +const NullFactory = require("./NullFactory"); + +/* eslint-disable camelcase */ +const REPLACEMENTS = { + __webpack_require__: "__webpack_require__", + __webpack_public_path__: "__webpack_require__.p", + __webpack_modules__: "__webpack_require__.m", + __webpack_chunk_load__: "__webpack_require__.e", + __non_webpack_require__: "require", + __webpack_nonce__: "__webpack_require__.nc", + "require.onError": "__webpack_require__.oe" +}; +const NO_WEBPACK_REQUIRE = { + __non_webpack_require__: true +}; +const REPLACEMENT_TYPES = { + __webpack_public_path__: "string", + __webpack_require__: "function", + __webpack_modules__: "object", + __webpack_chunk_load__: "function", + __webpack_nonce__: "string" +}; +/* eslint-enable camelcase */ + +class APIPlugin { + apply(compiler) { + compiler.hooks.compilation.tap( + "APIPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set(ConstDependency, new NullFactory()); + compilation.dependencyTemplates.set( + ConstDependency, + new ConstDependency.Template() + ); + + const handler = parser => { + Object.keys(REPLACEMENTS).forEach(key => { + parser.hooks.expression + .for(key) + .tap( + "APIPlugin", + NO_WEBPACK_REQUIRE[key] + ? ParserHelpers.toConstantDependency( + parser, + REPLACEMENTS[key] + ) + : ParserHelpers.toConstantDependencyWithWebpackRequire( + parser, + REPLACEMENTS[key] + ) + ); + parser.hooks.evaluateTypeof + .for(key) + .tap( + "APIPlugin", + ParserHelpers.evaluateToString(REPLACEMENT_TYPES[key]) + ); + }); + }; + + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("APIPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("APIPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/esm") + .tap("APIPlugin", handler); + } + ); + } +} + +module.exports = APIPlugin; diff --git a/node_modules/webpack/lib/AmdMainTemplatePlugin.js b/node_modules/webpack/lib/AmdMainTemplatePlugin.js index 727f49ba3..ff715ec6c 100644 --- a/node_modules/webpack/lib/AmdMainTemplatePlugin.js +++ b/node_modules/webpack/lib/AmdMainTemplatePlugin.js @@ -1,56 +1,87 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra - */ - -"use strict"; - -const ConcatSource = require("webpack-sources").ConcatSource; -const Template = require("./Template"); - -class AmdMainTemplatePlugin { - constructor(name) { - this.name = name; - } - - apply(compilation) { - const mainTemplate = compilation.mainTemplate; - - compilation.templatesPlugin("render-with-entry", (source, chunk, hash) => { - const externals = chunk.getModules().filter((m) => m.external); - const externalsDepsArray = JSON.stringify(externals.map((m) => - typeof m.request === "object" ? m.request.amd : m.request - )); - const externalsArguments = externals.map((m) => - Template.toIdentifier(`__WEBPACK_EXTERNAL_MODULE_${m.id}__`) - ).join(", "); - - if(this.name) { - const name = mainTemplate.applyPluginsWaterfall("asset-path", this.name, { - hash, - chunk - }); - - return new ConcatSource( - `define(${JSON.stringify(name)}, ${externalsDepsArray}, function(${externalsArguments}) { return `, source, "});" - ); - } else if(externalsArguments) { - return new ConcatSource(`define(${externalsDepsArray}, function(${externalsArguments}) { return `, source, "});"); - } else { - return new ConcatSource("define(function() { return ", source, "});"); - } - }); - - mainTemplate.plugin("global-hash-paths", (paths) => { - if(this.name) paths.push(this.name); - return paths; - }); - - mainTemplate.plugin("hash", (hash) => { - hash.update("exports amd"); - hash.update(this.name); - }); - } -} - -module.exports = AmdMainTemplatePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra + */ + +"use strict"; + +const { ConcatSource } = require("webpack-sources"); +const Template = require("./Template"); + +/** @typedef {import("./Compilation")} Compilation */ + +class AmdMainTemplatePlugin { + /** + * @param {string} name the library name + */ + constructor(name) { + /** @type {string} */ + this.name = name; + } + + /** + * @param {Compilation} compilation the compilation instance + * @returns {void} + */ + apply(compilation) { + const { mainTemplate, chunkTemplate } = compilation; + + const onRenderWithEntry = (source, chunk, hash) => { + const externals = chunk.getModules().filter(m => m.external); + const externalsDepsArray = JSON.stringify( + externals.map( + m => (typeof m.request === "object" ? m.request.amd : m.request) + ) + ); + const externalsArguments = externals + .map( + m => `__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(`${m.id}`)}__` + ) + .join(", "); + + if (this.name) { + const name = mainTemplate.getAssetPath(this.name, { + hash, + chunk + }); + + return new ConcatSource( + `define(${JSON.stringify( + name + )}, ${externalsDepsArray}, function(${externalsArguments}) { return `, + source, + "});" + ); + } else if (externalsArguments) { + return new ConcatSource( + `define(${externalsDepsArray}, function(${externalsArguments}) { return `, + source, + "});" + ); + } else { + return new ConcatSource("define(function() { return ", source, "});"); + } + }; + + for (const template of [mainTemplate, chunkTemplate]) { + template.hooks.renderWithEntry.tap( + "AmdMainTemplatePlugin", + onRenderWithEntry + ); + } + + mainTemplate.hooks.globalHashPaths.tap("AmdMainTemplatePlugin", paths => { + if (this.name) { + paths.push(this.name); + } + return paths; + }); + + mainTemplate.hooks.hash.tap("AmdMainTemplatePlugin", hash => { + hash.update("exports amd"); + hash.update(this.name); + }); + } +} + +module.exports = AmdMainTemplatePlugin; diff --git a/node_modules/webpack/lib/AsyncDependenciesBlock.js b/node_modules/webpack/lib/AsyncDependenciesBlock.js index 27d5988b6..a7e029131 100644 --- a/node_modules/webpack/lib/AsyncDependenciesBlock.js +++ b/node_modules/webpack/lib/AsyncDependenciesBlock.js @@ -1,43 +1,110 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const DependenciesBlock = require("./DependenciesBlock"); - -module.exports = class AsyncDependenciesBlock extends DependenciesBlock { - constructor(name, module, loc) { - super(); - this.chunkName = name; - this.chunks = null; - this.module = module; - this.loc = loc; - } - get chunk() { - throw new Error("`chunk` was been renamed to `chunks` and is now an array"); - } - set chunk(chunk) { - throw new Error("`chunk` was been renamed to `chunks` and is now an array"); - } - updateHash(hash) { - hash.update(this.chunkName || ""); - hash.update(this.chunks && this.chunks.map((chunk) => { - return chunk.id !== null ? chunk.id : ""; - }).join(",") || ""); - super.updateHash(hash); - } - disconnect() { - this.chunks = null; - super.disconnect(); - } - unseal() { - this.chunks = null; - super.unseal(); - } - sortItems() { - super.sortItems(); - if(this.chunks) { - this.chunks.sort((a, b) => a.compareTo(b)); - } - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const DependenciesBlock = require("./DependenciesBlock"); + +/** @typedef {import("./ChunkGroup")} ChunkGroup */ +/** @typedef {import("./Module")} Module */ +/** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */ +/** @typedef {import("./util/createHash").Hash} Hash */ +/** @typedef {TODO} GroupOptions */ + +module.exports = class AsyncDependenciesBlock extends DependenciesBlock { + /** + * @param {GroupOptions} groupOptions options for the group + * @param {Module} module the Module object + * @param {DependencyLocation=} loc the line of code + * @param {TODO=} request the request + */ + constructor(groupOptions, module, loc, request) { + super(); + if (typeof groupOptions === "string") { + groupOptions = { name: groupOptions }; + } else if (!groupOptions) { + groupOptions = { name: undefined }; + } + this.groupOptions = groupOptions; + /** @type {ChunkGroup=} */ + this.chunkGroup = undefined; + this.module = module; + this.loc = loc; + this.request = request; + /** @type {DependenciesBlock} */ + this.parent = undefined; + } + + /** + * @returns {string} The name of the chunk + */ + get chunkName() { + return this.groupOptions.name; + } + + /** + * @param {string} value The new chunk name + * @returns {void} + */ + set chunkName(value) { + this.groupOptions.name = value; + } + + /** + * @returns {never} this throws and should never be called + */ + get chunks() { + throw new Error("Moved to AsyncDependenciesBlock.chunkGroup"); + } + + /** + * @param {never} value setter value + * @returns {never} this is going to throw therefore we should throw type + * assertions by returning never + */ + set chunks(value) { + throw new Error("Moved to AsyncDependenciesBlock.chunkGroup"); + } + + /** + * @param {Hash} hash the hash used to track block changes, from "crypto" module + * @returns {void} + */ + updateHash(hash) { + hash.update(JSON.stringify(this.groupOptions)); + hash.update( + (this.chunkGroup && + this.chunkGroup.chunks + .map(chunk => { + return chunk.id !== null ? chunk.id : ""; + }) + .join(",")) || + "" + ); + super.updateHash(hash); + } + + /** + * @returns {void} + */ + disconnect() { + this.chunkGroup = undefined; + super.disconnect(); + } + + /** + * @returns {void} + */ + unseal() { + this.chunkGroup = undefined; + super.unseal(); + } + + /** + * @returns {void} + */ + sortItems() { + super.sortItems(); + } +}; diff --git a/node_modules/webpack/lib/AsyncDependencyToInitialChunkWarning.js b/node_modules/webpack/lib/AsyncDependencyToInitialChunkWarning.js deleted file mode 100644 index b917b4f60..000000000 --- a/node_modules/webpack/lib/AsyncDependencyToInitialChunkWarning.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Sean Larkin @thelarkinn -*/ -"use strict"; - -const WebpackError = require("./WebpackError"); - -module.exports = class AsyncDependencyToInitialChunkWarning extends WebpackError { - constructor(chunkName, module, loc) { - super(); - - this.name = "AsyncDependencyToInitialChunkWarning"; - this.message = `It's not allowed to load an initial chunk on demand. The chunk name "${chunkName}" is already used by an entrypoint.`; - this.module = module; - this.origin = module; - this.originLoc = loc; - - Error.captureStackTrace(this, this.constructor); - } -}; diff --git a/node_modules/webpack/lib/AutomaticPrefetchPlugin.js b/node_modules/webpack/lib/AutomaticPrefetchPlugin.js index 8652d1cc8..2d0db16ec 100644 --- a/node_modules/webpack/lib/AutomaticPrefetchPlugin.js +++ b/node_modules/webpack/lib/AutomaticPrefetchPlugin.js @@ -1,36 +1,57 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const asyncLib = require("async"); -const PrefetchDependency = require("./dependencies/PrefetchDependency"); -const NormalModule = require("./NormalModule"); - -class AutomaticPrefetchPlugin { - apply(compiler) { - compiler.plugin("compilation", (compilation, params) => { - const normalModuleFactory = params.normalModuleFactory; - - compilation.dependencyFactories.set(PrefetchDependency, normalModuleFactory); - }); - let lastModules = null; - compiler.plugin("after-compile", (compilation, callback) => { - lastModules = compilation.modules - .filter(m => m instanceof NormalModule) - .map(m => ({ - context: m.context, - request: m.request - })); - callback(); - }); - compiler.plugin("make", (compilation, callback) => { - if(!lastModules) return callback(); - asyncLib.forEach(lastModules, (m, callback) => { - compilation.prefetch(m.context || compiler.context, new PrefetchDependency(m.request), callback); - }, callback); - }); - } -} -module.exports = AutomaticPrefetchPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const asyncLib = require("neo-async"); +const PrefetchDependency = require("./dependencies/PrefetchDependency"); +const NormalModule = require("./NormalModule"); + +/** @typedef {import("./Compiler")} Compiler */ + +class AutomaticPrefetchPlugin { + /** + * Apply the plugin + * @param {Compiler} compiler Webpack Compiler + * @returns {void} + */ + apply(compiler) { + compiler.hooks.compilation.tap( + "AutomaticPrefetchPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set( + PrefetchDependency, + normalModuleFactory + ); + } + ); + let lastModules = null; + compiler.hooks.afterCompile.tap("AutomaticPrefetchPlugin", compilation => { + lastModules = compilation.modules + .filter(m => m instanceof NormalModule) + .map((/** @type {NormalModule} */ m) => ({ + context: m.context, + request: m.request + })); + }); + compiler.hooks.make.tapAsync( + "AutomaticPrefetchPlugin", + (compilation, callback) => { + if (!lastModules) return callback(); + asyncLib.forEach( + lastModules, + (m, callback) => { + compilation.prefetch( + m.context || compiler.context, + new PrefetchDependency(m.request), + callback + ); + }, + callback + ); + } + ); + } +} +module.exports = AutomaticPrefetchPlugin; diff --git a/node_modules/webpack/lib/BannerPlugin.js b/node_modules/webpack/lib/BannerPlugin.js index 342a30328..1e9aa343c 100644 --- a/node_modules/webpack/lib/BannerPlugin.js +++ b/node_modules/webpack/lib/BannerPlugin.js @@ -1,73 +1,117 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra - */ - -"use strict"; - -const ConcatSource = require("webpack-sources").ConcatSource; -const ModuleFilenameHelpers = require("./ModuleFilenameHelpers"); - -const wrapComment = (str) => { - if(!str.includes("\n")) return `/*! ${str} */`; - return `/*!\n * ${str.split("\n").join("\n * ")}\n */`; -}; - -class BannerPlugin { - constructor(options) { - if(arguments.length > 1) - throw new Error("BannerPlugin only takes one argument (pass an options object)"); - if(typeof options === "string") - options = { - banner: options - }; - this.options = options || {}; - this.banner = this.options.raw ? options.banner : wrapComment(options.banner); - } - - apply(compiler) { - const options = this.options; - const banner = this.banner; - - compiler.plugin("compilation", (compilation) => { - compilation.plugin("optimize-chunk-assets", (chunks, callback) => { - chunks.forEach((chunk) => { - if(options.entryOnly && !chunk.isInitial()) return; - chunk.files - .filter(ModuleFilenameHelpers.matchObject.bind(undefined, options)) - .forEach((file) => { - let basename; - let query = ""; - let filename = file; - const hash = compilation.hash; - const querySplit = filename.indexOf("?"); - - if(querySplit >= 0) { - query = filename.substr(querySplit); - filename = filename.substr(0, querySplit); - } - - if(filename.indexOf("/") < 0) { - basename = filename; - } else { - basename = filename.substr(filename.lastIndexOf("/") + 1); - } - - const comment = compilation.getPath(banner, { - hash, - chunk, - filename, - basename, - query, - }); - - return compilation.assets[file] = new ConcatSource(comment, "\n", compilation.assets[file]); - }); - }); - callback(); - }); - }); - } -} - -module.exports = BannerPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra + */ + +"use strict"; + +const { ConcatSource } = require("webpack-sources"); +const ModuleFilenameHelpers = require("./ModuleFilenameHelpers"); +const Template = require("./Template"); + +const validateOptions = require("schema-utils"); +const schema = require("../schemas/plugins/BannerPlugin.json"); + +const wrapComment = str => { + if (!str.includes("\n")) { + return Template.toComment(str); + } + return `/*!\n * ${str + .replace(/\*\//g, "* /") + .split("\n") + .join("\n * ")}\n */`; +}; + +class BannerPlugin { + constructor(options) { + if (arguments.length > 1) { + throw new Error( + "BannerPlugin only takes one argument (pass an options object)" + ); + } + + validateOptions(schema, options, "Banner Plugin"); + + if (typeof options === "string" || typeof options === "function") { + options = { + banner: options + }; + } + + this.options = options || {}; + + if (typeof options.banner === "function") { + const getBanner = this.options.banner; + this.banner = this.options.raw + ? getBanner + : data => wrapComment(getBanner(data)); + } else { + const banner = this.options.raw + ? this.options.banner + : wrapComment(this.options.banner); + this.banner = () => banner; + } + } + + apply(compiler) { + const options = this.options; + const banner = this.banner; + const matchObject = ModuleFilenameHelpers.matchObject.bind( + undefined, + options + ); + + compiler.hooks.compilation.tap("BannerPlugin", compilation => { + compilation.hooks.optimizeChunkAssets.tap("BannerPlugin", chunks => { + for (const chunk of chunks) { + if (options.entryOnly && !chunk.canBeInitial()) { + continue; + } + + for (const file of chunk.files) { + if (!matchObject(file)) { + continue; + } + + let basename; + let query = ""; + let filename = file; + const hash = compilation.hash; + const querySplit = filename.indexOf("?"); + + if (querySplit >= 0) { + query = filename.substr(querySplit); + filename = filename.substr(0, querySplit); + } + + const lastSlashIndex = filename.lastIndexOf("/"); + + if (lastSlashIndex === -1) { + basename = filename; + } else { + basename = filename.substr(lastSlashIndex + 1); + } + + const data = { + hash, + chunk, + filename, + basename, + query + }; + + const comment = compilation.getPath(banner(data), data); + + compilation.assets[file] = new ConcatSource( + comment, + "\n", + compilation.assets[file] + ); + } + } + }); + }); + } +} + +module.exports = BannerPlugin; diff --git a/node_modules/webpack/lib/BasicEvaluatedExpression.js b/node_modules/webpack/lib/BasicEvaluatedExpression.js index eab51de83..65db864f9 100644 --- a/node_modules/webpack/lib/BasicEvaluatedExpression.js +++ b/node_modules/webpack/lib/BasicEvaluatedExpression.js @@ -1,203 +1,211 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ - -"use strict"; - -class BasicEvaluatedExpression { - - constructor() { - this.range = null; - } - - isNull() { - return !!this.null; - } - - isString() { - return Object.prototype.hasOwnProperty.call(this, "string"); - } - - isNumber() { - return Object.prototype.hasOwnProperty.call(this, "number"); - } - - isBoolean() { - return Object.prototype.hasOwnProperty.call(this, "bool"); - } - - isRegExp() { - return Object.prototype.hasOwnProperty.call(this, "regExp"); - } - - isConditional() { - return Object.prototype.hasOwnProperty.call(this, "options"); - } - - isArray() { - return Object.prototype.hasOwnProperty.call(this, "items"); - } - - isConstArray() { - return Object.prototype.hasOwnProperty.call(this, "array"); - } - - isIdentifier() { - return Object.prototype.hasOwnProperty.call(this, "identifier"); - } - - isWrapped() { - return Object.prototype.hasOwnProperty.call(this, "prefix") || Object.prototype.hasOwnProperty.call(this, "postfix"); - } - - isTemplateString() { - return Object.prototype.hasOwnProperty.call(this, "quasis"); - } - - isTruthy() { - return this.truthy; - } - - isFalsy() { - return this.falsy; - } - - asBool() { - if(this.truthy) return true; - else if(this.falsy) return false; - else if(this.isBoolean()) return this.bool; - else if(this.isNull()) return false; - else if(this.isString()) return !!this.string; - else if(this.isNumber()) return !!this.number; - else if(this.isRegExp()) return true; - else if(this.isArray()) return true; - else if(this.isConstArray()) return true; - else if(this.isWrapped()) return this.prefix && this.prefix.asBool() || this.postfix && this.postfix.asBool() ? true : undefined; - else if(this.isTemplateString()) { - if(this.quasis.length === 1) return this.quasis[0].asBool(); - for(let i = 0; i < this.quasis.length; i++) { - if(this.quasis[i].asBool()) return true; - } - // can't tell if string will be empty without executing - } - return undefined; - } - - setString(str) { - if(str === null) - delete this.string; - else - this.string = str; - return this; - } - - setNull() { - this.null = true; - return this; - } - - setNumber(num) { - if(num === null) - delete this.number; - else - this.number = num; - return this; - } - - setBoolean(bool) { - if(bool === null) - delete this.bool; - else - this.bool = bool; - return this; - } - - setRegExp(regExp) { - if(regExp === null) - delete this.regExp; - else - this.regExp = regExp; - return this; - } - - setIdentifier(identifier) { - if(identifier === null) - delete this.identifier; - else - this.identifier = identifier; - return this; - } - - setWrapped(prefix, postfix) { - this.prefix = prefix; - this.postfix = postfix; - return this; - } - - unsetWrapped() { - delete this.prefix; - delete this.postfix; - return this; - } - - setOptions(options) { - if(options === null) - delete this.options; - else - this.options = options; - return this; - } - - setItems(items) { - if(items === null) - delete this.items; - else - this.items = items; - return this; - } - - setArray(array) { - if(array === null) - delete this.array; - else - this.array = array; - return this; - } - - setTemplateString(quasis) { - if(quasis === null) - delete this.quasis; - else - this.quasis = quasis; - return this; - } - - setTruthy() { - this.falsy = false; - this.truthy = true; - return this; - } - - setFalsy() { - this.falsy = true; - this.truthy = false; - return this; - } - - addOptions(options) { - if(!this.options) this.options = []; - options.forEach(item => { - this.options.push(item); - }, this); - return this; - } - - setRange(range) { - this.range = range; - return this; - } - -} - -module.exports = BasicEvaluatedExpression; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ + +"use strict"; + +const TypeUnknown = 0; +const TypeNull = 1; +const TypeString = 2; +const TypeNumber = 3; +const TypeBoolean = 4; +const TypeRegExp = 5; +const TypeConditional = 6; +const TypeArray = 7; +const TypeConstArray = 8; +const TypeIdentifier = 9; +const TypeWrapped = 10; +const TypeTemplateString = 11; + +class BasicEvaluatedExpression { + constructor() { + this.type = TypeUnknown; + this.range = null; + this.falsy = false; + this.truthy = false; + this.bool = null; + this.number = null; + this.regExp = null; + this.string = null; + this.quasis = null; + this.array = null; + this.items = null; + this.options = null; + this.prefix = null; + this.postfix = null; + } + + isNull() { + return this.type === TypeNull; + } + + isString() { + return this.type === TypeString; + } + + isNumber() { + return this.type === TypeNumber; + } + + isBoolean() { + return this.type === TypeBoolean; + } + + isRegExp() { + return this.type === TypeRegExp; + } + + isConditional() { + return this.type === TypeConditional; + } + + isArray() { + return this.type === TypeArray; + } + + isConstArray() { + return this.type === TypeConstArray; + } + + isIdentifier() { + return this.type === TypeIdentifier; + } + + isWrapped() { + return this.type === TypeWrapped; + } + + isTemplateString() { + return this.type === TypeTemplateString; + } + + isTruthy() { + return this.truthy; + } + + isFalsy() { + return this.falsy; + } + + asBool() { + if (this.truthy) return true; + if (this.falsy) return false; + if (this.isBoolean()) return this.bool; + if (this.isNull()) return false; + if (this.isString()) return this.string !== ""; + if (this.isNumber()) return this.number !== 0; + if (this.isRegExp()) return true; + if (this.isArray()) return true; + if (this.isConstArray()) return true; + if (this.isWrapped()) { + return (this.prefix && this.prefix.asBool()) || + (this.postfix && this.postfix.asBool()) + ? true + : undefined; + } + if (this.isTemplateString()) { + for (const quasi of this.quasis) { + if (quasi.asBool()) return true; + } + // can't tell if string will be empty without executing + } + return undefined; + } + + setString(string) { + this.type = TypeString; + this.string = string; + return this; + } + + setNull() { + this.type = TypeNull; + return this; + } + + setNumber(number) { + this.type = TypeNumber; + this.number = number; + return this; + } + + setBoolean(bool) { + this.type = TypeBoolean; + this.bool = bool; + return this; + } + + setRegExp(regExp) { + this.type = TypeRegExp; + this.regExp = regExp; + return this; + } + + setIdentifier(identifier) { + this.type = TypeIdentifier; + this.identifier = identifier; + return this; + } + + setWrapped(prefix, postfix) { + this.type = TypeWrapped; + this.prefix = prefix; + this.postfix = postfix; + return this; + } + + setOptions(options) { + this.type = TypeConditional; + this.options = options; + return this; + } + + addOptions(options) { + if (!this.options) { + this.type = TypeConditional; + this.options = []; + } + for (const item of options) { + this.options.push(item); + } + return this; + } + + setItems(items) { + this.type = TypeArray; + this.items = items; + return this; + } + + setArray(array) { + this.type = TypeConstArray; + this.array = array; + return this; + } + + setTemplateString(quasis) { + this.type = TypeTemplateString; + this.quasis = quasis; + return this; + } + + setTruthy() { + this.falsy = false; + this.truthy = true; + return this; + } + + setFalsy() { + this.falsy = true; + this.truthy = false; + return this; + } + + setRange(range) { + this.range = range; + return this; + } +} + +module.exports = BasicEvaluatedExpression; diff --git a/node_modules/webpack/lib/CachePlugin.js b/node_modules/webpack/lib/CachePlugin.js index 9c19b8140..0d1650be9 100644 --- a/node_modules/webpack/lib/CachePlugin.js +++ b/node_modules/webpack/lib/CachePlugin.js @@ -1,95 +1,102 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const asyncLib = require("async"); - -class CachePlugin { - constructor(cache) { - this.cache = cache || {}; - this.FS_ACCURENCY = 2000; - } - - apply(compiler) { - if(Array.isArray(compiler.compilers)) { - compiler.compilers.forEach((c, idx) => { - c.apply(new CachePlugin(this.cache[idx] = this.cache[idx] || {})); - }); - } else { - const registerCacheToCompiler = (compiler, cache) => { - compiler.plugin("this-compilation", compilation => { - // TODO remove notCacheable for webpack 4 - if(!compilation.notCacheable) { - compilation.cache = cache; - compilation.plugin("child-compiler", (childCompiler, compilerName, compilerIndex) => { - if(cache) { - let childCache; - if(!cache.children) cache.children = {}; - if(!cache.children[compilerName]) cache.children[compilerName] = []; - if(cache.children[compilerName][compilerIndex]) - childCache = cache.children[compilerName][compilerIndex]; - else - cache.children[compilerName].push(childCache = {}); - registerCacheToCompiler(childCompiler, childCache); - } - }); - } else if(this.watching) { - compilation.warnings.push( - new Error(`CachePlugin - Cache cannot be used because of: ${compilation.notCacheable}`) - ); - } - }); - }; - registerCacheToCompiler(compiler, this.cache); - compiler.plugin("watch-run", (compiler, callback) => { - this.watching = true; - callback(); - }); - compiler.plugin("run", (compiler, callback) => { - if(!compiler._lastCompilationFileDependencies) return callback(); - const fs = compiler.inputFileSystem; - const fileTs = compiler.fileTimestamps = {}; - asyncLib.forEach(compiler._lastCompilationFileDependencies, (file, callback) => { - fs.stat(file, (err, stat) => { - if(err) { - if(err.code === "ENOENT") return callback(); - return callback(err); - } - - if(stat.mtime) - this.applyMtime(+stat.mtime); - - fileTs[file] = +stat.mtime || Infinity; - callback(); - }); - }, err => { - if(err) return callback(err); - Object.keys(fileTs).forEach(key => { - fileTs[key] += this.FS_ACCURENCY; - }); - callback(); - }); - }); - compiler.plugin("after-compile", function(compilation, callback) { - compilation.compiler._lastCompilationFileDependencies = compilation.fileDependencies; - compilation.compiler._lastCompilationContextDependencies = compilation.contextDependencies; - callback(); - }); - } - } - - /* istanbul ignore next */ - applyMtime(mtime) { - if(this.FS_ACCURENCY > 1 && mtime % 2 !== 0) - this.FS_ACCURENCY = 1; - else if(this.FS_ACCURENCY > 10 && mtime % 20 !== 0) - this.FS_ACCURENCY = 10; - else if(this.FS_ACCURENCY > 100 && mtime % 200 !== 0) - this.FS_ACCURENCY = 100; - else if(this.FS_ACCURENCY > 1000 && mtime % 2000 !== 0) - this.FS_ACCURENCY = 1000; - } -} -module.exports = CachePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const asyncLib = require("neo-async"); + +class CachePlugin { + constructor(cache) { + this.cache = cache || {}; + this.FS_ACCURACY = 2000; + } + + apply(compiler) { + if (Array.isArray(compiler.compilers)) { + compiler.compilers.forEach((c, idx) => { + new CachePlugin((this.cache[idx] = this.cache[idx] || {})).apply(c); + }); + } else { + const registerCacheToCompiler = (compiler, cache) => { + compiler.hooks.thisCompilation.tap("CachePlugin", compilation => { + compilation.cache = cache; + compilation.hooks.childCompiler.tap( + "CachePlugin", + (childCompiler, compilerName, compilerIndex) => { + if (cache) { + let childCache; + if (!cache.children) { + cache.children = {}; + } + if (!cache.children[compilerName]) { + cache.children[compilerName] = []; + } + if (cache.children[compilerName][compilerIndex]) { + childCache = cache.children[compilerName][compilerIndex]; + } else { + cache.children[compilerName].push((childCache = {})); + } + registerCacheToCompiler(childCompiler, childCache); + } + } + ); + }); + }; + registerCacheToCompiler(compiler, this.cache); + compiler.hooks.watchRun.tap("CachePlugin", () => { + this.watching = true; + }); + compiler.hooks.run.tapAsync("CachePlugin", (compiler, callback) => { + if (!compiler._lastCompilationFileDependencies) { + return callback(); + } + const fs = compiler.inputFileSystem; + const fileTs = (compiler.fileTimestamps = new Map()); + asyncLib.forEach( + compiler._lastCompilationFileDependencies, + (file, callback) => { + fs.stat(file, (err, stat) => { + if (err) { + if (err.code === "ENOENT") return callback(); + return callback(err); + } + + if (stat.mtime) this.applyMtime(+stat.mtime); + + fileTs.set(file, +stat.mtime || Infinity); + + callback(); + }); + }, + err => { + if (err) return callback(err); + + for (const [file, ts] of fileTs) { + fileTs.set(file, ts + this.FS_ACCURACY); + } + + callback(); + } + ); + }); + compiler.hooks.afterCompile.tap("CachePlugin", compilation => { + compilation.compiler._lastCompilationFileDependencies = + compilation.fileDependencies; + compilation.compiler._lastCompilationContextDependencies = + compilation.contextDependencies; + }); + } + } + + /* istanbul ignore next */ + applyMtime(mtime) { + if (this.FS_ACCURACY > 1 && mtime % 2 !== 0) this.FS_ACCURACY = 1; + else if (this.FS_ACCURACY > 10 && mtime % 20 !== 0) this.FS_ACCURACY = 10; + else if (this.FS_ACCURACY > 100 && mtime % 200 !== 0) + this.FS_ACCURACY = 100; + else if (this.FS_ACCURACY > 1000 && mtime % 2000 !== 0) + this.FS_ACCURACY = 1000; + } +} +module.exports = CachePlugin; diff --git a/node_modules/webpack/lib/CaseSensitiveModulesWarning.js b/node_modules/webpack/lib/CaseSensitiveModulesWarning.js index 0cba12ca6..6bfeeca83 100644 --- a/node_modules/webpack/lib/CaseSensitiveModulesWarning.js +++ b/node_modules/webpack/lib/CaseSensitiveModulesWarning.js @@ -1,49 +1,67 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const WebpackError = require("./WebpackError"); - -module.exports = class CaseSensitiveModulesWarning extends WebpackError { - constructor(modules) { - super(); - - this.name = "CaseSensitiveModulesWarning"; - const sortedModules = this._sort(modules); - const modulesList = this._moduleMessages(sortedModules); - this.message = "There are multiple modules with names that only differ in casing.\n" + - "This can lead to unexpected behavior when compiling on a filesystem with other case-semantic.\n" + - `Use equal casing. Compare these module identifiers:\n${modulesList}`; - this.origin = this.module = sortedModules[0]; - - Error.captureStackTrace(this, this.constructor); - } - - _sort(modules) { - return modules.slice().sort((a, b) => { - a = a.identifier(); - b = b.identifier(); - /* istanbul ignore next */ - if(a < b) return -1; - /* istanbul ignore next */ - if(a > b) return 1; - /* istanbul ignore next */ - return 0; - }); - } - - _moduleMessages(modules) { - return modules.map((m) => { - let message = `* ${m.identifier()}`; - const validReasons = m.reasons.filter((reason) => reason.module); - - if(validReasons.length > 0) { - message += `\n Used by ${validReasons.length} module(s), i. e.`; - message += `\n ${validReasons[0].module.identifier()}`; - } - return message; - }).join("\n"); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const WebpackError = require("./WebpackError"); + +/** @typedef {import("./Module")} Module */ + +/** + * @param {Module[]} modules the modules to be sorted + * @returns {Module[]} sorted version of original modules + */ +const sortModules = modules => { + return modules.slice().sort((a, b) => { + const aIdent = a.identifier(); + const bIdent = b.identifier(); + /* istanbul ignore next */ + if (aIdent < bIdent) return -1; + /* istanbul ignore next */ + if (aIdent > bIdent) return 1; + /* istanbul ignore next */ + return 0; + }); +}; + +/** + * @param {Module[]} modules each module from throw + * @returns {string} each message from provided moduels + */ +const createModulesListMessage = modules => { + return modules + .map(m => { + let message = `* ${m.identifier()}`; + const validReasons = m.reasons.filter(reason => reason.module); + + if (validReasons.length > 0) { + message += `\n Used by ${validReasons.length} module(s), i. e.`; + message += `\n ${validReasons[0].module.identifier()}`; + } + return message; + }) + .join("\n"); +}; + +class CaseSensitiveModulesWarning extends WebpackError { + /** + * Creates an instance of CaseSensitiveModulesWarning. + * @param {Module[]} modules modules that were detected + */ + constructor(modules) { + const sortedModules = sortModules(modules); + const modulesList = createModulesListMessage(sortedModules); + super(`There are multiple modules with names that only differ in casing. +This can lead to unexpected behavior when compiling on a filesystem with other case-semantic. +Use equal casing. Compare these module identifiers: +${modulesList}`); + + this.name = "CaseSensitiveModulesWarning"; + this.origin = this.module = sortedModules[0]; + + Error.captureStackTrace(this, this.constructor); + } +} + +module.exports = CaseSensitiveModulesWarning; diff --git a/node_modules/webpack/lib/Chunk.js b/node_modules/webpack/lib/Chunk.js index 48ca2d1a3..f0bb2ea72 100644 --- a/node_modules/webpack/lib/Chunk.js +++ b/node_modules/webpack/lib/Chunk.js @@ -1,479 +1,833 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const util = require("util"); -const compareLocations = require("./compareLocations"); -const SortableSet = require("./util/SortableSet"); -let debugId = 1000; - -const sortById = (a, b) => { - if(a.id < b.id) return -1; - if(b.id < a.id) return 1; - return 0; -}; - -const sortByIdentifier = (a, b) => { - if(a.identifier() > b.identifier()) return 1; - if(a.identifier() < b.identifier()) return -1; - return 0; -}; - -class Chunk { - - constructor(name, module, loc) { - this.id = null; - this.ids = null; - this.debugId = debugId++; - this.name = name; - this._modules = new SortableSet(undefined, sortByIdentifier); - this.entrypoints = []; - this.chunks = []; - this.parents = []; - this.blocks = []; - this.origins = []; - this.files = []; - this.rendered = false; - if(module) { - this.origins.push({ - module, - loc, - name - }); - } - } - - get entry() { - throw new Error("Chunk.entry was removed. Use hasRuntime()"); - } - - set entry(data) { - throw new Error("Chunk.entry was removed. Use hasRuntime()"); - } - - get initial() { - throw new Error("Chunk.initial was removed. Use isInitial()"); - } - - set initial(data) { - throw new Error("Chunk.initial was removed. Use isInitial()"); - } - - hasRuntime() { - if(this.entrypoints.length === 0) return false; - return this.entrypoints[0].chunks[0] === this; - } - - isInitial() { - return this.entrypoints.length > 0; - } - - hasEntryModule() { - return !!this.entryModule; - } - - addToCollection(collection, item) { - if(item === this) { - return false; - } - - if(collection.indexOf(item) > -1) { - return false; - } - - collection.push(item); - return true; - } - - addChunk(chunk) { - return this.addToCollection(this.chunks, chunk); - } - - addParent(parentChunk) { - return this.addToCollection(this.parents, parentChunk); - } - - addModule(module) { - if(!this._modules.has(module)) { - this._modules.add(module); - return true; - } - return false; - } - - addBlock(block) { - return this.addToCollection(this.blocks, block); - } - - removeModule(module) { - if(this._modules.delete(module)) { - module.removeChunk(this); - return true; - } - return false; - } - - removeChunk(chunk) { - const idx = this.chunks.indexOf(chunk); - if(idx >= 0) { - this.chunks.splice(idx, 1); - chunk.removeParent(this); - return true; - } - return false; - } - - removeParent(chunk) { - const idx = this.parents.indexOf(chunk); - if(idx >= 0) { - this.parents.splice(idx, 1); - chunk.removeChunk(this); - return true; - } - return false; - } - - addOrigin(module, loc) { - this.origins.push({ - module, - loc, - name: this.name - }); - } - - setModules(modules) { - this._modules = new SortableSet(modules, sortByIdentifier); - } - - getNumberOfModules() { - return this._modules.size; - } - - get modulesIterable() { - return this._modules; - } - - forEachModule(fn) { - this._modules.forEach(fn); - } - - mapModules(fn) { - return Array.from(this._modules, fn); - } - - compareTo(otherChunk) { - this._modules.sort(); - otherChunk._modules.sort(); - if(this._modules.size > otherChunk._modules.size) return -1; - if(this._modules.size < otherChunk._modules.size) return 1; - const a = this._modules[Symbol.iterator](); - const b = otherChunk._modules[Symbol.iterator](); - while(true) { // eslint-disable-line - const aItem = a.next(); - const bItem = b.next(); - if(aItem.done) return 0; - const aModuleIdentifier = aItem.value.identifier(); - const bModuleIdentifier = bItem.value.identifier(); - if(aModuleIdentifier > bModuleIdentifier) return -1; - if(aModuleIdentifier < bModuleIdentifier) return 1; - } - } - - containsModule(module) { - return this._modules.has(module); - } - - getModules() { - return Array.from(this._modules); - } - - getModulesIdent() { - this._modules.sort(); - let str = ""; - this._modules.forEach(m => { - str += m.identifier() + "#"; - }); - return str; - } - - remove(reason) { - // cleanup modules - // Array.from is used here to create a clone, because removeChunk modifies this._modules - Array.from(this._modules).forEach(module => { - module.removeChunk(this); - }); - - // cleanup parents - this.parents.forEach(parentChunk => { - // remove this chunk from its parents - const idx = parentChunk.chunks.indexOf(this); - if(idx >= 0) { - parentChunk.chunks.splice(idx, 1); - } - - // cleanup "sub chunks" - this.chunks.forEach(chunk => { - /** - * remove this chunk as "intermediary" and connect - * it "sub chunks" and parents directly - */ - // add parent to each "sub chunk" - chunk.addParent(parentChunk); - // add "sub chunk" to parent - parentChunk.addChunk(chunk); - }); - }); - - /** - * we need to iterate again over the chunks - * to remove this from the chunks parents. - * This can not be done in the above loop - * as it is not garuanteed that `this.parents` contains anything. - */ - this.chunks.forEach(chunk => { - // remove this as parent of every "sub chunk" - const idx = chunk.parents.indexOf(this); - if(idx >= 0) { - chunk.parents.splice(idx, 1); - } - }); - - // cleanup blocks - this.blocks.forEach(block => { - const idx = block.chunks.indexOf(this); - if(idx >= 0) { - block.chunks.splice(idx, 1); - if(block.chunks.length === 0) { - block.chunks = null; - block.chunkReason = reason; - } - } - }); - } - - moveModule(module, otherChunk) { - module.removeChunk(this); - module.addChunk(otherChunk); - otherChunk.addModule(module); - module.rewriteChunkInReasons(this, [otherChunk]); - } - - replaceChunk(oldChunk, newChunk) { - const idx = this.chunks.indexOf(oldChunk); - if(idx >= 0) { - this.chunks.splice(idx, 1); - } - if(this !== newChunk && newChunk.addParent(this)) { - this.addChunk(newChunk); - } - } - - replaceParentChunk(oldParentChunk, newParentChunk) { - const idx = this.parents.indexOf(oldParentChunk); - if(idx >= 0) { - this.parents.splice(idx, 1); - } - if(this !== newParentChunk && newParentChunk.addChunk(this)) { - this.addParent(newParentChunk); - } - } - - integrate(otherChunk, reason) { - if(!this.canBeIntegrated(otherChunk)) { - return false; - } - - // Array.from is used here to create a clone, because moveModule modifies otherChunk._modules - const otherChunkModules = Array.from(otherChunk._modules); - otherChunkModules.forEach(module => otherChunk.moveModule(module, this)); - otherChunk._modules.clear(); - - otherChunk.parents.forEach(parentChunk => parentChunk.replaceChunk(otherChunk, this)); - otherChunk.parents.length = 0; - - otherChunk.chunks.forEach(chunk => chunk.replaceParentChunk(otherChunk, this)); - otherChunk.chunks.length = 0; - - otherChunk.blocks.forEach(b => { - b.chunks = b.chunks ? b.chunks.map(c => { - return c === otherChunk ? this : c; - }) : [this]; - b.chunkReason = reason; - this.addBlock(b); - }); - otherChunk.blocks.length = 0; - - otherChunk.origins.forEach(origin => { - this.origins.push(origin); - }); - this.blocks.forEach(b => { - b.chunkReason = reason; - }); - this.origins.forEach(origin => { - if(!origin.reasons) { - origin.reasons = [reason]; - } else if(origin.reasons[0] !== reason) { - origin.reasons.unshift(reason); - } - }); - this.chunks = this.chunks.filter(chunk => { - return chunk !== otherChunk && chunk !== this; - }); - this.parents = this.parents.filter(parentChunk => { - return parentChunk !== otherChunk && parentChunk !== this; - }); - return true; - } - - split(newChunk) { - this.blocks.forEach(block => { - newChunk.blocks.push(block); - block.chunks.push(newChunk); - }); - this.chunks.forEach(chunk => { - newChunk.chunks.push(chunk); - chunk.parents.push(newChunk); - }); - this.parents.forEach(parentChunk => { - parentChunk.chunks.push(newChunk); - newChunk.parents.push(parentChunk); - }); - this.entrypoints.forEach(entrypoint => { - entrypoint.insertChunk(newChunk, this); - }); - } - - isEmpty() { - return this._modules.size === 0; - } - - updateHash(hash) { - hash.update(`${this.id} `); - hash.update(this.ids ? this.ids.join(",") : ""); - hash.update(`${this.name || ""} `); - this._modules.forEach(m => m.updateHash(hash)); - } - - canBeIntegrated(otherChunk) { - if(otherChunk.isInitial()) { - return false; - } - if(this.isInitial()) { - if(otherChunk.parents.length !== 1 || otherChunk.parents[0] !== this) { - return false; - } - } - return true; - } - - addMultiplierAndOverhead(size, options) { - const overhead = typeof options.chunkOverhead === "number" ? options.chunkOverhead : 10000; - const multiplicator = this.isInitial() ? (options.entryChunkMultiplicator || 10) : 1; - - return size * multiplicator + overhead; - } - - modulesSize() { - let count = 0; - for(const module of this._modules) { - count += module.size(); - } - return count; - } - - size(options) { - return this.addMultiplierAndOverhead(this.modulesSize(), options); - } - - integratedSize(otherChunk, options) { - // Chunk if it's possible to integrate this chunk - if(!this.canBeIntegrated(otherChunk)) { - return false; - } - - let integratedModulesSize = this.modulesSize(); - // only count modules that do not exist in this chunk! - for(const otherModule of otherChunk._modules) { - if(!this._modules.has(otherModule)) { - integratedModulesSize += otherModule.size(); - } - } - - return this.addMultiplierAndOverhead(integratedModulesSize, options); - } - - getChunkMaps(includeEntries, realHash) { - const chunksProcessed = []; - const chunkHashMap = {}; - const chunkNameMap = {}; - (function addChunk(chunk) { - if(chunksProcessed.indexOf(chunk) >= 0) return; - chunksProcessed.push(chunk); - if(!chunk.hasRuntime() || includeEntries) { - chunkHashMap[chunk.id] = realHash ? chunk.hash : chunk.renderedHash; - if(chunk.name) - chunkNameMap[chunk.id] = chunk.name; - } - chunk.chunks.forEach(addChunk); - }(this)); - return { - hash: chunkHashMap, - name: chunkNameMap - }; - } - - sortModules(sortByFn) { - this._modules.sortWith(sortByFn || sortById); - } - - sortItems() { - this.sortModules(); - this.origins.sort((a, b) => { - const aIdent = a.module.identifier(); - const bIdent = b.module.identifier(); - if(aIdent < bIdent) return -1; - if(aIdent > bIdent) return 1; - return compareLocations(a.loc, b.loc); - }); - this.origins.forEach(origin => { - if(origin.reasons) - origin.reasons.sort(); - }); - this.parents.sort(sortById); - this.chunks.sort(sortById); - } - - toString() { - return `Chunk[${Array.from(this._modules).join()}]`; - } - - checkConstraints() { - const chunk = this; - chunk.chunks.forEach((child, idx) => { - if(chunk.chunks.indexOf(child) !== idx) - throw new Error(`checkConstraints: duplicate child in chunk ${chunk.debugId} ${child.debugId}`); - if(child.parents.indexOf(chunk) < 0) - throw new Error(`checkConstraints: child missing parent ${chunk.debugId} -> ${child.debugId}`); - }); - chunk.parents.forEach((parentChunk, idx) => { - if(chunk.parents.indexOf(parentChunk) !== idx) - throw new Error(`checkConstraints: duplicate parent in chunk ${chunk.debugId} ${parentChunk.debugId}`); - if(parentChunk.chunks.indexOf(chunk) < 0) - throw new Error(`checkConstraints: parent missing child ${parentChunk.debugId} <- ${chunk.debugId}`); - }); - } -} - -Object.defineProperty(Chunk.prototype, "modules", { - configurable: false, - get: util.deprecate(function() { - return Array.from(this._modules); - }, "Chunk.modules is deprecated. Use Chunk.getNumberOfModules/mapModules/forEachModule/containsModule instead."), - set: util.deprecate(function(value) { - this.setModules(value); - }, "Chunk.modules is deprecated. Use Chunk.addModule/removeModule instead.") -}); - -module.exports = Chunk; +/* +MIT License http://www.opensource.org/licenses/mit-license.php +Author Tobias Koppers @sokra +*/ +"use strict"; + +const util = require("util"); +const SortableSet = require("./util/SortableSet"); +const intersect = require("./util/SetHelpers").intersect; +const GraphHelpers = require("./GraphHelpers"); +const Entrypoint = require("./Entrypoint"); +let debugId = 1000; +const ERR_CHUNK_ENTRY = "Chunk.entry was removed. Use hasRuntime()"; +const ERR_CHUNK_INITIAL = + "Chunk.initial was removed. Use canBeInitial/isOnlyInitial()"; + +/** @typedef {import("./Module")} Module */ +/** @typedef {import("./ChunkGroup")} ChunkGroup */ +/** @typedef {import("./ModuleReason")} ModuleReason */ +/** @typedef {import("webpack-sources").Source} Source */ +/** @typedef {import("./util/createHash").Hash} Hash */ + +/** + * @typedef {Object} WithId an object who has an id property * + * @property {string | number} id the id of the object + */ + +/** + * Compare two Modules based on their ids for sorting + * @param {Module} a module + * @param {Module} b module + * @returns {-1|0|1} sort value + */ + +// TODO use @callback +/** @typedef {(a: Module, b: Module) => -1|0|1} ModuleSortPredicate */ +/** @typedef {(m: Module) => boolean} ModuleFilterPredicate */ +/** @typedef {(c: Chunk) => boolean} ChunkFilterPredicate */ + +const sortModuleById = (a, b) => { + if (a.id < b.id) return -1; + if (b.id < a.id) return 1; + return 0; +}; + +/** + * Compare two ChunkGroups based on their ids for sorting + * @param {ChunkGroup} a chunk group + * @param {ChunkGroup} b chunk group + * @returns {-1|0|1} sort value + */ +const sortChunkGroupById = (a, b) => { + if (a.id < b.id) return -1; + if (b.id < a.id) return 1; + return 0; +}; + +/** + * Compare two Identifiables , based on their ids for sorting + * @param {Module} a first object with ident fn + * @param {Module} b second object with ident fn + * @returns {-1|0|1} The order number of the sort + */ +const sortByIdentifier = (a, b) => { + if (a.identifier() > b.identifier()) return 1; + if (a.identifier() < b.identifier()) return -1; + return 0; +}; + +/** + * @returns {string} a concatenation of module identifiers sorted + * @param {SortableSet} set to pull module identifiers from + */ +const getModulesIdent = set => { + set.sort(); + let str = ""; + for (const m of set) { + str += m.identifier() + "#"; + } + return str; +}; + +/** + * @template T + * @param {SortableSet} set the sortable set to convert to array + * @returns {Array} the array returned from Array.from(set) + */ +const getArray = set => Array.from(set); + +/** + * @param {SortableSet} set the sortable Set to get the count/size of + * @returns {number} the size of the modules + */ +const getModulesSize = set => { + let size = 0; + for (const module of set) { + size += module.size(); + } + return size; +}; + +/** + * A Chunk is a unit of encapsulation for Modules. + * Chunks are "rendered" into bundles that get emitted when the build completes. + */ +class Chunk { + /** + * @param {string=} name of chunk being created, is optional (for subclasses) + */ + constructor(name) { + /** @type {number | null} */ + this.id = null; + /** @type {number[] | null} */ + this.ids = null; + /** @type {number} */ + this.debugId = debugId++; + /** @type {string} */ + this.name = name; + /** @type {boolean} */ + this.preventIntegration = false; + /** @type {Module=} */ + this.entryModule = undefined; + /** @private @type {SortableSet} */ + this._modules = new SortableSet(undefined, sortByIdentifier); + /** @type {string?} */ + this.filenameTemplate = undefined; + /** @private @type {SortableSet} */ + this._groups = new SortableSet(undefined, sortChunkGroupById); + /** @type {string[]} */ + this.files = []; + /** @type {boolean} */ + this.rendered = false; + /** @type {string=} */ + this.hash = undefined; + /** @type {Object} */ + this.contentHash = Object.create(null); + /** @type {string=} */ + this.renderedHash = undefined; + /** @type {string=} */ + this.chunkReason = undefined; + /** @type {boolean} */ + this.extraAsync = false; + this.removedModules = undefined; + } + + /** + * @deprecated Chunk.entry has been deprecated. Please use .hasRuntime() instead + * @returns {never} Throws an error trying to access this property + */ + get entry() { + throw new Error(ERR_CHUNK_ENTRY); + } + + /** + * @deprecated .entry has been deprecated. Please use .hasRuntime() instead + * @param {never} data The data that was attempting to be set + * @returns {never} Throws an error trying to access this property + */ + set entry(data) { + throw new Error(ERR_CHUNK_ENTRY); + } + + /** + * @deprecated Chunk.initial was removed. Use canBeInitial/isOnlyInitial() + * @returns {never} Throws an error trying to access this property + */ + get initial() { + throw new Error(ERR_CHUNK_INITIAL); + } + + /** + * @deprecated Chunk.initial was removed. Use canBeInitial/isOnlyInitial() + * @param {never} data The data attempting to be set + * @returns {never} Throws an error trying to access this property + */ + set initial(data) { + throw new Error(ERR_CHUNK_INITIAL); + } + + /** + * @returns {boolean} whether or not the Chunk will have a runtime + */ + hasRuntime() { + for (const chunkGroup of this._groups) { + // We only need to check the first one + return ( + chunkGroup.isInitial() && + chunkGroup instanceof Entrypoint && + chunkGroup.getRuntimeChunk() === this + ); + } + return false; + } + + /** + * @returns {boolean} whether or not this chunk can be an initial chunk + */ + canBeInitial() { + for (const chunkGroup of this._groups) { + if (chunkGroup.isInitial()) return true; + } + return false; + } + + /** + * @returns {boolean} whether this chunk can only be an initial chunk + */ + isOnlyInitial() { + if (this._groups.size <= 0) return false; + for (const chunkGroup of this._groups) { + if (!chunkGroup.isInitial()) return false; + } + return true; + } + + /** + * @returns {boolean} if this chunk contains the entry module + */ + hasEntryModule() { + return !!this.entryModule; + } + + /** + * @param {Module} module the module that will be added to this chunk. + * @returns {boolean} returns true if the chunk doesn't have the module and it was added + */ + addModule(module) { + if (!this._modules.has(module)) { + this._modules.add(module); + return true; + } + return false; + } + + /** + * @param {Module} module the module that will be removed from this chunk + * @returns {boolean} returns true if chunk exists and is successfully deleted + */ + removeModule(module) { + if (this._modules.delete(module)) { + module.removeChunk(this); + return true; + } + return false; + } + + /** + * @param {Module[]} modules the new modules to be set + * @returns {void} set new modules to this chunk and return nothing + */ + setModules(modules) { + this._modules = new SortableSet(modules, sortByIdentifier); + } + + /** + * @returns {number} the amount of modules in chunk + */ + getNumberOfModules() { + return this._modules.size; + } + + /** + * @returns {SortableSet} return the modules SortableSet for this chunk + */ + get modulesIterable() { + return this._modules; + } + + /** + * @param {ChunkGroup} chunkGroup the chunkGroup the chunk is being added + * @returns {boolean} returns true if chunk is not apart of chunkGroup and is added successfully + */ + addGroup(chunkGroup) { + if (this._groups.has(chunkGroup)) return false; + this._groups.add(chunkGroup); + return true; + } + + /** + * @param {ChunkGroup} chunkGroup the chunkGroup the chunk is being removed from + * @returns {boolean} returns true if chunk does exist in chunkGroup and is removed + */ + removeGroup(chunkGroup) { + if (!this._groups.has(chunkGroup)) return false; + this._groups.delete(chunkGroup); + return true; + } + + /** + * @param {ChunkGroup} chunkGroup the chunkGroup to check + * @returns {boolean} returns true if chunk has chunkGroup reference and exists in chunkGroup + */ + isInGroup(chunkGroup) { + return this._groups.has(chunkGroup); + } + + /** + * @returns {number} the amount of groups said chunk is in + */ + getNumberOfGroups() { + return this._groups.size; + } + + /** + * @returns {SortableSet} the chunkGroups that said chunk is referenced in + */ + get groupsIterable() { + return this._groups; + } + + /** + * @param {Chunk} otherChunk the chunk to compare itself with + * @returns {-1|0|1} this is a comparitor function like sort and returns -1, 0, or 1 based on sort order + */ + compareTo(otherChunk) { + if (this._modules.size > otherChunk._modules.size) return -1; + if (this._modules.size < otherChunk._modules.size) return 1; + this._modules.sort(); + otherChunk._modules.sort(); + const a = this._modules[Symbol.iterator](); + const b = otherChunk._modules[Symbol.iterator](); + // eslint-disable-next-line no-constant-condition + while (true) { + const aItem = a.next(); + if (aItem.done) return 0; + const bItem = b.next(); + const aModuleIdentifier = aItem.value.identifier(); + const bModuleIdentifier = bItem.value.identifier(); + if (aModuleIdentifier < bModuleIdentifier) return -1; + if (aModuleIdentifier > bModuleIdentifier) return 1; + } + } + + /** + * @param {Module} module Module to check + * @returns {boolean} returns true if module does exist in this chunk + */ + containsModule(module) { + return this._modules.has(module); + } + + getModules() { + return this._modules.getFromCache(getArray); + } + + getModulesIdent() { + return this._modules.getFromUnorderedCache(getModulesIdent); + } + + remove() { + // cleanup modules + // Array.from is used here to create a clone, because removeChunk modifies this._modules + for (const module of Array.from(this._modules)) { + module.removeChunk(this); + } + for (const chunkGroup of this._groups) { + chunkGroup.removeChunk(this); + } + } + + /** + * + * @param {Module} module module to move + * @param {Chunk} otherChunk other chunk to move it to + * @returns {void} + */ + moveModule(module, otherChunk) { + GraphHelpers.disconnectChunkAndModule(this, module); + GraphHelpers.connectChunkAndModule(otherChunk, module); + module.rewriteChunkInReasons(this, [otherChunk]); + } + + /** + * + * @param {Chunk} otherChunk the chunk to integrate with + * @param {ModuleReason} reason reason why the module is being integrated + * @returns {boolean} returns true or false if integration succeeds or fails + */ + integrate(otherChunk, reason) { + if (!this.canBeIntegrated(otherChunk)) { + return false; + } + + // Array.from is used here to create a clone, because moveModule modifies otherChunk._modules + for (const module of Array.from(otherChunk._modules)) { + otherChunk.moveModule(module, this); + } + otherChunk._modules.clear(); + + for (const chunkGroup of otherChunk._groups) { + chunkGroup.replaceChunk(otherChunk, this); + this.addGroup(chunkGroup); + } + otherChunk._groups.clear(); + + if (this.name && otherChunk.name) { + if (this.name.length !== otherChunk.name.length) { + this.name = + this.name.length < otherChunk.name.length + ? this.name + : otherChunk.name; + } else { + this.name = this.name < otherChunk.name ? this.name : otherChunk.name; + } + } + + return true; + } + + /** + * @param {Chunk} newChunk the new chunk that will be split out of, and then chunk raphi twil= + * @returns {void} + */ + split(newChunk) { + for (const chunkGroup of this._groups) { + chunkGroup.insertChunk(newChunk, this); + newChunk.addGroup(chunkGroup); + } + } + + isEmpty() { + return this._modules.size === 0; + } + + updateHash(hash) { + hash.update(`${this.id} `); + hash.update(this.ids ? this.ids.join(",") : ""); + hash.update(`${this.name || ""} `); + for (const m of this._modules) { + hash.update(m.hash); + } + } + + canBeIntegrated(otherChunk) { + const isAvailable = (a, b) => { + const queue = new Set(b.groupsIterable); + for (const chunkGroup of queue) { + if (a.isInGroup(chunkGroup)) continue; + if (chunkGroup.isInitial()) return false; + for (const parent of chunkGroup.parentsIterable) { + queue.add(parent); + } + } + return true; + }; + + if (this.preventIntegration || otherChunk.preventIntegration) { + return false; + } + + if (this.hasRuntime() !== otherChunk.hasRuntime()) { + if (this.hasRuntime()) { + return isAvailable(this, otherChunk); + } else if (otherChunk.hasRuntime()) { + return isAvailable(otherChunk, this); + } else { + return false; + } + } + + if (this.hasEntryModule() || otherChunk.hasEntryModule()) { + return false; + } + + return true; + } + + /** + * + * @param {number} size the size + * @param {Object} options the options passed in + * @returns {number} the multiplier returned + */ + addMultiplierAndOverhead(size, options) { + const overhead = + typeof options.chunkOverhead === "number" ? options.chunkOverhead : 10000; + const multiplicator = this.canBeInitial() + ? options.entryChunkMultiplicator || 10 + : 1; + + return size * multiplicator + overhead; + } + + /** + * @returns {number} the size of all modules + */ + modulesSize() { + return this._modules.getFromUnorderedCache(getModulesSize); + } + + /** + * @param {Object} options the size display options + * @returns {number} the chunk size + */ + size(options) { + return this.addMultiplierAndOverhead(this.modulesSize(), options); + } + + /** + * @param {Chunk} otherChunk the other chunk + * @param {TODO} options the options for this function + * @returns {number | false} the size, or false if it can't be integrated + */ + integratedSize(otherChunk, options) { + // Chunk if it's possible to integrate this chunk + if (!this.canBeIntegrated(otherChunk)) { + return false; + } + + let integratedModulesSize = this.modulesSize(); + // only count modules that do not exist in this chunk! + for (const otherModule of otherChunk._modules) { + if (!this._modules.has(otherModule)) { + integratedModulesSize += otherModule.size(); + } + } + + return this.addMultiplierAndOverhead(integratedModulesSize, options); + } + + /** + * @param {function(Module, Module): -1|0|1=} sortByFn a predicate function used to sort modules + * @returns {void} + */ + sortModules(sortByFn) { + this._modules.sortWith(sortByFn || sortModuleById); + } + + sortItems() { + this.sortModules(); + } + + /** + * @returns {Set} a set of all the async chunks + */ + getAllAsyncChunks() { + const queue = new Set(); + const chunks = new Set(); + + const initialChunks = intersect( + Array.from(this.groupsIterable, g => new Set(g.chunks)) + ); + + for (const chunkGroup of this.groupsIterable) { + for (const child of chunkGroup.childrenIterable) { + queue.add(child); + } + } + + for (const chunkGroup of queue) { + for (const chunk of chunkGroup.chunks) { + if (!initialChunks.has(chunk)) { + chunks.add(chunk); + } + } + for (const child of chunkGroup.childrenIterable) { + queue.add(child); + } + } + + return chunks; + } + + /** + * @typedef {Object} ChunkMaps + * @property {Record} hash + * @property {Record>} contentHash + * @property {Record} name + */ + + /** + * @param {boolean} realHash should the full hash or the rendered hash be used + * @returns {ChunkMaps} the chunk map information + */ + getChunkMaps(realHash) { + /** @type {Record} */ + const chunkHashMap = Object.create(null); + /** @type {Record>} */ + const chunkContentHashMap = Object.create(null); + /** @type {Record} */ + const chunkNameMap = Object.create(null); + + for (const chunk of this.getAllAsyncChunks()) { + chunkHashMap[chunk.id] = realHash ? chunk.hash : chunk.renderedHash; + for (const key of Object.keys(chunk.contentHash)) { + if (!chunkContentHashMap[key]) { + chunkContentHashMap[key] = Object.create(null); + } + chunkContentHashMap[key][chunk.id] = chunk.contentHash[key]; + } + if (chunk.name) { + chunkNameMap[chunk.id] = chunk.name; + } + } + + return { + hash: chunkHashMap, + contentHash: chunkContentHashMap, + name: chunkNameMap + }; + } + + /** + * @returns {Record[]>} a record object of names to lists of child ids(?) + */ + getChildIdsByOrders() { + const lists = new Map(); + for (const group of this.groupsIterable) { + if (group.chunks[group.chunks.length - 1] === this) { + for (const childGroup of group.childrenIterable) { + // TODO webpack 5 remove this check for options + if (typeof childGroup.options === "object") { + for (const key of Object.keys(childGroup.options)) { + if (key.endsWith("Order")) { + const name = key.substr(0, key.length - "Order".length); + let list = lists.get(name); + if (list === undefined) lists.set(name, (list = [])); + list.push({ + order: childGroup.options[key], + group: childGroup + }); + } + } + } + } + } + } + const result = Object.create(null); + for (const [name, list] of lists) { + list.sort((a, b) => { + const cmp = b.order - a.order; + if (cmp !== 0) return cmp; + // TODO webpack 5 remove this check of compareTo + if (a.group.compareTo) { + return a.group.compareTo(b.group); + } + return 0; + }); + result[name] = Array.from( + list.reduce((set, item) => { + for (const chunk of item.group.chunks) { + set.add(chunk.id); + } + return set; + }, new Set()) + ); + } + return result; + } + + getChildIdsByOrdersMap(includeDirectChildren) { + const chunkMaps = Object.create(null); + + const addChildIdsByOrdersToMap = chunk => { + const data = chunk.getChildIdsByOrders(); + for (const key of Object.keys(data)) { + let chunkMap = chunkMaps[key]; + if (chunkMap === undefined) { + chunkMaps[key] = chunkMap = Object.create(null); + } + chunkMap[chunk.id] = data[key]; + } + }; + + if (includeDirectChildren) { + addChildIdsByOrdersToMap(this); + } + + for (const chunk of this.getAllAsyncChunks()) { + addChildIdsByOrdersToMap(chunk); + } + + return chunkMaps; + } + + /** + * @typedef {Object} ChunkModuleMaps + * @property {Record} id + * @property {Record} hash + */ + + /** + * @param {ModuleFilterPredicate} filterFn function used to filter modules + * @returns {ChunkModuleMaps} module map information + */ + getChunkModuleMaps(filterFn) { + /** @type {Record} */ + const chunkModuleIdMap = Object.create(null); + /** @type {Record} */ + const chunkModuleHashMap = Object.create(null); + + for (const chunk of this.getAllAsyncChunks()) { + /** @type {(string|number)[]} */ + let array; + for (const module of chunk.modulesIterable) { + if (filterFn(module)) { + if (array === undefined) { + array = []; + chunkModuleIdMap[chunk.id] = array; + } + array.push(module.id); + chunkModuleHashMap[module.id] = module.renderedHash; + } + } + if (array !== undefined) { + array.sort(); + } + } + + return { + id: chunkModuleIdMap, + hash: chunkModuleHashMap + }; + } + + /** + * + * @param {function(Module): boolean} filterFn predicate function used to filter modules + * @param {function(Chunk): boolean} filterChunkFn predicate function used to filter chunks + * @returns {boolean} return true if module exists in graph + */ + hasModuleInGraph(filterFn, filterChunkFn) { + const queue = new Set(this.groupsIterable); + const chunksProcessed = new Set(); + + for (const chunkGroup of queue) { + for (const chunk of chunkGroup.chunks) { + if (!chunksProcessed.has(chunk)) { + chunksProcessed.add(chunk); + if (!filterChunkFn || filterChunkFn(chunk)) { + for (const module of chunk.modulesIterable) { + if (filterFn(module)) { + return true; + } + } + } + } + } + for (const child of chunkGroup.childrenIterable) { + queue.add(child); + } + } + return false; + } + + toString() { + return `Chunk[${Array.from(this._modules).join()}]`; + } +} + +// TODO remove in webpack 5 +Object.defineProperty(Chunk.prototype, "forEachModule", { + configurable: false, + value: util.deprecate( + /** + * @deprecated + * @this {Chunk} + * @typedef {function(any, any, Set): void} ForEachModuleCallback + * @param {ForEachModuleCallback} fn Callback function + * @returns {void} + */ + function(fn) { + this._modules.forEach(fn); + }, + "Chunk.forEachModule: Use for(const module of chunk.modulesIterable) instead" + ) +}); + +// TODO remove in webpack 5 +Object.defineProperty(Chunk.prototype, "mapModules", { + configurable: false, + value: util.deprecate( + /** + * @deprecated + * @this {Chunk} + * @typedef {function(any, number): any} MapModulesCallback + * @param {MapModulesCallback} fn Callback function + * @returns {TODO[]} result of mapped modules + */ + function(fn) { + return Array.from(this._modules, fn); + }, + "Chunk.mapModules: Use Array.from(chunk.modulesIterable, fn) instead" + ) +}); + +// TODO remove in webpack 5 +Object.defineProperty(Chunk.prototype, "chunks", { + configurable: false, + get() { + throw new Error("Chunk.chunks: Use ChunkGroup.getChildren() instead"); + }, + set() { + throw new Error("Chunk.chunks: Use ChunkGroup.add/removeChild() instead"); + } +}); + +// TODO remove in webpack 5 +Object.defineProperty(Chunk.prototype, "parents", { + configurable: false, + get() { + throw new Error("Chunk.parents: Use ChunkGroup.getParents() instead"); + }, + set() { + throw new Error("Chunk.parents: Use ChunkGroup.add/removeParent() instead"); + } +}); + +// TODO remove in webpack 5 +Object.defineProperty(Chunk.prototype, "blocks", { + configurable: false, + get() { + throw new Error("Chunk.blocks: Use ChunkGroup.getBlocks() instead"); + }, + set() { + throw new Error("Chunk.blocks: Use ChunkGroup.add/removeBlock() instead"); + } +}); + +// TODO remove in webpack 5 +Object.defineProperty(Chunk.prototype, "entrypoints", { + configurable: false, + get() { + throw new Error( + "Chunk.entrypoints: Use Chunks.groupsIterable and filter by instanceof Entrypoint instead" + ); + }, + set() { + throw new Error("Chunk.entrypoints: Use Chunks.addGroup instead"); + } +}); + +module.exports = Chunk; diff --git a/node_modules/webpack/lib/ChunkRenderError.js b/node_modules/webpack/lib/ChunkRenderError.js index 578104b53..0d0eb2cbc 100644 --- a/node_modules/webpack/lib/ChunkRenderError.js +++ b/node_modules/webpack/lib/ChunkRenderError.js @@ -1,24 +1,32 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const WebpackError = require("./WebpackError"); - -class ChunkRenderError extends WebpackError { - constructor(chunk, file, error) { - super(); - - this.name = "ChunkRenderError"; - this.error = error; - this.message = error.message; - this.details = error.stack; - this.file = file; - this.chunk = chunk; - - Error.captureStackTrace(this, this.constructor); - } -} - -module.exports = ChunkRenderError; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const WebpackError = require("./WebpackError"); + +/** @typedef {import("./Chunk")} Chunk */ + +class ChunkRenderError extends WebpackError { + /** + * Create a new ChunkRenderError + * @param {Chunk} chunk A chunk + * @param {string} file Related file + * @param {Error} error Original error + */ + constructor(chunk, file, error) { + super(); + + this.name = "ChunkRenderError"; + this.error = error; + this.message = error.message; + this.details = error.stack; + this.file = file; + this.chunk = chunk; + + Error.captureStackTrace(this, this.constructor); + } +} + +module.exports = ChunkRenderError; diff --git a/node_modules/webpack/lib/ChunkTemplate.js b/node_modules/webpack/lib/ChunkTemplate.js index 6bcb8a883..65861af49 100644 --- a/node_modules/webpack/lib/ChunkTemplate.js +++ b/node_modules/webpack/lib/ChunkTemplate.js @@ -1,36 +1,87 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ConcatSource = require("webpack-sources").ConcatSource; -const Template = require("./Template"); - -module.exports = class ChunkTemplate extends Template { - constructor(outputOptions) { - super(outputOptions); - } - - render(chunk, moduleTemplate, dependencyTemplates) { - const moduleSources = this.renderChunkModules(chunk, moduleTemplate, dependencyTemplates); - const core = this.applyPluginsWaterfall("modules", moduleSources, chunk, moduleTemplate, dependencyTemplates); - let source = this.applyPluginsWaterfall("render", core, chunk, moduleTemplate, dependencyTemplates); - if(chunk.hasEntryModule()) { - source = this.applyPluginsWaterfall("render-with-entry", source, chunk); - } - chunk.rendered = true; - return new ConcatSource(source, ";"); - } - - updateHash(hash) { - hash.update("ChunkTemplate"); - hash.update("2"); - this.applyPlugins("hash", hash); - } - - updateHashForChunk(hash, chunk) { - this.updateHash(hash); - this.applyPlugins("hash-for-chunk", hash, chunk); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const { Tapable, SyncWaterfallHook, SyncHook } = require("tapable"); + +/** @typedef {import("./ModuleTemplate")} ModuleTemplate */ +/** @typedef {import("./Chunk")} Chunk */ +/** @typedef {import("./Module")} Module} */ +/** @typedef {import("./Dependency").DependencyTemplate} DependencyTemplate} */ +/** @typedef {import("./util/createHash").Hash} Hash} */ + +/** + * @typedef {Object} RenderManifestOptions + * @property {Chunk} chunk the chunk used to render + * @property {string} hash + * @property {string} fullHash + * @property {TODO} outputOptions + * @property {{javascript: ModuleTemplate, webassembly: ModuleTemplate}} moduleTemplates + * @property {Map} dependencyTemplates + */ + +module.exports = class ChunkTemplate extends Tapable { + constructor(outputOptions) { + super(); + this.outputOptions = outputOptions || {}; + this.hooks = { + /** @type {SyncWaterfallHook} */ + renderManifest: new SyncWaterfallHook(["result", "options"]), + modules: new SyncWaterfallHook([ + "source", + "chunk", + "moduleTemplate", + "dependencyTemplates" + ]), + render: new SyncWaterfallHook([ + "source", + "chunk", + "moduleTemplate", + "dependencyTemplates" + ]), + renderWithEntry: new SyncWaterfallHook(["source", "chunk"]), + hash: new SyncHook(["hash"]), + hashForChunk: new SyncHook(["hash", "chunk"]) + }; + } + + /** + * + * @param {RenderManifestOptions} options render manifest options + * @returns {TODO[]} returns render manifest + */ + getRenderManifest(options) { + const result = []; + + this.hooks.renderManifest.call(result, options); + + return result; + } + + /** + * Updates hash with information from this template + * @param {Hash} hash the hash to update + * @returns {void} + */ + updateHash(hash) { + hash.update("ChunkTemplate"); + hash.update("2"); + this.hooks.hash.call(hash); + } + + /** + * TODO webpack 5: remove moduleTemplate and dependencyTemplates + * Updates hash with chunk-specific information from this template + * @param {Hash} hash the hash to update + * @param {Chunk} chunk the chunk + * @param {ModuleTemplate} moduleTemplate ModuleTemplate instance for render + * @param {Map} dependencyTemplates dependency templates + * @returns {void} + */ + updateHashForChunk(hash, chunk, moduleTemplate, dependencyTemplates) { + this.updateHash(hash); + this.hooks.hashForChunk.call(hash, chunk); + } +}; diff --git a/node_modules/webpack/lib/CompatibilityPlugin.js b/node_modules/webpack/lib/CompatibilityPlugin.js index 847611e9f..1544d6c82 100644 --- a/node_modules/webpack/lib/CompatibilityPlugin.js +++ b/node_modules/webpack/lib/CompatibilityPlugin.js @@ -1,57 +1,70 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ConstDependency = require("./dependencies/ConstDependency"); - -const NullFactory = require("./NullFactory"); - -const jsonLoaderPath = require.resolve("json-loader"); -const matchJson = /\.json$/i; - -class CompatibilityPlugin { - - apply(compiler) { - compiler.plugin("compilation", (compilation, params) => { - compilation.dependencyFactories.set(ConstDependency, new NullFactory()); - compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template()); - - params.normalModuleFactory.plugin("parser", (parser, parserOptions) => { - - if(typeof parserOptions.browserify !== "undefined" && !parserOptions.browserify) - return; - - parser.plugin("call require", (expr) => { - // support for browserify style require delegator: "require(o, !0)" - if(expr.arguments.length !== 2) return; - const second = parser.evaluateExpression(expr.arguments[1]); - if(!second.isBoolean()) return; - if(second.asBool() !== true) return; - const dep = new ConstDependency("require", expr.callee.range); - dep.loc = expr.loc; - if(parser.state.current.dependencies.length > 1) { - const last = parser.state.current.dependencies[parser.state.current.dependencies.length - 1]; - if(last.critical && last.request === "." && last.userRequest === "." && last.recursive) - parser.state.current.dependencies.pop(); - } - parser.state.current.addDependency(dep); - return true; - }); - }); - - params.normalModuleFactory.plugin("after-resolve", (data, done) => { - // if this is a json file and there are no loaders active, we use the json-loader in order to avoid parse errors - // @see https://github.com/webpack/webpack/issues/3363 - if(matchJson.test(data.request) && data.loaders.length === 0) { - data.loaders.push({ - loader: jsonLoaderPath - }); - } - done(null, data); - }); - }); - } -} -module.exports = CompatibilityPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const ConstDependency = require("./dependencies/ConstDependency"); + +const NullFactory = require("./NullFactory"); + +/** @typedef {import("./Compiler")} Compiler */ + +class CompatibilityPlugin { + /** + * Apply the plugin + * @param {Compiler} compiler Webpack Compiler + * @returns {void} + */ + apply(compiler) { + compiler.hooks.compilation.tap( + "CompatibilityPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set(ConstDependency, new NullFactory()); + compilation.dependencyTemplates.set( + ConstDependency, + new ConstDependency.Template() + ); + + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("CompatibilityPlugin", (parser, parserOptions) => { + if ( + parserOptions.browserify !== undefined && + !parserOptions.browserify + ) + return; + + parser.hooks.call + .for("require") + .tap("CompatibilityPlugin", expr => { + // support for browserify style require delegator: "require(o, !0)" + if (expr.arguments.length !== 2) return; + const second = parser.evaluateExpression(expr.arguments[1]); + if (!second.isBoolean()) return; + if (second.asBool() !== true) return; + const dep = new ConstDependency("require", expr.callee.range); + dep.loc = expr.loc; + if (parser.state.current.dependencies.length > 1) { + const last = + parser.state.current.dependencies[ + parser.state.current.dependencies.length - 1 + ]; + if ( + last.critical && + last.options && + last.options.request === "." && + last.userRequest === "." && + last.options.recursive + ) + parser.state.current.dependencies.pop(); + } + parser.state.current.addDependency(dep); + return true; + }); + }); + } + ); + } +} +module.exports = CompatibilityPlugin; diff --git a/node_modules/webpack/lib/Compilation.js b/node_modules/webpack/lib/Compilation.js index 05f5be60d..a420da696 100644 --- a/node_modules/webpack/lib/Compilation.js +++ b/node_modules/webpack/lib/Compilation.js @@ -1,1455 +1,2513 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra - */ -"use strict"; - -const asyncLib = require("async"); -const crypto = require("crypto"); -const Tapable = require("tapable"); -const EntryModuleNotFoundError = require("./EntryModuleNotFoundError"); -const ModuleNotFoundError = require("./ModuleNotFoundError"); -const ModuleDependencyWarning = require("./ModuleDependencyWarning"); -const ModuleDependencyError = require("./ModuleDependencyError"); -const Module = require("./Module"); -const Chunk = require("./Chunk"); -const Entrypoint = require("./Entrypoint"); -const MainTemplate = require("./MainTemplate"); -const ChunkTemplate = require("./ChunkTemplate"); -const HotUpdateChunkTemplate = require("./HotUpdateChunkTemplate"); -const ModuleTemplate = require("./ModuleTemplate"); -const Dependency = require("./Dependency"); -const ChunkRenderError = require("./ChunkRenderError"); -const AsyncDependencyToInitialChunkWarning = require("./AsyncDependencyToInitialChunkWarning"); -const CachedSource = require("webpack-sources").CachedSource; -const Stats = require("./Stats"); -const Semaphore = require("./util/Semaphore"); -const Queue = require("./util/Queue"); - -function byId(a, b) { - if(a.id < b.id) return -1; - if(a.id > b.id) return 1; - return 0; -} - -function iterationBlockVariable(variables, fn) { - for(let indexVariable = 0; indexVariable < variables.length; indexVariable++) { - let varDep = variables[indexVariable].dependencies; - for(let indexVDep = 0; indexVDep < varDep.length; indexVDep++) { - fn(varDep[indexVDep]); - } - } -} - -function iterationOfArrayCallback(arr, fn) { - for(let index = 0; index < arr.length; index++) { - fn(arr[index]); - } -} - -class Compilation extends Tapable { - constructor(compiler) { - super(); - this.compiler = compiler; - this.resolvers = compiler.resolvers; - this.inputFileSystem = compiler.inputFileSystem; - - const options = this.options = compiler.options; - this.outputOptions = options && options.output; - this.bail = options && options.bail; - this.profile = options && options.profile; - this.performance = options && options.performance; - - this.mainTemplate = new MainTemplate(this.outputOptions); - this.chunkTemplate = new ChunkTemplate(this.outputOptions); - this.hotUpdateChunkTemplate = new HotUpdateChunkTemplate(this.outputOptions); - this.moduleTemplate = new ModuleTemplate(this.outputOptions); - - this.semaphore = new Semaphore(options.parallelism || 100); - - this.entries = []; - this.preparedChunks = []; - this.entrypoints = {}; - this.chunks = []; - this.namedChunks = {}; - this.modules = []; - this._modules = {}; - this.cache = null; - this.records = null; - this.nextFreeModuleIndex = undefined; - this.nextFreeModuleIndex2 = undefined; - this.additionalChunkAssets = []; - this.assets = {}; - this.errors = []; - this.warnings = []; - this.children = []; - this.dependencyFactories = new Map(); - this.dependencyTemplates = new Map(); - this.dependencyTemplates.set("hash", ""); - this.childrenCounters = {}; - } - - getStats() { - return new Stats(this); - } - - templatesPlugin(name, fn) { - this.mainTemplate.plugin(name, fn); - this.chunkTemplate.plugin(name, fn); - } - - addModule(module, cacheGroup) { - const identifier = module.identifier(); - if(this._modules[identifier]) { - return false; - } - const cacheName = (cacheGroup || "m") + identifier; - if(this.cache && this.cache[cacheName]) { - const cacheModule = this.cache[cacheName]; - - let rebuild = true; - if(!cacheModule.error && cacheModule.cacheable && this.fileTimestamps && this.contextTimestamps) { - rebuild = cacheModule.needRebuild(this.fileTimestamps, this.contextTimestamps); - } - - if(!rebuild) { - cacheModule.disconnect(); - this._modules[identifier] = cacheModule; - this.modules.push(cacheModule); - cacheModule.errors.forEach(err => this.errors.push(err), this); - cacheModule.warnings.forEach(err => this.warnings.push(err), this); - return cacheModule; - } - } - module.unbuild(); - this._modules[identifier] = module; - if(this.cache) { - this.cache[cacheName] = module; - } - this.modules.push(module); - return true; - } - - getModule(module) { - const identifier = module.identifier(); - return this._modules[identifier]; - } - - findModule(identifier) { - return this._modules[identifier]; - } - - buildModule(module, optional, origin, dependencies, thisCallback) { - this.applyPlugins1("build-module", module); - if(module.building) return module.building.push(thisCallback); - const building = module.building = [thisCallback]; - - function callback(err) { - module.building = undefined; - building.forEach(cb => cb(err)); - } - module.build(this.options, this, this.resolvers.normal, this.inputFileSystem, (error) => { - const errors = module.errors; - for(let indexError = 0; indexError < errors.length; indexError++) { - const err = errors[indexError]; - err.origin = origin; - err.dependencies = dependencies; - if(optional) - this.warnings.push(err); - else - this.errors.push(err); - } - - const warnings = module.warnings; - for(let indexWarning = 0; indexWarning < warnings.length; indexWarning++) { - const war = warnings[indexWarning]; - war.origin = origin; - war.dependencies = dependencies; - this.warnings.push(war); - } - module.dependencies.sort(Dependency.compare); - if(error) { - this.applyPlugins2("failed-module", module, error); - return callback(error); - } - this.applyPlugins1("succeed-module", module); - return callback(); - }); - } - - processModuleDependencies(module, callback) { - const dependencies = []; - - function addDependency(dep) { - for(let i = 0; i < dependencies.length; i++) { - if(dep.isEqualResource(dependencies[i][0])) { - return dependencies[i].push(dep); - } - } - dependencies.push([dep]); - } - - function addDependenciesBlock(block) { - if(block.dependencies) { - iterationOfArrayCallback(block.dependencies, addDependency); - } - if(block.blocks) { - iterationOfArrayCallback(block.blocks, addDependenciesBlock); - } - if(block.variables) { - iterationBlockVariable(block.variables, addDependency); - } - } - addDependenciesBlock(module); - this.addModuleDependencies(module, dependencies, this.bail, null, true, callback); - } - - addModuleDependencies(module, dependencies, bail, cacheGroup, recursive, callback) { - let _this = this; - const start = _this.profile && Date.now(); - - const factories = []; - for(let i = 0; i < dependencies.length; i++) { - const factory = _this.dependencyFactories.get(dependencies[i][0].constructor); - if(!factory) { - return callback(new Error(`No module factory available for dependency type: ${dependencies[i][0].constructor.name}`)); - } - factories[i] = [factory, dependencies[i]]; - } - asyncLib.forEach(factories, function iteratorFactory(item, callback) { - const dependencies = item[1]; - - const errorAndCallback = function errorAndCallback(err) { - err.origin = module; - _this.errors.push(err); - if(bail) { - callback(err); - } else { - callback(); - } - }; - const warningAndCallback = function warningAndCallback(err) { - err.origin = module; - _this.warnings.push(err); - callback(); - }; - - const semaphore = _this.semaphore; - semaphore.acquire(() => { - if(_this === null) return semaphore.release(); - - const factory = item[0]; - factory.create({ - contextInfo: { - issuer: module.nameForCondition && module.nameForCondition(), - compiler: _this.compiler.name - }, - context: module.context, - dependencies: dependencies - }, function factoryCallback(err, dependentModule) { - if(_this === null) return semaphore.release(); - - let afterFactory; - - function isOptional() { - return dependencies.filter(d => !d.optional).length === 0; - } - - function errorOrWarningAndCallback(err) { - if(isOptional()) { - return warningAndCallback(err); - } else { - return errorAndCallback(err); - } - } - - function iterationDependencies(depend) { - for(let index = 0; index < depend.length; index++) { - const dep = depend[index]; - dep.module = dependentModule; - dependentModule.addReason(module, dep); - } - } - - if(err) { - semaphore.release(); - return errorOrWarningAndCallback(new ModuleNotFoundError(module, err, dependencies)); - } - if(!dependentModule) { - semaphore.release(); - return process.nextTick(callback); - } - if(_this.profile) { - if(!dependentModule.profile) { - dependentModule.profile = {}; - } - afterFactory = Date.now(); - dependentModule.profile.factory = afterFactory - start; - } - - dependentModule.issuer = module; - const newModule = _this.addModule(dependentModule, cacheGroup); - - if(!newModule) { // from cache - dependentModule = _this.getModule(dependentModule); - - if(dependentModule.optional) { - dependentModule.optional = isOptional(); - } - - iterationDependencies(dependencies); - - if(_this.profile) { - if(!module.profile) { - module.profile = {}; - } - const time = Date.now() - start; - if(!module.profile.dependencies || time > module.profile.dependencies) { - module.profile.dependencies = time; - } - } - - semaphore.release(); - return process.nextTick(callback); - } - - if(newModule instanceof Module) { - if(_this.profile) { - newModule.profile = dependentModule.profile; - } - - newModule.optional = isOptional(); - newModule.issuer = dependentModule.issuer; - dependentModule = newModule; - - iterationDependencies(dependencies); - - if(_this.profile) { - const afterBuilding = Date.now(); - module.profile.building = afterBuilding - afterFactory; - } - - semaphore.release(); - if(recursive) { - return process.nextTick(_this.processModuleDependencies.bind(_this, dependentModule, callback)); - } else { - return process.nextTick(callback); - } - } - - dependentModule.optional = isOptional(); - - iterationDependencies(dependencies); - - _this.buildModule(dependentModule, isOptional(), module, dependencies, err => { - if(_this === null) return semaphore.release(); - - if(err) { - semaphore.release(); - return errorOrWarningAndCallback(err); - } - - if(_this.profile) { - const afterBuilding = Date.now(); - dependentModule.profile.building = afterBuilding - afterFactory; - } - - semaphore.release(); - if(recursive) { - _this.processModuleDependencies(dependentModule, callback); - } else { - return callback(); - } - }); - - }); - }); - }, function finalCallbackAddModuleDependencies(err) { - // In V8, the Error objects keep a reference to the functions on the stack. These warnings & - // errors are created inside closures that keep a reference to the Compilation, so errors are - // leaking the Compilation object. Setting _this to null workarounds the following issue in V8. - // https://bugs.chromium.org/p/chromium/issues/detail?id=612191 - _this = null; - - if(err) { - return callback(err); - } - - return process.nextTick(callback); - }); - } - - _addModuleChain(context, dependency, onModule, callback) { - const start = this.profile && Date.now(); - - const errorAndCallback = this.bail ? (err) => { - callback(err); - } : (err) => { - err.dependencies = [dependency]; - this.errors.push(err); - callback(); - }; - - if(typeof dependency !== "object" || dependency === null || !dependency.constructor) { - throw new Error("Parameter 'dependency' must be a Dependency"); - } - - const moduleFactory = this.dependencyFactories.get(dependency.constructor); - if(!moduleFactory) { - throw new Error(`No dependency factory available for this dependency type: ${dependency.constructor.name}`); - } - - this.semaphore.acquire(() => { - moduleFactory.create({ - contextInfo: { - issuer: "", - compiler: this.compiler.name - }, - context: context, - dependencies: [dependency] - }, (err, module) => { - if(err) { - this.semaphore.release(); - return errorAndCallback(new EntryModuleNotFoundError(err)); - } - - let afterFactory; - - if(this.profile) { - if(!module.profile) { - module.profile = {}; - } - afterFactory = Date.now(); - module.profile.factory = afterFactory - start; - } - - const result = this.addModule(module); - if(!result) { - module = this.getModule(module); - - onModule(module); - - if(this.profile) { - const afterBuilding = Date.now(); - module.profile.building = afterBuilding - afterFactory; - } - - this.semaphore.release(); - return callback(null, module); - } - - if(result instanceof Module) { - if(this.profile) { - result.profile = module.profile; - } - - module = result; - - onModule(module); - - moduleReady.call(this); - return; - } - - onModule(module); - - this.buildModule(module, false, null, null, (err) => { - if(err) { - this.semaphore.release(); - return errorAndCallback(err); - } - - if(this.profile) { - const afterBuilding = Date.now(); - module.profile.building = afterBuilding - afterFactory; - } - - moduleReady.call(this); - }); - - function moduleReady() { - this.semaphore.release(); - this.processModuleDependencies(module, err => { - if(err) { - return callback(err); - } - - return callback(null, module); - }); - } - }); - }); - } - - addEntry(context, entry, name, callback) { - const slot = { - name: name, - module: null - }; - this.preparedChunks.push(slot); - this._addModuleChain(context, entry, (module) => { - - entry.module = module; - this.entries.push(module); - module.issuer = null; - - }, (err, module) => { - if(err) { - return callback(err); - } - - if(module) { - slot.module = module; - } else { - const idx = this.preparedChunks.indexOf(slot); - this.preparedChunks.splice(idx, 1); - } - return callback(null, module); - }); - } - - prefetch(context, dependency, callback) { - this._addModuleChain(context, dependency, module => { - - module.prefetched = true; - module.issuer = null; - - }, callback); - } - - rebuildModule(module, thisCallback) { - if(module.variables.length || module.blocks.length) - throw new Error("Cannot rebuild a complex module with variables or blocks"); - if(module.rebuilding) { - return module.rebuilding.push(thisCallback); - } - const rebuilding = module.rebuilding = [thisCallback]; - - function callback(err) { - module.rebuilding = undefined; - rebuilding.forEach(cb => cb(err)); - } - const deps = module.dependencies.slice(); - this.buildModule(module, false, module, null, (err) => { - if(err) return callback(err); - - this.processModuleDependencies(module, (err) => { - if(err) return callback(err); - deps.forEach(d => { - if(d.module && d.module.removeReason(module, d)) { - module.forEachChunk(chunk => { - if(!d.module.hasReasonForChunk(chunk)) { - if(d.module.removeChunk(chunk)) { - this.removeChunkFromDependencies(d.module, chunk); - } - } - }); - } - }); - callback(); - }); - - }); - } - - finish() { - const modules = this.modules; - this.applyPlugins1("finish-modules", modules); - - for(let index = 0; index < modules.length; index++) { - const module = modules[index]; - this.reportDependencyErrorsAndWarnings(module, [module]); - } - } - - unseal() { - this.applyPlugins0("unseal"); - this.chunks.length = 0; - this.namedChunks = {}; - this.additionalChunkAssets.length = 0; - this.assets = {}; - this.modules.forEach(module => module.unseal()); - } - - seal(callback) { - const self = this; - self.applyPlugins0("seal"); - self.nextFreeModuleIndex = 0; - self.nextFreeModuleIndex2 = 0; - self.preparedChunks.forEach(preparedChunk => { - const module = preparedChunk.module; - const chunk = self.addChunk(preparedChunk.name, module); - const entrypoint = self.entrypoints[chunk.name] = new Entrypoint(chunk.name); - entrypoint.unshiftChunk(chunk); - - chunk.addModule(module); - module.addChunk(chunk); - chunk.entryModule = module; - self.assignIndex(module); - self.assignDepth(module); - }); - self.processDependenciesBlocksForChunks(self.chunks.slice()); - self.sortModules(self.modules); - self.applyPlugins0("optimize"); - - while(self.applyPluginsBailResult1("optimize-modules-basic", self.modules) || - self.applyPluginsBailResult1("optimize-modules", self.modules) || - self.applyPluginsBailResult1("optimize-modules-advanced", self.modules)) { /* empty */ } - self.applyPlugins1("after-optimize-modules", self.modules); - - while(self.applyPluginsBailResult1("optimize-chunks-basic", self.chunks) || - self.applyPluginsBailResult1("optimize-chunks", self.chunks) || - self.applyPluginsBailResult1("optimize-chunks-advanced", self.chunks)) { /* empty */ } - self.applyPlugins1("after-optimize-chunks", self.chunks); - - self.applyPluginsAsyncSeries("optimize-tree", self.chunks, self.modules, function sealPart2(err) { - if(err) { - return callback(err); - } - - self.applyPlugins2("after-optimize-tree", self.chunks, self.modules); - - while(self.applyPluginsBailResult("optimize-chunk-modules-basic", self.chunks, self.modules) || - self.applyPluginsBailResult("optimize-chunk-modules", self.chunks, self.modules) || - self.applyPluginsBailResult("optimize-chunk-modules-advanced", self.chunks, self.modules)) { /* empty */ } - self.applyPlugins2("after-optimize-chunk-modules", self.chunks, self.modules); - - const shouldRecord = self.applyPluginsBailResult("should-record") !== false; - - self.applyPlugins2("revive-modules", self.modules, self.records); - self.applyPlugins1("optimize-module-order", self.modules); - self.applyPlugins1("advanced-optimize-module-order", self.modules); - self.applyPlugins1("before-module-ids", self.modules); - self.applyPlugins1("module-ids", self.modules); - self.applyModuleIds(); - self.applyPlugins1("optimize-module-ids", self.modules); - self.applyPlugins1("after-optimize-module-ids", self.modules); - - self.sortItemsWithModuleIds(); - - self.applyPlugins2("revive-chunks", self.chunks, self.records); - self.applyPlugins1("optimize-chunk-order", self.chunks); - self.applyPlugins1("before-chunk-ids", self.chunks); - self.applyChunkIds(); - self.applyPlugins1("optimize-chunk-ids", self.chunks); - self.applyPlugins1("after-optimize-chunk-ids", self.chunks); - - self.sortItemsWithChunkIds(); - - if(shouldRecord) - self.applyPlugins2("record-modules", self.modules, self.records); - if(shouldRecord) - self.applyPlugins2("record-chunks", self.chunks, self.records); - - self.applyPlugins0("before-hash"); - self.createHash(); - self.applyPlugins0("after-hash"); - - if(shouldRecord) - self.applyPlugins1("record-hash", self.records); - - self.applyPlugins0("before-module-assets"); - self.createModuleAssets(); - if(self.applyPluginsBailResult("should-generate-chunk-assets") !== false) { - self.applyPlugins0("before-chunk-assets"); - self.createChunkAssets(); - } - self.applyPlugins1("additional-chunk-assets", self.chunks); - self.summarizeDependencies(); - if(shouldRecord) - self.applyPlugins2("record", self, self.records); - - self.applyPluginsAsync("additional-assets", err => { - if(err) { - return callback(err); - } - self.applyPluginsAsync("optimize-chunk-assets", self.chunks, err => { - if(err) { - return callback(err); - } - self.applyPlugins1("after-optimize-chunk-assets", self.chunks); - self.applyPluginsAsync("optimize-assets", self.assets, err => { - if(err) { - return callback(err); - } - self.applyPlugins1("after-optimize-assets", self.assets); - if(self.applyPluginsBailResult("need-additional-seal")) { - self.unseal(); - return self.seal(callback); - } - return self.applyPluginsAsync("after-seal", callback); - }); - }); - }); - }); - } - - sortModules(modules) { - modules.sort((a, b) => { - if(a.index < b.index) return -1; - if(a.index > b.index) return 1; - return 0; - }); - } - - reportDependencyErrorsAndWarnings(module, blocks) { - for(let indexBlock = 0; indexBlock < blocks.length; indexBlock++) { - const block = blocks[indexBlock]; - const dependencies = block.dependencies; - - for(let indexDep = 0; indexDep < dependencies.length; indexDep++) { - const d = dependencies[indexDep]; - - const warnings = d.getWarnings(); - if(warnings) { - for(let indexWar = 0; indexWar < warnings.length; indexWar++) { - const w = warnings[indexWar]; - - const warning = new ModuleDependencyWarning(module, w, d.loc); - this.warnings.push(warning); - } - } - const errors = d.getErrors(); - if(errors) { - for(let indexErr = 0; indexErr < errors.length; indexErr++) { - const e = errors[indexErr]; - - const error = new ModuleDependencyError(module, e, d.loc); - this.errors.push(error); - } - } - } - - this.reportDependencyErrorsAndWarnings(module, block.blocks); - } - } - - addChunk(name, module, loc) { - if(name) { - if(Object.prototype.hasOwnProperty.call(this.namedChunks, name)) { - const chunk = this.namedChunks[name]; - if(module) { - chunk.addOrigin(module, loc); - } - return chunk; - } - } - const chunk = new Chunk(name, module, loc); - this.chunks.push(chunk); - if(name) { - this.namedChunks[name] = chunk; - } - return chunk; - } - - assignIndex(module) { - const _this = this; - - const queue = [() => { - assignIndexToModule(module); - }]; - - const iteratorAllDependencies = d => { - queue.push(() => assignIndexToDependency(d)); - }; - - function assignIndexToModule(module) { - // enter module - if(typeof module.index !== "number") { - module.index = _this.nextFreeModuleIndex++; - - // leave module - queue.push(() => module.index2 = _this.nextFreeModuleIndex2++); - - // enter it as block - assignIndexToDependencyBlock(module); - } - } - - function assignIndexToDependency(dependency) { - if(dependency.module) { - queue.push(() => assignIndexToModule(dependency.module)); - } - } - - function assignIndexToDependencyBlock(block) { - let allDependencies = []; - - function iteratorDependency(d) { - allDependencies.push(d); - } - - function iteratorBlock(b) { - queue.push(() => assignIndexToDependencyBlock(b)); - } - - if(block.variables) { - iterationBlockVariable(block.variables, iteratorDependency); - } - - if(block.dependencies) { - iterationOfArrayCallback(block.dependencies, iteratorDependency); - } - if(block.blocks) { - const blocks = block.blocks; - let indexBlock = blocks.length; - while(indexBlock--) { - iteratorBlock(blocks[indexBlock]); - } - } - - let indexAll = allDependencies.length; - while(indexAll--) { - iteratorAllDependencies(allDependencies[indexAll]); - } - } - - while(queue.length) { - queue.pop()(); - } - } - - assignDepth(module) { - function assignDepthToModule(module, depth) { - // enter module - if(typeof module.depth === "number" && module.depth <= depth) return; - module.depth = depth; - - // enter it as block - assignDepthToDependencyBlock(module, depth + 1); - } - - function assignDepthToDependency(dependency, depth) { - if(dependency.module) { - queue.push(() => assignDepthToModule(dependency.module, depth)); - } - } - - function assignDepthToDependencyBlock(block, depth) { - function iteratorDependency(d) { - assignDepthToDependency(d, depth); - } - - function iteratorBlock(b) { - assignDepthToDependencyBlock(b, depth); - } - - if(block.variables) { - iterationBlockVariable(block.variables, iteratorDependency); - } - - if(block.dependencies) { - iterationOfArrayCallback(block.dependencies, iteratorDependency); - } - - if(block.blocks) { - iterationOfArrayCallback(block.blocks, iteratorBlock); - } - } - - const queue = [() => { - assignDepthToModule(module, 0); - }]; - while(queue.length) { - queue.pop()(); - } - } - - // This method creates the Chunk graph from the Module graph - processDependenciesBlocksForChunks(inputChunks) { - // Process is splitting into two parts: - // Part one traverse the module graph and builds a very basic chunks graph - // in chunkDependencies. - // Part two traverse every possible way through the basic chunk graph and - // tracks the available modules. While traversing it connects chunks with - // eachother and Blocks with Chunks. It stops traversing when all modules - // for a chunk are already available. So it doesn't connect unneeded chunks. - - const chunkDependencies = new Map(); // Map> - const allCreatedChunks = new Set(); - - // PART ONE - - const blockChunks = new Map(); - - // Start with the provided modules/chunks - const queue = inputChunks.map(chunk => ({ - block: chunk.entryModule, - chunk: chunk - })); - - let block, chunk; - - // For each async Block in graph - const iteratorBlock = b => { - // 1. We create a chunk for this Block - // but only once (blockChunks map) - let c = blockChunks.get(b); - if(c === undefined) { - c = this.namedChunks[b.chunkName]; - if(c && c.isInitial()) { - // TODO webpack 4: convert this to an error - this.warnings.push(new AsyncDependencyToInitialChunkWarning(b.chunkName, b.module, b.loc)); - c = chunk; - } else { - c = this.addChunk(b.chunkName, b.module, b.loc); - blockChunks.set(b, c); - allCreatedChunks.add(c); - // We initialize the chunks property - // this is later filled with the chunk when needed - b.chunks = []; - } - } - - // 2. We store the Block+Chunk mapping as dependency for the chunk - let deps = chunkDependencies.get(chunk); - if(!deps) chunkDependencies.set(chunk, deps = []); - deps.push({ - block: b, - chunk: c - }); - - // 3. We enqueue the DependenciesBlock for traversal - queue.push({ - block: b, - chunk: c - }); - }; - - // For each Dependency in the graph - const iteratorDependency = d => { - // We skip Dependencies without Module pointer - if(!d.module) { - return; - } - // We skip weak Dependencies - if(d.weak) { - return; - } - // We connect Module and Chunk when not already done - if(chunk.addModule(d.module)) { - d.module.addChunk(chunk); - - // And enqueue the Module for traversal - queue.push({ - block: d.module, - chunk - }); - } - }; - - // Iterative traversal of the Module graph - // Recursive would be simpler to write but could result in Stack Overflows - while(queue.length) { - const queueItem = queue.pop(); - block = queueItem.block; - chunk = queueItem.chunk; - - // Traverse all variables, Dependencies and Blocks - if(block.variables) { - iterationBlockVariable(block.variables, iteratorDependency); - } - - if(block.dependencies) { - iterationOfArrayCallback(block.dependencies, iteratorDependency); - } - - if(block.blocks) { - iterationOfArrayCallback(block.blocks, iteratorBlock); - } - } - - // PART TWO - - let availableModules; - let newAvailableModules; - const queue2 = new Queue(inputChunks.map(chunk => ({ - chunk, - availableModules: new Set() - }))); - - // Helper function to check if all modules of a chunk are available - const areModulesAvailable = (chunk, availableModules) => { - for(const module of chunk.modulesIterable) { - if(!availableModules.has(module)) - return false; - } - return true; - }; - - // For each edge in the basic chunk graph - const filterFn = dep => { - // Filter egdes that are not needed because all modules are already available - // This also filters circular dependencies in the chunks graph - const depChunk = dep.chunk; - if(areModulesAvailable(depChunk, newAvailableModules)) - return false; // break all modules are already available - return true; - }; - - const minAvailableModulesMap = new Map(); - - // Iterative traversing of the basic chunk graph - while(queue2.length) { - const queueItem = queue2.dequeue(); - chunk = queueItem.chunk; - availableModules = queueItem.availableModules; - - // 1. Get minimal available modules - // It doesn't make sense to traverse a chunk again with more available modules. - // This step calculates the minimal available modules and skips traversal when - // the list didn't shrink. - let minAvailableModules = minAvailableModulesMap.get(chunk); - if(minAvailableModules === undefined) { - minAvailableModulesMap.set(chunk, new Set(availableModules)); - } else { - let deletedModules = false; - for(const m of minAvailableModules) { - if(!availableModules.has(m)) { - minAvailableModules.delete(m); - deletedModules = true; - } - } - if(!deletedModules) - continue; - availableModules = minAvailableModules; - } - - // 2. Get the edges at this point of the graph - const deps = chunkDependencies.get(chunk); - if(!deps) continue; - if(deps.length === 0) continue; - - // 3. Create a new Set of available modules at this points - newAvailableModules = new Set(availableModules); - for(const m of chunk.modulesIterable) - newAvailableModules.add(m); - - // 4. Filter edges with available modules - const filteredDeps = deps.filter(filterFn); - - // 5. Foreach remaining edge - const nextChunks = new Set(); - for(let i = 0; i < filteredDeps.length; i++) { - const dep = filteredDeps[i]; - const depChunk = dep.chunk; - const depBlock = dep.block; - - // 6. Connnect block with chunk - if(depChunk.addBlock(depBlock)) { - depBlock.chunks.push(depChunk); - } - - // 7. Connect chunk with parent - if(chunk.addChunk(depChunk)) { - depChunk.addParent(chunk); - } - - nextChunks.add(depChunk); - } - - // 8. Enqueue further traversal - for(const nextChunk of nextChunks) { - queue2.enqueue({ - chunk: nextChunk, - availableModules: newAvailableModules - }); - } - } - - // Remove all unconnected chunks - for(const chunk of allCreatedChunks) { - if(chunk.parents.length === 0) - chunk.remove("unconnected"); - } - } - - removeChunkFromDependencies(block, chunk) { - const iteratorDependency = d => { - if(!d.module) { - return; - } - if(!d.module.hasReasonForChunk(chunk)) { - if(d.module.removeChunk(chunk)) { - this.removeChunkFromDependencies(d.module, chunk); - } - } - }; - - const blocks = block.blocks; - for(let indexBlock = 0; indexBlock < blocks.length; indexBlock++) { - const chunks = blocks[indexBlock].chunks; - for(let indexChunk = 0; indexChunk < chunks.length; indexChunk++) { - const blockChunk = chunks[indexChunk]; - chunk.removeChunk(blockChunk); - blockChunk.removeParent(chunk); - this.removeChunkFromDependencies(chunks, blockChunk); - } - } - - if(block.dependencies) { - iterationOfArrayCallback(block.dependencies, iteratorDependency); - } - - if(block.variables) { - iterationBlockVariable(block.variables, iteratorDependency); - } - } - - applyModuleIds() { - let unusedIds = []; - let nextFreeModuleId = 0; - let usedIds = []; - // TODO consider Map when performance has improved https://gist.github.com/sokra/234c077e1299b7369461f1708519c392 - const usedIdMap = Object.create(null); - if(this.usedModuleIds) { - Object.keys(this.usedModuleIds).forEach(key => { - const id = this.usedModuleIds[key]; - if(!usedIdMap[id]) { - usedIds.push(id); - usedIdMap[id] = true; - } - }); - } - - const modules1 = this.modules; - for(let indexModule1 = 0; indexModule1 < modules1.length; indexModule1++) { - const module1 = modules1[indexModule1]; - if(module1.id && !usedIdMap[module1.id]) { - usedIds.push(module1.id); - usedIdMap[module1.id] = true; - } - } - - if(usedIds.length > 0) { - let usedIdMax = -1; - for(let index = 0; index < usedIds.length; index++) { - const usedIdKey = usedIds[index]; - - if(typeof usedIdKey !== "number") { - continue; - } - - usedIdMax = Math.max(usedIdMax, usedIdKey); - } - - let lengthFreeModules = nextFreeModuleId = usedIdMax + 1; - - while(lengthFreeModules--) { - if(!usedIdMap[lengthFreeModules]) { - unusedIds.push(lengthFreeModules); - } - } - } - - const modules2 = this.modules; - for(let indexModule2 = 0; indexModule2 < modules2.length; indexModule2++) { - const module2 = modules2[indexModule2]; - if(module2.id === null) { - if(unusedIds.length > 0) - module2.id = unusedIds.pop(); - else - module2.id = nextFreeModuleId++; - } - } - } - - applyChunkIds() { - const unusedIds = []; - let nextFreeChunkId = 0; - - function getNextFreeChunkId(usedChunkIds) { - const keyChunks = Object.keys(usedChunkIds); - let result = -1; - - for(let index = 0; index < keyChunks.length; index++) { - const usedIdKey = keyChunks[index]; - const usedIdValue = usedChunkIds[usedIdKey]; - - if(typeof usedIdValue !== "number") { - continue; - } - - result = Math.max(result, usedIdValue); - } - - return result; - } - - if(this.usedChunkIds) { - nextFreeChunkId = getNextFreeChunkId(this.usedChunkIds) + 1; - let index = nextFreeChunkId; - while(index--) { - if(this.usedChunkIds[index] !== index) { - unusedIds.push(index); - } - } - } - - const chunks = this.chunks; - for(let indexChunk = 0; indexChunk < chunks.length; indexChunk++) { - const chunk = chunks[indexChunk]; - if(chunk.id === null) { - if(unusedIds.length > 0) - chunk.id = unusedIds.pop(); - else - chunk.id = nextFreeChunkId++; - } - if(!chunk.ids) { - chunk.ids = [chunk.id]; - } - } - } - - sortItemsWithModuleIds() { - this.modules.sort(byId); - - const modules = this.modules; - for(let indexModule = 0; indexModule < modules.length; indexModule++) { - modules[indexModule].sortItems(false); - } - - const chunks = this.chunks; - for(let indexChunk = 0; indexChunk < chunks.length; indexChunk++) { - chunks[indexChunk].sortItems(); - } - } - - sortItemsWithChunkIds() { - this.chunks.sort(byId); - - const modules = this.modules; - for(let indexModule = 0; indexModule < modules.length; indexModule++) { - modules[indexModule].sortItems(true); - } - - const chunks = this.chunks; - for(let indexChunk = 0; indexChunk < chunks.length; indexChunk++) { - chunks[indexChunk].sortItems(); - } - - const byMessage = (a, b) => { - const ma = `${a.message}`; - const mb = `${b.message}`; - if(ma < mb) return -1; - if(mb < ma) return 1; - return 0; - }; - - this.errors.sort(byMessage); - this.warnings.sort(byMessage); - } - - summarizeDependencies() { - function filterDups(array) { - const newArray = []; - for(let i = 0; i < array.length; i++) { - if(i === 0 || array[i - 1] !== array[i]) - newArray.push(array[i]); - } - return newArray; - } - this.fileDependencies = (this.compilationDependencies || []).slice(); - this.contextDependencies = []; - this.missingDependencies = []; - - const children = this.children; - for(let indexChildren = 0; indexChildren < children.length; indexChildren++) { - const child = children[indexChildren]; - - this.fileDependencies = this.fileDependencies.concat(child.fileDependencies); - this.contextDependencies = this.contextDependencies.concat(child.contextDependencies); - this.missingDependencies = this.missingDependencies.concat(child.missingDependencies); - } - - const modules = this.modules; - for(let indexModule = 0; indexModule < modules.length; indexModule++) { - const module = modules[indexModule]; - - if(module.fileDependencies) { - const fileDependencies = module.fileDependencies; - for(let indexFileDep = 0; indexFileDep < fileDependencies.length; indexFileDep++) { - this.fileDependencies.push(fileDependencies[indexFileDep]); - } - } - if(module.contextDependencies) { - const contextDependencies = module.contextDependencies; - for(let indexContextDep = 0; indexContextDep < contextDependencies.length; indexContextDep++) { - this.contextDependencies.push(contextDependencies[indexContextDep]); - } - } - } - this.errors.forEach(error => { - if(Array.isArray(error.missing)) { - error.missing.forEach(item => this.missingDependencies.push(item)); - } - }); - this.fileDependencies.sort(); - this.fileDependencies = filterDups(this.fileDependencies); - this.contextDependencies.sort(); - this.contextDependencies = filterDups(this.contextDependencies); - this.missingDependencies.sort(); - this.missingDependencies = filterDups(this.missingDependencies); - } - - createHash() { - const outputOptions = this.outputOptions; - const hashFunction = outputOptions.hashFunction; - const hashDigest = outputOptions.hashDigest; - const hashDigestLength = outputOptions.hashDigestLength; - const hash = crypto.createHash(hashFunction); - if(outputOptions.hashSalt) - hash.update(outputOptions.hashSalt); - this.mainTemplate.updateHash(hash); - this.chunkTemplate.updateHash(hash); - this.moduleTemplate.updateHash(hash); - this.children.forEach(function(child) { - hash.update(child.hash); - }); - this.warnings.forEach(function(warning) { - hash.update(`${warning.message}`); - }); - this.errors.forEach(function(error) { - hash.update(`${error.message}`); - }); - // clone needed as sort below is inplace mutation - const chunks = this.chunks.slice(); - /** - * sort here will bring all "falsy" values to the beginning - * this is needed as the "hasRuntime()" chunks are dependent on the - * hashes of the non-runtime chunks. - */ - chunks.sort((a, b) => { - const aEntry = a.hasRuntime(); - const bEntry = b.hasRuntime(); - if(aEntry && !bEntry) return 1; - if(!aEntry && bEntry) return -1; - return 0; - }); - for(let i = 0; i < chunks.length; i++) { - const chunk = chunks[i]; - const chunkHash = crypto.createHash(hashFunction); - if(outputOptions.hashSalt) - chunkHash.update(outputOptions.hashSalt); - chunk.updateHash(chunkHash); - if(chunk.hasRuntime()) { - this.mainTemplate.updateHashForChunk(chunkHash, chunk); - } else { - this.chunkTemplate.updateHashForChunk(chunkHash, chunk); - } - this.applyPlugins2("chunk-hash", chunk, chunkHash); - chunk.hash = chunkHash.digest(hashDigest); - hash.update(chunk.hash); - chunk.renderedHash = chunk.hash.substr(0, hashDigestLength); - } - this.fullHash = hash.digest(hashDigest); - this.hash = this.fullHash.substr(0, hashDigestLength); - } - - modifyHash(update) { - const outputOptions = this.outputOptions; - const hashFunction = outputOptions.hashFunction; - const hashDigest = outputOptions.hashDigest; - const hashDigestLength = outputOptions.hashDigestLength; - const hash = crypto.createHash(hashFunction); - hash.update(this.fullHash); - hash.update(update); - this.fullHash = hash.digest(hashDigest); - this.hash = this.fullHash.substr(0, hashDigestLength); - } - - createModuleAssets() { - for(let i = 0; i < this.modules.length; i++) { - const module = this.modules[i]; - if(module.assets) { - Object.keys(module.assets).forEach((assetName) => { - const fileName = this.getPath(assetName); - this.assets[fileName] = module.assets[assetName]; - this.applyPlugins2("module-asset", module, fileName); - }); - } - } - } - - createChunkAssets() { - const outputOptions = this.outputOptions; - const filename = outputOptions.filename; - const chunkFilename = outputOptions.chunkFilename; - for(let i = 0; i < this.chunks.length; i++) { - const chunk = this.chunks[i]; - chunk.files = []; - const chunkHash = chunk.hash; - let source; - let file; - const filenameTemplate = chunk.filenameTemplate ? chunk.filenameTemplate : - chunk.isInitial() ? filename : - chunkFilename; - try { - const useChunkHash = !chunk.hasRuntime() || (this.mainTemplate.useChunkHash && this.mainTemplate.useChunkHash(chunk)); - const usedHash = useChunkHash ? chunkHash : this.fullHash; - const cacheName = "c" + chunk.id; - if(this.cache && this.cache[cacheName] && this.cache[cacheName].hash === usedHash) { - source = this.cache[cacheName].source; - } else { - if(chunk.hasRuntime()) { - source = this.mainTemplate.render(this.hash, chunk, this.moduleTemplate, this.dependencyTemplates); - } else { - source = this.chunkTemplate.render(chunk, this.moduleTemplate, this.dependencyTemplates); - } - if(this.cache) { - this.cache[cacheName] = { - hash: usedHash, - source: source = (source instanceof CachedSource ? source : new CachedSource(source)) - }; - } - } - file = this.getPath(filenameTemplate, { - noChunkHash: !useChunkHash, - chunk - }); - if(this.assets[file]) - throw new Error(`Conflict: Multiple assets emit to the same filename ${file}`); - this.assets[file] = source; - chunk.files.push(file); - this.applyPlugins2("chunk-asset", chunk, file); - } catch(err) { - this.errors.push(new ChunkRenderError(chunk, file || filenameTemplate, err)); - } - } - } - - getPath(filename, data) { - data = data || {}; - data.hash = data.hash || this.hash; - return this.mainTemplate.applyPluginsWaterfall("asset-path", filename, data); - } - - createChildCompiler(name, outputOptions, plugins) { - const idx = (this.childrenCounters[name] || 0); - this.childrenCounters[name] = idx + 1; - return this.compiler.createChildCompiler(this, name, idx, outputOptions, plugins); - } - - checkConstraints() { - const usedIds = {}; - - const modules = this.modules; - for(let indexModule = 0; indexModule < modules.length; indexModule++) { - const moduleId = modules[indexModule].id; - - if(usedIds[moduleId]) - throw new Error(`checkConstraints: duplicate module id ${moduleId}`); - } - - const chunks = this.chunks; - for(let indexChunk = 0; indexChunk < chunks.length; indexChunk++) { - const chunk = chunks[indexChunk]; - - if(chunks.indexOf(chunk) !== indexChunk) - throw new Error(`checkConstraints: duplicate chunk in compilation ${chunk.debugId}`); - chunk.checkConstraints(); - } - } -} - -module.exports = Compilation; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra + */ +"use strict"; + +const asyncLib = require("neo-async"); +const util = require("util"); +const { CachedSource } = require("webpack-sources"); +const { + Tapable, + SyncHook, + SyncBailHook, + SyncWaterfallHook, + AsyncSeriesHook +} = require("tapable"); +const EntryModuleNotFoundError = require("./EntryModuleNotFoundError"); +const ModuleNotFoundError = require("./ModuleNotFoundError"); +const ModuleDependencyWarning = require("./ModuleDependencyWarning"); +const ModuleDependencyError = require("./ModuleDependencyError"); +const ChunkGroup = require("./ChunkGroup"); +const Chunk = require("./Chunk"); +const Entrypoint = require("./Entrypoint"); +const MainTemplate = require("./MainTemplate"); +const ChunkTemplate = require("./ChunkTemplate"); +const HotUpdateChunkTemplate = require("./HotUpdateChunkTemplate"); +const ModuleTemplate = require("./ModuleTemplate"); +const RuntimeTemplate = require("./RuntimeTemplate"); +const ChunkRenderError = require("./ChunkRenderError"); +const AsyncDependencyToInitialChunkError = require("./AsyncDependencyToInitialChunkError"); +const Stats = require("./Stats"); +const Semaphore = require("./util/Semaphore"); +const createHash = require("./util/createHash"); +const Queue = require("./util/Queue"); +const SortableSet = require("./util/SortableSet"); +const GraphHelpers = require("./GraphHelpers"); +const ModuleDependency = require("./dependencies/ModuleDependency"); +const compareLocations = require("./compareLocations"); + +/** @typedef {import("./Module")} Module */ +/** @typedef {import("./Compiler")} Compiler */ +/** @typedef {import("webpack-sources").Source} Source */ +/** @typedef {import("./WebpackError")} WebpackError */ +/** @typedef {import("./DependenciesBlockVariable")} DependenciesBlockVariable */ +/** @typedef {import("./dependencies/SingleEntryDependency")} SingleEntryDependency */ +/** @typedef {import("./dependencies/MultiEntryDependency")} MultiEntryDependency */ +/** @typedef {import("./dependencies/DllEntryDependency")} DllEntryDependency */ +/** @typedef {import("./dependencies/DependencyReference")} DependencyReference */ +/** @typedef {import("./DependenciesBlock")} DependenciesBlock */ +/** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */ +/** @typedef {import("./Dependency")} Dependency */ +/** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */ +/** @typedef {import("./Dependency").DependencyTemplate} DependencyTemplate */ +/** @typedef {import("./util/createHash").Hash} Hash */ + +// TODO use @callback +/** @typedef {{[assetName: string]: Source}} CompilationAssets */ +/** @typedef {(err: Error|null, result?: Module) => void } ModuleCallback */ +/** @typedef {(err?: Error|null, result?: Module) => void } ModuleChainCallback */ +/** @typedef {(module: Module) => void} OnModuleCallback */ +/** @typedef {(err?: Error|null) => void} Callback */ +/** @typedef {(d: Dependency) => any} DepBlockVarDependenciesCallback */ +/** @typedef {new (...args: any[]) => Dependency} DepConstructor */ +/** @typedef {{apply: () => void}} Plugin */ + +/** + * @typedef {Object} ModuleFactoryCreateDataContextInfo + * @property {string} issuer + * @property {string} compiler + */ + +/** + * @typedef {Object} ModuleFactoryCreateData + * @property {ModuleFactoryCreateDataContextInfo} contextInfo + * @property {any=} resolveOptions + * @property {string} context + * @property {Dependency[]} dependencies + */ + +/** + * @typedef {Object} ModuleFactory + * @property {(data: ModuleFactoryCreateData, callback: ModuleCallback) => any} create + */ + +/** + * @typedef {Object} SortedDependency + * @property {ModuleFactory} factory + * @property {Dependency[]} dependencies + */ + +/** + * @typedef {Object} AvailableModulesChunkGroupMapping + * @property {ChunkGroup} chunkGroup + * @property {Set} availableModules + */ + +/** + * @typedef {Object} DependenciesBlockLike + * @property {Dependency[]} dependencies + * @property {AsyncDependenciesBlock[]} blocks + * @property {DependenciesBlockVariable[]} variables + */ + +/** + * @param {Chunk} a first chunk to sort by id + * @param {Chunk} b second chunk to sort by id + * @returns {-1|0|1} sort value + */ +const byId = (a, b) => { + if (a.id !== null && b.id !== null) { + if (a.id < b.id) return -1; + if (a.id > b.id) return 1; + } + return 0; +}; + +/** + * @param {Module} a first module to sort by + * @param {Module} b second module to sort by + * @returns {-1|0|1} sort value + */ +const byIdOrIdentifier = (a, b) => { + if (a.id < b.id) return -1; + if (a.id > b.id) return 1; + const identA = a.identifier(); + const identB = b.identifier(); + if (identA < identB) return -1; + if (identA > identB) return 1; + return 0; +}; + +/** + * @param {Module} a first module to sort by + * @param {Module} b second module to sort by + * @returns {-1|0|1} sort value + */ +const byIndexOrIdentifier = (a, b) => { + if (a.index < b.index) return -1; + if (a.index > b.index) return 1; + const identA = a.identifier(); + const identB = b.identifier(); + if (identA < identB) return -1; + if (identA > identB) return 1; + return 0; +}; + +/** + * @param {Compilation} a first compilation to sort by + * @param {Compilation} b second compilation to sort by + * @returns {-1|0|1} sort value + */ +const byNameOrHash = (a, b) => { + if (a.name < b.name) return -1; + if (a.name > b.name) return 1; + if (a.fullHash < b.fullHash) return -1; + if (a.fullHash > b.fullHash) return 1; + return 0; +}; + +/** + * @param {DependenciesBlockVariable[]} variables DepBlock Variables to iterate over + * @param {DepBlockVarDependenciesCallback} fn callback to apply on iterated elements + * @returns {void} + */ +const iterationBlockVariable = (variables, fn) => { + for ( + let indexVariable = 0; + indexVariable < variables.length; + indexVariable++ + ) { + const varDep = variables[indexVariable].dependencies; + for (let indexVDep = 0; indexVDep < varDep.length; indexVDep++) { + fn(varDep[indexVDep]); + } + } +}; + +/** + * @template T + * @param {T[]} arr array of elements to iterate over + * @param {function(T): void} fn callback applied to each element + * @returns {void} + */ +const iterationOfArrayCallback = (arr, fn) => { + for (let index = 0; index < arr.length; index++) { + fn(arr[index]); + } +}; + +/** + * @template T + * @param {Set} set set to add items to + * @param {Set} otherSet set to add items from + * @returns {void} + */ +const addAllToSet = (set, otherSet) => { + for (const item of otherSet) { + set.add(item); + } +}; + +class Compilation extends Tapable { + /** + * Creates an instance of Compilation. + * @param {Compiler} compiler the compiler which created the compilation + */ + constructor(compiler) { + super(); + this.hooks = { + /** @type {SyncHook} */ + buildModule: new SyncHook(["module"]), + /** @type {SyncHook} */ + rebuildModule: new SyncHook(["module"]), + /** @type {SyncHook} */ + failedModule: new SyncHook(["module", "error"]), + /** @type {SyncHook} */ + succeedModule: new SyncHook(["module"]), + + /** @type {SyncWaterfallHook} */ + dependencyReference: new SyncWaterfallHook([ + "dependencyReference", + "dependency", + "module" + ]), + + /** @type {SyncHook} */ + finishModules: new SyncHook(["modules"]), + /** @type {SyncHook} */ + finishRebuildingModule: new SyncHook(["module"]), + /** @type {SyncHook} */ + unseal: new SyncHook([]), + /** @type {SyncHook} */ + seal: new SyncHook([]), + + /** @type {SyncHook} */ + beforeChunks: new SyncHook([]), + /** @type {SyncHook} */ + afterChunks: new SyncHook(["chunks"]), + + /** @type {SyncBailHook} */ + optimizeDependenciesBasic: new SyncBailHook(["modules"]), + /** @type {SyncBailHook} */ + optimizeDependencies: new SyncBailHook(["modules"]), + /** @type {SyncBailHook} */ + optimizeDependenciesAdvanced: new SyncBailHook(["modules"]), + /** @type {SyncBailHook} */ + afterOptimizeDependencies: new SyncHook(["modules"]), + + /** @type {SyncHook} */ + optimize: new SyncHook([]), + /** @type {SyncBailHook} */ + optimizeModulesBasic: new SyncBailHook(["modules"]), + /** @type {SyncBailHook} */ + optimizeModules: new SyncBailHook(["modules"]), + /** @type {SyncBailHook} */ + optimizeModulesAdvanced: new SyncBailHook(["modules"]), + /** @type {SyncHook} */ + afterOptimizeModules: new SyncHook(["modules"]), + + /** @type {SyncBailHook} */ + optimizeChunksBasic: new SyncBailHook(["chunks", "chunkGroups"]), + /** @type {SyncBailHook} */ + optimizeChunks: new SyncBailHook(["chunks", "chunkGroups"]), + /** @type {SyncBailHook} */ + optimizeChunksAdvanced: new SyncBailHook(["chunks", "chunkGroups"]), + /** @type {SyncHook} */ + afterOptimizeChunks: new SyncHook(["chunks", "chunkGroups"]), + + /** @type {AsyncSeriesHook} */ + optimizeTree: new AsyncSeriesHook(["chunks", "modules"]), + /** @type {SyncHook} */ + afterOptimizeTree: new SyncHook(["chunks", "modules"]), + + /** @type {SyncBailHook} */ + optimizeChunkModulesBasic: new SyncBailHook(["chunks", "modules"]), + /** @type {SyncBailHook} */ + optimizeChunkModules: new SyncBailHook(["chunks", "modules"]), + /** @type {SyncBailHook} */ + optimizeChunkModulesAdvanced: new SyncBailHook(["chunks", "modules"]), + /** @type {SyncHook} */ + afterOptimizeChunkModules: new SyncHook(["chunks", "modules"]), + /** @type {SyncBailHook} */ + shouldRecord: new SyncBailHook([]), + + /** @type {SyncHook} */ + reviveModules: new SyncHook(["modules", "records"]), + /** @type {SyncHook} */ + optimizeModuleOrder: new SyncHook(["modules"]), + /** @type {SyncHook} */ + advancedOptimizeModuleOrder: new SyncHook(["modules"]), + /** @type {SyncHook} */ + beforeModuleIds: new SyncHook(["modules"]), + /** @type {SyncHook} */ + moduleIds: new SyncHook(["modules"]), + /** @type {SyncHook} */ + optimizeModuleIds: new SyncHook(["modules"]), + /** @type {SyncHook} */ + afterOptimizeModuleIds: new SyncHook(["modules"]), + + /** @type {SyncHook} */ + reviveChunks: new SyncHook(["chunks", "records"]), + /** @type {SyncHook} */ + optimizeChunkOrder: new SyncHook(["chunks"]), + /** @type {SyncHook} */ + beforeChunkIds: new SyncHook(["chunks"]), + /** @type {SyncHook} */ + optimizeChunkIds: new SyncHook(["chunks"]), + /** @type {SyncHook} */ + afterOptimizeChunkIds: new SyncHook(["chunks"]), + + /** @type {SyncHook} */ + recordModules: new SyncHook(["modules", "records"]), + /** @type {SyncHook} */ + recordChunks: new SyncHook(["chunks", "records"]), + + /** @type {SyncHook} */ + beforeHash: new SyncHook([]), + /** @type {SyncHook} */ + contentHash: new SyncHook(["chunk"]), + /** @type {SyncHook} */ + afterHash: new SyncHook([]), + /** @type {SyncHook} */ + recordHash: new SyncHook(["records"]), + /** @type {SyncHook} */ + record: new SyncHook(["compilation", "records"]), + + /** @type {SyncHook} */ + beforeModuleAssets: new SyncHook([]), + /** @type {SyncBailHook} */ + shouldGenerateChunkAssets: new SyncBailHook([]), + /** @type {SyncHook} */ + beforeChunkAssets: new SyncHook([]), + /** @type {SyncHook} */ + additionalChunkAssets: new SyncHook(["chunks"]), + + /** @type {AsyncSeriesHook} */ + additionalAssets: new AsyncSeriesHook([]), + /** @type {AsyncSeriesHook} */ + optimizeChunkAssets: new AsyncSeriesHook(["chunks"]), + /** @type {SyncHook} */ + afterOptimizeChunkAssets: new SyncHook(["chunks"]), + /** @type {AsyncSeriesHook} */ + optimizeAssets: new AsyncSeriesHook(["assets"]), + /** @type {SyncHook} */ + afterOptimizeAssets: new SyncHook(["assets"]), + + /** @type {SyncBailHook} */ + needAdditionalSeal: new SyncBailHook([]), + /** @type {AsyncSeriesHook} */ + afterSeal: new AsyncSeriesHook([]), + + /** @type {SyncHook} */ + chunkHash: new SyncHook(["chunk", "chunkHash"]), + /** @type {SyncHook} */ + moduleAsset: new SyncHook(["module", "filename"]), + /** @type {SyncHook} */ + chunkAsset: new SyncHook(["chunk", "filename"]), + + /** @type {SyncWaterfallHook} */ + assetPath: new SyncWaterfallHook(["filename", "data"]), // TODO MainTemplate + + /** @type {SyncBailHook} */ + needAdditionalPass: new SyncBailHook([]), + + /** @type {SyncHook} */ + childCompiler: new SyncHook([ + "childCompiler", + "compilerName", + "compilerIndex" + ]), + + // TODO the following hooks are weirdly located here + // TODO move them for webpack 5 + /** @type {SyncHook} */ + normalModuleLoader: new SyncHook(["loaderContext", "module"]), + + /** @type {SyncBailHook} */ + optimizeExtractedChunksBasic: new SyncBailHook(["chunks"]), + /** @type {SyncBailHook} */ + optimizeExtractedChunks: new SyncBailHook(["chunks"]), + /** @type {SyncBailHook} */ + optimizeExtractedChunksAdvanced: new SyncBailHook(["chunks"]), + /** @type {SyncHook} */ + afterOptimizeExtractedChunks: new SyncHook(["chunks"]) + }; + this._pluginCompat.tap("Compilation", options => { + switch (options.name) { + case "optimize-tree": + case "additional-assets": + case "optimize-chunk-assets": + case "optimize-assets": + case "after-seal": + options.async = true; + break; + } + }); + /** @type {string=} */ + this.name = undefined; + /** @type {Compiler} */ + this.compiler = compiler; + this.resolverFactory = compiler.resolverFactory; + this.inputFileSystem = compiler.inputFileSystem; + this.requestShortener = compiler.requestShortener; + + const options = (this.options = compiler.options); + this.outputOptions = options && options.output; + /** @type {boolean=} */ + this.bail = options && options.bail; + this.profile = options && options.profile; + this.performance = options && options.performance; + + this.mainTemplate = new MainTemplate(this.outputOptions); + this.chunkTemplate = new ChunkTemplate(this.outputOptions); + this.hotUpdateChunkTemplate = new HotUpdateChunkTemplate( + this.outputOptions + ); + this.runtimeTemplate = new RuntimeTemplate( + this.outputOptions, + this.requestShortener + ); + this.moduleTemplates = { + javascript: new ModuleTemplate(this.runtimeTemplate, "javascript"), + webassembly: new ModuleTemplate(this.runtimeTemplate, "webassembly") + }; + + this.semaphore = new Semaphore(options.parallelism || 100); + + this.entries = []; + /** @private @type {{name: string, request: string, module: Module}[]} */ + this._preparedEntrypoints = []; + this.entrypoints = new Map(); + /** @type {Chunk[]} */ + this.chunks = []; + /** @type {ChunkGroup[]} */ + this.chunkGroups = []; + /** @type {Map} */ + this.namedChunkGroups = new Map(); + /** @type {Map} */ + this.namedChunks = new Map(); + /** @type {Module[]} */ + this.modules = []; + /** @private @type {Map} */ + this._modules = new Map(); + this.cache = null; + this.records = null; + /** @type {string[]} */ + this.additionalChunkAssets = []; + /** @type {CompilationAssets} */ + this.assets = {}; + /** @type {WebpackError[]} */ + this.errors = []; + /** @type {WebpackError[]} */ + this.warnings = []; + /** @type {Compilation[]} */ + this.children = []; + /** @type {Map} */ + this.dependencyFactories = new Map(); + /** @type {Map} */ + this.dependencyTemplates = new Map(); + // TODO refactor this in webpack 5 to a custom DependencyTemplates class with a hash property + // @ts-ignore + this.dependencyTemplates.set("hash", ""); + this.childrenCounters = {}; + /** @type {Set} */ + this.usedChunkIds = null; + /** @type {Set} */ + this.usedModuleIds = null; + /** @type {Map=} */ + this.fileTimestamps = undefined; + /** @type {Map=} */ + this.contextTimestamps = undefined; + /** @type {Set=} */ + this.compilationDependencies = undefined; + /** @private @type {Map} */ + this._buildingModules = new Map(); + /** @private @type {Map} */ + this._rebuildingModules = new Map(); + } + + getStats() { + return new Stats(this); + } + + /** + * @typedef {Object} AddModuleResult + * @property {Module} module the added or existing module + * @property {boolean} issuer was this the first request for this module + * @property {boolean} build should the module be build + * @property {boolean} dependencies should dependencies be walked + */ + + /** + * @param {Module} module module to be added that was created + * @param {any=} cacheGroup cacheGroup it is apart of + * @returns {AddModuleResult} returns meta about whether or not the module had built + * had an issuer, or any dependnecies + */ + addModule(module, cacheGroup) { + const identifier = module.identifier(); + const alreadyAddedModule = this._modules.get(identifier); + if (alreadyAddedModule) { + return { + module: alreadyAddedModule, + issuer: false, + build: false, + dependencies: false + }; + } + const cacheName = (cacheGroup || "m") + identifier; + if (this.cache && this.cache[cacheName]) { + const cacheModule = this.cache[cacheName]; + + if (typeof cacheModule.updateCacheModule === "function") { + cacheModule.updateCacheModule(module); + } + + let rebuild = true; + if (this.fileTimestamps && this.contextTimestamps) { + rebuild = cacheModule.needRebuild( + this.fileTimestamps, + this.contextTimestamps + ); + } + + if (!rebuild) { + cacheModule.disconnect(); + this._modules.set(identifier, cacheModule); + this.modules.push(cacheModule); + for (const err of cacheModule.errors) { + this.errors.push(err); + } + for (const err of cacheModule.warnings) { + this.warnings.push(err); + } + return { + module: cacheModule, + issuer: true, + build: false, + dependencies: true + }; + } + cacheModule.unbuild(); + module = cacheModule; + } + this._modules.set(identifier, module); + if (this.cache) { + this.cache[cacheName] = module; + } + this.modules.push(module); + return { + module: module, + issuer: true, + build: true, + dependencies: true + }; + } + + /** + * Fetches a module from a compilation by its identifier + * @param {Module} module the module provided + * @returns {Module} the module requested + */ + getModule(module) { + const identifier = module.identifier(); + return this._modules.get(identifier); + } + + /** + * Attempts to search for a module by its identifier + * @param {string} identifier identifier (usually path) for module + * @returns {Module|undefined} attempt to search for module and return it, else undefined + */ + findModule(identifier) { + return this._modules.get(identifier); + } + + /** + * @param {Module} module module with its callback list + * @param {Callback} callback the callback function + * @returns {void} + */ + waitForBuildingFinished(module, callback) { + let callbackList = this._buildingModules.get(module); + if (callbackList) { + callbackList.push(() => callback()); + } else { + process.nextTick(callback); + } + } + + /** + * Builds the module object + * + * @param {Module} module module to be built + * @param {boolean} optional optional flag + * @param {Module=} origin origin module this module build was requested from + * @param {Dependency[]=} dependencies optional dependencies from the module to be built + * @param {TODO} thisCallback the callback + * @returns {TODO} returns the callback function with results + */ + buildModule(module, optional, origin, dependencies, thisCallback) { + let callbackList = this._buildingModules.get(module); + if (callbackList) { + callbackList.push(thisCallback); + return; + } + this._buildingModules.set(module, (callbackList = [thisCallback])); + + const callback = err => { + this._buildingModules.delete(module); + for (const cb of callbackList) { + cb(err); + } + }; + + this.hooks.buildModule.call(module); + module.build( + this.options, + this, + this.resolverFactory.get("normal", module.resolveOptions), + this.inputFileSystem, + error => { + const errors = module.errors; + for (let indexError = 0; indexError < errors.length; indexError++) { + const err = errors[indexError]; + err.origin = origin; + err.dependencies = dependencies; + if (optional) { + this.warnings.push(err); + } else { + this.errors.push(err); + } + } + + const warnings = module.warnings; + for ( + let indexWarning = 0; + indexWarning < warnings.length; + indexWarning++ + ) { + const war = warnings[indexWarning]; + war.origin = origin; + war.dependencies = dependencies; + this.warnings.push(war); + } + module.dependencies.sort((a, b) => compareLocations(a.loc, b.loc)); + if (error) { + this.hooks.failedModule.call(module, error); + return callback(error); + } + this.hooks.succeedModule.call(module); + return callback(); + } + ); + } + + /** + * @param {Module} module to be processed for deps + * @param {ModuleCallback} callback callback to be triggered + * @returns {void} + */ + processModuleDependencies(module, callback) { + const dependencies = new Map(); + + const addDependency = dep => { + const resourceIdent = dep.getResourceIdentifier(); + if (resourceIdent) { + const factory = this.dependencyFactories.get(dep.constructor); + if (factory === undefined) { + throw new Error( + `No module factory available for dependency type: ${ + dep.constructor.name + }` + ); + } + let innerMap = dependencies.get(factory); + if (innerMap === undefined) { + dependencies.set(factory, (innerMap = new Map())); + } + let list = innerMap.get(resourceIdent); + if (list === undefined) innerMap.set(resourceIdent, (list = [])); + list.push(dep); + } + }; + + const addDependenciesBlock = block => { + if (block.dependencies) { + iterationOfArrayCallback(block.dependencies, addDependency); + } + if (block.blocks) { + iterationOfArrayCallback(block.blocks, addDependenciesBlock); + } + if (block.variables) { + iterationBlockVariable(block.variables, addDependency); + } + }; + + try { + addDependenciesBlock(module); + } catch (e) { + callback(e); + } + + const sortedDependencies = []; + + for (const pair1 of dependencies) { + for (const pair2 of pair1[1]) { + sortedDependencies.push({ + factory: pair1[0], + dependencies: pair2[1] + }); + } + } + + this.addModuleDependencies( + module, + sortedDependencies, + this.bail, + null, + true, + callback + ); + } + + /** + * @param {Module} module module to add deps to + * @param {SortedDependency[]} dependencies set of sorted dependencies to iterate through + * @param {(boolean|null)=} bail whether to bail or not + * @param {TODO} cacheGroup optional cacheGroup + * @param {boolean} recursive whether it is recursive traversal + * @param {function} callback callback for when dependencies are finished being added + * @returns {void} + */ + addModuleDependencies( + module, + dependencies, + bail, + cacheGroup, + recursive, + callback + ) { + const start = this.profile && Date.now(); + const currentProfile = this.profile && {}; + + asyncLib.forEach( + dependencies, + (item, callback) => { + const dependencies = item.dependencies; + + const errorAndCallback = err => { + err.origin = module; + err.dependencies = dependencies; + this.errors.push(err); + if (bail) { + callback(err); + } else { + callback(); + } + }; + const warningAndCallback = err => { + err.origin = module; + this.warnings.push(err); + callback(); + }; + + const semaphore = this.semaphore; + semaphore.acquire(() => { + const factory = item.factory; + factory.create( + { + contextInfo: { + issuer: module.nameForCondition && module.nameForCondition(), + compiler: this.compiler.name + }, + resolveOptions: module.resolveOptions, + context: module.context, + dependencies: dependencies + }, + (err, dependentModule) => { + let afterFactory; + + const isOptional = () => { + return dependencies.every(d => d.optional); + }; + + const errorOrWarningAndCallback = err => { + if (isOptional()) { + return warningAndCallback(err); + } else { + return errorAndCallback(err); + } + }; + + if (err) { + semaphore.release(); + return errorOrWarningAndCallback( + new ModuleNotFoundError(module, err) + ); + } + if (!dependentModule) { + semaphore.release(); + return process.nextTick(callback); + } + if (currentProfile) { + afterFactory = Date.now(); + currentProfile.factory = afterFactory - start; + } + + const iterationDependencies = depend => { + for (let index = 0; index < depend.length; index++) { + const dep = depend[index]; + dep.module = dependentModule; + dependentModule.addReason(module, dep); + } + }; + + const addModuleResult = this.addModule( + dependentModule, + cacheGroup + ); + dependentModule = addModuleResult.module; + iterationDependencies(dependencies); + + const afterBuild = () => { + if (currentProfile) { + const afterBuilding = Date.now(); + currentProfile.building = afterBuilding - afterFactory; + } + + if (recursive && addModuleResult.dependencies) { + this.processModuleDependencies(dependentModule, callback); + } else { + return callback(); + } + }; + + if (addModuleResult.issuer) { + if (currentProfile) { + dependentModule.profile = currentProfile; + } + + dependentModule.issuer = module; + } else { + if (this.profile) { + if (module.profile) { + const time = Date.now() - start; + if ( + !module.profile.dependencies || + time > module.profile.dependencies + ) { + module.profile.dependencies = time; + } + } + } + } + + if (addModuleResult.build) { + this.buildModule( + dependentModule, + isOptional(), + module, + dependencies, + err => { + if (err) { + semaphore.release(); + return errorOrWarningAndCallback(err); + } + + if (currentProfile) { + const afterBuilding = Date.now(); + currentProfile.building = afterBuilding - afterFactory; + } + + semaphore.release(); + afterBuild(); + } + ); + } else { + semaphore.release(); + this.waitForBuildingFinished(dependentModule, afterBuild); + } + } + ); + }); + }, + err => { + // In V8, the Error objects keep a reference to the functions on the stack. These warnings & + // errors are created inside closures that keep a reference to the Compilation, so errors are + // leaking the Compilation object. + + if (err) { + // eslint-disable-next-line no-self-assign + err.stack = err.stack; + return callback(err); + } + + return process.nextTick(callback); + } + ); + } + + /** + * + * @param {string} context context string path + * @param {Dependency} dependency dependency used to create Module chain + * @param {OnModuleCallback} onModule function invoked on modules creation + * @param {ModuleChainCallback} callback callback for when module chain is complete + * @returns {void} will throw if dependency instance is not a valid Dependency + */ + _addModuleChain(context, dependency, onModule, callback) { + const start = this.profile && Date.now(); + const currentProfile = this.profile && {}; + + const errorAndCallback = this.bail + ? err => { + callback(err); + } + : err => { + err.dependencies = [dependency]; + this.errors.push(err); + callback(); + }; + + if ( + typeof dependency !== "object" || + dependency === null || + !dependency.constructor + ) { + throw new Error("Parameter 'dependency' must be a Dependency"); + } + const Dep = /** @type {DepConstructor} */ (dependency.constructor); + const moduleFactory = this.dependencyFactories.get(Dep); + if (!moduleFactory) { + throw new Error( + `No dependency factory available for this dependency type: ${ + dependency.constructor.name + }` + ); + } + + this.semaphore.acquire(() => { + moduleFactory.create( + { + contextInfo: { + issuer: "", + compiler: this.compiler.name + }, + context: context, + dependencies: [dependency] + }, + (err, module) => { + if (err) { + this.semaphore.release(); + return errorAndCallback(new EntryModuleNotFoundError(err)); + } + + let afterFactory; + + if (currentProfile) { + afterFactory = Date.now(); + currentProfile.factory = afterFactory - start; + } + + const addModuleResult = this.addModule(module); + module = addModuleResult.module; + + onModule(module); + + dependency.module = module; + module.addReason(null, dependency); + + const afterBuild = () => { + if (currentProfile) { + const afterBuilding = Date.now(); + currentProfile.building = afterBuilding - afterFactory; + } + + if (addModuleResult.dependencies) { + this.processModuleDependencies(module, err => { + if (err) return callback(err); + callback(null, module); + }); + } else { + return callback(null, module); + } + }; + + if (addModuleResult.issuer) { + if (currentProfile) { + module.profile = currentProfile; + } + } + + if (addModuleResult.build) { + this.buildModule(module, false, null, null, err => { + if (err) { + this.semaphore.release(); + return errorAndCallback(err); + } + + if (currentProfile) { + const afterBuilding = Date.now(); + currentProfile.building = afterBuilding - afterFactory; + } + + this.semaphore.release(); + afterBuild(); + }); + } else { + this.semaphore.release(); + this.waitForBuildingFinished(module, afterBuild); + } + } + ); + }); + } + + /** + * + * @param {string} context context path for entry + * @param {Dependency} entry entry dependency being created + * @param {string} name name of entry + * @param {ModuleCallback} callback callback function + * @returns {void} returns + */ + addEntry(context, entry, name, callback) { + const slot = { + name: name, + // TODO webpack 5 remove `request` + request: null, + module: null + }; + + if (entry instanceof ModuleDependency) { + slot.request = entry.request; + } + + // TODO webpack 5: merge modules instead when multiple entry modules are supported + const idx = this._preparedEntrypoints.findIndex(slot => slot.name === name); + if (idx >= 0) { + // Overwrite existing entrypoint + this._preparedEntrypoints[idx] = slot; + } else { + this._preparedEntrypoints.push(slot); + } + this._addModuleChain( + context, + entry, + module => { + this.entries.push(module); + }, + (err, module) => { + if (err) { + return callback(err); + } + + if (module) { + slot.module = module; + } else { + const idx = this._preparedEntrypoints.indexOf(slot); + if (idx >= 0) { + this._preparedEntrypoints.splice(idx, 1); + } + } + return callback(null, module); + } + ); + } + + /** + * @param {string} context context path string + * @param {Dependency} dependency dep used to create module + * @param {ModuleCallback} callback module callback sending module up a level + * @returns {void} + */ + prefetch(context, dependency, callback) { + this._addModuleChain( + context, + dependency, + module => { + module.prefetched = true; + }, + callback + ); + } + + /** + * @param {Module} module module to be rebuilt + * @param {Callback} thisCallback callback when module finishes rebuilding + * @returns {void} + */ + rebuildModule(module, thisCallback) { + let callbackList = this._rebuildingModules.get(module); + if (callbackList) { + callbackList.push(thisCallback); + return; + } + this._rebuildingModules.set(module, (callbackList = [thisCallback])); + + const callback = err => { + this._rebuildingModules.delete(module); + for (const cb of callbackList) { + cb(err); + } + }; + + this.hooks.rebuildModule.call(module); + const oldDependencies = module.dependencies.slice(); + const oldVariables = module.variables.slice(); + const oldBlocks = module.blocks.slice(); + module.unbuild(); + this.buildModule(module, false, module, null, err => { + if (err) { + this.hooks.finishRebuildingModule.call(module); + return callback(err); + } + + this.processModuleDependencies(module, err => { + if (err) return callback(err); + this.removeReasonsOfDependencyBlock(module, { + dependencies: oldDependencies, + variables: oldVariables, + blocks: oldBlocks + }); + this.hooks.finishRebuildingModule.call(module); + callback(); + }); + }); + } + + finish() { + const modules = this.modules; + this.hooks.finishModules.call(modules); + + for (let index = 0; index < modules.length; index++) { + const module = modules[index]; + this.reportDependencyErrorsAndWarnings(module, [module]); + } + } + + unseal() { + this.hooks.unseal.call(); + this.chunks.length = 0; + this.chunkGroups.length = 0; + this.namedChunks.clear(); + this.namedChunkGroups.clear(); + this.additionalChunkAssets.length = 0; + this.assets = {}; + for (const module of this.modules) { + module.unseal(); + } + } + + /** + * @param {Callback} callback signals when the seal method is finishes + * @returns {void} + */ + seal(callback) { + this.hooks.seal.call(); + + while ( + this.hooks.optimizeDependenciesBasic.call(this.modules) || + this.hooks.optimizeDependencies.call(this.modules) || + this.hooks.optimizeDependenciesAdvanced.call(this.modules) + ) { + /* empty */ + } + this.hooks.afterOptimizeDependencies.call(this.modules); + + this.hooks.beforeChunks.call(); + for (const preparedEntrypoint of this._preparedEntrypoints) { + const module = preparedEntrypoint.module; + const name = preparedEntrypoint.name; + const chunk = this.addChunk(name); + const entrypoint = new Entrypoint(name); + entrypoint.setRuntimeChunk(chunk); + entrypoint.addOrigin(null, name, preparedEntrypoint.request); + this.namedChunkGroups.set(name, entrypoint); + this.entrypoints.set(name, entrypoint); + this.chunkGroups.push(entrypoint); + + GraphHelpers.connectChunkGroupAndChunk(entrypoint, chunk); + GraphHelpers.connectChunkAndModule(chunk, module); + + chunk.entryModule = module; + chunk.name = name; + + this.assignDepth(module); + } + this.processDependenciesBlocksForChunkGroups(this.chunkGroups.slice()); + this.sortModules(this.modules); + this.hooks.afterChunks.call(this.chunks); + + this.hooks.optimize.call(); + + while ( + this.hooks.optimizeModulesBasic.call(this.modules) || + this.hooks.optimizeModules.call(this.modules) || + this.hooks.optimizeModulesAdvanced.call(this.modules) + ) { + /* empty */ + } + this.hooks.afterOptimizeModules.call(this.modules); + + while ( + this.hooks.optimizeChunksBasic.call(this.chunks, this.chunkGroups) || + this.hooks.optimizeChunks.call(this.chunks, this.chunkGroups) || + this.hooks.optimizeChunksAdvanced.call(this.chunks, this.chunkGroups) + ) { + /* empty */ + } + this.hooks.afterOptimizeChunks.call(this.chunks, this.chunkGroups); + + this.hooks.optimizeTree.callAsync(this.chunks, this.modules, err => { + if (err) { + return callback(err); + } + + this.hooks.afterOptimizeTree.call(this.chunks, this.modules); + + while ( + this.hooks.optimizeChunkModulesBasic.call(this.chunks, this.modules) || + this.hooks.optimizeChunkModules.call(this.chunks, this.modules) || + this.hooks.optimizeChunkModulesAdvanced.call(this.chunks, this.modules) + ) { + /* empty */ + } + this.hooks.afterOptimizeChunkModules.call(this.chunks, this.modules); + + const shouldRecord = this.hooks.shouldRecord.call() !== false; + + this.hooks.reviveModules.call(this.modules, this.records); + this.hooks.optimizeModuleOrder.call(this.modules); + this.hooks.advancedOptimizeModuleOrder.call(this.modules); + this.hooks.beforeModuleIds.call(this.modules); + this.hooks.moduleIds.call(this.modules); + this.applyModuleIds(); + this.hooks.optimizeModuleIds.call(this.modules); + this.hooks.afterOptimizeModuleIds.call(this.modules); + + this.sortItemsWithModuleIds(); + + this.hooks.reviveChunks.call(this.chunks, this.records); + this.hooks.optimizeChunkOrder.call(this.chunks); + this.hooks.beforeChunkIds.call(this.chunks); + this.applyChunkIds(); + this.hooks.optimizeChunkIds.call(this.chunks); + this.hooks.afterOptimizeChunkIds.call(this.chunks); + + this.sortItemsWithChunkIds(); + + if (shouldRecord) { + this.hooks.recordModules.call(this.modules, this.records); + this.hooks.recordChunks.call(this.chunks, this.records); + } + + this.hooks.beforeHash.call(); + this.createHash(); + this.hooks.afterHash.call(); + + if (shouldRecord) { + this.hooks.recordHash.call(this.records); + } + + this.hooks.beforeModuleAssets.call(); + this.createModuleAssets(); + if (this.hooks.shouldGenerateChunkAssets.call() !== false) { + this.hooks.beforeChunkAssets.call(); + this.createChunkAssets(); + } + this.hooks.additionalChunkAssets.call(this.chunks); + this.summarizeDependencies(); + if (shouldRecord) { + this.hooks.record.call(this, this.records); + } + + this.hooks.additionalAssets.callAsync(err => { + if (err) { + return callback(err); + } + this.hooks.optimizeChunkAssets.callAsync(this.chunks, err => { + if (err) { + return callback(err); + } + this.hooks.afterOptimizeChunkAssets.call(this.chunks); + this.hooks.optimizeAssets.callAsync(this.assets, err => { + if (err) { + return callback(err); + } + this.hooks.afterOptimizeAssets.call(this.assets); + if (this.hooks.needAdditionalSeal.call()) { + this.unseal(); + return this.seal(callback); + } + return this.hooks.afterSeal.callAsync(callback); + }); + }); + }); + }); + } + + /** + * @param {Module[]} modules the modules array on compilation to perform the sort for + * @returns {void} + */ + sortModules(modules) { + // TODO webpack 5: this should only be enabled when `moduleIds: "natural"` + // TODO move it into a plugin (NaturalModuleIdsPlugin) and use this in WebpackOptionsApply + // TODO remove this method + modules.sort(byIndexOrIdentifier); + } + + /** + * @param {Module} module moulde to report from + * @param {DependenciesBlock[]} blocks blocks to report from + * @returns {void} + */ + reportDependencyErrorsAndWarnings(module, blocks) { + for (let indexBlock = 0; indexBlock < blocks.length; indexBlock++) { + const block = blocks[indexBlock]; + const dependencies = block.dependencies; + + for (let indexDep = 0; indexDep < dependencies.length; indexDep++) { + const d = dependencies[indexDep]; + + const warnings = d.getWarnings(); + if (warnings) { + for (let indexWar = 0; indexWar < warnings.length; indexWar++) { + const w = warnings[indexWar]; + + const warning = new ModuleDependencyWarning(module, w, d.loc); + this.warnings.push(warning); + } + } + const errors = d.getErrors(); + if (errors) { + for (let indexErr = 0; indexErr < errors.length; indexErr++) { + const e = errors[indexErr]; + + const error = new ModuleDependencyError(module, e, d.loc); + this.errors.push(error); + } + } + } + + this.reportDependencyErrorsAndWarnings(module, block.blocks); + } + } + + /** + * @param {TODO} groupOptions options for the chunk group + * @param {Module} module the module the references the chunk group + * @param {DependencyLocation} loc the location from with the chunk group is referenced (inside of module) + * @param {string} request the request from which the the chunk group is referenced + * @returns {ChunkGroup} the new or existing chunk group + */ + addChunkInGroup(groupOptions, module, loc, request) { + if (typeof groupOptions === "string") { + groupOptions = { name: groupOptions }; + } + const name = groupOptions.name; + if (name) { + const chunkGroup = this.namedChunkGroups.get(name); + if (chunkGroup !== undefined) { + chunkGroup.addOptions(groupOptions); + if (module) { + chunkGroup.addOrigin(module, loc, request); + } + return chunkGroup; + } + } + const chunkGroup = new ChunkGroup(groupOptions); + if (module) chunkGroup.addOrigin(module, loc, request); + const chunk = this.addChunk(name); + + GraphHelpers.connectChunkGroupAndChunk(chunkGroup, chunk); + + this.chunkGroups.push(chunkGroup); + if (name) { + this.namedChunkGroups.set(name, chunkGroup); + } + return chunkGroup; + } + + /** + * This method first looks to see if a name is provided for a new chunk, + * and first looks to see if any named chunks already exist and reuse that chunk instead. + * + * @param {string=} name optional chunk name to be provided + * @returns {Chunk} create a chunk (invoked during seal event) + */ + addChunk(name) { + if (name) { + const chunk = this.namedChunks.get(name); + if (chunk !== undefined) { + return chunk; + } + } + const chunk = new Chunk(name); + this.chunks.push(chunk); + if (name) { + this.namedChunks.set(name, chunk); + } + return chunk; + } + + /** + * @param {Module} module module to assign depth + * @returns {void} + */ + assignDepth(module) { + const queue = new Set([module]); + let depth; + + module.depth = 0; + + /** + * @param {Module} module module for processeing + * @returns {void} + */ + const enqueueJob = module => { + const d = module.depth; + if (typeof d === "number" && d <= depth) return; + queue.add(module); + module.depth = depth; + }; + + /** + * @param {Dependency} dependency dependency to assign depth to + * @returns {void} + */ + const assignDepthToDependency = dependency => { + if (dependency.module) { + enqueueJob(dependency.module); + } + }; + + /** + * @param {DependenciesBlock} block block to assign depth to + * @returns {void} + */ + const assignDepthToDependencyBlock = block => { + if (block.variables) { + iterationBlockVariable(block.variables, assignDepthToDependency); + } + + if (block.dependencies) { + iterationOfArrayCallback(block.dependencies, assignDepthToDependency); + } + + if (block.blocks) { + iterationOfArrayCallback(block.blocks, assignDepthToDependencyBlock); + } + }; + + for (module of queue) { + queue.delete(module); + depth = module.depth; + + depth++; + assignDepthToDependencyBlock(module); + } + } + + /** + * @param {Module} module the module containing the dependency + * @param {Dependency} dependency the dependency + * @returns {DependencyReference} a reference for the dependency + */ + getDependencyReference(module, dependency) { + // TODO remove dep.getReference existence check in webpack 5 + if (typeof dependency.getReference !== "function") return null; + const ref = dependency.getReference(); + if (!ref) return null; + return this.hooks.dependencyReference.call(ref, dependency, module); + } + + /** + * This method creates the Chunk graph from the Module graph + * @private + * @param {TODO[]} inputChunkGroups chunk groups which are processed + * @returns {void} + */ + processDependenciesBlocksForChunkGroups(inputChunkGroups) { + // Process is splitting into two parts: + // Part one traverse the module graph and builds a very basic chunks graph + // in chunkDependencies. + // Part two traverse every possible way through the basic chunk graph and + // tracks the available modules. While traversing it connects chunks with + // eachother and Blocks with Chunks. It stops traversing when all modules + // for a chunk are already available. So it doesn't connect unneeded chunks. + + /** @type {Map} */ + const chunkDependencies = new Map(); + const allCreatedChunkGroups = new Set(); + + // PREPARE + /** @type {Map} */ + const blockInfoMap = new Map(); + + /** + * @param {Dependency} d dependency to iterate over + * @returns {void} + */ + const iteratorDependency = d => { + // We skip Dependencies without Reference + const ref = this.getDependencyReference(currentModule, d); + if (!ref) { + return; + } + // We skip Dependencies without Module pointer + const refModule = ref.module; + if (!refModule) { + return; + } + // We skip weak Dependencies + if (ref.weak) { + return; + } + + blockInfoModules.add(refModule); + }; + + /** + * @param {AsyncDependenciesBlock} b blocks to prepare + * @returns {void} + */ + const iteratorBlockPrepare = b => { + blockInfoBlocks.push(b); + blockQueue.push(b); + }; + + /** @type {Module} */ + let currentModule; + /** @type {DependenciesBlock} */ + let block; + /** @type {DependenciesBlock[]} */ + let blockQueue; + /** @type {Set} */ + let blockInfoModules; + /** @type {AsyncDependenciesBlock[]} */ + let blockInfoBlocks; + + for (const module of this.modules) { + blockQueue = [module]; + currentModule = module; + while (blockQueue.length > 0) { + block = blockQueue.pop(); + blockInfoModules = new Set(); + blockInfoBlocks = []; + + if (block.variables) { + iterationBlockVariable(block.variables, iteratorDependency); + } + + if (block.dependencies) { + iterationOfArrayCallback(block.dependencies, iteratorDependency); + } + + if (block.blocks) { + iterationOfArrayCallback(block.blocks, iteratorBlockPrepare); + } + + const blockInfo = { + modules: Array.from(blockInfoModules), + blocks: blockInfoBlocks + }; + blockInfoMap.set(block, blockInfo); + } + } + + // PART ONE + + /** @type {Map} */ + const chunkGroupCounters = new Map(); + for (const chunkGroup of inputChunkGroups) { + chunkGroupCounters.set(chunkGroup, { index: 0, index2: 0 }); + } + + let nextFreeModuleIndex = 0; + let nextFreeModuleIndex2 = 0; + + /** @type {Map} */ + const blockChunkGroups = new Map(); + + /** @type {Set} */ + const blocksWithNestedBlocks = new Set(); + + const ADD_AND_ENTER_MODULE = 0; + const ENTER_MODULE = 1; + const PROCESS_BLOCK = 2; + const LEAVE_MODULE = 3; + + /** + * @typedef {Object} QueueItem + * @property {number} action + * @property {DependenciesBlock} block + * @property {Module} module + * @property {Chunk} chunk + * @property {ChunkGroup} chunkGroup + */ + + /** + * @param {ChunkGroup} chunkGroup chunk group + * @returns {QueueItem} queue item + */ + const chunkGroupToQueueItem = chunkGroup => ({ + action: ENTER_MODULE, + block: chunkGroup.chunks[0].entryModule, + module: chunkGroup.chunks[0].entryModule, + chunk: chunkGroup.chunks[0], + chunkGroup + }); + + // Start with the provided modules/chunks + /** @type {QueueItem[]} */ + let queue = inputChunkGroups.map(chunkGroupToQueueItem).reverse(); + /** @type {QueueItem[]} */ + let queueDelayed = []; + + /** @type {Module} */ + let module; + /** @type {Chunk} */ + let chunk; + /** @type {ChunkGroup} */ + let chunkGroup; + + // For each async Block in graph + /** + * @param {AsyncDependenciesBlock} b iterating over each Async DepBlock + * @returns {void} + */ + const iteratorBlock = b => { + // 1. We create a chunk for this Block + // but only once (blockChunkGroups map) + let c = blockChunkGroups.get(b); + if (c === undefined) { + c = this.namedChunkGroups.get(b.chunkName); + if (c && c.isInitial()) { + this.errors.push( + new AsyncDependencyToInitialChunkError(b.chunkName, module, b.loc) + ); + c = chunkGroup; + } else { + c = this.addChunkInGroup( + b.groupOptions || b.chunkName, + module, + b.loc, + b.request + ); + chunkGroupCounters.set(c, { index: 0, index2: 0 }); + blockChunkGroups.set(b, c); + allCreatedChunkGroups.add(c); + } + } else { + // TODO webpack 5 remove addOptions check + if (c.addOptions) c.addOptions(b.groupOptions); + c.addOrigin(module, b.loc, b.request); + } + + // 2. We store the Block+Chunk mapping as dependency for the chunk + let deps = chunkDependencies.get(chunkGroup); + if (!deps) chunkDependencies.set(chunkGroup, (deps = [])); + deps.push({ + block: b, + chunkGroup: c + }); + + // 3. We enqueue the DependenciesBlock for traversal + queueDelayed.push({ + action: PROCESS_BLOCK, + block: b, + module: module, + chunk: c.chunks[0], + chunkGroup: c + }); + }; + + // Iterative traversal of the Module graph + // Recursive would be simpler to write but could result in Stack Overflows + while (queue.length) { + while (queue.length) { + const queueItem = queue.pop(); + module = queueItem.module; + block = queueItem.block; + chunk = queueItem.chunk; + chunkGroup = queueItem.chunkGroup; + + switch (queueItem.action) { + case ADD_AND_ENTER_MODULE: { + // We connect Module and Chunk when not already done + if (chunk.addModule(module)) { + module.addChunk(chunk); + } else { + // already connected, skip it + break; + } + } + // fallthrough + case ENTER_MODULE: { + if (chunkGroup !== undefined) { + const index = chunkGroup.getModuleIndex(module); + if (index === undefined) { + chunkGroup.setModuleIndex( + module, + chunkGroupCounters.get(chunkGroup).index++ + ); + } + } + + if (module.index === null) { + module.index = nextFreeModuleIndex++; + } + + queue.push({ + action: LEAVE_MODULE, + block, + module, + chunk, + chunkGroup + }); + } + // fallthrough + case PROCESS_BLOCK: { + // get prepared block info + const blockInfo = blockInfoMap.get(block); + + // Traverse all referenced modules + for (let i = blockInfo.modules.length - 1; i >= 0; i--) { + const refModule = blockInfo.modules[i]; + if (chunk.containsModule(refModule)) { + // skip early if already connected + continue; + } + // enqueue the add and enter to enter in the correct order + // this is relevant with circular dependencies + queue.push({ + action: ADD_AND_ENTER_MODULE, + block: refModule, + module: refModule, + chunk, + chunkGroup + }); + } + + // Traverse all Blocks + iterationOfArrayCallback(blockInfo.blocks, iteratorBlock); + + if (blockInfo.blocks.length > 0 && module !== block) { + blocksWithNestedBlocks.add(block); + } + break; + } + case LEAVE_MODULE: { + if (chunkGroup !== undefined) { + const index = chunkGroup.getModuleIndex2(module); + if (index === undefined) { + chunkGroup.setModuleIndex2( + module, + chunkGroupCounters.get(chunkGroup).index2++ + ); + } + } + + if (module.index2 === null) { + module.index2 = nextFreeModuleIndex2++; + } + break; + } + } + } + const tempQueue = queue; + queue = queueDelayed.reverse(); + queueDelayed = tempQueue; + } + + // PART TWO + /** @type {Set} */ + let availableModules; + let newAvailableModules; + /** @type {Queue} */ + const queue2 = new Queue( + inputChunkGroups.map(chunkGroup => ({ + chunkGroup, + availableModules: new Set() + })) + ); + + /** + * Helper function to check if all modules of a chunk are available + * + * @param {ChunkGroup} chunkGroup the chunkGroup to scan + * @param {Set} availableModules the comparitor set + * @returns {boolean} return true if all modules of a chunk are available + */ + const areModulesAvailable = (chunkGroup, availableModules) => { + for (const chunk of chunkGroup.chunks) { + for (const module of chunk.modulesIterable) { + if (!availableModules.has(module)) return false; + } + } + return true; + }; + + // For each edge in the basic chunk graph + /** + * @param {TODO} dep the dependency used for filtering + * @returns {boolean} used to filter "edges" (aka Dependencies) that were pointing + * to modules that are already available. Also filters circular dependencies in the chunks graph + */ + const filterFn = dep => { + const depChunkGroup = dep.chunkGroup; + if (blocksWithNestedBlocks.has(dep.block)) return true; + if (areModulesAvailable(depChunkGroup, newAvailableModules)) return false; // break all modules are already available + return true; + }; + + /** @type {Map>} */ + const minAvailableModulesMap = new Map(); + + // Iterative traversing of the basic chunk graph + while (queue2.length) { + const queueItem = queue2.dequeue(); + chunkGroup = queueItem.chunkGroup; + availableModules = queueItem.availableModules; + + // 1. Get minimal available modules + // It doesn't make sense to traverse a chunk again with more available modules. + // This step calculates the minimal available modules and skips traversal when + // the list didn't shrink. + let minAvailableModules = minAvailableModulesMap.get(chunkGroup); + if (minAvailableModules === undefined) { + minAvailableModulesMap.set(chunkGroup, new Set(availableModules)); + } else { + let deletedModules = false; + for (const m of minAvailableModules) { + if (!availableModules.has(m)) { + minAvailableModules.delete(m); + deletedModules = true; + } + } + if (!deletedModules) continue; + availableModules = minAvailableModules; + } + + // 2. Get the edges at this point of the graph + const deps = chunkDependencies.get(chunkGroup); + if (!deps) continue; + if (deps.length === 0) continue; + + // 3. Create a new Set of available modules at this points + newAvailableModules = new Set(availableModules); + for (const chunk of chunkGroup.chunks) { + for (const m of chunk.modulesIterable) { + newAvailableModules.add(m); + } + } + + // 4. Filter edges with available modules + const filteredDeps = deps.filter(filterFn); + + // 5. Foreach remaining edge + const nextChunkGroups = new Set(); + for (let i = 0; i < filteredDeps.length; i++) { + const dep = filteredDeps[i]; + const depChunkGroup = dep.chunkGroup; + const depBlock = dep.block; + + // 6. Connect block with chunk + GraphHelpers.connectDependenciesBlockAndChunkGroup( + depBlock, + depChunkGroup + ); + + // 7. Connect chunk with parent + GraphHelpers.connectChunkGroupParentAndChild(chunkGroup, depChunkGroup); + + nextChunkGroups.add(depChunkGroup); + } + + // 8. Enqueue further traversal + for (const nextChunkGroup of nextChunkGroups) { + queue2.enqueue({ + chunkGroup: nextChunkGroup, + availableModules: newAvailableModules + }); + } + } + + // Remove all unconnected chunk groups + for (const chunkGroup of allCreatedChunkGroups) { + if (chunkGroup.getNumberOfParents() === 0) { + for (const chunk of chunkGroup.chunks) { + const idx = this.chunks.indexOf(chunk); + if (idx >= 0) this.chunks.splice(idx, 1); + chunk.remove("unconnected"); + } + chunkGroup.remove("unconnected"); + } + } + } + + /** + * + * @param {Module} module module relationship for removal + * @param {DependenciesBlockLike} block //TODO: good description + * @returns {void} + */ + removeReasonsOfDependencyBlock(module, block) { + const iteratorDependency = d => { + if (!d.module) { + return; + } + if (d.module.removeReason(module, d)) { + for (const chunk of d.module.chunksIterable) { + this.patchChunksAfterReasonRemoval(d.module, chunk); + } + } + }; + + if (block.blocks) { + iterationOfArrayCallback(block.blocks, block => + this.removeReasonsOfDependencyBlock(module, block) + ); + } + + if (block.dependencies) { + iterationOfArrayCallback(block.dependencies, iteratorDependency); + } + + if (block.variables) { + iterationBlockVariable(block.variables, iteratorDependency); + } + } + + /** + * @param {Module} module module to patch tie + * @param {Chunk} chunk chunk to patch tie + * @returns {void} + */ + patchChunksAfterReasonRemoval(module, chunk) { + if (!module.hasReasons()) { + this.removeReasonsOfDependencyBlock(module, module); + } + if (!module.hasReasonForChunk(chunk)) { + if (module.removeChunk(chunk)) { + this.removeChunkFromDependencies(module, chunk); + } + } + } + + /** + * + * @param {DependenciesBlock} block block tie for Chunk + * @param {Chunk} chunk chunk to remove from dep + * @returns {void} + */ + removeChunkFromDependencies(block, chunk) { + const iteratorDependency = d => { + if (!d.module) { + return; + } + this.patchChunksAfterReasonRemoval(d.module, chunk); + }; + + const blocks = block.blocks; + for (let indexBlock = 0; indexBlock < blocks.length; indexBlock++) { + const asyncBlock = blocks[indexBlock]; + // Grab all chunks from the first Block's AsyncDepBlock + const chunks = asyncBlock.chunkGroup.chunks; + // For each chunk in chunkGroup + for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) { + const iteratedChunk = chunks[indexChunk]; + asyncBlock.chunkGroup.removeChunk(iteratedChunk); + asyncBlock.chunkGroup.removeParent(iteratedChunk); + // Recurse + this.removeChunkFromDependencies(block, iteratedChunk); + } + } + + if (block.dependencies) { + iterationOfArrayCallback(block.dependencies, iteratorDependency); + } + + if (block.variables) { + iterationBlockVariable(block.variables, iteratorDependency); + } + } + + applyModuleIds() { + const unusedIds = []; + let nextFreeModuleId = 0; + const usedIds = new Set(); + if (this.usedModuleIds) { + for (const id of this.usedModuleIds) { + usedIds.add(id); + } + } + + const modules1 = this.modules; + for (let indexModule1 = 0; indexModule1 < modules1.length; indexModule1++) { + const module1 = modules1[indexModule1]; + if (module1.id !== null) { + usedIds.add(module1.id); + } + } + + if (usedIds.size > 0) { + let usedIdMax = -1; + for (const usedIdKey of usedIds) { + if (typeof usedIdKey !== "number") { + continue; + } + + usedIdMax = Math.max(usedIdMax, usedIdKey); + } + + let lengthFreeModules = (nextFreeModuleId = usedIdMax + 1); + + while (lengthFreeModules--) { + if (!usedIds.has(lengthFreeModules)) { + unusedIds.push(lengthFreeModules); + } + } + } + + const modules2 = this.modules; + for (let indexModule2 = 0; indexModule2 < modules2.length; indexModule2++) { + const module2 = modules2[indexModule2]; + if (module2.id === null) { + if (unusedIds.length > 0) { + module2.id = unusedIds.pop(); + } else { + module2.id = nextFreeModuleId++; + } + } + } + } + + applyChunkIds() { + /** @type {Set} */ + const usedIds = new Set(); + + // Get used ids from usedChunkIds property (i. e. from records) + if (this.usedChunkIds) { + for (const id of this.usedChunkIds) { + if (typeof id !== "number") { + continue; + } + + usedIds.add(id); + } + } + + // Get used ids from existing chunks + const chunks = this.chunks; + for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) { + const chunk = chunks[indexChunk]; + const usedIdValue = chunk.id; + + if (typeof usedIdValue !== "number") { + continue; + } + + usedIds.add(usedIdValue); + } + + // Calculate maximum assigned chunk id + let nextFreeChunkId = -1; + for (const id of usedIds) { + nextFreeChunkId = Math.max(nextFreeChunkId, id); + } + nextFreeChunkId++; + + // Determine free chunk ids from 0 to maximum + /** @type {number[]} */ + const unusedIds = []; + if (nextFreeChunkId > 0) { + let index = nextFreeChunkId; + while (index--) { + if (!usedIds.has(index)) { + unusedIds.push(index); + } + } + } + + // Assign ids to chunk which has no id + for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) { + const chunk = chunks[indexChunk]; + if (chunk.id === null) { + if (unusedIds.length > 0) { + chunk.id = unusedIds.pop(); + } else { + chunk.id = nextFreeChunkId++; + } + } + if (!chunk.ids) { + chunk.ids = [chunk.id]; + } + } + } + + sortItemsWithModuleIds() { + this.modules.sort(byIdOrIdentifier); + + const modules = this.modules; + for (let indexModule = 0; indexModule < modules.length; indexModule++) { + modules[indexModule].sortItems(false); + } + + const chunks = this.chunks; + for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) { + chunks[indexChunk].sortItems(); + } + } + + sortItemsWithChunkIds() { + for (const chunkGroup of this.chunkGroups) { + chunkGroup.sortItems(); + } + + this.chunks.sort(byId); + + for ( + let indexModule = 0; + indexModule < this.modules.length; + indexModule++ + ) { + this.modules[indexModule].sortItems(true); + } + + const chunks = this.chunks; + for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) { + chunks[indexChunk].sortItems(); + } + + /** + * Used to sort errors and warnings in compilation. this.warnings, and + * this.errors contribute to the compilation hash and therefore should be + * updated whenever other references (having a chunk id) are sorted. This preserves the hash + * integrity + * + * @param {WebpackError} a first WebpackError instance (including subclasses) + * @param {WebpackError} b second WebpackError instance (including subclasses) + * @returns {-1|0|1} sort order index + */ + const byMessage = (a, b) => { + const ma = `${a.message}`; + const mb = `${b.message}`; + if (ma < mb) return -1; + if (mb < ma) return 1; + return 0; + }; + + this.errors.sort(byMessage); + this.warnings.sort(byMessage); + this.children.sort(byNameOrHash); + } + + summarizeDependencies() { + this.fileDependencies = new SortableSet(this.compilationDependencies); + this.contextDependencies = new SortableSet(); + this.missingDependencies = new SortableSet(); + + for ( + let indexChildren = 0; + indexChildren < this.children.length; + indexChildren++ + ) { + const child = this.children[indexChildren]; + + addAllToSet(this.fileDependencies, child.fileDependencies); + addAllToSet(this.contextDependencies, child.contextDependencies); + addAllToSet(this.missingDependencies, child.missingDependencies); + } + + for ( + let indexModule = 0; + indexModule < this.modules.length; + indexModule++ + ) { + const module = this.modules[indexModule]; + + if (module.buildInfo.fileDependencies) { + addAllToSet(this.fileDependencies, module.buildInfo.fileDependencies); + } + if (module.buildInfo.contextDependencies) { + addAllToSet( + this.contextDependencies, + module.buildInfo.contextDependencies + ); + } + } + for (const error of this.errors) { + if ( + typeof error.missing === "object" && + error.missing && + error.missing[Symbol.iterator] + ) { + addAllToSet(this.missingDependencies, error.missing); + } + } + this.fileDependencies.sort(); + this.contextDependencies.sort(); + this.missingDependencies.sort(); + } + + createHash() { + const outputOptions = this.outputOptions; + const hashFunction = outputOptions.hashFunction; + const hashDigest = outputOptions.hashDigest; + const hashDigestLength = outputOptions.hashDigestLength; + const hash = createHash(hashFunction); + if (outputOptions.hashSalt) { + hash.update(outputOptions.hashSalt); + } + this.mainTemplate.updateHash(hash); + this.chunkTemplate.updateHash(hash); + for (const key of Object.keys(this.moduleTemplates).sort()) { + this.moduleTemplates[key].updateHash(hash); + } + for (const child of this.children) { + hash.update(child.hash); + } + for (const warning of this.warnings) { + hash.update(`${warning.message}`); + } + for (const error of this.errors) { + hash.update(`${error.message}`); + } + const modules = this.modules; + for (let i = 0; i < modules.length; i++) { + const module = modules[i]; + const moduleHash = createHash(hashFunction); + module.updateHash(moduleHash); + module.hash = moduleHash.digest(hashDigest); + module.renderedHash = module.hash.substr(0, hashDigestLength); + } + // clone needed as sort below is inplace mutation + const chunks = this.chunks.slice(); + /** + * sort here will bring all "falsy" values to the beginning + * this is needed as the "hasRuntime()" chunks are dependent on the + * hashes of the non-runtime chunks. + */ + chunks.sort((a, b) => { + const aEntry = a.hasRuntime(); + const bEntry = b.hasRuntime(); + if (aEntry && !bEntry) return 1; + if (!aEntry && bEntry) return -1; + return byId(a, b); + }); + for (let i = 0; i < chunks.length; i++) { + const chunk = chunks[i]; + const chunkHash = createHash(hashFunction); + if (outputOptions.hashSalt) { + chunkHash.update(outputOptions.hashSalt); + } + chunk.updateHash(chunkHash); + const template = chunk.hasRuntime() + ? this.mainTemplate + : this.chunkTemplate; + template.updateHashForChunk( + chunkHash, + chunk, + this.moduleTemplates.javascript, + this.dependencyTemplates + ); + this.hooks.chunkHash.call(chunk, chunkHash); + chunk.hash = chunkHash.digest(hashDigest); + hash.update(chunk.hash); + chunk.renderedHash = chunk.hash.substr(0, hashDigestLength); + this.hooks.contentHash.call(chunk); + } + this.fullHash = hash.digest(hashDigest); + this.hash = this.fullHash.substr(0, hashDigestLength); + } + + /** + * @param {string} update extra information + * @returns {void} + */ + modifyHash(update) { + const outputOptions = this.outputOptions; + const hashFunction = outputOptions.hashFunction; + const hashDigest = outputOptions.hashDigest; + const hashDigestLength = outputOptions.hashDigestLength; + const hash = createHash(hashFunction); + hash.update(this.fullHash); + hash.update(update); + this.fullHash = hash.digest(hashDigest); + this.hash = this.fullHash.substr(0, hashDigestLength); + } + + createModuleAssets() { + for (let i = 0; i < this.modules.length; i++) { + const module = this.modules[i]; + if (module.buildInfo.assets) { + for (const assetName of Object.keys(module.buildInfo.assets)) { + const fileName = this.getPath(assetName); + this.assets[fileName] = module.buildInfo.assets[assetName]; + this.hooks.moduleAsset.call(module, fileName); + } + } + } + } + + createChunkAssets() { + const outputOptions = this.outputOptions; + const cachedSourceMap = new Map(); + /** @type {Map} */ + const alreadyWrittenFiles = new Map(); + for (let i = 0; i < this.chunks.length; i++) { + const chunk = this.chunks[i]; + chunk.files = []; + let source; + let file; + let filenameTemplate; + try { + const template = chunk.hasRuntime() + ? this.mainTemplate + : this.chunkTemplate; + const manifest = template.getRenderManifest({ + chunk, + hash: this.hash, + fullHash: this.fullHash, + outputOptions, + moduleTemplates: this.moduleTemplates, + dependencyTemplates: this.dependencyTemplates + }); // [{ render(), filenameTemplate, pathOptions, identifier, hash }] + for (const fileManifest of manifest) { + const cacheName = fileManifest.identifier; + const usedHash = fileManifest.hash; + filenameTemplate = fileManifest.filenameTemplate; + file = this.getPath(filenameTemplate, fileManifest.pathOptions); + + // check if the same filename was already written by another chunk + const alreadyWritten = alreadyWrittenFiles.get(file); + if (alreadyWritten !== undefined) { + if (alreadyWritten.hash === usedHash) { + if (this.cache) { + this.cache[cacheName] = { + hash: usedHash, + source: alreadyWritten.source + }; + } + chunk.files.push(file); + this.hooks.chunkAsset.call(chunk, file); + continue; + } else { + throw new Error( + `Conflict: Multiple chunks emit assets to the same filename ${file}` + + ` (chunks ${alreadyWritten.chunk.id} and ${chunk.id})` + ); + } + } + if ( + this.cache && + this.cache[cacheName] && + this.cache[cacheName].hash === usedHash + ) { + source = this.cache[cacheName].source; + } else { + source = fileManifest.render(); + // Ensure that source is a cached source to avoid additional cost because of repeated access + if (!(source instanceof CachedSource)) { + const cacheEntry = cachedSourceMap.get(source); + if (cacheEntry) { + source = cacheEntry; + } else { + const cachedSource = new CachedSource(source); + cachedSourceMap.set(source, cachedSource); + source = cachedSource; + } + } + if (this.cache) { + this.cache[cacheName] = { + hash: usedHash, + source + }; + } + } + if (this.assets[file] && this.assets[file] !== source) { + throw new Error( + `Conflict: Multiple assets emit to the same filename ${file}` + ); + } + this.assets[file] = source; + chunk.files.push(file); + this.hooks.chunkAsset.call(chunk, file); + alreadyWrittenFiles.set(file, { + hash: usedHash, + source, + chunk + }); + } + } catch (err) { + this.errors.push( + new ChunkRenderError(chunk, file || filenameTemplate, err) + ); + } + } + } + + /** + * @param {string} filename used to get asset path with hash + * @param {TODO=} data // TODO: figure out this param type + * @returns {string} interpolated path + */ + getPath(filename, data) { + data = data || {}; + data.hash = data.hash || this.hash; + return this.mainTemplate.getAssetPath(filename, data); + } + + /** + * This function allows you to run another instance of webpack inside of webpack however as + * a child with different settings and configurations (if desired) applied. It copies all hooks, plugins + * from parent (or top level compiler) and creates a child Compilation + * + * @param {string} name name of the child compiler + * @param {TODO} outputOptions // Need to convert config schema to types for this + * @param {Plugin[]} plugins webpack plugins that will be applied + * @returns {Compiler} creates a child Compiler instance + */ + createChildCompiler(name, outputOptions, plugins) { + const idx = this.childrenCounters[name] || 0; + this.childrenCounters[name] = idx + 1; + return this.compiler.createChildCompiler( + this, + name, + idx, + outputOptions, + plugins + ); + } + + checkConstraints() { + /** @type {Set} */ + const usedIds = new Set(); + + const modules = this.modules; + for (let indexModule = 0; indexModule < modules.length; indexModule++) { + const moduleId = modules[indexModule].id; + if (moduleId === null) continue; + if (usedIds.has(moduleId)) { + throw new Error(`checkConstraints: duplicate module id ${moduleId}`); + } + usedIds.add(moduleId); + } + + const chunks = this.chunks; + for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) { + const chunk = chunks[indexChunk]; + if (chunks.indexOf(chunk) !== indexChunk) { + throw new Error( + `checkConstraints: duplicate chunk in compilation ${chunk.debugId}` + ); + } + } + + for (const chunkGroup of this.chunkGroups) { + chunkGroup.checkConstraints(); + } + } +} + +// TODO remove in webpack 5 +Compilation.prototype.applyPlugins = util.deprecate( + /** + * @deprecated + * @param {string} name Name + * @param {any[]} args Other arguments + * @returns {void} + * @this {Compilation} + */ + function(name, ...args) { + this.hooks[ + name.replace(/[- ]([a-z])/g, match => match[1].toUpperCase()) + ].call(...args); + }, + "Compilation.applyPlugins is deprecated. Use new API on `.hooks` instead" +); + +// TODO remove in webpack 5 +Object.defineProperty(Compilation.prototype, "moduleTemplate", { + configurable: false, + get: util.deprecate( + /** + * @deprecated + * @this {Compilation} + * @returns {TODO} module template + */ + function() { + return this.moduleTemplates.javascript; + }, + "Compilation.moduleTemplate: Use Compilation.moduleTemplates.javascript instead" + ), + set: util.deprecate( + /** + * @deprecated + * @param {ModuleTemplate} value Template value + * @this {Compilation} + * @returns {void} + */ + function(value) { + this.moduleTemplates.javascript = value; + }, + "Compilation.moduleTemplate: Use Compilation.moduleTemplates.javascript instead." + ) +}); + +module.exports = Compilation; diff --git a/node_modules/webpack/lib/Compiler.js b/node_modules/webpack/lib/Compiler.js index 4c7e02b4e..bf7338fca 100644 --- a/node_modules/webpack/lib/Compiler.js +++ b/node_modules/webpack/lib/Compiler.js @@ -1,519 +1,561 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const path = require("path"); -const Tapable = require("tapable"); -const util = require("util"); - -const Compilation = require("./Compilation"); -const Stats = require("./Stats"); -const NormalModuleFactory = require("./NormalModuleFactory"); -const ContextModuleFactory = require("./ContextModuleFactory"); - -const makePathsRelative = require("./util/identifier").makePathsRelative; - -class Watching { - constructor(compiler, watchOptions, handler) { - this.startTime = null; - this.invalid = false; - this.handler = handler; - this.callbacks = []; - this.closed = false; - if(typeof watchOptions === "number") { - this.watchOptions = { - aggregateTimeout: watchOptions - }; - } else if(watchOptions && typeof watchOptions === "object") { - this.watchOptions = Object.assign({}, watchOptions); - } else { - this.watchOptions = {}; - } - this.watchOptions.aggregateTimeout = this.watchOptions.aggregateTimeout || 200; - this.compiler = compiler; - this.running = true; - this.compiler.readRecords(err => { - if(err) return this._done(err); - - this._go(); - }); - } - - _go() { - this.startTime = Date.now(); - this.running = true; - this.invalid = false; - this.compiler.applyPluginsAsync("watch-run", this, err => { - if(err) return this._done(err); - const onCompiled = (err, compilation) => { - if(err) return this._done(err); - if(this.invalid) return this._done(); - - if(this.compiler.applyPluginsBailResult("should-emit", compilation) === false) { - return this._done(null, compilation); - } - - this.compiler.emitAssets(compilation, err => { - if(err) return this._done(err); - if(this.invalid) return this._done(); - - this.compiler.emitRecords(err => { - if(err) return this._done(err); - - if(compilation.applyPluginsBailResult("need-additional-pass")) { - compilation.needAdditionalPass = true; - - const stats = new Stats(compilation); - stats.startTime = this.startTime; - stats.endTime = Date.now(); - this.compiler.applyPlugins("done", stats); - - this.compiler.applyPluginsAsync("additional-pass", err => { - if(err) return this._done(err); - this.compiler.compile(onCompiled); - }); - return; - } - return this._done(null, compilation); - }); - }); - }; - this.compiler.compile(onCompiled); - }); - } - - _getStats(compilation) { - const stats = new Stats(compilation); - stats.startTime = this.startTime; - stats.endTime = Date.now(); - return stats; - } - - _done(err, compilation) { - this.running = false; - if(this.invalid) return this._go(); - - const stats = compilation ? this._getStats(compilation) : null; - if(err) { - this.compiler.applyPlugins("failed", err); - this.handler(err, stats); - return; - } - - this.compiler.applyPlugins("done", stats); - this.handler(null, stats); - if(!this.closed) { - this.watch(compilation.fileDependencies, compilation.contextDependencies, compilation.missingDependencies); - } - this.callbacks.forEach(cb => cb()); - this.callbacks.length = 0; - } - - watch(files, dirs, missing) { - this.pausedWatcher = null; - this.watcher = this.compiler.watchFileSystem.watch(files, dirs, missing, this.startTime, this.watchOptions, (err, filesModified, contextModified, missingModified, fileTimestamps, contextTimestamps) => { - this.pausedWatcher = this.watcher; - this.watcher = null; - if(err) return this.handler(err); - - this.compiler.fileTimestamps = fileTimestamps; - this.compiler.contextTimestamps = contextTimestamps; - this.invalidate(); - }, (fileName, changeTime) => { - this.compiler.applyPlugins("invalid", fileName, changeTime); - }); - } - - invalidate(callback) { - if(callback) { - this.callbacks.push(callback); - } - if(this.watcher) { - this.pausedWatcher = this.watcher; - this.watcher.pause(); - this.watcher = null; - } - if(this.running) { - this.invalid = true; - return false; - } else { - this._go(); - } - } - - close(callback) { - if(callback === undefined) callback = function() {}; - - this.closed = true; - if(this.watcher) { - this.watcher.close(); - this.watcher = null; - } - if(this.pausedWatcher) { - this.pausedWatcher.close(); - this.pausedWatcher = null; - } - if(this.running) { - this.invalid = true; - this._done = () => { - this.compiler.applyPlugins("watch-close"); - callback(); - }; - } else { - this.compiler.applyPlugins("watch-close"); - callback(); - } - } -} - -class Compiler extends Tapable { - constructor() { - super(); - this.outputPath = ""; - this.outputFileSystem = null; - this.inputFileSystem = null; - - this.recordsInputPath = null; - this.recordsOutputPath = null; - this.records = {}; - - this.fileTimestamps = {}; - this.contextTimestamps = {}; - - this.resolvers = { - normal: null, - loader: null, - context: null - }; - this.parser = { - plugin: util.deprecate( - (hook, fn) => { - this.plugin("compilation", (compilation, data) => { - data.normalModuleFactory.plugin("parser", parser => { - parser.plugin(hook, fn); - }); - }); - }, - "webpack: Using compiler.parser is deprecated.\n" + - "Use compiler.plugin(\"compilation\", function(compilation, data) {\n data.normalModuleFactory.plugin(\"parser\", function(parser, options) { parser.plugin(/* ... */); });\n}); instead. " - ), - apply: util.deprecate( - () => { - const args = arguments; - this.plugin("compilation", (compilation, data) => { - data.normalModuleFactory.plugin("parser", parser => { - parser.apply.apply(parser, args); - }); - }); - }, - "webpack: Using compiler.parser is deprecated.\n" + - "Use compiler.plugin(\"compilation\", function(compilation, data) {\n data.normalModuleFactory.plugin(\"parser\", function(parser, options) { parser.apply(/* ... */); });\n}); instead. " - ) - }; - - this.options = {}; - } - - watch(watchOptions, handler) { - this.fileTimestamps = {}; - this.contextTimestamps = {}; - const watching = new Watching(this, watchOptions, handler); - return watching; - } - - run(callback) { - const startTime = Date.now(); - - const onCompiled = (err, compilation) => { - if(err) return callback(err); - - if(this.applyPluginsBailResult("should-emit", compilation) === false) { - const stats = new Stats(compilation); - stats.startTime = startTime; - stats.endTime = Date.now(); - this.applyPlugins("done", stats); - return callback(null, stats); - } - - this.emitAssets(compilation, err => { - if(err) return callback(err); - - if(compilation.applyPluginsBailResult("need-additional-pass")) { - compilation.needAdditionalPass = true; - - const stats = new Stats(compilation); - stats.startTime = startTime; - stats.endTime = Date.now(); - this.applyPlugins("done", stats); - - this.applyPluginsAsync("additional-pass", err => { - if(err) return callback(err); - this.compile(onCompiled); - }); - return; - } - - this.emitRecords(err => { - if(err) return callback(err); - - const stats = new Stats(compilation); - stats.startTime = startTime; - stats.endTime = Date.now(); - this.applyPlugins("done", stats); - return callback(null, stats); - }); - }); - }; - - this.applyPluginsAsync("before-run", this, err => { - if(err) return callback(err); - - this.applyPluginsAsync("run", this, err => { - if(err) return callback(err); - - this.readRecords(err => { - if(err) return callback(err); - - this.compile(onCompiled); - }); - }); - }); - } - - runAsChild(callback) { - this.compile((err, compilation) => { - if(err) return callback(err); - - this.parentCompilation.children.push(compilation); - Object.keys(compilation.assets).forEach(name => { - this.parentCompilation.assets[name] = compilation.assets[name]; - }); - - const entries = Object.keys(compilation.entrypoints).map(name => { - return compilation.entrypoints[name].chunks; - }).reduce((array, chunks) => { - return array.concat(chunks); - }, []); - - return callback(null, entries, compilation); - }); - } - - purgeInputFileSystem() { - if(this.inputFileSystem && this.inputFileSystem.purge) - this.inputFileSystem.purge(); - } - - emitAssets(compilation, callback) { - let outputPath; - - const emitFiles = (err) => { - if(err) return callback(err); - - require("async").forEach(Object.keys(compilation.assets), (file, callback) => { - - let targetFile = file; - const queryStringIdx = targetFile.indexOf("?"); - if(queryStringIdx >= 0) { - targetFile = targetFile.substr(0, queryStringIdx); - } - - const writeOut = (err) => { - if(err) return callback(err); - const targetPath = this.outputFileSystem.join(outputPath, targetFile); - const source = compilation.assets[file]; - if(source.existsAt === targetPath) { - source.emitted = false; - return callback(); - } - let content = source.source(); - - if(!Buffer.isBuffer(content)) { - content = new Buffer(content, "utf8"); // eslint-disable-line - } - - source.existsAt = targetPath; - source.emitted = true; - this.outputFileSystem.writeFile(targetPath, content, callback); - }; - - if(targetFile.match(/\/|\\/)) { - const dir = path.dirname(targetFile); - this.outputFileSystem.mkdirp(this.outputFileSystem.join(outputPath, dir), writeOut); - } else writeOut(); - - }, err => { - if(err) return callback(err); - - afterEmit.call(this); - }); - }; - - this.applyPluginsAsync("emit", compilation, err => { - if(err) return callback(err); - outputPath = compilation.getPath(this.outputPath); - this.outputFileSystem.mkdirp(outputPath, emitFiles); - }); - - function afterEmit() { - this.applyPluginsAsyncSeries1("after-emit", compilation, err => { - if(err) return callback(err); - - return callback(); - }); - } - - } - - emitRecords(callback) { - if(!this.recordsOutputPath) return callback(); - const idx1 = this.recordsOutputPath.lastIndexOf("/"); - const idx2 = this.recordsOutputPath.lastIndexOf("\\"); - let recordsOutputPathDirectory = null; - if(idx1 > idx2) recordsOutputPathDirectory = this.recordsOutputPath.substr(0, idx1); - if(idx1 < idx2) recordsOutputPathDirectory = this.recordsOutputPath.substr(0, idx2); - if(!recordsOutputPathDirectory) return writeFile.call(this); - this.outputFileSystem.mkdirp(recordsOutputPathDirectory, err => { - if(err) return callback(err); - writeFile.call(this); - }); - - function writeFile() { - this.outputFileSystem.writeFile(this.recordsOutputPath, JSON.stringify(this.records, undefined, 2), callback); - } - } - - readRecords(callback) { - if(!this.recordsInputPath) { - this.records = {}; - return callback(); - } - this.inputFileSystem.stat(this.recordsInputPath, err => { - // It doesn't exist - // We can ignore this. - if(err) return callback(); - - this.inputFileSystem.readFile(this.recordsInputPath, (err, content) => { - if(err) return callback(err); - - try { - this.records = JSON.parse(content.toString("utf-8")); - } catch(e) { - e.message = "Cannot parse records: " + e.message; - return callback(e); - } - - return callback(); - }); - }); - } - - createChildCompiler(compilation, compilerName, compilerIndex, outputOptions, plugins) { - const childCompiler = new Compiler(); - if(Array.isArray(plugins)) { - plugins.forEach(plugin => childCompiler.apply(plugin)); - } - for(const name in this._plugins) { - if(["make", "compile", "emit", "after-emit", "invalid", "done", "this-compilation"].indexOf(name) < 0) - childCompiler._plugins[name] = this._plugins[name].slice(); - } - childCompiler.name = compilerName; - childCompiler.outputPath = this.outputPath; - childCompiler.inputFileSystem = this.inputFileSystem; - childCompiler.outputFileSystem = null; - childCompiler.resolvers = this.resolvers; - childCompiler.fileTimestamps = this.fileTimestamps; - childCompiler.contextTimestamps = this.contextTimestamps; - - const relativeCompilerName = makePathsRelative(this.context, compilerName); - if(!this.records[relativeCompilerName]) this.records[relativeCompilerName] = []; - if(this.records[relativeCompilerName][compilerIndex]) - childCompiler.records = this.records[relativeCompilerName][compilerIndex]; - else - this.records[relativeCompilerName].push(childCompiler.records = {}); - - childCompiler.options = Object.create(this.options); - childCompiler.options.output = Object.create(childCompiler.options.output); - for(const name in outputOptions) { - childCompiler.options.output[name] = outputOptions[name]; - } - childCompiler.parentCompilation = compilation; - - compilation.applyPlugins("child-compiler", childCompiler, compilerName, compilerIndex); - - return childCompiler; - } - - isChild() { - return !!this.parentCompilation; - } - - createCompilation() { - return new Compilation(this); - } - - newCompilation(params) { - const compilation = this.createCompilation(); - compilation.fileTimestamps = this.fileTimestamps; - compilation.contextTimestamps = this.contextTimestamps; - compilation.name = this.name; - compilation.records = this.records; - compilation.compilationDependencies = params.compilationDependencies; - this.applyPlugins("this-compilation", compilation, params); - this.applyPlugins("compilation", compilation, params); - return compilation; - } - - createNormalModuleFactory() { - const normalModuleFactory = new NormalModuleFactory(this.options.context, this.resolvers, this.options.module || {}); - this.applyPlugins("normal-module-factory", normalModuleFactory); - return normalModuleFactory; - } - - createContextModuleFactory() { - const contextModuleFactory = new ContextModuleFactory(this.resolvers, this.inputFileSystem); - this.applyPlugins("context-module-factory", contextModuleFactory); - return contextModuleFactory; - } - - newCompilationParams() { - const params = { - normalModuleFactory: this.createNormalModuleFactory(), - contextModuleFactory: this.createContextModuleFactory(), - compilationDependencies: [] - }; - return params; - } - - compile(callback) { - const params = this.newCompilationParams(); - this.applyPluginsAsync("before-compile", params, err => { - if(err) return callback(err); - - this.applyPlugins("compile", params); - - const compilation = this.newCompilation(params); - - this.applyPluginsParallel("make", compilation, err => { - if(err) return callback(err); - - compilation.finish(); - - compilation.seal(err => { - if(err) return callback(err); - - this.applyPluginsAsync("after-compile", compilation, err => { - if(err) return callback(err); - - return callback(null, compilation); - }); - }); - }); - }); - } -} - -Compiler.Watching = Watching; -module.exports = Compiler; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const parseJson = require("json-parse-better-errors"); +const asyncLib = require("neo-async"); +const path = require("path"); +const util = require("util"); +const { + Tapable, + SyncHook, + SyncBailHook, + AsyncParallelHook, + AsyncSeriesHook +} = require("tapable"); + +const Compilation = require("./Compilation"); +const Stats = require("./Stats"); +const Watching = require("./Watching"); +const NormalModuleFactory = require("./NormalModuleFactory"); +const ContextModuleFactory = require("./ContextModuleFactory"); +const ResolverFactory = require("./ResolverFactory"); + +const RequestShortener = require("./RequestShortener"); +const { makePathsRelative } = require("./util/identifier"); +const ConcurrentCompilationError = require("./ConcurrentCompilationError"); + +/** + * @typedef {Object} CompilationParams + * @property {NormalModuleFactory} normalModuleFactory + * @property {ContextModuleFactory} contextModuleFactory + * @property {Set} compilationDependencies + */ + +/** @typedef {string|string[]} EntryValues */ +/** @typedef {Record} EntryOptionValues */ + +/** + * @callback EntryOptionValuesFunction + * @returns {EntryOptionValues | EntryValues} the computed value + */ + +/** @typedef {EntryOptionValuesFunction | EntryOptionValues | EntryValues} EntryOptions */ + +class Compiler extends Tapable { + constructor(context) { + super(); + this.hooks = { + /** @type {SyncBailHook} */ + shouldEmit: new SyncBailHook(["compilation"]), + /** @type {AsyncSeriesHook} */ + done: new AsyncSeriesHook(["stats"]), + /** @type {AsyncSeriesHook<>} */ + additionalPass: new AsyncSeriesHook([]), + /** @type {AsyncSeriesHook} */ + beforeRun: new AsyncSeriesHook(["compiler"]), + /** @type {AsyncSeriesHook} */ + run: new AsyncSeriesHook(["compiler"]), + /** @type {AsyncSeriesHook} */ + emit: new AsyncSeriesHook(["compilation"]), + /** @type {AsyncSeriesHook} */ + afterEmit: new AsyncSeriesHook(["compilation"]), + + /** @type {SyncHook} */ + thisCompilation: new SyncHook(["compilation", "params"]), + /** @type {SyncHook} */ + compilation: new SyncHook(["compilation", "params"]), + /** @type {SyncHook} */ + normalModuleFactory: new SyncHook(["normalModuleFactory"]), + /** @type {SyncHook} */ + contextModuleFactory: new SyncHook(["contextModulefactory"]), + + /** @type {AsyncSeriesHook} */ + beforeCompile: new AsyncSeriesHook(["params"]), + /** @type {SyncHook} */ + compile: new SyncHook(["params"]), + /** @type {AsyncParallelHook} */ + make: new AsyncParallelHook(["compilation"]), + /** @type {AsyncSeriesHook} */ + afterCompile: new AsyncSeriesHook(["compilation"]), + + /** @type {AsyncSeriesHook} */ + watchRun: new AsyncSeriesHook(["compiler"]), + /** @type {SyncHook} */ + failed: new SyncHook(["error"]), + /** @type {SyncHook} */ + invalid: new SyncHook(["filename", "changeTime"]), + /** @type {SyncHook} */ + watchClose: new SyncHook([]), + + // TODO the following hooks are weirdly located here + // TODO move them for webpack 5 + /** @type {SyncHook} */ + environment: new SyncHook([]), + /** @type {SyncHook} */ + afterEnvironment: new SyncHook([]), + /** @type {SyncHook} */ + afterPlugins: new SyncHook(["compiler"]), + /** @type {SyncHook} */ + afterResolvers: new SyncHook(["compiler"]), + /** @type {SyncBailHook} */ + entryOption: new SyncBailHook(["context", "entry"]) + }; + + this._pluginCompat.tap("Compiler", options => { + switch (options.name) { + case "additional-pass": + case "before-run": + case "run": + case "emit": + case "after-emit": + case "before-compile": + case "make": + case "after-compile": + case "watch-run": + options.async = true; + break; + } + }); + + /** @type {string=} */ + this.name = undefined; + /** @type {Compilation=} */ + this.parentCompilation = undefined; + /** @type {string} */ + this.outputPath = ""; + + this.outputFileSystem = null; + this.inputFileSystem = null; + + /** @type {string|null} */ + this.recordsInputPath = null; + /** @type {string|null} */ + this.recordsOutputPath = null; + this.records = {}; + /** @type {Map} */ + this.fileTimestamps = new Map(); + /** @type {Map} */ + this.contextTimestamps = new Map(); + /** @type {ResolverFactory} */ + this.resolverFactory = new ResolverFactory(); + + // TODO remove in webpack 5 + this.resolvers = { + normal: { + plugins: util.deprecate((hook, fn) => { + this.resolverFactory.plugin("resolver normal", resolver => { + resolver.plugin(hook, fn); + }); + }, "webpack: Using compiler.resolvers.normal is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver normal", resolver => {\n resolver.plugin(/* … */);\n}); instead.'), + apply: util.deprecate((...args) => { + this.resolverFactory.plugin("resolver normal", resolver => { + resolver.apply(...args); + }); + }, "webpack: Using compiler.resolvers.normal is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver normal", resolver => {\n resolver.apply(/* … */);\n}); instead.') + }, + loader: { + plugins: util.deprecate((hook, fn) => { + this.resolverFactory.plugin("resolver loader", resolver => { + resolver.plugin(hook, fn); + }); + }, "webpack: Using compiler.resolvers.loader is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver loader", resolver => {\n resolver.plugin(/* … */);\n}); instead.'), + apply: util.deprecate((...args) => { + this.resolverFactory.plugin("resolver loader", resolver => { + resolver.apply(...args); + }); + }, "webpack: Using compiler.resolvers.loader is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver loader", resolver => {\n resolver.apply(/* … */);\n}); instead.') + }, + context: { + plugins: util.deprecate((hook, fn) => { + this.resolverFactory.plugin("resolver context", resolver => { + resolver.plugin(hook, fn); + }); + }, "webpack: Using compiler.resolvers.context is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver context", resolver => {\n resolver.plugin(/* … */);\n}); instead.'), + apply: util.deprecate((...args) => { + this.resolverFactory.plugin("resolver context", resolver => { + resolver.apply(...args); + }); + }, "webpack: Using compiler.resolvers.context is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver context", resolver => {\n resolver.apply(/* … */);\n}); instead.') + } + }; + + this.options = {}; + + this.context = context; + + this.requestShortener = new RequestShortener(context); + + /** @type {boolean} */ + this.running = false; + } + + watch(watchOptions, handler) { + if (this.running) return handler(new ConcurrentCompilationError()); + + this.running = true; + this.fileTimestamps = new Map(); + this.contextTimestamps = new Map(); + return new Watching(this, watchOptions, handler); + } + + run(callback) { + if (this.running) return callback(new ConcurrentCompilationError()); + + const finalCallback = (err, stats) => { + this.running = false; + + if (callback !== undefined) return callback(err, stats); + }; + + const startTime = Date.now(); + + this.running = true; + + const onCompiled = (err, compilation) => { + if (err) return finalCallback(err); + + if (this.hooks.shouldEmit.call(compilation) === false) { + const stats = new Stats(compilation); + stats.startTime = startTime; + stats.endTime = Date.now(); + this.hooks.done.callAsync(stats, err => { + if (err) return finalCallback(err); + return finalCallback(null, stats); + }); + return; + } + + this.emitAssets(compilation, err => { + if (err) return finalCallback(err); + + if (compilation.hooks.needAdditionalPass.call()) { + compilation.needAdditionalPass = true; + + const stats = new Stats(compilation); + stats.startTime = startTime; + stats.endTime = Date.now(); + this.hooks.done.callAsync(stats, err => { + if (err) return finalCallback(err); + + this.hooks.additionalPass.callAsync(err => { + if (err) return finalCallback(err); + this.compile(onCompiled); + }); + }); + return; + } + + this.emitRecords(err => { + if (err) return finalCallback(err); + + const stats = new Stats(compilation); + stats.startTime = startTime; + stats.endTime = Date.now(); + this.hooks.done.callAsync(stats, err => { + if (err) return finalCallback(err); + return finalCallback(null, stats); + }); + }); + }); + }; + + this.hooks.beforeRun.callAsync(this, err => { + if (err) return finalCallback(err); + + this.hooks.run.callAsync(this, err => { + if (err) return finalCallback(err); + + this.readRecords(err => { + if (err) return finalCallback(err); + + this.compile(onCompiled); + }); + }); + }); + } + + runAsChild(callback) { + this.compile((err, compilation) => { + if (err) return callback(err); + + this.parentCompilation.children.push(compilation); + for (const name of Object.keys(compilation.assets)) { + this.parentCompilation.assets[name] = compilation.assets[name]; + } + + const entries = Array.from( + compilation.entrypoints.values(), + ep => ep.chunks + ).reduce((array, chunks) => { + return array.concat(chunks); + }, []); + + return callback(null, entries, compilation); + }); + } + + purgeInputFileSystem() { + if (this.inputFileSystem && this.inputFileSystem.purge) { + this.inputFileSystem.purge(); + } + } + + emitAssets(compilation, callback) { + let outputPath; + + const emitFiles = err => { + if (err) return callback(err); + + asyncLib.forEach( + compilation.assets, + (source, file, callback) => { + let targetFile = file; + const queryStringIdx = targetFile.indexOf("?"); + if (queryStringIdx >= 0) { + targetFile = targetFile.substr(0, queryStringIdx); + } + + const writeOut = err => { + if (err) return callback(err); + const targetPath = this.outputFileSystem.join( + outputPath, + targetFile + ); + if (source.existsAt === targetPath) { + source.emitted = false; + return callback(); + } + let content = source.source(); + + if (!Buffer.isBuffer(content)) { + content = Buffer.from(content, "utf8"); + } + + source.existsAt = targetPath; + source.emitted = true; + this.outputFileSystem.writeFile(targetPath, content, callback); + }; + + if (targetFile.match(/\/|\\/)) { + const dir = path.dirname(targetFile); + this.outputFileSystem.mkdirp( + this.outputFileSystem.join(outputPath, dir), + writeOut + ); + } else { + writeOut(); + } + }, + err => { + if (err) return callback(err); + + this.hooks.afterEmit.callAsync(compilation, err => { + if (err) return callback(err); + + return callback(); + }); + } + ); + }; + + this.hooks.emit.callAsync(compilation, err => { + if (err) return callback(err); + outputPath = compilation.getPath(this.outputPath); + this.outputFileSystem.mkdirp(outputPath, emitFiles); + }); + } + + emitRecords(callback) { + if (!this.recordsOutputPath) return callback(); + const idx1 = this.recordsOutputPath.lastIndexOf("/"); + const idx2 = this.recordsOutputPath.lastIndexOf("\\"); + let recordsOutputPathDirectory = null; + if (idx1 > idx2) { + recordsOutputPathDirectory = this.recordsOutputPath.substr(0, idx1); + } else if (idx1 < idx2) { + recordsOutputPathDirectory = this.recordsOutputPath.substr(0, idx2); + } + + const writeFile = () => { + this.outputFileSystem.writeFile( + this.recordsOutputPath, + JSON.stringify(this.records, undefined, 2), + callback + ); + }; + + if (!recordsOutputPathDirectory) { + return writeFile(); + } + this.outputFileSystem.mkdirp(recordsOutputPathDirectory, err => { + if (err) return callback(err); + writeFile(); + }); + } + + readRecords(callback) { + if (!this.recordsInputPath) { + this.records = {}; + return callback(); + } + this.inputFileSystem.stat(this.recordsInputPath, err => { + // It doesn't exist + // We can ignore this. + if (err) return callback(); + + this.inputFileSystem.readFile(this.recordsInputPath, (err, content) => { + if (err) return callback(err); + + try { + this.records = parseJson(content.toString("utf-8")); + } catch (e) { + e.message = "Cannot parse records: " + e.message; + return callback(e); + } + + return callback(); + }); + }); + } + + createChildCompiler( + compilation, + compilerName, + compilerIndex, + outputOptions, + plugins + ) { + const childCompiler = new Compiler(this.context); + if (Array.isArray(plugins)) { + for (const plugin of plugins) { + plugin.apply(childCompiler); + } + } + for (const name in this.hooks) { + if ( + ![ + "make", + "compile", + "emit", + "afterEmit", + "invalid", + "done", + "thisCompilation" + ].includes(name) + ) { + if (childCompiler.hooks[name]) { + childCompiler.hooks[name].taps = this.hooks[name].taps.slice(); + } + } + } + childCompiler.name = compilerName; + childCompiler.outputPath = this.outputPath; + childCompiler.inputFileSystem = this.inputFileSystem; + childCompiler.outputFileSystem = null; + childCompiler.resolverFactory = this.resolverFactory; + childCompiler.fileTimestamps = this.fileTimestamps; + childCompiler.contextTimestamps = this.contextTimestamps; + + const relativeCompilerName = makePathsRelative(this.context, compilerName); + if (!this.records[relativeCompilerName]) { + this.records[relativeCompilerName] = []; + } + if (this.records[relativeCompilerName][compilerIndex]) { + childCompiler.records = this.records[relativeCompilerName][compilerIndex]; + } else { + this.records[relativeCompilerName].push((childCompiler.records = {})); + } + + childCompiler.options = Object.create(this.options); + childCompiler.options.output = Object.create(childCompiler.options.output); + for (const name in outputOptions) { + childCompiler.options.output[name] = outputOptions[name]; + } + childCompiler.parentCompilation = compilation; + + compilation.hooks.childCompiler.call( + childCompiler, + compilerName, + compilerIndex + ); + + return childCompiler; + } + + isChild() { + return !!this.parentCompilation; + } + + createCompilation() { + return new Compilation(this); + } + + newCompilation(params) { + const compilation = this.createCompilation(); + compilation.fileTimestamps = this.fileTimestamps; + compilation.contextTimestamps = this.contextTimestamps; + compilation.name = this.name; + compilation.records = this.records; + compilation.compilationDependencies = params.compilationDependencies; + this.hooks.thisCompilation.call(compilation, params); + this.hooks.compilation.call(compilation, params); + return compilation; + } + + createNormalModuleFactory() { + const normalModuleFactory = new NormalModuleFactory( + this.options.context, + this.resolverFactory, + this.options.module || {} + ); + this.hooks.normalModuleFactory.call(normalModuleFactory); + return normalModuleFactory; + } + + createContextModuleFactory() { + const contextModuleFactory = new ContextModuleFactory(this.resolverFactory); + this.hooks.contextModuleFactory.call(contextModuleFactory); + return contextModuleFactory; + } + + newCompilationParams() { + const params = { + normalModuleFactory: this.createNormalModuleFactory(), + contextModuleFactory: this.createContextModuleFactory(), + compilationDependencies: new Set() + }; + return params; + } + + compile(callback) { + const params = this.newCompilationParams(); + this.hooks.beforeCompile.callAsync(params, err => { + if (err) return callback(err); + + this.hooks.compile.call(params); + + const compilation = this.newCompilation(params); + + this.hooks.make.callAsync(compilation, err => { + if (err) return callback(err); + + compilation.finish(); + + compilation.seal(err => { + if (err) return callback(err); + + this.hooks.afterCompile.callAsync(compilation, err => { + if (err) return callback(err); + + return callback(null, compilation); + }); + }); + }); + }); + } +} + +module.exports = Compiler; diff --git a/node_modules/webpack/lib/ConstPlugin.js b/node_modules/webpack/lib/ConstPlugin.js index 8534a6fe8..03b279b64 100644 --- a/node_modules/webpack/lib/ConstPlugin.js +++ b/node_modules/webpack/lib/ConstPlugin.js @@ -1,60 +1,258 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ConstDependency = require("./dependencies/ConstDependency"); -const NullFactory = require("./NullFactory"); -const ParserHelpers = require("./ParserHelpers"); - -const getQuery = (request) => { - const i = request.indexOf("?"); - return request.indexOf("?") < 0 ? "" : request.substr(i); -}; - -class ConstPlugin { - apply(compiler) { - compiler.plugin("compilation", (compilation, params) => { - compilation.dependencyFactories.set(ConstDependency, new NullFactory()); - compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template()); - - params.normalModuleFactory.plugin("parser", parser => { - parser.plugin("statement if", function(statement) { - const param = this.evaluateExpression(statement.test); - const bool = param.asBool(); - if(typeof bool === "boolean") { - if(statement.test.type !== "Literal") { - const dep = new ConstDependency(`${bool}`, param.range); - dep.loc = statement.loc; - this.state.current.addDependency(dep); - } - return bool; - } - }); - parser.plugin("expression ?:", function(expression) { - const param = this.evaluateExpression(expression.test); - const bool = param.asBool(); - if(typeof bool === "boolean") { - if(expression.test.type !== "Literal") { - const dep = new ConstDependency(` ${bool}`, param.range); - dep.loc = expression.loc; - this.state.current.addDependency(dep); - } - return bool; - } - }); - parser.plugin("evaluate Identifier __resourceQuery", function(expr) { - if(!this.state.module) return; - return ParserHelpers.evaluateToString(getQuery(this.state.module.resource))(expr); - }); - parser.plugin("expression __resourceQuery", function() { - if(!this.state.module) return; - this.state.current.addVariable("__resourceQuery", JSON.stringify(getQuery(this.state.module.resource))); - return true; - }); - }); - }); - } -} - -module.exports = ConstPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const ConstDependency = require("./dependencies/ConstDependency"); +const NullFactory = require("./NullFactory"); +const ParserHelpers = require("./ParserHelpers"); + +const getQuery = request => { + const i = request.indexOf("?"); + return i !== -1 ? request.substr(i) : ""; +}; + +const collectDeclaration = (declarations, pattern) => { + const stack = [pattern]; + while (stack.length > 0) { + const node = stack.pop(); + switch (node.type) { + case "Identifier": + declarations.add(node.name); + break; + case "ArrayPattern": + for (const element of node.elements) { + if (element) { + stack.push(element); + } + } + break; + case "AssignmentPattern": + stack.push(node.left); + break; + case "ObjectPattern": + for (const property of node.properties) { + stack.push(property.value); + } + break; + case "RestElement": + stack.push(node.argument); + break; + } + } +}; + +const getHoistedDeclarations = (branch, includeFunctionDeclarations) => { + const declarations = new Set(); + const stack = [branch]; + while (stack.length > 0) { + const node = stack.pop(); + // Some node could be `null` or `undefined`. + if (!node) continue; + switch (node.type) { + // Walk through control statements to look for hoisted declarations. + // Some branches are skipped since they do not allow declarations. + case "BlockStatement": + for (const stmt of node.body) { + stack.push(stmt); + } + break; + case "IfStatement": + stack.push(node.consequent); + stack.push(node.alternate); + break; + case "ForStatement": + stack.push(node.init); + stack.push(node.body); + break; + case "ForInStatement": + case "ForOfStatement": + stack.push(node.left); + stack.push(node.body); + break; + case "DoWhileStatement": + case "WhileStatement": + case "LabeledStatement": + stack.push(node.body); + break; + case "SwitchStatement": + for (const cs of node.cases) { + for (const consequent of cs.consequent) { + stack.push(consequent); + } + } + break; + case "TryStatement": + stack.push(node.block); + if (node.handler) { + stack.push(node.handler.body); + } + stack.push(node.finalizer); + break; + case "FunctionDeclaration": + if (includeFunctionDeclarations) { + collectDeclaration(declarations, node.id); + } + break; + case "VariableDeclaration": + if (node.kind === "var") { + for (const decl of node.declarations) { + collectDeclaration(declarations, decl.id); + } + } + break; + } + } + return Array.from(declarations); +}; + +class ConstPlugin { + apply(compiler) { + compiler.hooks.compilation.tap( + "ConstPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set(ConstDependency, new NullFactory()); + compilation.dependencyTemplates.set( + ConstDependency, + new ConstDependency.Template() + ); + + const handler = parser => { + parser.hooks.statementIf.tap("ConstPlugin", statement => { + const param = parser.evaluateExpression(statement.test); + const bool = param.asBool(); + if (typeof bool === "boolean") { + if (statement.test.type !== "Literal") { + const dep = new ConstDependency(`${bool}`, param.range); + dep.loc = statement.loc; + parser.state.current.addDependency(dep); + } + const branchToRemove = bool + ? statement.alternate + : statement.consequent; + if (branchToRemove) { + // Before removing the dead branch, the hoisted declarations + // must be collected. + // + // Given the following code: + // + // if (true) f() else g() + // if (false) { + // function f() {} + // const g = function g() {} + // if (someTest) { + // let a = 1 + // var x, {y, z} = obj + // } + // } else { + // … + // } + // + // the generated code is: + // + // if (true) f() else {} + // if (false) { + // var f, x, y, z; (in loose mode) + // var x, y, z; (in strict mode) + // } else { + // … + // } + // + // NOTE: When code runs in strict mode, `var` declarations + // are hoisted but `function` declarations don't. + // + let declarations; + if (parser.scope.isStrict) { + // If the code runs in strict mode, variable declarations + // using `var` must be hoisted. + declarations = getHoistedDeclarations(branchToRemove, false); + } else { + // Otherwise, collect all hoisted declaration. + declarations = getHoistedDeclarations(branchToRemove, true); + } + let replacement; + if (declarations.length > 0) { + replacement = `{ var ${declarations.join(", ")}; }`; + } else { + replacement = "{}"; + } + const dep = new ConstDependency( + replacement, + branchToRemove.range + ); + dep.loc = branchToRemove.loc; + parser.state.current.addDependency(dep); + } + return bool; + } + }); + parser.hooks.expressionConditionalOperator.tap( + "ConstPlugin", + expression => { + const param = parser.evaluateExpression(expression.test); + const bool = param.asBool(); + if (typeof bool === "boolean") { + if (expression.test.type !== "Literal") { + const dep = new ConstDependency(` ${bool}`, param.range); + dep.loc = expression.loc; + parser.state.current.addDependency(dep); + } + // Expressions do not hoist. + // It is safe to remove the dead branch. + // + // Given the following code: + // + // false ? someExpression() : otherExpression(); + // + // the generated code is: + // + // false ? undefined : otherExpression(); + // + const branchToRemove = bool + ? expression.alternate + : expression.consequent; + const dep = new ConstDependency( + "undefined", + branchToRemove.range + ); + dep.loc = branchToRemove.loc; + parser.state.current.addDependency(dep); + return bool; + } + } + ); + parser.hooks.evaluateIdentifier + .for("__resourceQuery") + .tap("ConstPlugin", expr => { + if (!parser.state.module) return; + return ParserHelpers.evaluateToString( + getQuery(parser.state.module.resource) + )(expr); + }); + parser.hooks.expression + .for("__resourceQuery") + .tap("ConstPlugin", () => { + if (!parser.state.module) return; + parser.state.current.addVariable( + "__resourceQuery", + JSON.stringify(getQuery(parser.state.module.resource)) + ); + return true; + }); + }; + + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("ConstPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("ConstPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/esm") + .tap("ConstPlugin", handler); + } + ); + } +} + +module.exports = ConstPlugin; diff --git a/node_modules/webpack/lib/ContextExclusionPlugin.js b/node_modules/webpack/lib/ContextExclusionPlugin.js index db6c81b27..0b1dda0e9 100644 --- a/node_modules/webpack/lib/ContextExclusionPlugin.js +++ b/node_modules/webpack/lib/ContextExclusionPlugin.js @@ -1,17 +1,28 @@ -"use strict"; - -class ContextExclusionPlugin { - constructor(negativeMatcher) { - this.negativeMatcher = negativeMatcher; - } - - apply(compiler) { - compiler.plugin("context-module-factory", (cmf) => { - cmf.plugin("context-module-files", (files) => { - return files.filter(filePath => !this.negativeMatcher.test(filePath)); - }); - }); - } -} - -module.exports = ContextExclusionPlugin; +"use strict"; + +/** @typedef {import("./Compiler")} Compiler */ +/** @typedef {import("./ContextModuleFactory")} ContextModuleFactory */ + +class ContextExclusionPlugin { + /** + * @param {RegExp} negativeMatcher Matcher regular expression + */ + constructor(negativeMatcher) { + this.negativeMatcher = negativeMatcher; + } + + /** + * Apply the plugin + * @param {Compiler} compiler Webpack Compiler + * @returns {void} + */ + apply(compiler) { + compiler.hooks.contextModuleFactory.tap("ContextExclusionPlugin", cmf => { + cmf.hooks.contextModuleFiles.tap("ContextExclusionPlugin", files => { + return files.filter(filePath => !this.negativeMatcher.test(filePath)); + }); + }); + } +} + +module.exports = ContextExclusionPlugin; diff --git a/node_modules/webpack/lib/ContextModule.js b/node_modules/webpack/lib/ContextModule.js index a894e6268..78e0e47aa 100644 --- a/node_modules/webpack/lib/ContextModule.js +++ b/node_modules/webpack/lib/ContextModule.js @@ -1,431 +1,844 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const path = require("path"); -const Module = require("./Module"); -const OriginalSource = require("webpack-sources").OriginalSource; -const RawSource = require("webpack-sources").RawSource; -const AsyncDependenciesBlock = require("./AsyncDependenciesBlock"); -const DepBlockHelpers = require("./dependencies/DepBlockHelpers"); -const Template = require("./Template"); - -class ContextModule extends Module { - constructor(resolveDependencies, context, recursive, regExp, addon, asyncMode, chunkName) { - super(); - this.resolveDependencies = resolveDependencies; - this.context = context; - this.recursive = recursive; - this.regExp = regExp; - this.addon = addon; - this.async = asyncMode; - this.cacheable = true; - this.contextDependencies = [context]; - this.built = false; - this.chunkName = chunkName; - } - - prettyRegExp(regexString) { - // remove the "/" at the front and the beginning - // "/foo/" -> "foo" - return regexString.substring(1, regexString.length - 1); - } - - contextify(context, request) { - return request.split("!").map(subrequest => { - let rp = path.relative(context, subrequest); - if(path.sep === "\\") - rp = rp.replace(/\\/g, "/"); - if(rp.indexOf("../") !== 0) - rp = "./" + rp; - return rp; - }).join("!"); - } - - identifier() { - let identifier = this.context; - if(this.async) - identifier += ` ${this.async}`; - if(!this.recursive) - identifier += " nonrecursive"; - if(this.addon) - identifier += ` ${this.addon}`; - if(this.regExp) - identifier += ` ${this.regExp}`; - - return identifier; - } - - readableIdentifier(requestShortener) { - let identifier = requestShortener.shorten(this.context); - if(this.async) - identifier += ` ${this.async}`; - if(!this.recursive) - identifier += " nonrecursive"; - if(this.addon) - identifier += ` ${requestShortener.shorten(this.addon)}`; - if(this.regExp) - identifier += ` ${this.prettyRegExp(this.regExp + "")}`; - - return identifier; - } - - libIdent(options) { - let identifier = this.contextify(options.context, this.context); - if(this.async) - identifier += ` ${this.async}`; - if(this.recursive) - identifier += " recursive"; - if(this.addon) - identifier += ` ${this.contextify(options.context, this.addon)}`; - if(this.regExp) - identifier += ` ${this.prettyRegExp(this.regExp + "")}`; - - return identifier; - } - - needRebuild(fileTimestamps, contextTimestamps) { - const ts = contextTimestamps[this.context]; - if(!ts) { - return true; - } - - return ts >= this.builtTime; - } - - unbuild() { - this.built = false; - super.unbuild(); - } - - build(options, compilation, resolver, fs, callback) { - this.built = true; - this.builtTime = Date.now(); - this.resolveDependencies(fs, this.context, this.recursive, this.regExp, (err, dependencies) => { - if(err) return callback(err); - - // Reset children - this.dependencies = []; - this.blocks = []; - - // abort if something failed - // this will create an empty context - if(!dependencies) { - callback(); - return; - } - - // enhance dependencies with meta info - dependencies.forEach(dep => { - dep.loc = dep.userRequest; - dep.request = this.addon + dep.request; - }); - - if(!this.async || this.async === "eager") { - - // if we have an sync or eager context - // just add all dependencies and continue - this.dependencies = dependencies; - - } else if(this.async === "lazy-once") { - - // for the lazy-once mode create a new async dependency block - // and add that block to this context - if(dependencies.length > 0) { - const block = new AsyncDependenciesBlock(this.chunkName, this); - dependencies.forEach(dep => { - block.addDependency(dep); - }); - this.addBlock(block); - } - - } else if(this.async === "weak" || this.async === "async-weak") { - - // we mark all dependencies as weak - dependencies.forEach(dep => dep.weak = true); - this.dependencies = dependencies; - - } else { - // if we are lazy create a new async dependency block per dependency - // and add all blocks to this context - dependencies.forEach((dep, idx) => { - let chunkName = this.chunkName; - if(chunkName) { - if(!/\[(index|request)\]/.test(chunkName)) - chunkName += "[index]"; - chunkName = chunkName.replace(/\[index\]/g, idx); - chunkName = chunkName.replace(/\[request\]/g, Template.toPath(dep.userRequest)); - } - const block = new AsyncDependenciesBlock(chunkName, dep.module, dep.loc); - block.addDependency(dep); - this.addBlock(block); - }); - } - callback(); - }); - } - - getUserRequestMap(dependencies) { - // if we filter first we get a new array - // therefor we dont need to create a clone of dependencies explicitly - // therefore the order of this is !important! - return dependencies - .filter(dependency => dependency.module) - .sort((a, b) => { - if(a.userRequest === b.userRequest) { - return 0; - } - return a.userRequest < b.userRequest ? -1 : 1; - }).reduce(function(map, dep) { - map[dep.userRequest] = dep.module.id; - return map; - }, Object.create(null)); - } - - getSyncSource(dependencies, id) { - const map = this.getUserRequestMap(dependencies); - return `var map = ${JSON.stringify(map, null, "\t")}; -function webpackContext(req) { - return __webpack_require__(webpackContextResolve(req)); -}; -function webpackContextResolve(req) { - var id = map[req]; - if(!(id + 1)) // check for number or string - throw new Error("Cannot find module '" + req + "'."); - return id; -}; -webpackContext.keys = function webpackContextKeys() { - return Object.keys(map); -}; -webpackContext.resolve = webpackContextResolve; -module.exports = webpackContext; -webpackContext.id = ${JSON.stringify(id)};`; - } - - getWeakSyncSource(dependencies, id) { - const map = this.getUserRequestMap(dependencies); - return `var map = ${JSON.stringify(map, null, "\t")}; -function webpackContext(req) { - var id = webpackContextResolve(req); - if(!__webpack_require__.m[id]) - throw new Error("Module '" + req + "' ('" + id + "') is not available (weak dependency)"); - return __webpack_require__(id); -}; -function webpackContextResolve(req) { - var id = map[req]; - if(!(id + 1)) // check for number or string - throw new Error("Cannot find module '" + req + "'."); - return id; -}; -webpackContext.keys = function webpackContextKeys() { - return Object.keys(map); -}; -webpackContext.resolve = webpackContextResolve; -webpackContext.id = ${JSON.stringify(id)}; -module.exports = webpackContext;`; - } - - getAsyncWeakSource(dependencies, id) { - const map = this.getUserRequestMap(dependencies); - - return `var map = ${JSON.stringify(map, null, "\t")}; -function webpackAsyncContext(req) { - return webpackAsyncContextResolve(req).then(function(id) { - if(!__webpack_require__.m[id]) - throw new Error("Module '" + req + "' ('" + id + "') is not available (weak dependency)"); - return __webpack_require__(id); - }); -}; -function webpackAsyncContextResolve(req) { - // Here Promise.resolve().then() is used instead of new Promise() to prevent - // uncatched exception popping up in devtools - return Promise.resolve().then(function() { - var id = map[req]; - if(!(id + 1)) // check for number or string - throw new Error("Cannot find module '" + req + "'."); - return id; - }); -}; -webpackAsyncContext.keys = function webpackAsyncContextKeys() { - return Object.keys(map); -}; -webpackAsyncContext.resolve = webpackAsyncContextResolve; -webpackAsyncContext.id = ${JSON.stringify(id)}; -module.exports = webpackAsyncContext;`; - } - - getEagerSource(dependencies, id) { - const map = this.getUserRequestMap(dependencies); - return `var map = ${JSON.stringify(map, null, "\t")}; -function webpackAsyncContext(req) { - return webpackAsyncContextResolve(req).then(__webpack_require__); -}; -function webpackAsyncContextResolve(req) { - // Here Promise.resolve().then() is used instead of new Promise() to prevent - // uncatched exception popping up in devtools - return Promise.resolve().then(function() { - var id = map[req]; - if(!(id + 1)) // check for number or string - throw new Error("Cannot find module '" + req + "'."); - return id; - }); -}; -webpackAsyncContext.keys = function webpackAsyncContextKeys() { - return Object.keys(map); -}; -webpackAsyncContext.resolve = webpackAsyncContextResolve; -webpackAsyncContext.id = ${JSON.stringify(id)}; -module.exports = webpackAsyncContext;`; - } - - getLazyOnceSource(block, dependencies, id, outputOptions, requestShortener) { - const promise = DepBlockHelpers.getDepBlockPromise(block, outputOptions, requestShortener, "lazy-once context"); - const map = this.getUserRequestMap(dependencies); - return `var map = ${JSON.stringify(map, null, "\t")}; -function webpackAsyncContext(req) { - return webpackAsyncContextResolve(req).then(__webpack_require__); -}; -function webpackAsyncContextResolve(req) { - return ${promise}.then(function() { - var id = map[req]; - if(!(id + 1)) // check for number or string - throw new Error("Cannot find module '" + req + "'."); - return id; - }); -}; -webpackAsyncContext.keys = function webpackAsyncContextKeys() { - return Object.keys(map); -}; -webpackAsyncContext.resolve = webpackAsyncContextResolve; -webpackAsyncContext.id = ${JSON.stringify(id)}; -module.exports = webpackAsyncContext;`; - } - - getLazySource(blocks, id) { - let hasMultipleOrNoChunks = false; - const map = blocks - .filter(block => block.dependencies[0].module) - .map((block) => ({ - dependency: block.dependencies[0], - block: block, - userRequest: block.dependencies[0].userRequest - })).sort((a, b) => { - if(a.userRequest === b.userRequest) return 0; - return a.userRequest < b.userRequest ? -1 : 1; - }).reduce((map, item) => { - const chunks = item.block.chunks || []; - if(chunks.length !== 1) { - hasMultipleOrNoChunks = true; - } - map[item.userRequest] = [item.dependency.module.id] - .concat(chunks.map(chunk => chunk.id)); - - return map; - }, Object.create(null)); - - const requestPrefix = hasMultipleOrNoChunks ? - "Promise.all(ids.slice(1).map(__webpack_require__.e))" : - "__webpack_require__.e(ids[1])"; - - return `var map = ${JSON.stringify(map, null, "\t")}; -function webpackAsyncContext(req) { - var ids = map[req]; - if(!ids) - return Promise.reject(new Error("Cannot find module '" + req + "'.")); - return ${requestPrefix}.then(function() { - return __webpack_require__(ids[0]); - }); -}; -webpackAsyncContext.keys = function webpackAsyncContextKeys() { - return Object.keys(map); -}; -webpackAsyncContext.id = ${JSON.stringify(id)}; -module.exports = webpackAsyncContext;`; - } - - getSourceForEmptyContext(id) { - return `function webpackEmptyContext(req) { - throw new Error("Cannot find module '" + req + "'."); -} -webpackEmptyContext.keys = function() { return []; }; -webpackEmptyContext.resolve = webpackEmptyContext; -module.exports = webpackEmptyContext; -webpackEmptyContext.id = ${JSON.stringify(id)};`; - } - - getSourceForEmptyAsyncContext(id) { - return `function webpackEmptyAsyncContext(req) { - // Here Promise.resolve().then() is used instead of new Promise() to prevent - // uncatched exception popping up in devtools - return Promise.resolve().then(function() { - throw new Error("Cannot find module '" + req + "'."); - }); -} -webpackEmptyAsyncContext.keys = function() { return []; }; -webpackEmptyAsyncContext.resolve = webpackEmptyAsyncContext; -module.exports = webpackEmptyAsyncContext; -webpackEmptyAsyncContext.id = ${JSON.stringify(id)};`; - } - - getSourceString(asyncMode, outputOptions, requestShortener) { - if(asyncMode === "lazy") { - if(this.blocks && this.blocks.length > 0) { - return this.getLazySource(this.blocks, this.id); - } - return this.getSourceForEmptyAsyncContext(this.id); - } - if(asyncMode === "eager") { - if(this.dependencies && this.dependencies.length > 0) { - return this.getEagerSource(this.dependencies, this.id); - } - return this.getSourceForEmptyAsyncContext(this.id); - } - if(asyncMode === "lazy-once") { - const block = this.blocks[0]; - if(block) { - return this.getLazyOnceSource(block, block.dependencies, this.id, outputOptions, requestShortener); - } - return this.getSourceForEmptyAsyncContext(this.id); - } - if(asyncMode === "async-weak") { - if(this.dependencies && this.dependencies.length > 0) { - return this.getAsyncWeakSource(this.dependencies, this.id); - } - return this.getSourceForEmptyAsyncContext(this.id); - } - if(asyncMode === "weak") { - if(this.dependencies && this.dependencies.length > 0) { - return this.getWeakSyncSource(this.dependencies, this.id); - } - } - if(this.dependencies && this.dependencies.length > 0) { - return this.getSyncSource(this.dependencies, this.id); - } - return this.getSourceForEmptyContext(this.id); - } - - getSource(sourceString) { - if(this.useSourceMap) { - return new OriginalSource(sourceString, this.identifier()); - } - return new RawSource(sourceString); - } - - source(dependencyTemplates, outputOptions, requestShortener) { - return this.getSource( - this.getSourceString(this.async, outputOptions, requestShortener) - ); - } - - size() { - // base penalty - const initialSize = 160; - - // if we dont have dependencies we stop here. - return this.dependencies - .reduce((size, dependency) => size + 5 + dependency.userRequest.length, initialSize); - } -} - -module.exports = ContextModule; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const util = require("util"); +const { OriginalSource, RawSource } = require("webpack-sources"); +const Module = require("./Module"); +const AsyncDependenciesBlock = require("./AsyncDependenciesBlock"); +const Template = require("./Template"); +const contextify = require("./util/identifier").contextify; + +/** @typedef {"sync" | "eager" | "weak" | "async-weak" | "lazy" | "lazy-once"} ContextMode Context mode */ +/** @typedef {import("./dependencies/ContextElementDependency")} ContextElementDependency */ + +/** + * @callback ResolveDependenciesCallback + * @param {Error=} err + * @param {ContextElementDependency[]} dependencies + */ + +/** + * @callback ResolveDependencies + * @param {TODO} fs + * @param {TODO} options + * @param {ResolveDependenciesCallback} callback + */ + +class ContextModule extends Module { + // type ContextMode = "sync" | "eager" | "weak" | "async-weak" | "lazy" | "lazy-once" + // type ContextOptions = { resource: string, recursive: boolean, regExp: RegExp, addon?: string, mode?: ContextMode, chunkName?: string, include?: RegExp, exclude?: RegExp, groupOptions?: Object } + // resolveDependencies: (fs: FS, options: ContextOptions, (err: Error?, dependencies: Dependency[]) => void) => void + // options: ContextOptions + /** + * @param {ResolveDependencies} resolveDependencies function to get dependencies in this context + * @param {TODO} options options object + */ + constructor(resolveDependencies, options) { + let resource; + let resourceQuery; + const queryIdx = options.resource.indexOf("?"); + if (queryIdx >= 0) { + resource = options.resource.substr(0, queryIdx); + resourceQuery = options.resource.substr(queryIdx); + } else { + resource = options.resource; + resourceQuery = ""; + } + + super("javascript/dynamic", resource); + + // Info from Factory + this.resolveDependencies = resolveDependencies; + this.options = Object.assign({}, options, { + resource: resource, + resourceQuery: resourceQuery + }); + if (options.resolveOptions !== undefined) { + this.resolveOptions = options.resolveOptions; + } + + // Info from Build + this._contextDependencies = new Set([this.context]); + + if (typeof options.mode !== "string") { + throw new Error("options.mode is a required option"); + } + + this._identifier = this._createIdentifier(); + } + + updateCacheModule(module) { + this.resolveDependencies = module.resolveDependencies; + this.options = module.options; + this.resolveOptions = module.resolveOptions; + } + + prettyRegExp(regexString) { + // remove the "/" at the front and the beginning + // "/foo/" -> "foo" + return regexString.substring(1, regexString.length - 1); + } + + _createIdentifier() { + let identifier = this.context; + if (this.options.resourceQuery) { + identifier += ` ${this.options.resourceQuery}`; + } + if (this.options.mode) { + identifier += ` ${this.options.mode}`; + } + if (!this.options.recursive) { + identifier += " nonrecursive"; + } + if (this.options.addon) { + identifier += ` ${this.options.addon}`; + } + if (this.options.regExp) { + identifier += ` ${this.options.regExp}`; + } + if (this.options.include) { + identifier += ` include: ${this.options.include}`; + } + if (this.options.exclude) { + identifier += ` exclude: ${this.options.exclude}`; + } + if (this.options.groupOptions) { + identifier += ` groupOptions: ${JSON.stringify( + this.options.groupOptions + )}`; + } + if (this.options.namespaceObject === "strict") { + identifier += " strict namespace object"; + } else if (this.options.namespaceObject) { + identifier += " namespace object"; + } + + return identifier; + } + + identifier() { + return this._identifier; + } + + readableIdentifier(requestShortener) { + let identifier = requestShortener.shorten(this.context); + if (this.options.resourceQuery) { + identifier += ` ${this.options.resourceQuery}`; + } + if (this.options.mode) { + identifier += ` ${this.options.mode}`; + } + if (!this.options.recursive) { + identifier += " nonrecursive"; + } + if (this.options.addon) { + identifier += ` ${requestShortener.shorten(this.options.addon)}`; + } + if (this.options.regExp) { + identifier += ` ${this.prettyRegExp(this.options.regExp + "")}`; + } + if (this.options.include) { + identifier += ` include: ${this.prettyRegExp(this.options.include + "")}`; + } + if (this.options.exclude) { + identifier += ` exclude: ${this.prettyRegExp(this.options.exclude + "")}`; + } + if (this.options.groupOptions) { + const groupOptions = this.options.groupOptions; + for (const key of Object.keys(groupOptions)) { + identifier += ` ${key}: ${groupOptions[key]}`; + } + } + if (this.options.namespaceObject === "strict") { + identifier += " strict namespace object"; + } else if (this.options.namespaceObject) { + identifier += " namespace object"; + } + + return identifier; + } + + libIdent(options) { + let identifier = contextify(options.context, this.context); + if (this.options.mode) { + identifier += ` ${this.options.mode}`; + } + if (this.options.recursive) { + identifier += " recursive"; + } + if (this.options.addon) { + identifier += ` ${contextify(options.context, this.options.addon)}`; + } + if (this.options.regExp) { + identifier += ` ${this.prettyRegExp(this.options.regExp + "")}`; + } + if (this.options.include) { + identifier += ` include: ${this.prettyRegExp(this.options.include + "")}`; + } + if (this.options.exclude) { + identifier += ` exclude: ${this.prettyRegExp(this.options.exclude + "")}`; + } + + return identifier; + } + + needRebuild(fileTimestamps, contextTimestamps) { + const ts = contextTimestamps.get(this.context); + if (!ts) { + return true; + } + + return ts >= this.buildInfo.builtTime; + } + + build(options, compilation, resolver, fs, callback) { + this.built = true; + this.buildMeta = {}; + this.buildInfo = { + builtTime: Date.now(), + contextDependencies: this._contextDependencies + }; + this.resolveDependencies(fs, this.options, (err, dependencies) => { + if (err) return callback(err); + + // abort if something failed + // this will create an empty context + if (!dependencies) { + callback(); + return; + } + + // enhance dependencies with meta info + for (const dep of dependencies) { + dep.loc = { + name: dep.userRequest + }; + dep.request = this.options.addon + dep.request; + } + + if (this.options.mode === "sync" || this.options.mode === "eager") { + // if we have an sync or eager context + // just add all dependencies and continue + this.dependencies = dependencies; + } else if (this.options.mode === "lazy-once") { + // for the lazy-once mode create a new async dependency block + // and add that block to this context + if (dependencies.length > 0) { + const block = new AsyncDependenciesBlock( + Object.assign({}, this.options.groupOptions, { + name: this.options.chunkName + }), + this + ); + for (const dep of dependencies) { + block.addDependency(dep); + } + this.addBlock(block); + } + } else if ( + this.options.mode === "weak" || + this.options.mode === "async-weak" + ) { + // we mark all dependencies as weak + for (const dep of dependencies) { + dep.weak = true; + } + this.dependencies = dependencies; + } else if (this.options.mode === "lazy") { + // if we are lazy create a new async dependency block per dependency + // and add all blocks to this context + let index = 0; + for (const dep of dependencies) { + let chunkName = this.options.chunkName; + if (chunkName) { + if (!/\[(index|request)\]/.test(chunkName)) { + chunkName += "[index]"; + } + chunkName = chunkName.replace(/\[index\]/g, index++); + chunkName = chunkName.replace( + /\[request\]/g, + Template.toPath(dep.userRequest) + ); + } + const block = new AsyncDependenciesBlock( + Object.assign({}, this.options.groupOptions, { + name: chunkName + }), + dep.module, + dep.loc, + dep.userRequest + ); + block.addDependency(dep); + this.addBlock(block); + } + } else { + callback( + new Error(`Unsupported mode "${this.options.mode}" in context`) + ); + return; + } + callback(); + }); + } + + getUserRequestMap(dependencies) { + // if we filter first we get a new array + // therefor we dont need to create a clone of dependencies explicitly + // therefore the order of this is !important! + return dependencies + .filter(dependency => dependency.module) + .sort((a, b) => { + if (a.userRequest === b.userRequest) { + return 0; + } + return a.userRequest < b.userRequest ? -1 : 1; + }) + .reduce((map, dep) => { + map[dep.userRequest] = dep.module.id; + return map; + }, Object.create(null)); + } + + getFakeMap(dependencies) { + if (!this.options.namespaceObject) { + return 9; + } + // if we filter first we get a new array + // therefor we dont need to create a clone of dependencies explicitly + // therefore the order of this is !important! + let hasNonHarmony = false; + let hasNamespace = false; + let hasNamed = false; + const fakeMap = dependencies + .filter(dependency => dependency.module) + .sort((a, b) => { + return b.module.id - a.module.id; + }) + .reduce((map, dep) => { + const exportsType = + dep.module.buildMeta && dep.module.buildMeta.exportsType; + const id = dep.module.id; + if (!exportsType) { + map[id] = this.options.namespaceObject === "strict" ? 1 : 7; + hasNonHarmony = true; + } else if (exportsType === "namespace") { + map[id] = 9; + hasNamespace = true; + } else if (exportsType === "named") { + map[id] = 3; + hasNamed = true; + } + return map; + }, Object.create(null)); + if (!hasNamespace && hasNonHarmony && !hasNamed) { + return this.options.namespaceObject === "strict" ? 1 : 7; + } + if (hasNamespace && !hasNonHarmony && !hasNamed) { + return 9; + } + if (!hasNamespace && !hasNonHarmony && hasNamed) { + return 3; + } + if (!hasNamespace && !hasNonHarmony && !hasNamed) { + return 9; + } + return fakeMap; + } + + getFakeMapInitStatement(fakeMap) { + return typeof fakeMap === "object" + ? `var fakeMap = ${JSON.stringify(fakeMap, null, "\t")};` + : ""; + } + + getReturn(type) { + if (type === 9) { + return "__webpack_require__(id)"; + } + return `__webpack_require__.t(id, ${type})`; + } + + getReturnModuleObjectSource(fakeMap, fakeMapDataExpression = "fakeMap[id]") { + if (typeof fakeMap === "number") { + return `return ${this.getReturn(fakeMap)};`; + } + return `return __webpack_require__.t(id, ${fakeMapDataExpression})`; + } + + getSyncSource(dependencies, id) { + const map = this.getUserRequestMap(dependencies); + const fakeMap = this.getFakeMap(dependencies); + const returnModuleObject = this.getReturnModuleObjectSource(fakeMap); + + return `var map = ${JSON.stringify(map, null, "\t")}; +${this.getFakeMapInitStatement(fakeMap)} + +function webpackContext(req) { + var id = webpackContextResolve(req); + ${returnModuleObject} +} +function webpackContextResolve(req) { + var id = map[req]; + if(!(id + 1)) { // check for number or string + var e = new Error("Cannot find module '" + req + "'"); + e.code = 'MODULE_NOT_FOUND'; + throw e; + } + return id; +} +webpackContext.keys = function webpackContextKeys() { + return Object.keys(map); +}; +webpackContext.resolve = webpackContextResolve; +module.exports = webpackContext; +webpackContext.id = ${JSON.stringify(id)};`; + } + + getWeakSyncSource(dependencies, id) { + const map = this.getUserRequestMap(dependencies); + const fakeMap = this.getFakeMap(dependencies); + const returnModuleObject = this.getReturnModuleObjectSource(fakeMap); + + return `var map = ${JSON.stringify(map, null, "\t")}; +${this.getFakeMapInitStatement(fakeMap)} + +function webpackContext(req) { + var id = webpackContextResolve(req); + if(!__webpack_require__.m[id]) { + var e = new Error("Module '" + req + "' ('" + id + "') is not available (weak dependency)"); + e.code = 'MODULE_NOT_FOUND'; + throw e; + } + ${returnModuleObject} +} +function webpackContextResolve(req) { + var id = map[req]; + if(!(id + 1)) { // check for number or string + var e = new Error("Cannot find module '" + req + "'"); + e.code = 'MODULE_NOT_FOUND'; + throw e; + } + return id; +} +webpackContext.keys = function webpackContextKeys() { + return Object.keys(map); +}; +webpackContext.resolve = webpackContextResolve; +webpackContext.id = ${JSON.stringify(id)}; +module.exports = webpackContext;`; + } + + getAsyncWeakSource(dependencies, id) { + const map = this.getUserRequestMap(dependencies); + const fakeMap = this.getFakeMap(dependencies); + const returnModuleObject = this.getReturnModuleObjectSource(fakeMap); + + return `var map = ${JSON.stringify(map, null, "\t")}; +${this.getFakeMapInitStatement(fakeMap)} + +function webpackAsyncContext(req) { + return webpackAsyncContextResolve(req).then(function(id) { + if(!__webpack_require__.m[id]) { + var e = new Error("Module '" + req + "' ('" + id + "') is not available (weak dependency)"); + e.code = 'MODULE_NOT_FOUND'; + throw e; + } + ${returnModuleObject} + }); +} +function webpackAsyncContextResolve(req) { + // Here Promise.resolve().then() is used instead of new Promise() to prevent + // uncaught exception popping up in devtools + return Promise.resolve().then(function() { + var id = map[req]; + if(!(id + 1)) { // check for number or string + var e = new Error("Cannot find module '" + req + "'"); + e.code = 'MODULE_NOT_FOUND'; + throw e; + } + return id; + }); +} +webpackAsyncContext.keys = function webpackAsyncContextKeys() { + return Object.keys(map); +}; +webpackAsyncContext.resolve = webpackAsyncContextResolve; +webpackAsyncContext.id = ${JSON.stringify(id)}; +module.exports = webpackAsyncContext;`; + } + + getEagerSource(dependencies, id) { + const map = this.getUserRequestMap(dependencies); + const fakeMap = this.getFakeMap(dependencies); + const thenFunction = + fakeMap !== 9 + ? `function(id) { + ${this.getReturnModuleObjectSource(fakeMap)} + }` + : "__webpack_require__"; + return `var map = ${JSON.stringify(map, null, "\t")}; +${this.getFakeMapInitStatement(fakeMap)} + +function webpackAsyncContext(req) { + return webpackAsyncContextResolve(req).then(${thenFunction}); +} +function webpackAsyncContextResolve(req) { + // Here Promise.resolve().then() is used instead of new Promise() to prevent + // uncaught exception popping up in devtools + return Promise.resolve().then(function() { + var id = map[req]; + if(!(id + 1)) { // check for number or string + var e = new Error("Cannot find module '" + req + "'"); + e.code = 'MODULE_NOT_FOUND'; + throw e; + } + return id; + }); +} +webpackAsyncContext.keys = function webpackAsyncContextKeys() { + return Object.keys(map); +}; +webpackAsyncContext.resolve = webpackAsyncContextResolve; +webpackAsyncContext.id = ${JSON.stringify(id)}; +module.exports = webpackAsyncContext;`; + } + + getLazyOnceSource(block, dependencies, id, runtimeTemplate) { + const promise = runtimeTemplate.blockPromise({ + block, + message: "lazy-once context" + }); + const map = this.getUserRequestMap(dependencies); + const fakeMap = this.getFakeMap(dependencies); + const thenFunction = + fakeMap !== 9 + ? `function(id) { + ${this.getReturnModuleObjectSource(fakeMap)}; + }` + : "__webpack_require__"; + + return `var map = ${JSON.stringify(map, null, "\t")}; +${this.getFakeMapInitStatement(fakeMap)} + +function webpackAsyncContext(req) { + return webpackAsyncContextResolve(req).then(${thenFunction}); +} +function webpackAsyncContextResolve(req) { + return ${promise}.then(function() { + var id = map[req]; + if(!(id + 1)) { // check for number or string + var e = new Error("Cannot find module '" + req + "'"); + e.code = 'MODULE_NOT_FOUND'; + throw e; + } + return id; + }); +} +webpackAsyncContext.keys = function webpackAsyncContextKeys() { + return Object.keys(map); +}; +webpackAsyncContext.resolve = webpackAsyncContextResolve; +webpackAsyncContext.id = ${JSON.stringify(id)}; +module.exports = webpackAsyncContext;`; + } + + getLazySource(blocks, id) { + let hasMultipleOrNoChunks = false; + const fakeMap = this.getFakeMap(blocks.map(b => b.dependencies[0])); + const map = blocks + .filter(block => block.dependencies[0].module) + .map(block => ({ + dependency: block.dependencies[0], + block: block, + userRequest: block.dependencies[0].userRequest + })) + .sort((a, b) => { + if (a.userRequest === b.userRequest) return 0; + return a.userRequest < b.userRequest ? -1 : 1; + }) + .reduce((map, item) => { + const chunks = + (item.block.chunkGroup && item.block.chunkGroup.chunks) || []; + if (chunks.length !== 1) { + hasMultipleOrNoChunks = true; + } + const arrayStart = [item.dependency.module.id]; + if (typeof fakeMap === "object") { + arrayStart.push(fakeMap[item.dependency.module.id]); + } + map[item.userRequest] = arrayStart.concat( + chunks.map(chunk => chunk.id) + ); + + return map; + }, Object.create(null)); + + const chunksStartPosition = typeof fakeMap === "object" ? 2 : 1; + const requestPrefix = hasMultipleOrNoChunks + ? `Promise.all(ids.slice(${chunksStartPosition}).map(__webpack_require__.e))` + : `__webpack_require__.e(ids[${chunksStartPosition}])`; + const returnModuleObject = this.getReturnModuleObjectSource( + fakeMap, + "ids[1]" + ); + + return `var map = ${JSON.stringify(map, null, "\t")}; +function webpackAsyncContext(req) { + var ids = map[req]; + if(!ids) { + return Promise.resolve().then(function() { + var e = new Error("Cannot find module '" + req + "'"); + e.code = 'MODULE_NOT_FOUND'; + throw e; + }); + } + return ${requestPrefix}.then(function() { + var id = ids[0]; + ${returnModuleObject} + }); +} +webpackAsyncContext.keys = function webpackAsyncContextKeys() { + return Object.keys(map); +}; +webpackAsyncContext.id = ${JSON.stringify(id)}; +module.exports = webpackAsyncContext;`; + } + + getSourceForEmptyContext(id) { + return `function webpackEmptyContext(req) { + var e = new Error("Cannot find module '" + req + "'"); + e.code = 'MODULE_NOT_FOUND'; + throw e; +} +webpackEmptyContext.keys = function() { return []; }; +webpackEmptyContext.resolve = webpackEmptyContext; +module.exports = webpackEmptyContext; +webpackEmptyContext.id = ${JSON.stringify(id)};`; + } + + getSourceForEmptyAsyncContext(id) { + return `function webpackEmptyAsyncContext(req) { + // Here Promise.resolve().then() is used instead of new Promise() to prevent + // uncaught exception popping up in devtools + return Promise.resolve().then(function() { + var e = new Error("Cannot find module '" + req + "'"); + e.code = 'MODULE_NOT_FOUND'; + throw e; + }); +} +webpackEmptyAsyncContext.keys = function() { return []; }; +webpackEmptyAsyncContext.resolve = webpackEmptyAsyncContext; +module.exports = webpackEmptyAsyncContext; +webpackEmptyAsyncContext.id = ${JSON.stringify(id)};`; + } + + getSourceString(asyncMode, runtimeTemplate) { + if (asyncMode === "lazy") { + if (this.blocks && this.blocks.length > 0) { + return this.getLazySource(this.blocks, this.id); + } + return this.getSourceForEmptyAsyncContext(this.id); + } + if (asyncMode === "eager") { + if (this.dependencies && this.dependencies.length > 0) { + return this.getEagerSource(this.dependencies, this.id); + } + return this.getSourceForEmptyAsyncContext(this.id); + } + if (asyncMode === "lazy-once") { + const block = this.blocks[0]; + if (block) { + return this.getLazyOnceSource( + block, + block.dependencies, + this.id, + runtimeTemplate + ); + } + return this.getSourceForEmptyAsyncContext(this.id); + } + if (asyncMode === "async-weak") { + if (this.dependencies && this.dependencies.length > 0) { + return this.getAsyncWeakSource(this.dependencies, this.id); + } + return this.getSourceForEmptyAsyncContext(this.id); + } + if (asyncMode === "weak") { + if (this.dependencies && this.dependencies.length > 0) { + return this.getWeakSyncSource(this.dependencies, this.id); + } + } + if (this.dependencies && this.dependencies.length > 0) { + return this.getSyncSource(this.dependencies, this.id); + } + return this.getSourceForEmptyContext(this.id); + } + + getSource(sourceString) { + if (this.useSourceMap) { + return new OriginalSource(sourceString, this.identifier()); + } + return new RawSource(sourceString); + } + + source(dependencyTemplates, runtimeTemplate) { + return this.getSource( + this.getSourceString(this.options.mode, runtimeTemplate) + ); + } + + size() { + // base penalty + const initialSize = 160; + + // if we dont have dependencies we stop here. + return this.dependencies.reduce((size, dependency) => { + const element = /** @type {ContextElementDependency} */ (dependency); + return size + 5 + element.userRequest.length; + }, initialSize); + } +} + +// TODO remove in webpack 5 +Object.defineProperty(ContextModule.prototype, "recursive", { + configurable: false, + get: util.deprecate( + /** + * @deprecated + * @this {ContextModule} + * @returns {boolean} is recursive + */ + function() { + return this.options.recursive; + }, + "ContextModule.recursive has been moved to ContextModule.options.recursive" + ), + set: util.deprecate( + /** + * @deprecated + * @this {ContextModule} + * @param {boolean} value is recursive + * @returns {void} + */ + function(value) { + this.options.recursive = value; + }, + "ContextModule.recursive has been moved to ContextModule.options.recursive" + ) +}); + +// TODO remove in webpack 5 +Object.defineProperty(ContextModule.prototype, "regExp", { + configurable: false, + get: util.deprecate( + /** + * @deprecated + * @this {ContextModule} + * @returns {RegExp} regular expression + */ + function() { + return this.options.regExp; + }, + "ContextModule.regExp has been moved to ContextModule.options.regExp" + ), + set: util.deprecate( + /** + * @deprecated + * @this {ContextModule} + * @param {RegExp} value Regular expression + * @returns {void} + */ + function(value) { + this.options.regExp = value; + }, + "ContextModule.regExp has been moved to ContextModule.options.regExp" + ) +}); + +// TODO remove in webpack 5 +Object.defineProperty(ContextModule.prototype, "addon", { + configurable: false, + get: util.deprecate( + /** + * @deprecated + * @this {ContextModule} + * @returns {string} addon + */ + function() { + return this.options.addon; + }, + "ContextModule.addon has been moved to ContextModule.options.addon" + ), + set: util.deprecate( + /** + * @deprecated + * @this {ContextModule} + * @param {string} value addon + * @returns {void} + */ + function(value) { + this.options.addon = value; + }, + "ContextModule.addon has been moved to ContextModule.options.addon" + ) +}); + +// TODO remove in webpack 5 +Object.defineProperty(ContextModule.prototype, "async", { + configurable: false, + get: util.deprecate( + /** + * @deprecated + * @this {ContextModule} + * @returns {boolean} is async + */ + function() { + return this.options.mode; + }, + "ContextModule.async has been moved to ContextModule.options.mode" + ), + set: util.deprecate( + /** + * @deprecated + * @this {ContextModule} + * @param {ContextMode} value Context mode + * @returns {void} + */ + function(value) { + this.options.mode = value; + }, + "ContextModule.async has been moved to ContextModule.options.mode" + ) +}); + +// TODO remove in webpack 5 +Object.defineProperty(ContextModule.prototype, "chunkName", { + configurable: false, + get: util.deprecate( + /** + * @deprecated + * @this {ContextModule} + * @returns {string} chunk name + */ + function() { + return this.options.chunkName; + }, + "ContextModule.chunkName has been moved to ContextModule.options.chunkName" + ), + set: util.deprecate( + /** + * @deprecated + * @this {ContextModule} + * @param {string} value chunk name + * @returns {void} + */ + function(value) { + this.options.chunkName = value; + }, + "ContextModule.chunkName has been moved to ContextModule.options.chunkName" + ) +}); + +module.exports = ContextModule; diff --git a/node_modules/webpack/lib/ContextModuleFactory.js b/node_modules/webpack/lib/ContextModuleFactory.js index a3bc34e7e..f59411288 100644 --- a/node_modules/webpack/lib/ContextModuleFactory.js +++ b/node_modules/webpack/lib/ContextModuleFactory.js @@ -1,169 +1,262 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const asyncLib = require("async"); -const path = require("path"); - -const Tapable = require("tapable"); -const ContextModule = require("./ContextModule"); -const ContextElementDependency = require("./dependencies/ContextElementDependency"); - -module.exports = class ContextModuleFactory extends Tapable { - constructor(resolvers) { - super(); - this.resolvers = resolvers; - } - - create(data, callback) { - const context = data.context; - const dependencies = data.dependencies; - const dependency = dependencies[0]; - this.applyPluginsAsyncWaterfall("before-resolve", { - context: context, - request: dependency.request, - recursive: dependency.recursive, - regExp: dependency.regExp, - async: dependency.async, - dependencies: dependencies - }, (err, result) => { - if(err) return callback(err); - - // Ignored - if(!result) return callback(); - - const context = result.context; - const request = result.request; - const recursive = result.recursive; - const regExp = result.regExp; - const asyncContext = result.async; - const dependencies = result.dependencies; - - let loaders, resource, loadersPrefix = ""; - const idx = request.lastIndexOf("!"); - if(idx >= 0) { - loaders = request.substr(0, idx + 1); - let i; - for(i = 0; i < loaders.length && loaders[i] === "!"; i++) { - loadersPrefix += "!"; - } - loaders = loaders.substr(i).replace(/!+$/, "").replace(/!!+/g, "!"); - if(loaders === "") loaders = []; - else loaders = loaders.split("!"); - resource = request.substr(idx + 1); - } else { - loaders = []; - resource = request; - } - - const resolvers = this.resolvers; - - asyncLib.parallel([ - function(callback) { - resolvers.context.resolve({}, context, resource, function(err, result) { - if(err) return callback(err); - callback(null, result); - }); - }, - function(callback) { - asyncLib.map(loaders, function(loader, callback) { - resolvers.loader.resolve({}, context, loader, function(err, result) { - if(err) return callback(err); - callback(null, result); - }); - }, callback); - } - ], (err, result) => { - if(err) return callback(err); - - this.applyPluginsAsyncWaterfall("after-resolve", { - loaders: loadersPrefix + result[1].join("!") + (result[1].length > 0 ? "!" : ""), - resource: result[0], - recursive: recursive, - regExp: regExp, - async: asyncContext, - dependencies: dependencies, - resolveDependencies: this.resolveDependencies.bind(this) - }, function(err, result) { - if(err) return callback(err); - - // Ignored - if(!result) return callback(); - - return callback(null, new ContextModule(result.resolveDependencies, result.resource, result.recursive, result.regExp, result.loaders, result.async, dependency.chunkName)); - }); - }); - }); - } - - resolveDependencies(fs, resource, recursive, regExp, callback) { - const cmf = this; - if(!regExp || !resource) - return callback(null, []); - (function addDirectory(directory, callback) { - fs.readdir(directory, (err, files) => { - if(err) return callback(err); - files = cmf.applyPluginsWaterfall("context-module-files", files); - if(!files || files.length === 0) return callback(null, []); - asyncLib.map(files.filter(function(p) { - return p.indexOf(".") !== 0; - }), (seqment, callback) => { - - const subResource = path.join(directory, seqment); - - fs.stat(subResource, (err, stat) => { - if(err) { - if(err.code === "ENOENT") { - // ENOENT is ok here because the file may have been deleted between - // the readdir and stat calls. - return callback(); - } else { - return callback(err); - } - } - - if(stat.isDirectory()) { - - if(!recursive) return callback(); - addDirectory.call(this, subResource, callback); - - } else if(stat.isFile()) { - - const obj = { - context: resource, - request: "." + subResource.substr(resource.length).replace(/\\/g, "/") - }; - - this.applyPluginsAsyncWaterfall("alternatives", [obj], (err, alternatives) => { - if(err) return callback(err); - alternatives = alternatives.filter(function(obj) { - return regExp.test(obj.request); - }).map(function(obj) { - const dep = new ContextElementDependency(obj.request); - dep.optional = true; - return dep; - }); - callback(null, alternatives); - }); - - } else callback(); - - }); - - }, (err, result) => { - if(err) return callback(err); - - if(!result) return callback(null, []); - - callback(null, result.filter(function(i) { - return !!i; - }).reduce(function(a, i) { - return a.concat(i); - }, [])); - }); - }); - }.call(this, resource, callback)); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const asyncLib = require("neo-async"); +const path = require("path"); + +const { + Tapable, + AsyncSeriesWaterfallHook, + SyncWaterfallHook +} = require("tapable"); +const ContextModule = require("./ContextModule"); +const ContextElementDependency = require("./dependencies/ContextElementDependency"); + +/** @typedef {import("./Module")} Module */ + +const EMPTY_RESOLVE_OPTIONS = {}; + +module.exports = class ContextModuleFactory extends Tapable { + constructor(resolverFactory) { + super(); + this.hooks = { + /** @type {AsyncSeriesWaterfallHook} */ + beforeResolve: new AsyncSeriesWaterfallHook(["data"]), + /** @type {AsyncSeriesWaterfallHook} */ + afterResolve: new AsyncSeriesWaterfallHook(["data"]), + /** @type {SyncWaterfallHook} */ + contextModuleFiles: new SyncWaterfallHook(["files"]), + /** @type {SyncWaterfallHook} */ + alternatives: new AsyncSeriesWaterfallHook(["modules"]) + }; + this._pluginCompat.tap("ContextModuleFactory", options => { + switch (options.name) { + case "before-resolve": + case "after-resolve": + case "alternatives": + options.async = true; + break; + } + }); + this.resolverFactory = resolverFactory; + } + + create(data, callback) { + const context = data.context; + const dependencies = data.dependencies; + const resolveOptions = data.resolveOptions; + const dependency = dependencies[0]; + this.hooks.beforeResolve.callAsync( + Object.assign( + { + context: context, + dependencies: dependencies, + resolveOptions + }, + dependency.options + ), + (err, beforeResolveResult) => { + if (err) return callback(err); + + // Ignored + if (!beforeResolveResult) return callback(); + + const context = beforeResolveResult.context; + const request = beforeResolveResult.request; + const resolveOptions = beforeResolveResult.resolveOptions; + + let loaders, + resource, + loadersPrefix = ""; + const idx = request.lastIndexOf("!"); + if (idx >= 0) { + let loadersRequest = request.substr(0, idx + 1); + let i; + for ( + i = 0; + i < loadersRequest.length && loadersRequest[i] === "!"; + i++ + ) { + loadersPrefix += "!"; + } + loadersRequest = loadersRequest + .substr(i) + .replace(/!+$/, "") + .replace(/!!+/g, "!"); + if (loadersRequest === "") { + loaders = []; + } else { + loaders = loadersRequest.split("!"); + } + resource = request.substr(idx + 1); + } else { + loaders = []; + resource = request; + } + + const contextResolver = this.resolverFactory.get( + "context", + resolveOptions || EMPTY_RESOLVE_OPTIONS + ); + const loaderResolver = this.resolverFactory.get( + "loader", + EMPTY_RESOLVE_OPTIONS + ); + + asyncLib.parallel( + [ + callback => { + contextResolver.resolve( + {}, + context, + resource, + {}, + (err, result) => { + if (err) return callback(err); + callback(null, result); + } + ); + }, + callback => { + asyncLib.map( + loaders, + (loader, callback) => { + loaderResolver.resolve( + {}, + context, + loader, + {}, + (err, result) => { + if (err) return callback(err); + callback(null, result); + } + ); + }, + callback + ); + } + ], + (err, result) => { + if (err) return callback(err); + + this.hooks.afterResolve.callAsync( + Object.assign( + { + addon: + loadersPrefix + + result[1].join("!") + + (result[1].length > 0 ? "!" : ""), + resource: result[0], + resolveDependencies: this.resolveDependencies.bind(this) + }, + beforeResolveResult + ), + (err, result) => { + if (err) return callback(err); + + // Ignored + if (!result) return callback(); + + return callback( + null, + new ContextModule(result.resolveDependencies, result) + ); + } + ); + } + ); + } + ); + } + + resolveDependencies(fs, options, callback) { + const cmf = this; + let resource = options.resource; + let resourceQuery = options.resourceQuery; + let recursive = options.recursive; + let regExp = options.regExp; + let include = options.include; + let exclude = options.exclude; + if (!regExp || !resource) return callback(null, []); + + const addDirectory = (directory, callback) => { + fs.readdir(directory, (err, files) => { + if (err) return callback(err); + files = cmf.hooks.contextModuleFiles.call(files); + if (!files || files.length === 0) return callback(null, []); + asyncLib.map( + files.filter(p => p.indexOf(".") !== 0), + (segment, callback) => { + const subResource = path.join(directory, segment); + + if (!exclude || !subResource.match(exclude)) { + fs.stat(subResource, (err, stat) => { + if (err) { + if (err.code === "ENOENT") { + // ENOENT is ok here because the file may have been deleted between + // the readdir and stat calls. + return callback(); + } else { + return callback(err); + } + } + + if (stat.isDirectory()) { + if (!recursive) return callback(); + addDirectory.call(this, subResource, callback); + } else if ( + stat.isFile() && + (!include || subResource.match(include)) + ) { + const obj = { + context: resource, + request: + "." + + subResource.substr(resource.length).replace(/\\/g, "/") + }; + + this.hooks.alternatives.callAsync( + [obj], + (err, alternatives) => { + if (err) return callback(err); + alternatives = alternatives + .filter(obj => regExp.test(obj.request)) + .map(obj => { + const dep = new ContextElementDependency( + obj.request + resourceQuery, + obj.request + ); + dep.optional = true; + return dep; + }); + callback(null, alternatives); + } + ); + } else { + callback(); + } + }); + } else { + callback(); + } + }, + (err, result) => { + if (err) return callback(err); + + if (!result) return callback(null, []); + + callback( + null, + result.filter(Boolean).reduce((a, i) => a.concat(i), []) + ); + } + ); + }); + }; + + addDirectory(resource, callback); + } +}; diff --git a/node_modules/webpack/lib/ContextReplacementPlugin.js b/node_modules/webpack/lib/ContextReplacementPlugin.js index 29fede826..5523c8ab6 100644 --- a/node_modules/webpack/lib/ContextReplacementPlugin.js +++ b/node_modules/webpack/lib/ContextReplacementPlugin.js @@ -1,111 +1,133 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const path = require("path"); -const ContextElementDependency = require("./dependencies/ContextElementDependency"); - -class ContextReplacementPlugin { - constructor(resourceRegExp, newContentResource, newContentRecursive, newContentRegExp) { - this.resourceRegExp = resourceRegExp; - - if(typeof newContentResource === "function") { - this.newContentCallback = newContentResource; - } else if(typeof newContentResource === "string" && typeof newContentRecursive === "object") { - this.newContentResource = newContentResource; - this.newContentCreateContextMap = (fs, callback) => { - callback(null, newContentRecursive); - }; - } else if(typeof newContentResource === "string" && typeof newContentRecursive === "function") { - this.newContentResource = newContentResource; - this.newContentCreateContextMap = newContentRecursive; - } else { - if(typeof newContentResource !== "string") { - newContentRegExp = newContentRecursive; - newContentRecursive = newContentResource; - newContentResource = undefined; - } - if(typeof newContentRecursive !== "boolean") { - newContentRegExp = newContentRecursive; - newContentRecursive = undefined; - } - this.newContentResource = newContentResource; - this.newContentRecursive = newContentRecursive; - this.newContentRegExp = newContentRegExp; - } - } - - apply(compiler) { - const resourceRegExp = this.resourceRegExp; - const newContentCallback = this.newContentCallback; - const newContentResource = this.newContentResource; - const newContentRecursive = this.newContentRecursive; - const newContentRegExp = this.newContentRegExp; - const newContentCreateContextMap = this.newContentCreateContextMap; - - compiler.plugin("context-module-factory", (cmf) => { - cmf.plugin("before-resolve", (result, callback) => { - if(!result) return callback(); - if(resourceRegExp.test(result.request)) { - if(typeof newContentResource !== "undefined") - result.request = newContentResource; - if(typeof newContentRecursive !== "undefined") - result.recursive = newContentRecursive; - if(typeof newContentRegExp !== "undefined") - result.regExp = newContentRegExp; - if(typeof newContentCallback === "function") { - newContentCallback(result); - } else { - result.dependencies.forEach((d) => { - if(d.critical) - d.critical = false; - }); - } - } - return callback(null, result); - }); - cmf.plugin("after-resolve", (result, callback) => { - if(!result) return callback(); - if(resourceRegExp.test(result.resource)) { - if(typeof newContentResource !== "undefined") - result.resource = path.resolve(result.resource, newContentResource); - if(typeof newContentRecursive !== "undefined") - result.recursive = newContentRecursive; - if(typeof newContentRegExp !== "undefined") - result.regExp = newContentRegExp; - if(typeof newContentCreateContextMap === "function") - result.resolveDependencies = createResolveDependenciesFromContextMap(newContentCreateContextMap); - if(typeof newContentCallback === "function") { - const origResource = result.resource; - newContentCallback(result); - if(result.resource !== origResource) { - result.resource = path.resolve(origResource, result.resource); - } - } else { - result.dependencies.forEach((d) => { - if(d.critical) - d.critical = false; - }); - } - } - return callback(null, result); - }); - }); - } -} - -const createResolveDependenciesFromContextMap = (createContextMap) => { - return function resolveDependenciesFromContextMap(fs, resource, recursive, regExp, callback) { - createContextMap(fs, (err, map) => { - if(err) return callback(err); - const dependencies = Object.keys(map).map((key) => { - return new ContextElementDependency(map[key], key); - }); - callback(null, dependencies); - }); - }; -}; - -module.exports = ContextReplacementPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const path = require("path"); +const ContextElementDependency = require("./dependencies/ContextElementDependency"); + +class ContextReplacementPlugin { + constructor( + resourceRegExp, + newContentResource, + newContentRecursive, + newContentRegExp + ) { + this.resourceRegExp = resourceRegExp; + + if (typeof newContentResource === "function") { + this.newContentCallback = newContentResource; + } else if ( + typeof newContentResource === "string" && + typeof newContentRecursive === "object" + ) { + this.newContentResource = newContentResource; + this.newContentCreateContextMap = (fs, callback) => { + callback(null, newContentRecursive); + }; + } else if ( + typeof newContentResource === "string" && + typeof newContentRecursive === "function" + ) { + this.newContentResource = newContentResource; + this.newContentCreateContextMap = newContentRecursive; + } else { + if (typeof newContentResource !== "string") { + newContentRegExp = newContentRecursive; + newContentRecursive = newContentResource; + newContentResource = undefined; + } + if (typeof newContentRecursive !== "boolean") { + newContentRegExp = newContentRecursive; + newContentRecursive = undefined; + } + this.newContentResource = newContentResource; + this.newContentRecursive = newContentRecursive; + this.newContentRegExp = newContentRegExp; + } + } + + apply(compiler) { + const resourceRegExp = this.resourceRegExp; + const newContentCallback = this.newContentCallback; + const newContentResource = this.newContentResource; + const newContentRecursive = this.newContentRecursive; + const newContentRegExp = this.newContentRegExp; + const newContentCreateContextMap = this.newContentCreateContextMap; + + compiler.hooks.contextModuleFactory.tap("ContextReplacementPlugin", cmf => { + cmf.hooks.beforeResolve.tap("ContextReplacementPlugin", result => { + if (!result) return; + if (resourceRegExp.test(result.request)) { + if (newContentResource !== undefined) { + result.request = newContentResource; + } + if (newContentRecursive !== undefined) { + result.recursive = newContentRecursive; + } + if (newContentRegExp !== undefined) { + result.regExp = newContentRegExp; + } + if (typeof newContentCallback === "function") { + newContentCallback(result); + } else { + for (const d of result.dependencies) { + if (d.critical) d.critical = false; + } + } + } + return result; + }); + cmf.hooks.afterResolve.tap("ContextReplacementPlugin", result => { + if (!result) return; + if (resourceRegExp.test(result.resource)) { + if (newContentResource !== undefined) { + result.resource = path.resolve(result.resource, newContentResource); + } + if (newContentRecursive !== undefined) { + result.recursive = newContentRecursive; + } + if (newContentRegExp !== undefined) { + result.regExp = newContentRegExp; + } + if (typeof newContentCreateContextMap === "function") { + result.resolveDependencies = createResolveDependenciesFromContextMap( + newContentCreateContextMap + ); + } + if (typeof newContentCallback === "function") { + const origResource = result.resource; + newContentCallback(result); + if (result.resource !== origResource) { + result.resource = path.resolve(origResource, result.resource); + } + } else { + for (const d of result.dependencies) { + if (d.critical) d.critical = false; + } + } + } + return result; + }); + }); + } +} + +const createResolveDependenciesFromContextMap = createContextMap => { + const resolveDependenciesFromContextMap = (fs, options, callback) => { + createContextMap(fs, (err, map) => { + if (err) return callback(err); + const dependencies = Object.keys(map).map(key => { + return new ContextElementDependency( + map[key] + options.resourceQuery, + key + ); + }); + callback(null, dependencies); + }); + }; + return resolveDependenciesFromContextMap; +}; + +module.exports = ContextReplacementPlugin; diff --git a/node_modules/webpack/lib/DefinePlugin.js b/node_modules/webpack/lib/DefinePlugin.js index 6318124f5..805b055ef 100644 --- a/node_modules/webpack/lib/DefinePlugin.js +++ b/node_modules/webpack/lib/DefinePlugin.js @@ -1,123 +1,283 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ConstDependency = require("./dependencies/ConstDependency"); -const BasicEvaluatedExpression = require("./BasicEvaluatedExpression"); -const ParserHelpers = require("./ParserHelpers"); -const NullFactory = require("./NullFactory"); - -class DefinePlugin { - constructor(definitions) { - this.definitions = definitions; - } - - apply(compiler) { - const definitions = this.definitions; - compiler.plugin("compilation", (compilation, params) => { - compilation.dependencyFactories.set(ConstDependency, new NullFactory()); - compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template()); - - params.normalModuleFactory.plugin("parser", (parser) => { - (function walkDefinitions(definitions, prefix) { - Object.keys(definitions).forEach((key) => { - const code = definitions[key]; - if(code && typeof code === "object" && !(code instanceof RegExp)) { - walkDefinitions(code, prefix + key + "."); - applyObjectDefine(prefix + key, code); - return; - } - applyDefineKey(prefix, key); - applyDefine(prefix + key, code); - }); - }(definitions, "")); - - function stringifyObj(obj) { - return "Object({" + Object.keys(obj).map((key) => { - const code = obj[key]; - return JSON.stringify(key) + ":" + toCode(code); - }).join(",") + "})"; - } - - function toCode(code) { - if(code === null) return "null"; - else if(code === undefined) return "undefined"; - else if(code instanceof RegExp && code.toString) return code.toString(); - else if(typeof code === "function" && code.toString) return "(" + code.toString() + ")"; - else if(typeof code === "object") return stringifyObj(code); - else return code + ""; - } - - function applyDefineKey(prefix, key) { - const splittedKey = key.split("."); - splittedKey.slice(1).forEach((_, i) => { - const fullKey = prefix + splittedKey.slice(0, i + 1).join("."); - parser.plugin("can-rename " + fullKey, ParserHelpers.approve); - }); - } - - function applyDefine(key, code) { - const isTypeof = /^typeof\s+/.test(key); - if(isTypeof) key = key.replace(/^typeof\s+/, ""); - let recurse = false; - let recurseTypeof = false; - code = toCode(code); - if(!isTypeof) { - parser.plugin("can-rename " + key, ParserHelpers.approve); - parser.plugin("evaluate Identifier " + key, (expr) => { - /** - * this is needed in case there is a recursion in the DefinePlugin - * to prevent an endless recursion - * e.g.: new DefinePlugin({ - * "a": "b", - * "b": "a" - * }); - */ - if(recurse) return; - recurse = true; - const res = parser.evaluate(code); - recurse = false; - res.setRange(expr.range); - return res; - }); - parser.plugin("expression " + key, ParserHelpers.toConstantDependency(code)); - } - const typeofCode = isTypeof ? code : "typeof (" + code + ")"; - parser.plugin("evaluate typeof " + key, (expr) => { - /** - * this is needed in case there is a recursion in the DefinePlugin - * to prevent an endless recursion - * e.g.: new DefinePlugin({ - * "typeof a": "tyepof b", - * "typeof b": "typeof a" - * }); - */ - if(recurseTypeof) return; - recurseTypeof = true; - const res = parser.evaluate(typeofCode); - recurseTypeof = false; - res.setRange(expr.range); - return res; - }); - parser.plugin("typeof " + key, (expr) => { - const res = parser.evaluate(typeofCode); - if(!res.isString()) return; - return ParserHelpers.toConstantDependency(JSON.stringify(res.string)).bind(parser)(expr); - }); - } - - function applyObjectDefine(key, obj) { - const code = stringifyObj(obj); - parser.plugin("can-rename " + key, ParserHelpers.approve); - parser.plugin("evaluate Identifier " + key, (expr) => new BasicEvaluatedExpression().setTruthy().setRange(expr.range)); - parser.plugin("evaluate typeof " + key, ParserHelpers.evaluateToString("object")); - parser.plugin("expression " + key, ParserHelpers.toConstantDependency(code)); - parser.plugin("typeof " + key, ParserHelpers.toConstantDependency(JSON.stringify("object"))); - } - }); - }); - } -} -module.exports = DefinePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const ConstDependency = require("./dependencies/ConstDependency"); +const BasicEvaluatedExpression = require("./BasicEvaluatedExpression"); +const ParserHelpers = require("./ParserHelpers"); +const NullFactory = require("./NullFactory"); + +/** @typedef {import("./Compiler")} Compiler */ +/** @typedef {import("./Parser")} Parser */ +/** @typedef {null|undefined|RegExp|Function|string|number} CodeValuePrimitive */ +/** @typedef {CodeValuePrimitive|Record|RuntimeValue} CodeValue */ + +class RuntimeValue { + constructor(fn, fileDependencies) { + this.fn = fn; + this.fileDependencies = fileDependencies || []; + } + + exec(parser) { + for (const fileDependency of this.fileDependencies) { + parser.state.module.buildInfo.fileDependencies.add(fileDependency); + } + + return this.fn(); + } +} + +const stringifyObj = (obj, parser) => { + return ( + "Object({" + + Object.keys(obj) + .map(key => { + const code = obj[key]; + return JSON.stringify(key) + ":" + toCode(code, parser); + }) + .join(",") + + "})" + ); +}; + +/** + * Convert code to a string that evaluates + * @param {CodeValue} code Code to evaluate + * @param {Parser} parser Parser + * @returns {string} code converted to string that evaluates + */ +const toCode = (code, parser) => { + if (code === null) { + return "null"; + } + if (code === undefined) { + return "undefined"; + } + if (code instanceof RuntimeValue) { + return toCode(code.exec(parser), parser); + } + if (code instanceof RegExp && code.toString) { + return code.toString(); + } + if (typeof code === "function" && code.toString) { + return "(" + code.toString() + ")"; + } + if (typeof code === "object") { + return stringifyObj(code, parser); + } + return code + ""; +}; + +class DefinePlugin { + /** + * Create a new define plugin + * @param {Record} definitions A map of global object definitions + */ + constructor(definitions) { + this.definitions = definitions; + } + + static runtimeValue(fn, fileDependencies) { + return new RuntimeValue(fn, fileDependencies); + } + + /** + * Apply the plugin + * @param {Compiler} compiler Webpack compiler + * @returns {void} + */ + apply(compiler) { + const definitions = this.definitions; + compiler.hooks.compilation.tap( + "DefinePlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set(ConstDependency, new NullFactory()); + compilation.dependencyTemplates.set( + ConstDependency, + new ConstDependency.Template() + ); + + /** + * Handler + * @param {Parser} parser Parser + * @returns {void} + */ + const handler = parser => { + /** + * Walk definitions + * @param {Object} definitions Definitions map + * @param {string} prefix Prefix string + * @returns {void} + */ + const walkDefinitions = (definitions, prefix) => { + Object.keys(definitions).forEach(key => { + const code = definitions[key]; + if ( + code && + typeof code === "object" && + !(code instanceof RuntimeValue) && + !(code instanceof RegExp) + ) { + walkDefinitions(code, prefix + key + "."); + applyObjectDefine(prefix + key, code); + return; + } + applyDefineKey(prefix, key); + applyDefine(prefix + key, code); + }); + }; + + /** + * Apply define key + * @param {string} prefix Prefix + * @param {string} key Key + * @returns {void} + */ + const applyDefineKey = (prefix, key) => { + const splittedKey = key.split("."); + splittedKey.slice(1).forEach((_, i) => { + const fullKey = prefix + splittedKey.slice(0, i + 1).join("."); + parser.hooks.canRename + .for(fullKey) + .tap("DefinePlugin", ParserHelpers.approve); + }); + }; + + /** + * Apply Code + * @param {string} key Key + * @param {CodeValue} code Code + * @returns {void} + */ + const applyDefine = (key, code) => { + const isTypeof = /^typeof\s+/.test(key); + if (isTypeof) key = key.replace(/^typeof\s+/, ""); + let recurse = false; + let recurseTypeof = false; + if (!isTypeof) { + parser.hooks.canRename + .for(key) + .tap("DefinePlugin", ParserHelpers.approve); + parser.hooks.evaluateIdentifier + .for(key) + .tap("DefinePlugin", expr => { + /** + * this is needed in case there is a recursion in the DefinePlugin + * to prevent an endless recursion + * e.g.: new DefinePlugin({ + * "a": "b", + * "b": "a" + * }); + */ + if (recurse) return; + recurse = true; + const res = parser.evaluate(toCode(code, parser)); + recurse = false; + res.setRange(expr.range); + return res; + }); + parser.hooks.expression.for(key).tap("DefinePlugin", expr => { + const strCode = toCode(code, parser); + if (/__webpack_require__/.test(strCode)) { + return ParserHelpers.toConstantDependencyWithWebpackRequire( + parser, + strCode + )(expr); + } else { + return ParserHelpers.toConstantDependency(parser, strCode)( + expr + ); + } + }); + } + parser.hooks.evaluateTypeof.for(key).tap("DefinePlugin", expr => { + /** + * this is needed in case there is a recursion in the DefinePlugin + * to prevent an endless recursion + * e.g.: new DefinePlugin({ + * "typeof a": "typeof b", + * "typeof b": "typeof a" + * }); + */ + if (recurseTypeof) return; + recurseTypeof = true; + const typeofCode = isTypeof + ? toCode(code, parser) + : "typeof (" + toCode(code, parser) + ")"; + const res = parser.evaluate(typeofCode); + recurseTypeof = false; + res.setRange(expr.range); + return res; + }); + parser.hooks.typeof.for(key).tap("DefinePlugin", expr => { + const typeofCode = isTypeof + ? toCode(code, parser) + : "typeof (" + toCode(code, parser) + ")"; + const res = parser.evaluate(typeofCode); + if (!res.isString()) return; + return ParserHelpers.toConstantDependency( + parser, + JSON.stringify(res.string) + ).bind(parser)(expr); + }); + }; + + /** + * Apply Object + * @param {string} key Key + * @param {Object} obj Object + * @returns {void} + */ + const applyObjectDefine = (key, obj) => { + parser.hooks.canRename + .for(key) + .tap("DefinePlugin", ParserHelpers.approve); + parser.hooks.evaluateIdentifier + .for(key) + .tap("DefinePlugin", expr => + new BasicEvaluatedExpression().setTruthy().setRange(expr.range) + ); + parser.hooks.evaluateTypeof.for(key).tap("DefinePlugin", expr => { + return ParserHelpers.evaluateToString("object")(expr); + }); + parser.hooks.expression.for(key).tap("DefinePlugin", expr => { + const strCode = stringifyObj(obj, parser); + + if (/__webpack_require__/.test(strCode)) { + return ParserHelpers.toConstantDependencyWithWebpackRequire( + parser, + strCode + )(expr); + } else { + return ParserHelpers.toConstantDependency(parser, strCode)( + expr + ); + } + }); + parser.hooks.typeof.for(key).tap("DefinePlugin", expr => { + return ParserHelpers.toConstantDependency( + parser, + JSON.stringify("object") + )(expr); + }); + }; + + walkDefinitions(definitions, ""); + }; + + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("DefinePlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("DefinePlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/esm") + .tap("DefinePlugin", handler); + } + ); + } +} +module.exports = DefinePlugin; diff --git a/node_modules/webpack/lib/DelegatedModule.js b/node_modules/webpack/lib/DelegatedModule.js index 4046d03d5..170ceca7a 100644 --- a/node_modules/webpack/lib/DelegatedModule.js +++ b/node_modules/webpack/lib/DelegatedModule.js @@ -1,98 +1,114 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const Module = require("./Module"); -const OriginalSource = require("webpack-sources").OriginalSource; -const RawSource = require("webpack-sources").RawSource; -const WebpackMissingModule = require("./dependencies/WebpackMissingModule"); -const DelegatedSourceDependency = require("./dependencies/DelegatedSourceDependency"); -const DelegatedExportsDependency = require("./dependencies/DelegatedExportsDependency"); - -class DelegatedModule extends Module { - constructor(sourceRequest, data, type, userRequest, originalRequest) { - super(); - this.sourceRequest = sourceRequest; - this.request = data.id; - this.meta = data.meta; - this.type = type; - this.originalRequest = originalRequest; - this.userRequest = userRequest; - this.built = false; - this.delegated = true; - this.delegateData = data; - } - - libIdent(options) { - return typeof this.originalRequest === "string" ? this.originalRequest : this.originalRequest.libIdent(options); - } - - identifier() { - return `delegated ${JSON.stringify(this.request)} from ${this.sourceRequest}`; - } - - readableIdentifier() { - return `delegated ${this.userRequest} from ${this.sourceRequest}`; - } - - needRebuild() { - return false; - } - - build(options, compilation, resolver, fs, callback) { - this.built = true; - this.builtTime = Date.now(); - this.cacheable = true; - this.dependencies.length = 0; - this.addDependency(new DelegatedSourceDependency(this.sourceRequest)); - this.addDependency(new DelegatedExportsDependency(this, this.delegateData.exports || true)); - callback(); - } - - unbuild() { - this.built = false; - super.unbuild(); - } - - source() { - const sourceModule = this.dependencies[0].module; - let str; - - if(!sourceModule) { - str = WebpackMissingModule.moduleCode(this.sourceRequest); - } else { - str = `module.exports = (__webpack_require__(${JSON.stringify(sourceModule.id)}))`; - - switch(this.type) { - case "require": - str += `(${JSON.stringify(this.request)})`; - break; - case "object": - str += `[${JSON.stringify(this.request)}]`; - break; - } - - str += ";"; - } - - if(this.useSourceMap) { - return new OriginalSource(str, this.identifier()); - } else { - return new RawSource(str); - } - } - - size() { - return 42; - } - - updateHash(hash) { - hash.update(this.type); - hash.update(JSON.stringify(this.request)); - super.updateHash(hash); - } -} - -module.exports = DelegatedModule; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const { OriginalSource, RawSource } = require("webpack-sources"); + +const Module = require("./Module"); +const WebpackMissingModule = require("./dependencies/WebpackMissingModule"); +const DelegatedSourceDependency = require("./dependencies/DelegatedSourceDependency"); +const DelegatedExportsDependency = require("./dependencies/DelegatedExportsDependency"); + +/** @typedef {import("./dependencies/ModuleDependency")} ModuleDependency */ +/** @typedef {import("./util/createHash").Hash} Hash */ + +class DelegatedModule extends Module { + constructor(sourceRequest, data, type, userRequest, originalRequest) { + super("javascript/dynamic", null); + + // Info from Factory + this.sourceRequest = sourceRequest; + this.request = data.id; + this.type = type; + this.userRequest = userRequest; + this.originalRequest = originalRequest; + this.delegateData = data; + + // Build info + this.delegatedSourceDependency = undefined; + } + + libIdent(options) { + return typeof this.originalRequest === "string" + ? this.originalRequest + : this.originalRequest.libIdent(options); + } + + identifier() { + return `delegated ${JSON.stringify(this.request)} from ${ + this.sourceRequest + }`; + } + + readableIdentifier() { + return `delegated ${this.userRequest} from ${this.sourceRequest}`; + } + + needRebuild() { + return false; + } + + build(options, compilation, resolver, fs, callback) { + this.built = true; + this.buildMeta = Object.assign({}, this.delegateData.buildMeta); + this.buildInfo = {}; + this.delegatedSourceDependency = new DelegatedSourceDependency( + this.sourceRequest + ); + this.addDependency(this.delegatedSourceDependency); + this.addDependency( + new DelegatedExportsDependency(this, this.delegateData.exports || true) + ); + callback(); + } + + source(depTemplates, runtime) { + const dep = /** @type {DelegatedSourceDependency} */ (this.dependencies[0]); + const sourceModule = dep.module; + let str; + + if (!sourceModule) { + str = WebpackMissingModule.moduleCode(this.sourceRequest); + } else { + str = `module.exports = (${runtime.moduleExports({ + module: sourceModule, + request: dep.request + })})`; + + switch (this.type) { + case "require": + str += `(${JSON.stringify(this.request)})`; + break; + case "object": + str += `[${JSON.stringify(this.request)}]`; + break; + } + + str += ";"; + } + + if (this.useSourceMap) { + return new OriginalSource(str, this.identifier()); + } else { + return new RawSource(str); + } + } + + size() { + return 42; + } + + /** + * @param {Hash} hash the hash used to track dependencies + * @returns {void} + */ + updateHash(hash) { + hash.update(this.type); + hash.update(JSON.stringify(this.request)); + super.updateHash(hash); + } +} + +module.exports = DelegatedModule; diff --git a/node_modules/webpack/lib/DelegatedModuleFactoryPlugin.js b/node_modules/webpack/lib/DelegatedModuleFactoryPlugin.js index f26dfca94..a0a05a438 100644 --- a/node_modules/webpack/lib/DelegatedModuleFactoryPlugin.js +++ b/node_modules/webpack/lib/DelegatedModuleFactoryPlugin.js @@ -1,59 +1,95 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const DelegatedModule = require("./DelegatedModule"); - -// options.source -// options.type -// options.context -// options.scope -// options.content -class DelegatedModuleFactoryPlugin { - constructor(options) { - this.options = options; - options.type = options.type || "require"; - options.extensions = options.extensions || ["", ".js"]; - } - - apply(normalModuleFactory) { - const scope = this.options.scope; - if(scope) { - normalModuleFactory.plugin("factory", factory => (data, callback) => { - const dependency = data.dependencies[0]; - const request = dependency.request; - if(request && request.indexOf(scope + "/") === 0) { - const innerRequest = "." + request.substr(scope.length); - let resolved; - if(innerRequest in this.options.content) { - resolved = this.options.content[innerRequest]; - return callback(null, new DelegatedModule(this.options.source, resolved, this.options.type, innerRequest, request)); - } - for(let i = 0; i < this.options.extensions.length; i++) { - const extension = this.options.extensions[i]; - const requestPlusExt = innerRequest + extension; - if(requestPlusExt in this.options.content) { - resolved = this.options.content[requestPlusExt]; - return callback(null, new DelegatedModule(this.options.source, resolved, this.options.type, requestPlusExt, request + extension)); - } - } - } - return factory(data, callback); - }); - } else { - normalModuleFactory.plugin("module", module => { - if(module.libIdent) { - const request = module.libIdent(this.options); - if(request && request in this.options.content) { - const resolved = this.options.content[request]; - return new DelegatedModule(this.options.source, resolved, this.options.type, request, module); - } - } - return module; - }); - } - } -} -module.exports = DelegatedModuleFactoryPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const DelegatedModule = require("./DelegatedModule"); + +// options.source +// options.type +// options.context +// options.scope +// options.content +class DelegatedModuleFactoryPlugin { + constructor(options) { + this.options = options; + options.type = options.type || "require"; + options.extensions = options.extensions || [ + "", + ".wasm", + ".mjs", + ".js", + ".json" + ]; + } + + apply(normalModuleFactory) { + const scope = this.options.scope; + if (scope) { + normalModuleFactory.hooks.factory.tap( + "DelegatedModuleFactoryPlugin", + factory => (data, callback) => { + const dependency = data.dependencies[0]; + const request = dependency.request; + if (request && request.indexOf(scope + "/") === 0) { + const innerRequest = "." + request.substr(scope.length); + let resolved; + if (innerRequest in this.options.content) { + resolved = this.options.content[innerRequest]; + return callback( + null, + new DelegatedModule( + this.options.source, + resolved, + this.options.type, + innerRequest, + request + ) + ); + } + for (let i = 0; i < this.options.extensions.length; i++) { + const extension = this.options.extensions[i]; + const requestPlusExt = innerRequest + extension; + if (requestPlusExt in this.options.content) { + resolved = this.options.content[requestPlusExt]; + return callback( + null, + new DelegatedModule( + this.options.source, + resolved, + this.options.type, + requestPlusExt, + request + extension + ) + ); + } + } + } + return factory(data, callback); + } + ); + } else { + normalModuleFactory.hooks.module.tap( + "DelegatedModuleFactoryPlugin", + module => { + if (module.libIdent) { + const request = module.libIdent(this.options); + if (request && request in this.options.content) { + const resolved = this.options.content[request]; + return new DelegatedModule( + this.options.source, + resolved, + this.options.type, + request, + module + ); + } + } + return module; + } + ); + } + } +} +module.exports = DelegatedModuleFactoryPlugin; diff --git a/node_modules/webpack/lib/DelegatedPlugin.js b/node_modules/webpack/lib/DelegatedPlugin.js index 67894d9bd..714eb8533 100644 --- a/node_modules/webpack/lib/DelegatedPlugin.js +++ b/node_modules/webpack/lib/DelegatedPlugin.js @@ -1,30 +1,39 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ - -"use strict"; - -const DelegatedModuleFactoryPlugin = require("./DelegatedModuleFactoryPlugin"); -const DelegatedSourceDependency = require("./dependencies/DelegatedSourceDependency"); -const DelegatedExportsDependency = require("./dependencies/DelegatedExportsDependency"); -const NullFactory = require("./NullFactory"); - -class DelegatedPlugin { - constructor(options) { - this.options = options; - } - - apply(compiler) { - compiler.plugin("compilation", (compilation, params) => { - compilation.dependencyFactories.set(DelegatedSourceDependency, params.normalModuleFactory); - compilation.dependencyFactories.set(DelegatedExportsDependency, new NullFactory()); - }); - - compiler.plugin("compile", (params) => { - params.normalModuleFactory.apply(new DelegatedModuleFactoryPlugin(this.options)); - }); - } -} - -module.exports = DelegatedPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ + +"use strict"; + +const DelegatedModuleFactoryPlugin = require("./DelegatedModuleFactoryPlugin"); +const DelegatedSourceDependency = require("./dependencies/DelegatedSourceDependency"); +const DelegatedExportsDependency = require("./dependencies/DelegatedExportsDependency"); +const NullFactory = require("./NullFactory"); + +class DelegatedPlugin { + constructor(options) { + this.options = options; + } + + apply(compiler) { + compiler.hooks.compilation.tap( + "DelegatedPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set( + DelegatedSourceDependency, + normalModuleFactory + ); + compilation.dependencyFactories.set( + DelegatedExportsDependency, + new NullFactory() + ); + } + ); + + compiler.hooks.compile.tap("DelegatedPlugin", ({ normalModuleFactory }) => { + new DelegatedModuleFactoryPlugin(this.options).apply(normalModuleFactory); + }); + } +} + +module.exports = DelegatedPlugin; diff --git a/node_modules/webpack/lib/DependenciesBlock.js b/node_modules/webpack/lib/DependenciesBlock.js index d8b07c1db..142f3eacb 100644 --- a/node_modules/webpack/lib/DependenciesBlock.js +++ b/node_modules/webpack/lib/DependenciesBlock.js @@ -1,81 +1,124 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra - */ -"use strict"; - -const DependenciesBlockVariable = require("./DependenciesBlockVariable"); - -function disconnect(i) { - i.disconnect(); -} - -function unseal(i) { - i.unseal(); -} - -class DependenciesBlock { - constructor() { - this.dependencies = []; - this.blocks = []; - this.variables = []; - } - - addBlock(block) { - this.blocks.push(block); - block.parent = this; - } - - addVariable(name, expression, dependencies) { - for(let v of this.variables) { - if(v.name === name && v.expression === expression) { - return; - } - } - this.variables.push(new DependenciesBlockVariable(name, expression, dependencies)); - } - - addDependency(dependency) { - this.dependencies.push(dependency); - } - - updateHash(hash) { - function updateHash(i) { - i.updateHash(hash); - } - - this.dependencies.forEach(updateHash); - this.blocks.forEach(updateHash); - this.variables.forEach(updateHash); - } - - disconnect() { - this.dependencies.forEach(disconnect); - this.blocks.forEach(disconnect); - this.variables.forEach(disconnect); - } - - unseal() { - this.blocks.forEach(unseal); - } - - hasDependencies(filter) { - if(filter) { - if(this.dependencies.some(filter)) { - return true; - } - } else { - if(this.dependencies.length > 0) { - return true; - } - } - - return this.blocks.concat(this.variables).some(item => item.hasDependencies(filter)); - } - - sortItems() { - this.blocks.forEach(block => block.sortItems()); - } -} - -module.exports = DependenciesBlock; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra + */ +"use strict"; + +const DependenciesBlockVariable = require("./DependenciesBlockVariable"); + +/** @typedef {import("./ChunkGroup")} ChunkGroup */ +/** @typedef {import("./Dependency")} Dependency */ +/** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */ +/** @typedef {import("./DependenciesBlockVariable")} DependenciesBlockVariable */ +/** @typedef {(d: Dependency) => boolean} DependencyFilterFunction */ +/** @typedef {import("./util/createHash").Hash} Hash */ + +class DependenciesBlock { + constructor() { + /** @type {Dependency[]} */ + this.dependencies = []; + /** @type {AsyncDependenciesBlock[]} */ + this.blocks = []; + /** @type {DependenciesBlockVariable[]} */ + this.variables = []; + } + + /** + * Adds a DependencyBlock to DependencyBlock relationship. + * This is used for when a Module has a AsyncDependencyBlock tie (for code-splitting) + * + * @param {AsyncDependenciesBlock} block block being added + * @returns {void} + */ + addBlock(block) { + this.blocks.push(block); + block.parent = this; + } + + /** + * @param {string} name name of dependency + * @param {string} expression expression string for variable + * @param {Dependency[]} dependencies dependency instances tied to variable + * @returns {void} + */ + addVariable(name, expression, dependencies) { + for (let v of this.variables) { + if (v.name === name && v.expression === expression) { + return; + } + } + this.variables.push( + new DependenciesBlockVariable(name, expression, dependencies) + ); + } + + /** + * @param {Dependency} dependency dependency being tied to block. + * This is an "edge" pointing to another "node" on module graph. + * @returns {void} + */ + addDependency(dependency) { + this.dependencies.push(dependency); + } + + /** + * @param {Dependency} dependency dependency being removed + * @returns {void} + */ + removeDependency(dependency) { + const idx = this.dependencies.indexOf(dependency); + if (idx >= 0) { + this.dependencies.splice(idx, 1); + } + } + + /** + * @param {Hash} hash the hash used to track dependencies + * @returns {void} + */ + updateHash(hash) { + for (const dep of this.dependencies) dep.updateHash(hash); + for (const block of this.blocks) block.updateHash(hash); + for (const variable of this.variables) variable.updateHash(hash); + } + + disconnect() { + for (const dep of this.dependencies) dep.disconnect(); + for (const block of this.blocks) block.disconnect(); + for (const variable of this.variables) variable.disconnect(); + } + + unseal() { + for (const block of this.blocks) block.unseal(); + } + + /** + * @param {DependencyFilterFunction} filter filter function for dependencies, gets passed all dependency ties from current instance + * @returns {boolean} returns boolean for filter + */ + hasDependencies(filter) { + if (filter) { + for (const dep of this.dependencies) { + if (filter(dep)) return true; + } + } else { + if (this.dependencies.length > 0) { + return true; + } + } + + for (const block of this.blocks) { + if (block.hasDependencies(filter)) return true; + } + for (const variable of this.variables) { + if (variable.hasDependencies(filter)) return true; + } + return false; + } + + sortItems() { + for (const block of this.blocks) block.sortItems(); + } +} + +module.exports = DependenciesBlock; diff --git a/node_modules/webpack/lib/DependenciesBlockVariable.js b/node_modules/webpack/lib/DependenciesBlockVariable.js index 0da641674..c4ed91627 100644 --- a/node_modules/webpack/lib/DependenciesBlockVariable.js +++ b/node_modules/webpack/lib/DependenciesBlockVariable.js @@ -1,51 +1,72 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ReplaceSource = require("webpack-sources").ReplaceSource; -const RawSource = require("webpack-sources").RawSource; - -class DependenciesBlockVariable { - constructor(name, expression, dependencies) { - this.name = name; - this.expression = expression; - this.dependencies = dependencies || []; - } - - updateHash(hash) { - hash.update(this.name); - hash.update(this.expression); - this.dependencies.forEach(d => { - d.updateHash(hash); - }); - } - - expressionSource(dependencyTemplates, outputOptions, requestShortener) { - const source = new ReplaceSource(new RawSource(this.expression)); - this.dependencies.forEach(dep => { - const template = dependencyTemplates.get(dep.constructor); - if(!template) throw new Error(`No template for dependency: ${dep.constructor.name}`); - template.apply(dep, source, outputOptions, requestShortener, dependencyTemplates); - }); - return source; - } - - disconnect() { - this.dependencies.forEach(d => { - d.disconnect(); - }); - } - - hasDependencies(filter) { - if(filter) { - if(this.dependencies.some(filter)) return true; - } else { - if(this.dependencies.length > 0) return true; - } - return false; - } -} - -module.exports = DependenciesBlockVariable; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const { RawSource, ReplaceSource } = require("webpack-sources"); + +/** @typedef {import("./Dependency")} Dependency */ +/** @typedef {import("./Dependency").DependencyTemplate} DependencyTemplate */ +/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */ +/** @typedef {import("./util/createHash").Hash} Hash */ +/** @typedef {(d: Dependency) => boolean} DependencyFilterFunction */ +/** @typedef {Map} DependencyTemplates */ + +class DependenciesBlockVariable { + /** + * Creates an instance of DependenciesBlockVariable. + * @param {string} name name of DependenciesBlockVariable + * @param {string} expression expression string + * @param {Dependency[]=} dependencies dependencies tied to this varaiable + */ + constructor(name, expression, dependencies) { + this.name = name; + this.expression = expression; + this.dependencies = dependencies || []; + } + + /** + * @param {Hash} hash hash for instance to update + * @returns {void} + */ + updateHash(hash) { + hash.update(this.name); + hash.update(this.expression); + for (const d of this.dependencies) { + d.updateHash(hash); + } + } + + /** + * @param {DependencyTemplates} dependencyTemplates Dependency constructors and templates Map. + * @param {RuntimeTemplate} runtimeTemplate runtimeTemplate to generate expression souce + * @returns {ReplaceSource} returns constructed source for expression via templates + */ + expressionSource(dependencyTemplates, runtimeTemplate) { + const source = new ReplaceSource(new RawSource(this.expression)); + for (const dep of this.dependencies) { + const template = dependencyTemplates.get(dep.constructor); + if (!template) { + throw new Error(`No template for dependency: ${dep.constructor.name}`); + } + template.apply(dep, source, runtimeTemplate, dependencyTemplates); + } + return source; + } + + disconnect() { + for (const d of this.dependencies) { + d.disconnect(); + } + } + + hasDependencies(filter) { + if (filter) { + return this.dependencies.some(filter); + } + return this.dependencies.length > 0; + } +} + +module.exports = DependenciesBlockVariable; diff --git a/node_modules/webpack/lib/Dependency.js b/node_modules/webpack/lib/Dependency.js index d9ebc287f..6d27b1ed6 100644 --- a/node_modules/webpack/lib/Dependency.js +++ b/node_modules/webpack/lib/Dependency.js @@ -1,54 +1,89 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const compareLocations = require("./compareLocations"); - -class Dependency { - constructor() { - this.module = null; - } - - isEqualResource() { - return false; - } - - // Returns the referenced module and export - getReference() { - if(!this.module) return null; - return { - module: this.module, - importedNames: true, // true: full object, false: only sideeffects/no export, array of strings: the exports with this names - }; - } - - // Returns the exported names - getExports() { - return null; - } - - getWarnings() { - return null; - } - - getErrors() { - return null; - } - - updateHash(hash) { - hash.update((this.module && this.module.id) + ""); - } - - disconnect() { - this.module = null; - } - - // TODO: remove in webpack 3 - compare(a, b) { - return compareLocations(a.loc, b.loc); - } -} -Dependency.compare = (a, b) => compareLocations(a.loc, b.loc); - -module.exports = Dependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const util = require("util"); +const compareLocations = require("./compareLocations"); +const DependencyReference = require("./dependencies/DependencyReference"); + +/** @typedef {import("./Module")} Module */ +/** @typedef {import("webpack-sources").Source} Source */ +/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */ + +/** + * @typedef {Object} DependencyTemplate + * @property {function(Dependency, Source, RuntimeTemplate, Map): void} apply + */ + +/** @typedef {Object} SourcePosition + * @property {number} line + * @property {number=} column + */ + +/** @typedef {Object} RealDependencyLocation + * @property {SourcePosition} start + * @property {SourcePosition=} end + * @property {number=} index + */ + +/** @typedef {Object} SynteticDependencyLocation + * @property {string} name + * @property {number=} index + */ + +/** @typedef {SynteticDependencyLocation|RealDependencyLocation} DependencyLocation */ + +class Dependency { + constructor() { + /** @type {Module|null} */ + this.module = null; + // TODO remove in webpack 5 + /** @type {boolean} */ + this.weak = false; + /** @type {boolean} */ + this.optional = false; + /** @type {DependencyLocation} */ + this.loc = undefined; + } + + getResourceIdentifier() { + return null; + } + + // Returns the referenced module and export + getReference() { + if (!this.module) return null; + return new DependencyReference(this.module, true, this.weak); + } + + // Returns the exported names + getExports() { + return null; + } + + getWarnings() { + return null; + } + + getErrors() { + return null; + } + + updateHash(hash) { + hash.update((this.module && this.module.id) + ""); + } + + disconnect() { + this.module = null; + } +} + +// TODO remove in webpack 5 +Dependency.compare = util.deprecate( + (a, b) => compareLocations(a.loc, b.loc), + "Dependency.compare is deprecated and will be removed in the next major version" +); + +module.exports = Dependency; diff --git a/node_modules/webpack/lib/DllEntryPlugin.js b/node_modules/webpack/lib/DllEntryPlugin.js index 92b3c92c8..562628d90 100644 --- a/node_modules/webpack/lib/DllEntryPlugin.js +++ b/node_modules/webpack/lib/DllEntryPlugin.js @@ -1,37 +1,54 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const DllEntryDependency = require("./dependencies/DllEntryDependency"); -const SingleEntryDependency = require("./dependencies/SingleEntryDependency"); -const DllModuleFactory = require("./DllModuleFactory"); - -class DllEntryPlugin { - constructor(context, entries, name) { - this.context = context; - this.entries = entries; - this.name = name; - } - - apply(compiler) { - compiler.plugin("compilation", (compilation, params) => { - const dllModuleFactory = new DllModuleFactory(); - const normalModuleFactory = params.normalModuleFactory; - - compilation.dependencyFactories.set(DllEntryDependency, dllModuleFactory); - - compilation.dependencyFactories.set(SingleEntryDependency, normalModuleFactory); - }); - compiler.plugin("make", (compilation, callback) => { - compilation.addEntry(this.context, new DllEntryDependency(this.entries.map((e, idx) => { - const dep = new SingleEntryDependency(e); - dep.loc = `${this.name}:${idx}`; - return dep; - }), this.name), this.name, callback); - }); - } -} - -module.exports = DllEntryPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const DllEntryDependency = require("./dependencies/DllEntryDependency"); +const SingleEntryDependency = require("./dependencies/SingleEntryDependency"); +const DllModuleFactory = require("./DllModuleFactory"); + +class DllEntryPlugin { + constructor(context, entries, name) { + this.context = context; + this.entries = entries; + this.name = name; + } + + apply(compiler) { + compiler.hooks.compilation.tap( + "DllEntryPlugin", + (compilation, { normalModuleFactory }) => { + const dllModuleFactory = new DllModuleFactory(); + compilation.dependencyFactories.set( + DllEntryDependency, + dllModuleFactory + ); + compilation.dependencyFactories.set( + SingleEntryDependency, + normalModuleFactory + ); + } + ); + compiler.hooks.make.tapAsync("DllEntryPlugin", (compilation, callback) => { + compilation.addEntry( + this.context, + new DllEntryDependency( + this.entries.map((e, idx) => { + const dep = new SingleEntryDependency(e); + dep.loc = { + name: this.name, + index: idx + }; + return dep; + }), + this.name + ), + this.name, + callback + ); + }); + } +} + +module.exports = DllEntryPlugin; diff --git a/node_modules/webpack/lib/DllModule.js b/node_modules/webpack/lib/DllModule.js index 5e83129e9..0cd9cbcf8 100644 --- a/node_modules/webpack/lib/DllModule.js +++ b/node_modules/webpack/lib/DllModule.js @@ -1,58 +1,60 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra - */ -"use strict"; - -const Module = require("./Module"); -const RawSource = require("webpack-sources").RawSource; - -class DllModule extends Module { - constructor(context, dependencies, name, type) { - super(); - this.context = context; - this.dependencies = dependencies; - this.name = name; - this.built = false; - this.cacheable = true; - this.type = type; - } - - identifier() { - return `dll ${this.name}`; - } - - readableIdentifier() { - return `dll ${this.name}`; - } - - disconnect() { - this.built = false; - super.disconnect(); - } - - build(options, compilation, resolver, fs, callback) { - this.built = true; - return callback(); - } - - source() { - return new RawSource("module.exports = __webpack_require__;"); - } - - needRebuild() { - return false; - } - - size() { - return 12; - } - - updateHash(hash) { - hash.update("dll module"); - hash.update(this.name || ""); - super.updateHash(hash); - } -} - -module.exports = DllModule; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra + */ +"use strict"; + +const { RawSource } = require("webpack-sources"); +const Module = require("./Module"); + +/** @typedef {import("./util/createHash").Hash} Hash */ + +class DllModule extends Module { + constructor(context, dependencies, name, type) { + super("javascript/dynamic", context); + + // Info from Factory + this.dependencies = dependencies; + this.name = name; + this.type = type; + } + + identifier() { + return `dll ${this.name}`; + } + + readableIdentifier() { + return `dll ${this.name}`; + } + + build(options, compilation, resolver, fs, callback) { + this.built = true; + this.buildMeta = {}; + this.buildInfo = {}; + return callback(); + } + + source() { + return new RawSource("module.exports = __webpack_require__;"); + } + + needRebuild() { + return false; + } + + size() { + return 12; + } + + /** + * @param {Hash} hash the hash used to track dependencies + * @returns {void} + */ + updateHash(hash) { + hash.update("dll module"); + hash.update(this.name || ""); + super.updateHash(hash); + } +} + +module.exports = DllModule; diff --git a/node_modules/webpack/lib/DllModuleFactory.js b/node_modules/webpack/lib/DllModuleFactory.js index 7fba3126f..f5d12ddc4 100644 --- a/node_modules/webpack/lib/DllModuleFactory.js +++ b/node_modules/webpack/lib/DllModuleFactory.js @@ -1,20 +1,29 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const Tapable = require("tapable"); -const DllModule = require("./DllModule"); - -class DllModuleFactory extends Tapable { - constructor() { - super(); - } - create(data, callback) { - const dependency = data.dependencies[0]; - callback(null, new DllModule(data.context, dependency.dependencies, dependency.name, dependency.type)); - } -} - -module.exports = DllModuleFactory; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const { Tapable } = require("tapable"); +const DllModule = require("./DllModule"); + +class DllModuleFactory extends Tapable { + constructor() { + super(); + this.hooks = {}; + } + create(data, callback) { + const dependency = data.dependencies[0]; + callback( + null, + new DllModule( + data.context, + dependency.dependencies, + dependency.name, + dependency.type + ) + ); + } +} + +module.exports = DllModuleFactory; diff --git a/node_modules/webpack/lib/DllPlugin.js b/node_modules/webpack/lib/DllPlugin.js index 6fd929d6e..554283371 100644 --- a/node_modules/webpack/lib/DllPlugin.js +++ b/node_modules/webpack/lib/DllPlugin.js @@ -1,38 +1,44 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra - */ -"use strict"; - -const DllEntryPlugin = require("./DllEntryPlugin"); -const LibManifestPlugin = require("./LibManifestPlugin"); -const FlagInitialModulesAsUsedPlugin = require("./FlagInitialModulesAsUsedPlugin"); - -class DllPlugin { - constructor(options) { - this.options = options; - } - - apply(compiler) { - compiler.plugin("entry-option", (context, entry) => { - function itemToPlugin(item, name) { - if(Array.isArray(item)) - return new DllEntryPlugin(context, item, name); - else - throw new Error("DllPlugin: supply an Array as entry"); - } - if(typeof entry === "object" && !Array.isArray(entry)) { - Object.keys(entry).forEach(name => { - compiler.apply(itemToPlugin(entry[name], name)); - }); - } else { - compiler.apply(itemToPlugin(entry, "main")); - } - return true; - }); - compiler.apply(new LibManifestPlugin(this.options)); - compiler.apply(new FlagInitialModulesAsUsedPlugin()); - } -} - -module.exports = DllPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra + */ +"use strict"; + +const DllEntryPlugin = require("./DllEntryPlugin"); +const LibManifestPlugin = require("./LibManifestPlugin"); +const FlagInitialModulesAsUsedPlugin = require("./FlagInitialModulesAsUsedPlugin"); + +const validateOptions = require("schema-utils"); +const schema = require("../schemas/plugins/DllPlugin.json"); + +class DllPlugin { + constructor(options) { + validateOptions(schema, options, "Dll Plugin"); + this.options = options; + } + + apply(compiler) { + compiler.hooks.entryOption.tap("DllPlugin", (context, entry) => { + const itemToPlugin = (item, name) => { + if (Array.isArray(item)) { + return new DllEntryPlugin(context, item, name); + } + throw new Error("DllPlugin: supply an Array as entry"); + }; + if (typeof entry === "object" && !Array.isArray(entry)) { + Object.keys(entry).forEach(name => { + itemToPlugin(entry[name], name).apply(compiler); + }); + } else { + itemToPlugin(entry, "main").apply(compiler); + } + return true; + }); + new LibManifestPlugin(this.options).apply(compiler); + if (!this.options.entryOnly) { + new FlagInitialModulesAsUsedPlugin("DllPlugin").apply(compiler); + } + } +} + +module.exports = DllPlugin; diff --git a/node_modules/webpack/lib/DllReferencePlugin.js b/node_modules/webpack/lib/DllReferencePlugin.js index b0e386792..151862e5f 100644 --- a/node_modules/webpack/lib/DllReferencePlugin.js +++ b/node_modules/webpack/lib/DllReferencePlugin.js @@ -1,62 +1,132 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const DelegatedSourceDependency = require("./dependencies/DelegatedSourceDependency"); -const DelegatedModuleFactoryPlugin = require("./DelegatedModuleFactoryPlugin"); -const ExternalModuleFactoryPlugin = require("./ExternalModuleFactoryPlugin"); -const DelegatedExportsDependency = require("./dependencies/DelegatedExportsDependency"); -const NullFactory = require("./NullFactory"); - -class DllReferencePlugin { - constructor(options) { - this.options = options; - } - - apply(compiler) { - compiler.plugin("compilation", (compilation, params) => { - const normalModuleFactory = params.normalModuleFactory; - compilation.dependencyFactories.set(DelegatedSourceDependency, normalModuleFactory); - compilation.dependencyFactories.set(DelegatedExportsDependency, new NullFactory()); - }); - - compiler.plugin("before-compile", (params, callback) => { - const manifest = this.options.manifest; - if(typeof manifest === "string") { - params.compilationDependencies.push(manifest); - compiler.inputFileSystem.readFile(manifest, function(err, result) { - if(err) return callback(err); - params["dll reference " + manifest] = JSON.parse(result.toString("utf-8")); - return callback(); - }); - } else { - return callback(); - } - }); - - compiler.plugin("compile", (params) => { - let manifest = this.options.manifest; - if(typeof manifest === "string") { - manifest = params["dll reference " + manifest]; - } - const name = this.options.name || manifest.name; - const sourceType = this.options.sourceType || (manifest && manifest.type) || "var"; - const externals = {}; - const source = "dll-reference " + name; - externals[source] = name; - params.normalModuleFactory.apply(new ExternalModuleFactoryPlugin(sourceType, externals)); - params.normalModuleFactory.apply(new DelegatedModuleFactoryPlugin({ - source: source, - type: this.options.type, - scope: this.options.scope, - context: this.options.context || compiler.options.context, - content: this.options.content || manifest.content, - extensions: this.options.extensions - })); - }); - } -} - -module.exports = DllReferencePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const parseJson = require("json-parse-better-errors"); +const DelegatedSourceDependency = require("./dependencies/DelegatedSourceDependency"); +const DelegatedModuleFactoryPlugin = require("./DelegatedModuleFactoryPlugin"); +const ExternalModuleFactoryPlugin = require("./ExternalModuleFactoryPlugin"); +const DelegatedExportsDependency = require("./dependencies/DelegatedExportsDependency"); +const NullFactory = require("./NullFactory"); +const makePathsRelative = require("./util/identifier").makePathsRelative; +const WebpackError = require("./WebpackError"); + +const validateOptions = require("schema-utils"); +const schema = require("../schemas/plugins/DllReferencePlugin.json"); + +class DllReferencePlugin { + constructor(options) { + validateOptions(schema, options, "Dll Reference Plugin"); + this.options = options; + } + + apply(compiler) { + compiler.hooks.compilation.tap( + "DllReferencePlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set( + DelegatedSourceDependency, + normalModuleFactory + ); + compilation.dependencyFactories.set( + DelegatedExportsDependency, + new NullFactory() + ); + } + ); + + compiler.hooks.beforeCompile.tapAsync( + "DllReferencePlugin", + (params, callback) => { + const manifest = this.options.manifest; + if (typeof manifest === "string") { + params.compilationDependencies.add(manifest); + compiler.inputFileSystem.readFile(manifest, (err, result) => { + if (err) return callback(err); + // Catch errors parsing the manifest so that blank + // or malformed manifest files don't kill the process. + try { + params["dll reference " + manifest] = parseJson( + result.toString("utf-8") + ); + } catch (e) { + // Store the error in the params so that it can + // be added as a compilation error later on. + const manifestPath = makePathsRelative( + compiler.options.context, + manifest + ); + params[ + "dll reference parse error " + manifest + ] = new DllManifestError(manifestPath, e.message); + } + return callback(); + }); + } else { + return callback(); + } + } + ); + + compiler.hooks.compile.tap("DllReferencePlugin", params => { + let manifest = this.options.manifest; + if (typeof manifest === "string") { + // If there was an error parsing the manifest + // file, exit now because the error will be added + // as a compilation error in the "compilation" hook. + if (params["dll reference parse error " + manifest]) { + return; + } + manifest = params["dll reference " + manifest]; + } + const name = this.options.name || manifest.name; + const sourceType = + this.options.sourceType || (manifest && manifest.type) || "var"; + const externals = {}; + const source = "dll-reference " + name; + externals[source] = name; + const normalModuleFactory = params.normalModuleFactory; + new ExternalModuleFactoryPlugin(sourceType, externals).apply( + normalModuleFactory + ); + new DelegatedModuleFactoryPlugin({ + source: source, + type: this.options.type, + scope: this.options.scope, + context: this.options.context || compiler.options.context, + content: this.options.content || manifest.content, + extensions: this.options.extensions + }).apply(normalModuleFactory); + }); + + compiler.hooks.compilation.tap( + "DllReferencePlugin", + (compilation, params) => { + let manifest = this.options.manifest; + if (typeof manifest === "string") { + // If there was an error parsing the manifest file, add the + // error as a compilation error to make the compilation fail. + let e = params["dll reference parse error " + manifest]; + if (e) { + compilation.errors.push(e); + } + } + } + ); + } +} + +class DllManifestError extends WebpackError { + constructor(filename, message) { + super(); + + this.name = "DllManifestError"; + this.message = `Dll manifest ${filename}\n${message}`; + + Error.captureStackTrace(this, this.constructor); + } +} + +module.exports = DllReferencePlugin; diff --git a/node_modules/webpack/lib/DynamicEntryPlugin.js b/node_modules/webpack/lib/DynamicEntryPlugin.js index 2079e1276..99c1be2bf 100644 --- a/node_modules/webpack/lib/DynamicEntryPlugin.js +++ b/node_modules/webpack/lib/DynamicEntryPlugin.js @@ -1,59 +1,93 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Naoyuki Kanezawa @nkzawa -*/ -"use strict"; - -const MultiEntryDependency = require("./dependencies/MultiEntryDependency"); -const SingleEntryDependency = require("./dependencies/SingleEntryDependency"); -const MultiModuleFactory = require("./MultiModuleFactory"); -const MultiEntryPlugin = require("./MultiEntryPlugin"); -const SingleEntryPlugin = require("./SingleEntryPlugin"); - -class DynamicEntryPlugin { - constructor(context, entry) { - this.context = context; - this.entry = entry; - } - - apply(compiler) { - compiler.plugin("compilation", (compilation, params) => { - const multiModuleFactory = new MultiModuleFactory(); - const normalModuleFactory = params.normalModuleFactory; - - compilation.dependencyFactories.set(MultiEntryDependency, multiModuleFactory); - compilation.dependencyFactories.set(SingleEntryDependency, normalModuleFactory); - }); - - compiler.plugin("make", (compilation, callback) => { - const addEntry = (entry, name) => { - const dep = DynamicEntryPlugin.createDependency(entry, name); - return new Promise((resolve, reject) => { - compilation.addEntry(this.context, dep, name, (err) => { - if(err) return reject(err); - resolve(); - }); - }); - }; - - Promise.resolve(this.entry()).then((entry) => { - if(typeof entry === "string" || Array.isArray(entry)) { - addEntry(entry, "main").then(() => callback(), callback); - } else if(typeof entry === "object") { - Promise.all(Object.keys(entry).map((name) => { - return addEntry(entry[name], name); - })).then(() => callback(), callback); - } - }); - }); - } -} - -module.exports = DynamicEntryPlugin; - -DynamicEntryPlugin.createDependency = function(entry, name) { - if(Array.isArray(entry)) - return MultiEntryPlugin.createDependency(entry, name); - else - return SingleEntryPlugin.createDependency(entry, name); -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Naoyuki Kanezawa @nkzawa +*/ +"use strict"; + +const MultiEntryDependency = require("./dependencies/MultiEntryDependency"); +const SingleEntryDependency = require("./dependencies/SingleEntryDependency"); +const MultiModuleFactory = require("./MultiModuleFactory"); +const MultiEntryPlugin = require("./MultiEntryPlugin"); +const SingleEntryPlugin = require("./SingleEntryPlugin"); + +/** @typedef {import("./Compiler")} Compiler */ +/** @typedef {import("./Compiler").EntryOptionValuesFunction} EntryOptionValuesFunction */ + +class DynamicEntryPlugin { + /** + * @param {string} context the context path + * @param {EntryOptionValuesFunction} entry the entry value + */ + constructor(context, entry) { + this.context = context; + this.entry = entry; + } + + /** + * @param {Compiler} compiler the compiler instance + * @returns {void} + */ + apply(compiler) { + compiler.hooks.compilation.tap( + "DynamicEntryPlugin", + (compilation, { normalModuleFactory }) => { + const multiModuleFactory = new MultiModuleFactory(); + + compilation.dependencyFactories.set( + MultiEntryDependency, + multiModuleFactory + ); + compilation.dependencyFactories.set( + SingleEntryDependency, + normalModuleFactory + ); + } + ); + + compiler.hooks.make.tapAsync( + "DynamicEntryPlugin", + (compilation, callback) => { + /** + * @param {string|string[]} entry entry value or array of entry values + * @param {string} name name of entry + * @returns {Promise} returns the promise resolving the Compilation#addEntry function + */ + const addEntry = (entry, name) => { + const dep = DynamicEntryPlugin.createDependency(entry, name); + return new Promise((resolve, reject) => { + compilation.addEntry(this.context, dep, name, err => { + if (err) return reject(err); + resolve(); + }); + }); + }; + + Promise.resolve(this.entry()).then(entry => { + if (typeof entry === "string" || Array.isArray(entry)) { + addEntry(entry, "main").then(() => callback(), callback); + } else if (typeof entry === "object") { + Promise.all( + Object.keys(entry).map(name => { + return addEntry(entry[name], name); + }) + ).then(() => callback(), callback); + } + }); + } + ); + } +} + +module.exports = DynamicEntryPlugin; +/** + * @param {string|string[]} entry entry value or array of entry paths + * @param {string} name name of entry + * @returns {SingleEntryDependency|MultiEntryDependency} returns dep + */ +DynamicEntryPlugin.createDependency = (entry, name) => { + if (Array.isArray(entry)) { + return MultiEntryPlugin.createDependency(entry, name); + } else { + return SingleEntryPlugin.createDependency(entry, name); + } +}; diff --git a/node_modules/webpack/lib/EntryModuleNotFoundError.js b/node_modules/webpack/lib/EntryModuleNotFoundError.js index d7b5d24fb..b2458d6f2 100644 --- a/node_modules/webpack/lib/EntryModuleNotFoundError.js +++ b/node_modules/webpack/lib/EntryModuleNotFoundError.js @@ -1,22 +1,21 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const WebpackError = require("./WebpackError"); - -class EntryModuleNotFoundError extends WebpackError { - constructor(err) { - super(); - - this.name = "EntryModuleNotFoundError"; - this.message = "Entry module not found: " + err; - this.details = err.details; - this.error = err; - - Error.captureStackTrace(this, this.constructor); - } -} - -module.exports = EntryModuleNotFoundError; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const WebpackError = require("./WebpackError"); + +class EntryModuleNotFoundError extends WebpackError { + constructor(err) { + super("Entry module not found: " + err); + + this.name = "EntryModuleNotFoundError"; + this.details = err.details; + this.error = err; + + Error.captureStackTrace(this, this.constructor); + } +} + +module.exports = EntryModuleNotFoundError; diff --git a/node_modules/webpack/lib/EntryOptionPlugin.js b/node_modules/webpack/lib/EntryOptionPlugin.js index 03692edd4..e992bc2c9 100644 --- a/node_modules/webpack/lib/EntryOptionPlugin.js +++ b/node_modules/webpack/lib/EntryOptionPlugin.js @@ -1,31 +1,45 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const SingleEntryPlugin = require("./SingleEntryPlugin"); -const MultiEntryPlugin = require("./MultiEntryPlugin"); -const DynamicEntryPlugin = require("./DynamicEntryPlugin"); - -function itemToPlugin(context, item, name) { - if(Array.isArray(item)) { - return new MultiEntryPlugin(context, item, name); - } - return new SingleEntryPlugin(context, item, name); -} - -module.exports = class EntryOptionPlugin { - apply(compiler) { - compiler.plugin("entry-option", (context, entry) => { - if(typeof entry === "string" || Array.isArray(entry)) { - compiler.apply(itemToPlugin(context, entry, "main")); - } else if(typeof entry === "object") { - Object.keys(entry).forEach(name => compiler.apply(itemToPlugin(context, entry[name], name))); - } else if(typeof entry === "function") { - compiler.apply(new DynamicEntryPlugin(context, entry)); - } - return true; - }); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const SingleEntryPlugin = require("./SingleEntryPlugin"); +const MultiEntryPlugin = require("./MultiEntryPlugin"); +const DynamicEntryPlugin = require("./DynamicEntryPlugin"); + +/** @typedef {import("./Compiler")} Compiler */ + +/** + * @param {string} context context path + * @param {string | string[]} item entry array or single path + * @param {string} name entry key name + * @returns {SingleEntryPlugin | MultiEntryPlugin} returns either a single or multi entry plugin + */ +const itemToPlugin = (context, item, name) => { + if (Array.isArray(item)) { + return new MultiEntryPlugin(context, item, name); + } + return new SingleEntryPlugin(context, item, name); +}; + +module.exports = class EntryOptionPlugin { + /** + * @param {Compiler} compiler the compiler instance one is tapping into + * @returns {void} + */ + apply(compiler) { + compiler.hooks.entryOption.tap("EntryOptionPlugin", (context, entry) => { + if (typeof entry === "string" || Array.isArray(entry)) { + itemToPlugin(context, entry, "main").apply(compiler); + } else if (typeof entry === "object") { + for (const name of Object.keys(entry)) { + itemToPlugin(context, entry[name], name).apply(compiler); + } + } else if (typeof entry === "function") { + new DynamicEntryPlugin(context, entry).apply(compiler); + } + return true; + }); + } +}; diff --git a/node_modules/webpack/lib/Entrypoint.js b/node_modules/webpack/lib/Entrypoint.js index 04dc2084b..c67ff44ed 100644 --- a/node_modules/webpack/lib/Entrypoint.js +++ b/node_modules/webpack/lib/Entrypoint.js @@ -1,43 +1,54 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class Entrypoint { - constructor(name) { - this.name = name; - this.chunks = []; - } - - unshiftChunk(chunk) { - this.chunks.unshift(chunk); - chunk.entrypoints.push(this); - } - - insertChunk(chunk, before) { - const idx = this.chunks.indexOf(before); - if(idx >= 0) { - this.chunks.splice(idx, 0, chunk); - } else { - throw new Error("before chunk not found"); - } - chunk.entrypoints.push(this); - } - - getFiles() { - const files = []; - - for(let chunkIdx = 0; chunkIdx < this.chunks.length; chunkIdx++) { - for(let fileIdx = 0; fileIdx < this.chunks[chunkIdx].files.length; fileIdx++) { - if(files.indexOf(this.chunks[chunkIdx].files[fileIdx]) === -1) { - files.push(this.chunks[chunkIdx].files[fileIdx]); - } - } - } - - return files; - } -} - -module.exports = Entrypoint; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const ChunkGroup = require("./ChunkGroup"); + +/** @typedef {import("./Chunk")} Chunk */ + +/** + * Entrypoint serves as an encapsulation primitive for chunks that are + * a part of a single ChunkGroup. They represent all bundles that need to be loaded for a + * single instance of a page. Multi-page application architectures will typically yield multiple Entrypoint objects + * inside of the compilation, whereas a Single Page App may only contain one with many lazy-loaded chunks. + */ +class Entrypoint extends ChunkGroup { + /** + * Creates an instance of Entrypoint. + * @param {string} name the name of the entrypoint + */ + constructor(name) { + super(name); + /** @type {Chunk=} */ + this.runtimeChunk = undefined; + } + + /** + * isInitial will always return true for Entrypoint ChunkGroup. + * @returns {true} returns true as all entrypoints are initial ChunkGroups + */ + isInitial() { + return true; + } + + /** + * Sets the runtimeChunk for an entrypoint. + * @param {Chunk} chunk the chunk being set as the runtime chunk. + * @returns {void} + */ + setRuntimeChunk(chunk) { + this.runtimeChunk = chunk; + } + + /** + * Fetches the chunk reference containing the webpack bootstrap code + * @returns {Chunk} returns the runtime chunk or first chunk in `this.chunks` + */ + getRuntimeChunk() { + return this.runtimeChunk || this.chunks[0]; + } +} + +module.exports = Entrypoint; diff --git a/node_modules/webpack/lib/EnvironmentPlugin.js b/node_modules/webpack/lib/EnvironmentPlugin.js index 3f03fabdf..c9fafaa8a 100644 --- a/node_modules/webpack/lib/EnvironmentPlugin.js +++ b/node_modules/webpack/lib/EnvironmentPlugin.js @@ -1,50 +1,72 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Authors Simen Brekken @simenbrekken, Einar Löve @einarlove -*/ - -"use strict"; - -const DefinePlugin = require("./DefinePlugin"); - -class EnvironmentPlugin { - constructor(keys) { - if(Array.isArray(keys)) { - this.keys = keys; - this.defaultValues = {}; - } else if(keys && typeof keys === "object") { - this.keys = Object.keys(keys); - this.defaultValues = keys; - } else { - this.keys = Array.prototype.slice.call(arguments); - this.defaultValues = {}; - } - } - - apply(compiler) { - const definitions = this.keys.reduce((defs, key) => { - const value = process.env[key] !== undefined ? process.env[key] : this.defaultValues[key]; - - if(value === undefined) { - compiler.plugin("this-compilation", compilation => { - const error = new Error( - `EnvironmentPlugin - ${key} environment variable is undefined.\n\n` + - "You can pass an object with default values to suppress this warning.\n" + - "See https://webpack.js.org/plugins/environment-plugin for example." - ); - - error.name = "EnvVariableNotDefinedError"; - compilation.warnings.push(error); - }); - } - - defs[`process.env.${key}`] = typeof value === "undefined" ? "undefined" : JSON.stringify(value); - - return defs; - }, {}); - - compiler.apply(new DefinePlugin(definitions)); - } -} - -module.exports = EnvironmentPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Authors Simen Brekken @simenbrekken, Einar Löve @einarlove +*/ + +"use strict"; + +/** @typedef {import("./Compiler")} Compiler */ + +const WebpackError = require("./WebpackError"); +const DefinePlugin = require("./DefinePlugin"); + +const needsEnvVarFix = + ["8", "9"].indexOf(process.versions.node.split(".")[0]) >= 0 && + process.platform === "win32"; + +class EnvironmentPlugin { + constructor(...keys) { + if (keys.length === 1 && Array.isArray(keys[0])) { + this.keys = keys[0]; + this.defaultValues = {}; + } else if (keys.length === 1 && keys[0] && typeof keys[0] === "object") { + this.keys = Object.keys(keys[0]); + this.defaultValues = keys[0]; + } else { + this.keys = keys; + this.defaultValues = {}; + } + } + + /** + * @param {Compiler} compiler webpack compiler instance + * @returns {void} + */ + apply(compiler) { + const definitions = this.keys.reduce((defs, key) => { + // TODO remove once the fix has made its way into Node 8. + // Work around https://github.com/nodejs/node/pull/18463, + // affecting Node 8 & 9 by performing an OS-level + // operation that always succeeds before reading + // environment variables: + if (needsEnvVarFix) require("os").cpus(); + + const value = + process.env[key] !== undefined + ? process.env[key] + : this.defaultValues[key]; + + if (value === undefined) { + compiler.hooks.thisCompilation.tap("EnvironmentPlugin", compilation => { + const error = new WebpackError( + `EnvironmentPlugin - ${key} environment variable is undefined.\n\n` + + "You can pass an object with default values to suppress this warning.\n" + + "See https://webpack.js.org/plugins/environment-plugin for example." + ); + + error.name = "EnvVariableNotDefinedError"; + compilation.warnings.push(error); + }); + } + + defs[`process.env.${key}`] = + value === undefined ? "undefined" : JSON.stringify(value); + + return defs; + }, {}); + + new DefinePlugin(definitions).apply(compiler); + } +} + +module.exports = EnvironmentPlugin; diff --git a/node_modules/webpack/lib/ErrorHelpers.js b/node_modules/webpack/lib/ErrorHelpers.js index 527e0ed21..900ae4d59 100644 --- a/node_modules/webpack/lib/ErrorHelpers.js +++ b/node_modules/webpack/lib/ErrorHelpers.js @@ -1,31 +1,60 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const loaderFlag = "LOADER_EXECUTION"; - -exports.cutOffLoaderExecution = (stack) => { - stack = stack.split("\n"); - for(let i = 0; i < stack.length; i++) - if(stack[i].indexOf(loaderFlag) >= 0) - stack.length = i; - return stack.join("\n"); -}; - -exports.cutOffMessage = (stack, message) => { - const nextLine = stack.indexOf("\n"); - if(nextLine === -1) { - return stack === message ? "" : stack; - } else { - const firstLine = stack.substr(0, nextLine); - return firstLine === message ? stack.substr(nextLine + 1) : stack; - } -}; - -exports.cleanUp = (stack, message) => { - stack = exports.cutOffLoaderExecution(stack); - stack = exports.cutOffMessage(stack, message); - return stack; -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const loaderFlag = "LOADER_EXECUTION"; + +const webpackOptionsFlag = "WEBPACK_OPTIONS"; + +exports.cutOffByFlag = (stack, flag) => { + stack = stack.split("\n"); + for (let i = 0; i < stack.length; i++) { + if (stack[i].includes(flag)) { + stack.length = i; + } + } + return stack.join("\n"); +}; + +exports.cutOffLoaderExecution = stack => + exports.cutOffByFlag(stack, loaderFlag); + +exports.cutOffWebpackOptions = stack => + exports.cutOffByFlag(stack, webpackOptionsFlag); + +exports.cutOffMultilineMessage = (stack, message) => { + stack = stack.split("\n"); + message = message.split("\n"); + + return stack + .reduce( + (acc, line, idx) => + line.includes(message[idx]) ? acc : acc.concat(line), + [] + ) + .join("\n"); +}; + +exports.cutOffMessage = (stack, message) => { + const nextLine = stack.indexOf("\n"); + if (nextLine === -1) { + return stack === message ? "" : stack; + } else { + const firstLine = stack.substr(0, nextLine); + return firstLine === message ? stack.substr(nextLine + 1) : stack; + } +}; + +exports.cleanUp = (stack, message) => { + stack = exports.cutOffLoaderExecution(stack); + stack = exports.cutOffMessage(stack, message); + return stack; +}; + +exports.cleanUpWebpackOptions = (stack, message) => { + stack = exports.cutOffWebpackOptions(stack); + stack = exports.cutOffMultilineMessage(stack, message); + return stack; +}; diff --git a/node_modules/webpack/lib/EvalDevToolModulePlugin.js b/node_modules/webpack/lib/EvalDevToolModulePlugin.js index 69f1e9d85..2af11f9c3 100644 --- a/node_modules/webpack/lib/EvalDevToolModulePlugin.js +++ b/node_modules/webpack/lib/EvalDevToolModulePlugin.js @@ -1,22 +1,27 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const EvalDevToolModuleTemplatePlugin = require("./EvalDevToolModuleTemplatePlugin"); - -class EvalDevToolModulePlugin { - constructor(sourceUrlComment, moduleFilenameTemplate) { - this.sourceUrlComment = sourceUrlComment; - this.moduleFilenameTemplate = moduleFilenameTemplate; - } - - apply(compiler) { - compiler.plugin("compilation", (compilation) => { - compilation.moduleTemplate.apply(new EvalDevToolModuleTemplatePlugin(this.sourceUrlComment, this.moduleFilenameTemplate)); - }); - } -} - -module.exports = EvalDevToolModulePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const EvalDevToolModuleTemplatePlugin = require("./EvalDevToolModuleTemplatePlugin"); + +class EvalDevToolModulePlugin { + constructor(options) { + this.sourceUrlComment = options.sourceUrlComment; + this.moduleFilenameTemplate = options.moduleFilenameTemplate; + this.namespace = options.namespace; + } + + apply(compiler) { + compiler.hooks.compilation.tap("EvalDevToolModulePlugin", compilation => { + new EvalDevToolModuleTemplatePlugin({ + sourceUrlComment: this.sourceUrlComment, + moduleFilenameTemplate: this.moduleFilenameTemplate, + namespace: this.namespace + }).apply(compilation.moduleTemplates.javascript); + }); + } +} + +module.exports = EvalDevToolModulePlugin; diff --git a/node_modules/webpack/lib/EvalDevToolModuleTemplatePlugin.js b/node_modules/webpack/lib/EvalDevToolModuleTemplatePlugin.js index e56970ce9..ab5dd1aac 100644 --- a/node_modules/webpack/lib/EvalDevToolModuleTemplatePlugin.js +++ b/node_modules/webpack/lib/EvalDevToolModuleTemplatePlugin.js @@ -1,33 +1,61 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const RawSource = require("webpack-sources").RawSource; -const ModuleFilenameHelpers = require("./ModuleFilenameHelpers"); - -class EvalDevToolModuleTemplatePlugin { - constructor(sourceUrlComment, moduleFilenameTemplate) { - this.sourceUrlComment = sourceUrlComment || "\n//# sourceURL=[url]"; - this.moduleFilenameTemplate = moduleFilenameTemplate || "webpack:///[resourcePath]?[loaders]"; - } - - apply(moduleTemplate) { - moduleTemplate.plugin("module", (source, module) => { - const content = source.source(); - const str = ModuleFilenameHelpers.createFilename(module, this.moduleFilenameTemplate, moduleTemplate.requestShortener); - const footer = ["\n", - ModuleFilenameHelpers.createFooter(module, moduleTemplate.requestShortener), - this.sourceUrlComment.replace(/\[url\]/g, encodeURI(str).replace(/%2F/g, "/").replace(/%20/g, "_").replace(/%5E/g, "^").replace(/%5C/g, "\\").replace(/^\//, "")) - ].join("\n"); - return new RawSource(`eval(${JSON.stringify(content + footer)});`); - }); - moduleTemplate.plugin("hash", hash => { - hash.update("EvalDevToolModuleTemplatePlugin"); - hash.update("2"); - }); - } -} - -module.exports = EvalDevToolModuleTemplatePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const { RawSource } = require("webpack-sources"); +const ModuleFilenameHelpers = require("./ModuleFilenameHelpers"); + +const cache = new WeakMap(); + +class EvalDevToolModuleTemplatePlugin { + constructor(options) { + this.sourceUrlComment = options.sourceUrlComment || "\n//# sourceURL=[url]"; + this.moduleFilenameTemplate = + options.moduleFilenameTemplate || + "webpack://[namespace]/[resourcePath]?[loaders]"; + this.namespace = options.namespace || ""; + } + + apply(moduleTemplate) { + moduleTemplate.hooks.module.tap( + "EvalDevToolModuleTemplatePlugin", + (source, module) => { + const cacheEntry = cache.get(source); + if (cacheEntry !== undefined) return cacheEntry; + const content = source.source(); + const str = ModuleFilenameHelpers.createFilename( + module, + { + moduleFilenameTemplate: this.moduleFilenameTemplate, + namespace: this.namespace + }, + moduleTemplate.runtimeTemplate.requestShortener + ); + const footer = + "\n" + + this.sourceUrlComment.replace( + /\[url\]/g, + encodeURI(str) + .replace(/%2F/g, "/") + .replace(/%20/g, "_") + .replace(/%5E/g, "^") + .replace(/%5C/g, "\\") + .replace(/^\//, "") + ); + const result = new RawSource( + `eval(${JSON.stringify(content + footer)});` + ); + cache.set(source, result); + return result; + } + ); + moduleTemplate.hooks.hash.tap("EvalDevToolModuleTemplatePlugin", hash => { + hash.update("EvalDevToolModuleTemplatePlugin"); + hash.update("2"); + }); + } +} + +module.exports = EvalDevToolModuleTemplatePlugin; diff --git a/node_modules/webpack/lib/EvalSourceMapDevToolModuleTemplatePlugin.js b/node_modules/webpack/lib/EvalSourceMapDevToolModuleTemplatePlugin.js index 944266b8f..ac22c6897 100644 --- a/node_modules/webpack/lib/EvalSourceMapDevToolModuleTemplatePlugin.js +++ b/node_modules/webpack/lib/EvalSourceMapDevToolModuleTemplatePlugin.js @@ -1,75 +1,115 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const RawSource = require("webpack-sources").RawSource; -const ModuleFilenameHelpers = require("./ModuleFilenameHelpers"); - -class EvalSourceMapDevToolModuleTemplatePlugin { - constructor(compilation, options) { - this.compilation = compilation; - this.sourceMapComment = options.append || "//# sourceURL=[module]\n//# sourceMappingURL=[url]"; - this.moduleFilenameTemplate = options.moduleFilenameTemplate || "webpack:///[resource-path]?[hash]"; - this.options = options; - } - - apply(moduleTemplate) { - const self = this; - const options = this.options; - moduleTemplate.plugin("module", function(source, module) { - if(source.__EvalSourceMapDevToolData) - return source.__EvalSourceMapDevToolData; - let sourceMap; - let content; - if(source.sourceAndMap) { - const sourceAndMap = source.sourceAndMap(options); - sourceMap = sourceAndMap.map; - content = sourceAndMap.source; - } else { - sourceMap = source.map(options); - content = source.source(); - } - if(!sourceMap) { - return source; - } - - // Clone (flat) the sourcemap to ensure that the mutations below do not persist. - sourceMap = Object.keys(sourceMap).reduce(function(obj, key) { - obj[key] = sourceMap[key]; - return obj; - }, {}); - const modules = sourceMap.sources.map(function(source) { - const module = self.compilation.findModule(source); - return module || source; - }); - let moduleFilenames = modules.map(function(module) { - return ModuleFilenameHelpers.createFilename(module, self.moduleFilenameTemplate, this.requestShortener); - }, this); - moduleFilenames = ModuleFilenameHelpers.replaceDuplicates(moduleFilenames, function(filename, i, n) { - for(let j = 0; j < n; j++) - filename += "*"; - return filename; - }); - sourceMap.sources = moduleFilenames; - if(sourceMap.sourcesContent) { - sourceMap.sourcesContent = sourceMap.sourcesContent.map(function(content, i) { - return typeof content === "string" ? `${content}\n\n\n${ModuleFilenameHelpers.createFooter(modules[i], this.requestShortener)}` : null; - }, this); - } - sourceMap.sourceRoot = options.sourceRoot || ""; - sourceMap.file = `${module.id}.js`; - - const footer = self.sourceMapComment.replace(/\[url\]/g, `data:application/json;charset=utf-8;base64,${new Buffer(JSON.stringify(sourceMap), "utf8").toString("base64")}`) + //eslint-disable-line - `\n//# sourceURL=webpack-internal:///${module.id}\n`; // workaround for chrome bug - source.__EvalSourceMapDevToolData = new RawSource(`eval(${JSON.stringify(content + footer)});`); - return source.__EvalSourceMapDevToolData; - }); - moduleTemplate.plugin("hash", function(hash) { - hash.update("eval-source-map"); - hash.update("2"); - }); - } -} -module.exports = EvalSourceMapDevToolModuleTemplatePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const { RawSource } = require("webpack-sources"); +const ModuleFilenameHelpers = require("./ModuleFilenameHelpers"); + +const cache = new WeakMap(); + +class EvalSourceMapDevToolModuleTemplatePlugin { + constructor(compilation, options) { + this.compilation = compilation; + this.sourceMapComment = + options.append || "//# sourceURL=[module]\n//# sourceMappingURL=[url]"; + this.moduleFilenameTemplate = + options.moduleFilenameTemplate || + "webpack://[namespace]/[resource-path]?[hash]"; + this.namespace = options.namespace || ""; + this.options = options; + } + + apply(moduleTemplate) { + const self = this; + const options = this.options; + const matchModule = ModuleFilenameHelpers.matchObject.bind( + ModuleFilenameHelpers, + options + ); + moduleTemplate.hooks.module.tap( + "EvalSourceMapDevToolModuleTemplatePlugin", + (source, module) => { + const cachedSource = cache.get(source); + if (cachedSource !== undefined) { + return cachedSource; + } + + if (!matchModule(module.resource)) { + return source; + } + + /** @type {{ [key: string]: TODO; }} */ + let sourceMap; + let content; + if (source.sourceAndMap) { + const sourceAndMap = source.sourceAndMap(options); + sourceMap = sourceAndMap.map; + content = sourceAndMap.source; + } else { + sourceMap = source.map(options); + content = source.source(); + } + if (!sourceMap) { + return source; + } + + // Clone (flat) the sourcemap to ensure that the mutations below do not persist. + sourceMap = Object.keys(sourceMap).reduce((obj, key) => { + obj[key] = sourceMap[key]; + return obj; + }, {}); + const modules = sourceMap.sources.map(source => { + const module = self.compilation.findModule(source); + return module || source; + }); + let moduleFilenames = modules.map(module => { + return ModuleFilenameHelpers.createFilename( + module, + { + moduleFilenameTemplate: self.moduleFilenameTemplate, + namespace: self.namespace + }, + moduleTemplate.runtimeTemplate.requestShortener + ); + }); + moduleFilenames = ModuleFilenameHelpers.replaceDuplicates( + moduleFilenames, + (filename, i, n) => { + for (let j = 0; j < n; j++) filename += "*"; + return filename; + } + ); + sourceMap.sources = moduleFilenames; + sourceMap.sourceRoot = options.sourceRoot || ""; + sourceMap.file = `${module.id}.js`; + + const footer = + self.sourceMapComment.replace( + /\[url\]/g, + `data:application/json;charset=utf-8;base64,${Buffer.from( + JSON.stringify(sourceMap), + "utf8" + ).toString("base64")}` + ) + `\n//# sourceURL=webpack-internal:///${module.id}\n`; // workaround for chrome bug + + const evalSource = new RawSource( + `eval(${JSON.stringify(content + footer)});` + ); + + cache.set(source, evalSource); + + return evalSource; + } + ); + moduleTemplate.hooks.hash.tap( + "EvalSourceMapDevToolModuleTemplatePlugin", + hash => { + hash.update("eval-source-map"); + hash.update("2"); + } + ); + } +} +module.exports = EvalSourceMapDevToolModuleTemplatePlugin; diff --git a/node_modules/webpack/lib/EvalSourceMapDevToolPlugin.js b/node_modules/webpack/lib/EvalSourceMapDevToolPlugin.js index 1a2aed396..daf9aaddf 100644 --- a/node_modules/webpack/lib/EvalSourceMapDevToolPlugin.js +++ b/node_modules/webpack/lib/EvalSourceMapDevToolPlugin.js @@ -1,32 +1,41 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const EvalSourceMapDevToolModuleTemplatePlugin = require("./EvalSourceMapDevToolModuleTemplatePlugin"); -const SourceMapDevToolModuleOptionsPlugin = require("./SourceMapDevToolModuleOptionsPlugin"); - -class EvalSourceMapDevToolPlugin { - constructor(options) { - if(arguments.length > 1) - throw new Error("EvalSourceMapDevToolPlugin only takes one argument (pass an options object)"); - if(typeof options === "string") { - options = { - append: options - }; - } - if(!options) options = {}; - this.options = options; - } - - apply(compiler) { - const options = this.options; - compiler.plugin("compilation", (compilation) => { - new SourceMapDevToolModuleOptionsPlugin(options).apply(compilation); - compilation.moduleTemplate.apply(new EvalSourceMapDevToolModuleTemplatePlugin(compilation, options)); - }); - } -} - -module.exports = EvalSourceMapDevToolPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const EvalSourceMapDevToolModuleTemplatePlugin = require("./EvalSourceMapDevToolModuleTemplatePlugin"); +const SourceMapDevToolModuleOptionsPlugin = require("./SourceMapDevToolModuleOptionsPlugin"); + +class EvalSourceMapDevToolPlugin { + constructor(options) { + if (arguments.length > 1) { + throw new Error( + "EvalSourceMapDevToolPlugin only takes one argument (pass an options object)" + ); + } + if (typeof options === "string") { + options = { + append: options + }; + } + if (!options) options = {}; + this.options = options; + } + + apply(compiler) { + const options = this.options; + compiler.hooks.compilation.tap( + "EvalSourceMapDevToolPlugin", + compilation => { + new SourceMapDevToolModuleOptionsPlugin(options).apply(compilation); + new EvalSourceMapDevToolModuleTemplatePlugin( + compilation, + options + ).apply(compilation.moduleTemplates.javascript); + } + ); + } +} + +module.exports = EvalSourceMapDevToolPlugin; diff --git a/node_modules/webpack/lib/ExportPropertyMainTemplatePlugin.js b/node_modules/webpack/lib/ExportPropertyMainTemplatePlugin.js index 8dd80901e..90df031aa 100644 --- a/node_modules/webpack/lib/ExportPropertyMainTemplatePlugin.js +++ b/node_modules/webpack/lib/ExportPropertyMainTemplatePlugin.js @@ -1,31 +1,53 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ConcatSource = require("webpack-sources").ConcatSource; - -function accessorToObjectAccess(accessor) { - return accessor.map(a => `[${JSON.stringify(a)}]`).join(""); -} - -class ExportPropertyMainTemplatePlugin { - constructor(property) { - this.property = property; - } - - apply(compilation) { - const mainTemplate = compilation.mainTemplate; - compilation.templatesPlugin("render-with-entry", (source, chunk, hash) => { - const postfix = `${accessorToObjectAccess([].concat(this.property))}`; - return new ConcatSource(source, postfix); - }); - mainTemplate.plugin("hash", hash => { - hash.update("export property"); - hash.update(`${this.property}`); - }); - } -} - -module.exports = ExportPropertyMainTemplatePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const { ConcatSource } = require("webpack-sources"); + +/** @typedef {import("./Compilation")} Compilation */ + +/** + * @param {string[]} accessor the accessor to convert to path + * @returns {string} the path + */ +const accessorToObjectAccess = accessor => { + return accessor.map(a => `[${JSON.stringify(a)}]`).join(""); +}; + +class ExportPropertyMainTemplatePlugin { + /** + * @param {string|string[]} property the name of the property to export + */ + constructor(property) { + this.property = property; + } + + /** + * @param {Compilation} compilation the compilation instance + * @returns {void} + */ + apply(compilation) { + const { mainTemplate, chunkTemplate } = compilation; + + const onRenderWithEntry = (source, chunk, hash) => { + const postfix = `${accessorToObjectAccess([].concat(this.property))}`; + return new ConcatSource(source, postfix); + }; + + for (const template of [mainTemplate, chunkTemplate]) { + template.hooks.renderWithEntry.tap( + "ExportPropertyMainTemplatePlugin", + onRenderWithEntry + ); + } + + mainTemplate.hooks.hash.tap("ExportPropertyMainTemplatePlugin", hash => { + hash.update("export property"); + hash.update(`${this.property}`); + }); + } +} + +module.exports = ExportPropertyMainTemplatePlugin; diff --git a/node_modules/webpack/lib/ExtendedAPIPlugin.js b/node_modules/webpack/lib/ExtendedAPIPlugin.js index 5b0b913d4..e41defb1f 100644 --- a/node_modules/webpack/lib/ExtendedAPIPlugin.js +++ b/node_modules/webpack/lib/ExtendedAPIPlugin.js @@ -1,47 +1,88 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ConstDependency = require("./dependencies/ConstDependency"); -const ParserHelpers = require("./ParserHelpers"); -const NullFactory = require("./NullFactory"); - -const REPLACEMENTS = { - __webpack_hash__: "__webpack_require__.h", // eslint-disable-line camelcase - __webpack_chunkname__: "__webpack_require__.cn" // eslint-disable-line camelcase -}; -const REPLACEMENT_TYPES = { - __webpack_hash__: "string", // eslint-disable-line camelcase - __webpack_chunkname__: "string" // eslint-disable-line camelcase -}; - -class ExtendedAPIPlugin { - apply(compiler) { - compiler.plugin("compilation", (compilation, params) => { - compilation.dependencyFactories.set(ConstDependency, new NullFactory()); - compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template()); - compilation.mainTemplate.plugin("require-extensions", function(source, chunk, hash) { - const buf = [source]; - buf.push(""); - buf.push("// __webpack_hash__"); - buf.push(`${this.requireFn}.h = ${JSON.stringify(hash)};`); - buf.push(""); - buf.push("// __webpack_chunkname__"); - buf.push(`${this.requireFn}.cn = ${JSON.stringify(chunk.name)};`); - return this.asString(buf); - }); - compilation.mainTemplate.plugin("global-hash", () => true); - - params.normalModuleFactory.plugin("parser", (parser, parserOptions) => { - Object.keys(REPLACEMENTS).forEach(key => { - parser.plugin(`expression ${key}`, ParserHelpers.toConstantDependency(REPLACEMENTS[key])); - parser.plugin(`evaluate typeof ${key}`, ParserHelpers.evaluateToString(REPLACEMENT_TYPES[key])); - }); - }); - }); - } -} - -module.exports = ExtendedAPIPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const Template = require("./Template"); +const ConstDependency = require("./dependencies/ConstDependency"); +const ParserHelpers = require("./ParserHelpers"); +const NullFactory = require("./NullFactory"); + +const REPLACEMENTS = { + // eslint-disable-next-line camelcase + __webpack_hash__: "__webpack_require__.h", + // eslint-disable-next-line camelcase + __webpack_chunkname__: "__webpack_require__.cn" +}; +const REPLACEMENT_TYPES = { + // eslint-disable-next-line camelcase + __webpack_hash__: "string", + // eslint-disable-next-line camelcase + __webpack_chunkname__: "string" +}; + +class ExtendedAPIPlugin { + apply(compiler) { + compiler.hooks.compilation.tap( + "ExtendedAPIPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set(ConstDependency, new NullFactory()); + compilation.dependencyTemplates.set( + ConstDependency, + new ConstDependency.Template() + ); + + const mainTemplate = compilation.mainTemplate; + mainTemplate.hooks.requireExtensions.tap( + "ExtendedAPIPlugin", + (source, chunk, hash) => { + const buf = [source]; + buf.push(""); + buf.push("// __webpack_hash__"); + buf.push(`${mainTemplate.requireFn}.h = ${JSON.stringify(hash)};`); + buf.push(""); + buf.push("// __webpack_chunkname__"); + buf.push( + `${mainTemplate.requireFn}.cn = ${JSON.stringify(chunk.name)};` + ); + return Template.asString(buf); + } + ); + mainTemplate.hooks.globalHash.tap("ExtendedAPIPlugin", () => true); + + const handler = (parser, parserOptions) => { + Object.keys(REPLACEMENTS).forEach(key => { + parser.hooks.expression + .for(key) + .tap( + "ExtendedAPIPlugin", + ParserHelpers.toConstantDependencyWithWebpackRequire( + parser, + REPLACEMENTS[key] + ) + ); + parser.hooks.evaluateTypeof + .for(key) + .tap( + "ExtendedAPIPlugin", + ParserHelpers.evaluateToString(REPLACEMENT_TYPES[key]) + ); + }); + }; + + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("ExtendedAPIPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("ExtendedAPIPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/esm") + .tap("ExtendedAPIPlugin", handler); + } + ); + } +} + +module.exports = ExtendedAPIPlugin; diff --git a/node_modules/webpack/lib/ExternalModule.js b/node_modules/webpack/lib/ExternalModule.js index 45c183b1a..8cb5e071c 100644 --- a/node_modules/webpack/lib/ExternalModule.js +++ b/node_modules/webpack/lib/ExternalModule.js @@ -1,128 +1,177 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const Module = require("./Module"); -const OriginalSource = require("webpack-sources").OriginalSource; -const RawSource = require("webpack-sources").RawSource; -const WebpackMissingModule = require("./dependencies/WebpackMissingModule"); -const Template = require("./Template"); - -class ExternalModule extends Module { - constructor(request, type, userRequest) { - super(); - this.request = request; - this.userRequest = userRequest; - this.type = type; - this.built = false; - this.external = true; - } - - libIdent() { - return this.userRequest; - } - - chunkCondition(chunk) { - return chunk.hasEntryModule(); - } - - identifier() { - return "external " + JSON.stringify(this.request); - } - - readableIdentifier() { - return "external " + JSON.stringify(this.request); - } - - needRebuild() { - return false; - } - - build(options, compilation, resolver, fs, callback) { - this.builtTime = Date.now(); - callback(); - } - - getSourceForGlobalVariableExternal(variableName, type) { - if(!Array.isArray(variableName)) { - // make it an array as the look up works the same basically - variableName = [variableName]; - } - - // needed for e.g. window["some"]["thing"] - const objectLookup = variableName.map(r => `[${JSON.stringify(r)}]`).join(""); - return `(function() { module.exports = ${type}${objectLookup}; }());`; - } - - getSourceForCommonJsExternal(moduleAndSpecifiers) { - if(!Array.isArray(moduleAndSpecifiers)) { - return `module.exports = require(${JSON.stringify(moduleAndSpecifiers)});`; - } - - const moduleName = moduleAndSpecifiers[0]; - const objectLookup = moduleAndSpecifiers.slice(1).map(r => `[${JSON.stringify(r)}]`).join(""); - return `module.exports = require(${moduleName})${objectLookup};`; - } - - checkExternalVariable(variableToCheck, request) { - return `if(typeof ${variableToCheck} === 'undefined') {${WebpackMissingModule.moduleCode(request)}}\n`; - } - - getSourceForAmdOrUmdExternal(id, optional, request) { - const externalVariable = Template.toIdentifier(`__WEBPACK_EXTERNAL_MODULE_${id}__`); - const missingModuleError = optional ? this.checkExternalVariable(externalVariable, request) : ""; - return `${missingModuleError}module.exports = ${externalVariable};`; - } - - getSourceForDefaultCase(optional, request) { - const missingModuleError = optional ? this.checkExternalVariable(request, request) : ""; - return `${missingModuleError}module.exports = ${request};`; - } - - getSourceString() { - const request = typeof this.request === "object" ? this.request[this.type] : this.request; - switch(this.type) { - case "this": - case "window": - case "global": - return this.getSourceForGlobalVariableExternal(request, this.type); - case "commonjs": - case "commonjs2": - return this.getSourceForCommonJsExternal(request); - case "amd": - case "umd": - case "umd2": - return this.getSourceForAmdOrUmdExternal(this.id, this.optional, request); - default: - return this.getSourceForDefaultCase(this.optional, request); - } - } - - getSource(sourceString) { - if(this.useSourceMap) { - return new OriginalSource(sourceString, this.identifier()); - } - - return new RawSource(sourceString); - } - - source() { - return this.getSource( - this.getSourceString() - ); - } - - size() { - return 42; - } - - updateHash(hash) { - hash.update(this.type); - hash.update(JSON.stringify(this.request)); - hash.update(JSON.stringify(Boolean(this.optional))); - super.updateHash(hash); - } -} - -module.exports = ExternalModule; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const { OriginalSource, RawSource } = require("webpack-sources"); +const Module = require("./Module"); +const WebpackMissingModule = require("./dependencies/WebpackMissingModule"); +const Template = require("./Template"); + +/** @typedef {import("./util/createHash").Hash} Hash */ + +class ExternalModule extends Module { + constructor(request, type, userRequest) { + super("javascript/dynamic", null); + + // Info from Factory + this.request = request; + this.externalType = type; + this.userRequest = userRequest; + this.external = true; + } + + libIdent() { + return this.userRequest; + } + + chunkCondition(chunk) { + return chunk.hasEntryModule(); + } + + identifier() { + return "external " + JSON.stringify(this.request); + } + + readableIdentifier() { + return "external " + JSON.stringify(this.request); + } + + needRebuild() { + return false; + } + + build(options, compilation, resolver, fs, callback) { + this.built = true; + this.buildMeta = {}; + this.buildInfo = {}; + callback(); + } + + getSourceForGlobalVariableExternal(variableName, type) { + if (!Array.isArray(variableName)) { + // make it an array as the look up works the same basically + variableName = [variableName]; + } + + // needed for e.g. window["some"]["thing"] + const objectLookup = variableName + .map(r => `[${JSON.stringify(r)}]`) + .join(""); + return `(function() { module.exports = ${type}${objectLookup}; }());`; + } + + getSourceForCommonJsExternal(moduleAndSpecifiers) { + if (!Array.isArray(moduleAndSpecifiers)) { + return `module.exports = require(${JSON.stringify( + moduleAndSpecifiers + )});`; + } + + const moduleName = moduleAndSpecifiers[0]; + const objectLookup = moduleAndSpecifiers + .slice(1) + .map(r => `[${JSON.stringify(r)}]`) + .join(""); + return `module.exports = require(${JSON.stringify( + moduleName + )})${objectLookup};`; + } + + checkExternalVariable(variableToCheck, request) { + return `if(typeof ${variableToCheck} === 'undefined') {${WebpackMissingModule.moduleCode( + request + )}}\n`; + } + + getSourceForAmdOrUmdExternal(id, optional, request) { + const externalVariable = `__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier( + `${id}` + )}__`; + const missingModuleError = optional + ? this.checkExternalVariable(externalVariable, request) + : ""; + return `${missingModuleError}module.exports = ${externalVariable};`; + } + + getSourceForDefaultCase(optional, request) { + if (!Array.isArray(request)) { + // make it an array as the look up works the same basically + request = [request]; + } + + const variableName = request[0]; + const missingModuleError = optional + ? this.checkExternalVariable(variableName, request.join(".")) + : ""; + const objectLookup = request + .slice(1) + .map(r => `[${JSON.stringify(r)}]`) + .join(""); + return `${missingModuleError}module.exports = ${variableName}${objectLookup};`; + } + + getSourceString(runtime) { + const request = + typeof this.request === "object" && !Array.isArray(this.request) + ? this.request[this.externalType] + : this.request; + switch (this.externalType) { + case "this": + case "window": + case "self": + return this.getSourceForGlobalVariableExternal( + request, + this.externalType + ); + case "global": + return this.getSourceForGlobalVariableExternal( + runtime.outputOptions.globalObject, + this.externalType + ); + case "commonjs": + case "commonjs2": + return this.getSourceForCommonJsExternal(request); + case "amd": + case "umd": + case "umd2": + return this.getSourceForAmdOrUmdExternal( + this.id, + this.optional, + request + ); + default: + return this.getSourceForDefaultCase(this.optional, request); + } + } + + getSource(sourceString) { + if (this.useSourceMap) { + return new OriginalSource(sourceString, this.identifier()); + } + + return new RawSource(sourceString); + } + + source(dependencyTemplates, runtime) { + return this.getSource(this.getSourceString(runtime)); + } + + size() { + return 42; + } + + /** + * @param {Hash} hash the hash used to track dependencies + * @returns {void} + */ + updateHash(hash) { + hash.update(this.externalType); + hash.update(JSON.stringify(this.request)); + hash.update(JSON.stringify(Boolean(this.optional))); + super.updateHash(hash); + } +} + +module.exports = ExternalModule; diff --git a/node_modules/webpack/lib/ExternalModuleFactoryPlugin.js b/node_modules/webpack/lib/ExternalModuleFactoryPlugin.js index 7066aae42..b75cc7476 100644 --- a/node_modules/webpack/lib/ExternalModuleFactoryPlugin.js +++ b/node_modules/webpack/lib/ExternalModuleFactoryPlugin.js @@ -1,91 +1,110 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ExternalModule = require("./ExternalModule"); - -class ExternalModuleFactoryPlugin { - constructor(type, externals) { - this.type = type; - this.externals = externals; - } - - apply(normalModuleFactory) { - const globalType = this.type; - normalModuleFactory.plugin("factory", factory => (data, callback) => { - const context = data.context; - const dependency = data.dependencies[0]; - - function handleExternal(value, type, callback) { - if(typeof type === "function") { - callback = type; - type = undefined; - } - if(value === false) return factory(data, callback); - if(value === true) value = dependency.request; - if(typeof type === "undefined" && /^[a-z0-9]+ /.test(value)) { - const idx = value.indexOf(" "); - type = value.substr(0, idx); - value = value.substr(idx + 1); - } - callback(null, new ExternalModule(value, type || globalType, dependency.request)); - return true; - } - (function handleExternals(externals, callback) { - if(typeof externals === "string") { - if(externals === dependency.request) { - return handleExternal(dependency.request, callback); - } - } else if(Array.isArray(externals)) { - let i = 0; - (function next() { - let asyncFlag; - const handleExternalsAndCallback = function handleExternalsAndCallback(err, module) { - if(err) return callback(err); - if(!module) { - if(asyncFlag) { - asyncFlag = false; - return; - } - return next(); - } - callback(null, module); - }; - - do { - asyncFlag = true; - if(i >= externals.length) return callback(); - handleExternals(externals[i++], handleExternalsAndCallback); - } while (!asyncFlag); // eslint-disable-line keyword-spacing - asyncFlag = false; - }()); - return; - } else if(externals instanceof RegExp) { - if(externals.test(dependency.request)) { - return handleExternal(dependency.request, callback); - } - } else if(typeof externals === "function") { - externals.call(null, context, dependency.request, function(err, value, type) { - if(err) return callback(err); - if(typeof value !== "undefined") { - handleExternal(value, type, callback); - } else { - callback(); - } - }); - return; - } else if(typeof externals === "object" && Object.prototype.hasOwnProperty.call(externals, dependency.request)) { - return handleExternal(externals[dependency.request], callback); - } - callback(); - }(this.externals, function(err, module) { - if(err) return callback(err); - if(!module) return handleExternal(false, callback); - return callback(null, module); - })); - }); - } -} -module.exports = ExternalModuleFactoryPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const ExternalModule = require("./ExternalModule"); + +class ExternalModuleFactoryPlugin { + constructor(type, externals) { + this.type = type; + this.externals = externals; + } + + apply(normalModuleFactory) { + const globalType = this.type; + normalModuleFactory.hooks.factory.tap( + "ExternalModuleFactoryPlugin", + factory => (data, callback) => { + const context = data.context; + const dependency = data.dependencies[0]; + + const handleExternal = (value, type, callback) => { + if (typeof type === "function") { + callback = type; + type = undefined; + } + if (value === false) return factory(data, callback); + if (value === true) value = dependency.request; + if (type === undefined && /^[a-z0-9]+ /.test(value)) { + const idx = value.indexOf(" "); + type = value.substr(0, idx); + value = value.substr(idx + 1); + } + callback( + null, + new ExternalModule(value, type || globalType, dependency.request) + ); + return true; + }; + + const handleExternals = (externals, callback) => { + if (typeof externals === "string") { + if (externals === dependency.request) { + return handleExternal(dependency.request, callback); + } + } else if (Array.isArray(externals)) { + let i = 0; + const next = () => { + let asyncFlag; + const handleExternalsAndCallback = (err, module) => { + if (err) return callback(err); + if (!module) { + if (asyncFlag) { + asyncFlag = false; + return; + } + return next(); + } + callback(null, module); + }; + + do { + asyncFlag = true; + if (i >= externals.length) return callback(); + handleExternals(externals[i++], handleExternalsAndCallback); + } while (!asyncFlag); + asyncFlag = false; + }; + + next(); + return; + } else if (externals instanceof RegExp) { + if (externals.test(dependency.request)) { + return handleExternal(dependency.request, callback); + } + } else if (typeof externals === "function") { + externals.call( + null, + context, + dependency.request, + (err, value, type) => { + if (err) return callback(err); + if (value !== undefined) { + handleExternal(value, type, callback); + } else { + callback(); + } + } + ); + return; + } else if ( + typeof externals === "object" && + Object.prototype.hasOwnProperty.call(externals, dependency.request) + ) { + return handleExternal(externals[dependency.request], callback); + } + callback(); + }; + + handleExternals(this.externals, (err, module) => { + if (err) return callback(err); + if (!module) return handleExternal(false, callback); + return callback(null, module); + }); + } + ); + } +} +module.exports = ExternalModuleFactoryPlugin; diff --git a/node_modules/webpack/lib/ExternalsPlugin.js b/node_modules/webpack/lib/ExternalsPlugin.js index 24cc3ad3a..697f1aaa0 100644 --- a/node_modules/webpack/lib/ExternalsPlugin.js +++ b/node_modules/webpack/lib/ExternalsPlugin.js @@ -1,21 +1,23 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ExternalModuleFactoryPlugin = require("./ExternalModuleFactoryPlugin"); - -class ExternalsPlugin { - constructor(type, externals) { - this.type = type; - this.externals = externals; - } - apply(compiler) { - compiler.plugin("compile", (params) => { - params.normalModuleFactory.apply(new ExternalModuleFactoryPlugin(this.type, this.externals)); - }); - } -} - -module.exports = ExternalsPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const ExternalModuleFactoryPlugin = require("./ExternalModuleFactoryPlugin"); + +class ExternalsPlugin { + constructor(type, externals) { + this.type = type; + this.externals = externals; + } + apply(compiler) { + compiler.hooks.compile.tap("ExternalsPlugin", ({ normalModuleFactory }) => { + new ExternalModuleFactoryPlugin(this.type, this.externals).apply( + normalModuleFactory + ); + }); + } +} + +module.exports = ExternalsPlugin; diff --git a/node_modules/webpack/lib/FlagDependencyExportsPlugin.js b/node_modules/webpack/lib/FlagDependencyExportsPlugin.js index ff5e11255..0aafb0b4a 100644 --- a/node_modules/webpack/lib/FlagDependencyExportsPlugin.js +++ b/node_modules/webpack/lib/FlagDependencyExportsPlugin.js @@ -1,101 +1,146 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class FlagDependencyExportsPlugin { - - apply(compiler) { - compiler.plugin("compilation", (compilation) => { - compilation.plugin("finish-modules", (modules) => { - const dependencies = Object.create(null); - - let module; - let moduleWithExports; - let moduleProvidedExports; - const queue = modules.filter((m) => !m.providedExports); - for(let i = 0; i < queue.length; i++) { - module = queue[i]; - - if(module.providedExports !== true) { - moduleWithExports = module.meta && module.meta.harmonyModule; - moduleProvidedExports = Array.isArray(module.providedExports) ? new Set(module.providedExports) : new Set(); - processDependenciesBlock(module); - if(!moduleWithExports) { - module.providedExports = true; - notifyDependencies(); - } else if(module.providedExports !== true) { - module.providedExports = Array.from(moduleProvidedExports); - } - } - } - - function processDependenciesBlock(depBlock) { - depBlock.dependencies.forEach((dep) => processDependency(dep)); - depBlock.variables.forEach((variable) => { - variable.dependencies.forEach((dep) => processDependency(dep)); - }); - depBlock.blocks.forEach(processDependenciesBlock); - } - - function processDependency(dep) { - const exportDesc = dep.getExports && dep.getExports(); - if(!exportDesc) return; - moduleWithExports = true; - const exports = exportDesc.exports; - const exportDeps = exportDesc.dependencies; - if(exportDeps) { - exportDeps.forEach((dep) => { - const depIdent = dep.identifier(); - // if this was not yet initialized - // initialize it as an array containing the module and stop - const array = dependencies[depIdent]; - if(!array) { - dependencies[depIdent] = [module]; - return; - } - - // check if this module is known - // if not, add it to the dependencies for this identifier - if(array.indexOf(module) < 0) - array.push(module); - }); - } - let changed = false; - if(module.providedExports !== true) { - if(exports === true) { - module.providedExports = true; - changed = true; - } else if(Array.isArray(exports)) { - changed = addToSet(moduleProvidedExports, exports); - } - } - if(changed) { - notifyDependencies(); - } - } - - function notifyDependencies() { - const deps = dependencies[module.identifier()]; - if(deps) { - deps.forEach((dep) => queue.push(dep)); - } - } - }); - - function addToSet(a, b) { - let changed = false; - b.forEach((item) => { - if(!a.has(item)) { - a.add(item); - changed = true; - } - }); - return changed; - } - }); - } -} - -module.exports = FlagDependencyExportsPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const Queue = require("./util/Queue"); + +const addToSet = (a, b) => { + let changed = false; + for (const item of b) { + if (!a.has(item)) { + a.add(item); + changed = true; + } + } + return changed; +}; + +class FlagDependencyExportsPlugin { + apply(compiler) { + compiler.hooks.compilation.tap( + "FlagDependencyExportsPlugin", + compilation => { + compilation.hooks.finishModules.tap( + "FlagDependencyExportsPlugin", + modules => { + const dependencies = new Map(); + + const queue = new Queue(); + + let module; + let moduleWithExports; + let moduleProvidedExports; + + const processDependenciesBlock = depBlock => { + for (const dep of depBlock.dependencies) { + if (processDependency(dep)) return true; + } + for (const variable of depBlock.variables) { + for (const dep of variable.dependencies) { + if (processDependency(dep)) return true; + } + } + for (const block of depBlock.blocks) { + if (processDependenciesBlock(block)) return true; + } + return false; + }; + + const processDependency = dep => { + const exportDesc = dep.getExports && dep.getExports(); + if (!exportDesc) return; + moduleWithExports = true; + const exports = exportDesc.exports; + // break early if it's only in the worst state + if (module.buildMeta.providedExports === true) { + return true; + } + // break if it should move to the worst state + if (exports === true) { + module.buildMeta.providedExports = true; + notifyDependencies(); + return true; + } + // merge in new exports + if (Array.isArray(exports)) { + if (addToSet(moduleProvidedExports, exports)) { + notifyDependencies(); + } + } + // store dependencies + const exportDeps = exportDesc.dependencies; + if (exportDeps) { + for (const exportDependency of exportDeps) { + // add dependency for this module + const set = dependencies.get(exportDependency); + if (set === undefined) { + dependencies.set(exportDependency, new Set([module])); + } else { + set.add(module); + } + } + } + return false; + }; + + const notifyDependencies = () => { + const deps = dependencies.get(module); + if (deps !== undefined) { + for (const dep of deps) { + queue.enqueue(dep); + } + } + }; + + // Start with all modules without provided exports + for (const module of modules) { + if (!module.buildMeta.providedExports) { + queue.enqueue(module); + } + } + + while (queue.length > 0) { + module = queue.dequeue(); + + if (module.buildMeta.providedExports !== true) { + moduleWithExports = + module.buildMeta && module.buildMeta.exportsType; + moduleProvidedExports = Array.isArray( + module.buildMeta.providedExports + ) + ? new Set(module.buildMeta.providedExports) + : new Set(); + processDependenciesBlock(module); + if (!moduleWithExports) { + module.buildMeta.providedExports = true; + notifyDependencies(); + } else if (module.buildMeta.providedExports !== true) { + module.buildMeta.providedExports = Array.from( + moduleProvidedExports + ); + } + } + } + } + ); + const providedExportsCache = new WeakMap(); + compilation.hooks.rebuildModule.tap( + "FlagDependencyExportsPlugin", + module => { + providedExportsCache.set(module, module.buildMeta.providedExports); + } + ); + compilation.hooks.finishRebuildingModule.tap( + "FlagDependencyExportsPlugin", + module => { + module.buildMeta.providedExports = providedExportsCache.get(module); + } + ); + } + ); + } +} + +module.exports = FlagDependencyExportsPlugin; diff --git a/node_modules/webpack/lib/FlagDependencyUsagePlugin.js b/node_modules/webpack/lib/FlagDependencyUsagePlugin.js index 40e1769b1..85c221608 100644 --- a/node_modules/webpack/lib/FlagDependencyUsagePlugin.js +++ b/node_modules/webpack/lib/FlagDependencyUsagePlugin.js @@ -1,81 +1,116 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class FlagDependencyUsagePlugin { - apply(compiler) { - compiler.plugin("compilation", compilation => { - compilation.plugin("optimize-modules-advanced", modules => { - - modules.forEach(module => module.used = false); - - const queue = []; - compilation.chunks.forEach(chunk => { - if(chunk.entryModule) { - processModule(chunk.entryModule, true); - } - }); - - while(queue.length) { - const queueItem = queue.pop(); - processDependenciesBlock(queueItem[0], queueItem[1]); - } - - function processModule(module, usedExports) { - module.used = true; - if(module.usedExports === true) - return; - else if(usedExports === true) - module.usedExports = true; - else if(Array.isArray(usedExports)) { - const old = module.usedExports ? module.usedExports.length : -1; - module.usedExports = addToSet(module.usedExports || [], usedExports); - if(module.usedExports.length === old) - return; - } else if(Array.isArray(module.usedExports)) - return; - else - module.usedExports = false; - - queue.push([module, module.usedExports]); - } - - function processDependenciesBlock(depBlock, usedExports) { - depBlock.dependencies.forEach(dep => processDependency(dep)); - depBlock.variables.forEach(variable => variable.dependencies.forEach(dep => processDependency(dep))); - depBlock.blocks.forEach(block => queue.push([block, usedExports])); - } - - function processDependency(dep) { - const reference = dep.getReference && dep.getReference(); - if(!reference) return; - const module = reference.module; - const importedNames = reference.importedNames; - const oldUsed = module.used; - const oldUsedExports = module.usedExports; - if(!oldUsed || (importedNames && (!oldUsedExports || !isSubset(oldUsedExports, importedNames)))) { - processModule(module, importedNames); - } - } - - }); - - function addToSet(a, b) { - b.forEach(item => { - if(a.indexOf(item) < 0) - a.push(item); - }); - return a; - } - - function isSubset(biggerSet, subset) { - if(biggerSet === true) return true; - if(subset === true) return false; - return subset.every(item => biggerSet.indexOf(item) >= 0); - } - }); - } -} -module.exports = FlagDependencyUsagePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +/** @typedef {import("./Module")} Module */ +/** @typedef {import("./DependenciesBlock")} DependenciesBlock */ + +/** @typedef {false | true | string[]} UsedExports */ + +const addToSet = (a, b) => { + for (const item of b) { + if (!a.includes(item)) a.push(item); + } + return a; +}; + +const isSubset = (biggerSet, subset) => { + if (biggerSet === true) return true; + if (subset === true) return false; + return subset.every(item => biggerSet.indexOf(item) >= 0); +}; + +class FlagDependencyUsagePlugin { + apply(compiler) { + compiler.hooks.compilation.tap("FlagDependencyUsagePlugin", compilation => { + compilation.hooks.optimizeDependencies.tap( + "FlagDependencyUsagePlugin", + modules => { + const processModule = (module, usedExports) => { + module.used = true; + if (module.usedExports === true) return; + if (usedExports === true) { + module.usedExports = true; + } else if (Array.isArray(usedExports)) { + const old = module.usedExports ? module.usedExports.length : -1; + module.usedExports = addToSet( + module.usedExports || [], + usedExports + ); + if (module.usedExports.length === old) { + return; + } + } else if (Array.isArray(module.usedExports)) { + return; + } else { + module.usedExports = false; + } + + // for a module without side effects we stop tracking usage here when no export is used + // This module won't be evaluated in this case + if (module.factoryMeta.sideEffectFree) { + if (module.usedExports === false) return; + if ( + Array.isArray(module.usedExports) && + module.usedExports.length === 0 + ) + return; + } + + queue.push([module, module, module.usedExports]); + }; + + const processDependenciesBlock = (module, depBlock, usedExports) => { + for (const dep of depBlock.dependencies) { + processDependency(module, dep); + } + for (const variable of depBlock.variables) { + for (const dep of variable.dependencies) { + processDependency(module, dep); + } + } + for (const block of depBlock.blocks) { + queue.push([module, block, usedExports]); + } + }; + + const processDependency = (module, dep) => { + const reference = compilation.getDependencyReference(module, dep); + if (!reference) return; + const referenceModule = reference.module; + const importedNames = reference.importedNames; + const oldUsed = referenceModule.used; + const oldUsedExports = referenceModule.usedExports; + if ( + !oldUsed || + (importedNames && + (!oldUsedExports || !isSubset(oldUsedExports, importedNames))) + ) { + processModule(referenceModule, importedNames); + } + }; + + for (const module of modules) { + module.used = false; + } + + /** @type {[Module, DependenciesBlock, UsedExports][]} */ + const queue = []; + for (const preparedEntrypoint of compilation._preparedEntrypoints) { + if (preparedEntrypoint.module) { + processModule(preparedEntrypoint.module, true); + } + } + + while (queue.length) { + const queueItem = queue.pop(); + processDependenciesBlock(queueItem[0], queueItem[1], queueItem[2]); + } + } + ); + }); + } +} +module.exports = FlagDependencyUsagePlugin; diff --git a/node_modules/webpack/lib/FlagInitialModulesAsUsedPlugin.js b/node_modules/webpack/lib/FlagInitialModulesAsUsedPlugin.js index 0356006ab..7272ddb3a 100644 --- a/node_modules/webpack/lib/FlagInitialModulesAsUsedPlugin.js +++ b/node_modules/webpack/lib/FlagInitialModulesAsUsedPlugin.js @@ -1,24 +1,36 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class FlagInitialModulesAsUsedPlugin { - apply(compiler) { - compiler.plugin("compilation", (compilation) => { - compilation.plugin("after-optimize-chunks", (chunks) => { - chunks.forEach((chunk) => { - if(!chunk.isInitial()) { - return; - } - chunk.forEachModule((module) => { - module.usedExports = true; - }); - }); - }); - }); - } -} - -module.exports = FlagInitialModulesAsUsedPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +class FlagInitialModulesAsUsedPlugin { + constructor(explanation) { + this.explanation = explanation; + } + + apply(compiler) { + compiler.hooks.compilation.tap( + "FlagInitialModulesAsUsedPlugin", + compilation => { + compilation.hooks.afterOptimizeChunks.tap( + "FlagInitialModulesAsUsedPlugin", + chunks => { + for (const chunk of chunks) { + if (!chunk.isOnlyInitial()) { + return; + } + for (const module of chunk.modulesIterable) { + module.used = true; + module.usedExports = true; + module.addReason(null, null, this.explanation); + } + } + } + ); + } + ); + } +} + +module.exports = FlagInitialModulesAsUsedPlugin; diff --git a/node_modules/webpack/lib/FunctionModulePlugin.js b/node_modules/webpack/lib/FunctionModulePlugin.js index a150a94e3..fc4b2707f 100644 --- a/node_modules/webpack/lib/FunctionModulePlugin.js +++ b/node_modules/webpack/lib/FunctionModulePlugin.js @@ -1,24 +1,19 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const FunctionModuleTemplatePlugin = require("./FunctionModuleTemplatePlugin"); -const RequestShortener = require("./RequestShortener"); - -class FunctionModulePlugin { - constructor(options, requestShortener) { - this.options = options; - this.requestShortener = requestShortener; - } - - apply(compiler) { - compiler.plugin("compilation", (compilation) => { - compilation.moduleTemplate.requestShortener = this.requestShortener || new RequestShortener(compiler.context); - compilation.moduleTemplate.apply(new FunctionModuleTemplatePlugin()); - }); - } -} - -module.exports = FunctionModulePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const FunctionModuleTemplatePlugin = require("./FunctionModuleTemplatePlugin"); + +class FunctionModulePlugin { + apply(compiler) { + compiler.hooks.compilation.tap("FunctionModulePlugin", compilation => { + new FunctionModuleTemplatePlugin().apply( + compilation.moduleTemplates.javascript + ); + }); + } +} + +module.exports = FunctionModulePlugin; diff --git a/node_modules/webpack/lib/FunctionModuleTemplatePlugin.js b/node_modules/webpack/lib/FunctionModuleTemplatePlugin.js index 234a840f5..cf2e1b0ea 100644 --- a/node_modules/webpack/lib/FunctionModuleTemplatePlugin.js +++ b/node_modules/webpack/lib/FunctionModuleTemplatePlugin.js @@ -1,61 +1,100 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ConcatSource = require("webpack-sources").ConcatSource; - -class FunctionModuleTemplatePlugin { - apply(moduleTemplate) { - moduleTemplate.plugin("render", function(moduleSource, module) { - const source = new ConcatSource(); - const defaultArguments = [module.moduleArgument || "module", module.exportsArgument || "exports"]; - if((module.arguments && module.arguments.length !== 0) || module.hasDependencies(d => d.requireWebpackRequire !== false)) { - defaultArguments.push("__webpack_require__"); - } - source.add("/***/ (function(" + defaultArguments.concat(module.arguments || []).join(", ") + ") {\n\n"); - if(module.strict) source.add("\"use strict\";\n"); - source.add(moduleSource); - source.add("\n\n/***/ })"); - return source; - }); - - moduleTemplate.plugin("package", function(moduleSource, module) { - if(this.outputOptions.pathinfo) { - const source = new ConcatSource(); - const req = module.readableIdentifier(this.requestShortener); - source.add("/*!****" + req.replace(/./g, "*") + "****!*\\\n"); - source.add(" !*** " + req.replace(/\*\//g, "*_/") + " ***!\n"); - source.add(" \\****" + req.replace(/./g, "*") + "****/\n"); - if(Array.isArray(module.providedExports) && module.providedExports.length === 0) - source.add("/*! no exports provided */\n"); - else if(Array.isArray(module.providedExports)) - source.add("/*! exports provided: " + module.providedExports.join(", ") + " */\n"); - else if(module.providedExports) - source.add("/*! dynamic exports provided */\n"); - if(Array.isArray(module.usedExports) && module.usedExports.length === 0) - source.add("/*! no exports used */\n"); - else if(Array.isArray(module.usedExports)) - source.add("/*! exports used: " + module.usedExports.join(", ") + " */\n"); - else if(module.usedExports) - source.add("/*! all exports used */\n"); - if(module.optimizationBailout) { - module.optimizationBailout.forEach(text => { - if(typeof text === "function") text = text(this.requestShortener); - source.add(`/*! ${text} */\n`); - }); - } - source.add(moduleSource); - return source; - } - return moduleSource; - }); - - moduleTemplate.plugin("hash", function(hash) { - hash.update("FunctionModuleTemplatePlugin"); - hash.update("2"); - }); - } -} -module.exports = FunctionModuleTemplatePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const { ConcatSource } = require("webpack-sources"); +const Template = require("./Template"); + +class FunctionModuleTemplatePlugin { + apply(moduleTemplate) { + moduleTemplate.hooks.render.tap( + "FunctionModuleTemplatePlugin", + (moduleSource, module) => { + const source = new ConcatSource(); + const args = [module.moduleArgument]; + // TODO remove HACK checking type for javascript + if (module.type && module.type.startsWith("javascript")) { + args.push(module.exportsArgument); + if (module.hasDependencies(d => d.requireWebpackRequire !== false)) { + args.push("__webpack_require__"); + } + } else if (module.type && module.type.startsWith("json")) { + // no additional arguments needed + } else { + args.push(module.exportsArgument, "__webpack_require__"); + } + source.add("/***/ (function(" + args.join(", ") + ") {\n\n"); + if (module.buildInfo.strict) source.add('"use strict";\n'); + source.add(moduleSource); + source.add("\n\n/***/ })"); + return source; + } + ); + + moduleTemplate.hooks.package.tap( + "FunctionModuleTemplatePlugin", + (moduleSource, module) => { + if (moduleTemplate.runtimeTemplate.outputOptions.pathinfo) { + const source = new ConcatSource(); + const req = module.readableIdentifier( + moduleTemplate.runtimeTemplate.requestShortener + ); + source.add("/*!****" + req.replace(/./g, "*") + "****!*\\\n"); + source.add(" !*** " + req.replace(/\*\//g, "*_/") + " ***!\n"); + source.add(" \\****" + req.replace(/./g, "*") + "****/\n"); + if ( + Array.isArray(module.buildMeta.providedExports) && + module.buildMeta.providedExports.length === 0 + ) { + source.add(Template.toComment("no exports provided") + "\n"); + } else if (Array.isArray(module.buildMeta.providedExports)) { + source.add( + Template.toComment( + "exports provided: " + + module.buildMeta.providedExports.join(", ") + ) + "\n" + ); + } else if (module.buildMeta.providedExports) { + source.add(Template.toComment("no static exports found") + "\n"); + } + if ( + Array.isArray(module.usedExports) && + module.usedExports.length === 0 + ) { + source.add(Template.toComment("no exports used") + "\n"); + } else if (Array.isArray(module.usedExports)) { + source.add( + Template.toComment( + "exports used: " + module.usedExports.join(", ") + ) + "\n" + ); + } else if (module.usedExports) { + source.add(Template.toComment("all exports used") + "\n"); + } + if (module.optimizationBailout) { + for (const text of module.optimizationBailout) { + let code; + if (typeof text === "function") { + code = text(moduleTemplate.runtimeTemplate.requestShortener); + } else { + code = text; + } + source.add(Template.toComment(`${code}`) + "\n"); + } + } + source.add(moduleSource); + return source; + } + return moduleSource; + } + ); + + moduleTemplate.hooks.hash.tap("FunctionModuleTemplatePlugin", hash => { + hash.update("FunctionModuleTemplatePlugin"); + hash.update("2"); + }); + } +} +module.exports = FunctionModuleTemplatePlugin; diff --git a/node_modules/webpack/lib/HashedModuleIdsPlugin.js b/node_modules/webpack/lib/HashedModuleIdsPlugin.js index 40a491b07..aeb9f1d93 100644 --- a/node_modules/webpack/lib/HashedModuleIdsPlugin.js +++ b/node_modules/webpack/lib/HashedModuleIdsPlugin.js @@ -1,42 +1,53 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const createHash = require("crypto").createHash; - -class HashedModuleIdsPlugin { - constructor(options) { - this.options = Object.assign({ - hashFunction: "md5", - hashDigest: "base64", - hashDigestLength: 4 - }, options); - } - - apply(compiler) { - const options = this.options; - compiler.plugin("compilation", (compilation) => { - const usedIds = new Set(); - compilation.plugin("before-module-ids", (modules) => { - modules.forEach((module) => { - if(module.id === null && module.libIdent) { - const id = module.libIdent({ - context: this.options.context || compiler.options.context - }); - const hash = createHash(options.hashFunction); - hash.update(id); - const hashId = hash.digest(options.hashDigest); - let len = options.hashDigestLength; - while(usedIds.has(hashId.substr(0, len))) - len++; - module.id = hashId.substr(0, len); - usedIds.add(module.id); - } - }); - }); - }); - } -} - -module.exports = HashedModuleIdsPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const createHash = require("./util/createHash"); + +const validateOptions = require("schema-utils"); +const schema = require("../schemas/plugins/HashedModuleIdsPlugin.json"); + +class HashedModuleIdsPlugin { + constructor(options) { + validateOptions(schema, options || {}, "Hashed Module Ids Plugin"); + + this.options = Object.assign( + { + context: null, + hashFunction: "md4", + hashDigest: "base64", + hashDigestLength: 4 + }, + options + ); + } + + apply(compiler) { + const options = this.options; + compiler.hooks.compilation.tap("HashedModuleIdsPlugin", compilation => { + const usedIds = new Set(); + compilation.hooks.beforeModuleIds.tap( + "HashedModuleIdsPlugin", + modules => { + for (const module of modules) { + if (module.id === null && module.libIdent) { + const id = module.libIdent({ + context: this.options.context || compiler.options.context + }); + const hash = createHash(options.hashFunction); + hash.update(id); + const hashId = hash.digest(options.hashDigest); + let len = options.hashDigestLength; + while (usedIds.has(hashId.substr(0, len))) len++; + module.id = hashId.substr(0, len); + usedIds.add(module.id); + } + } + } + ); + }); + } +} + +module.exports = HashedModuleIdsPlugin; diff --git a/node_modules/webpack/lib/HotModuleReplacement.runtime.js b/node_modules/webpack/lib/HotModuleReplacement.runtime.js index 6db89aa2d..5497091c8 100644 --- a/node_modules/webpack/lib/HotModuleReplacement.runtime.js +++ b/node_modules/webpack/lib/HotModuleReplacement.runtime.js @@ -1,602 +1,645 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -/*global $hash$ $requestTimeout$ installedModules $require$ hotDownloadManifest hotDownloadUpdateChunk hotDisposeChunk modules */ -module.exports = function() { - - var hotApplyOnUpdate = true; - var hotCurrentHash = $hash$; // eslint-disable-line no-unused-vars - var hotRequestTimeout = $requestTimeout$; - var hotCurrentModuleData = {}; - var hotCurrentChildModule; // eslint-disable-line no-unused-vars - var hotCurrentParents = []; // eslint-disable-line no-unused-vars - var hotCurrentParentsTemp = []; // eslint-disable-line no-unused-vars - - function hotCreateRequire(moduleId) { // eslint-disable-line no-unused-vars - var me = installedModules[moduleId]; - if(!me) return $require$; - var fn = function(request) { - if(me.hot.active) { - if(installedModules[request]) { - if(installedModules[request].parents.indexOf(moduleId) < 0) - installedModules[request].parents.push(moduleId); - } else { - hotCurrentParents = [moduleId]; - hotCurrentChildModule = request; - } - if(me.children.indexOf(request) < 0) - me.children.push(request); - } else { - console.warn("[HMR] unexpected require(" + request + ") from disposed module " + moduleId); - hotCurrentParents = []; - } - return $require$(request); - }; - var ObjectFactory = function ObjectFactory(name) { - return { - configurable: true, - enumerable: true, - get: function() { - return $require$[name]; - }, - set: function(value) { - $require$[name] = value; - } - }; - }; - for(var name in $require$) { - if(Object.prototype.hasOwnProperty.call($require$, name) && name !== "e") { - Object.defineProperty(fn, name, ObjectFactory(name)); - } - } - fn.e = function(chunkId) { - if(hotStatus === "ready") - hotSetStatus("prepare"); - hotChunksLoading++; - return $require$.e(chunkId).then(finishChunkLoading, function(err) { - finishChunkLoading(); - throw err; - }); - - function finishChunkLoading() { - hotChunksLoading--; - if(hotStatus === "prepare") { - if(!hotWaitingFilesMap[chunkId]) { - hotEnsureUpdateChunk(chunkId); - } - if(hotChunksLoading === 0 && hotWaitingFiles === 0) { - hotUpdateDownloaded(); - } - } - } - }; - return fn; - } - - function hotCreateModule(moduleId) { // eslint-disable-line no-unused-vars - var hot = { - // private stuff - _acceptedDependencies: {}, - _declinedDependencies: {}, - _selfAccepted: false, - _selfDeclined: false, - _disposeHandlers: [], - _main: hotCurrentChildModule !== moduleId, - - // Module API - active: true, - accept: function(dep, callback) { - if(typeof dep === "undefined") - hot._selfAccepted = true; - else if(typeof dep === "function") - hot._selfAccepted = dep; - else if(typeof dep === "object") - for(var i = 0; i < dep.length; i++) - hot._acceptedDependencies[dep[i]] = callback || function() {}; - else - hot._acceptedDependencies[dep] = callback || function() {}; - }, - decline: function(dep) { - if(typeof dep === "undefined") - hot._selfDeclined = true; - else if(typeof dep === "object") - for(var i = 0; i < dep.length; i++) - hot._declinedDependencies[dep[i]] = true; - else - hot._declinedDependencies[dep] = true; - }, - dispose: function(callback) { - hot._disposeHandlers.push(callback); - }, - addDisposeHandler: function(callback) { - hot._disposeHandlers.push(callback); - }, - removeDisposeHandler: function(callback) { - var idx = hot._disposeHandlers.indexOf(callback); - if(idx >= 0) hot._disposeHandlers.splice(idx, 1); - }, - - // Management API - check: hotCheck, - apply: hotApply, - status: function(l) { - if(!l) return hotStatus; - hotStatusHandlers.push(l); - }, - addStatusHandler: function(l) { - hotStatusHandlers.push(l); - }, - removeStatusHandler: function(l) { - var idx = hotStatusHandlers.indexOf(l); - if(idx >= 0) hotStatusHandlers.splice(idx, 1); - }, - - //inherit from previous dispose call - data: hotCurrentModuleData[moduleId] - }; - hotCurrentChildModule = undefined; - return hot; - } - - var hotStatusHandlers = []; - var hotStatus = "idle"; - - function hotSetStatus(newStatus) { - hotStatus = newStatus; - for(var i = 0; i < hotStatusHandlers.length; i++) - hotStatusHandlers[i].call(null, newStatus); - } - - // while downloading - var hotWaitingFiles = 0; - var hotChunksLoading = 0; - var hotWaitingFilesMap = {}; - var hotRequestedFilesMap = {}; - var hotAvailableFilesMap = {}; - var hotDeferred; - - // The update info - var hotUpdate, hotUpdateNewHash; - - function toModuleId(id) { - var isNumber = (+id) + "" === id; - return isNumber ? +id : id; - } - - function hotCheck(apply) { - if(hotStatus !== "idle") throw new Error("check() is only allowed in idle status"); - hotApplyOnUpdate = apply; - hotSetStatus("check"); - return hotDownloadManifest(hotRequestTimeout).then(function(update) { - if(!update) { - hotSetStatus("idle"); - return null; - } - hotRequestedFilesMap = {}; - hotWaitingFilesMap = {}; - hotAvailableFilesMap = update.c; - hotUpdateNewHash = update.h; - - hotSetStatus("prepare"); - var promise = new Promise(function(resolve, reject) { - hotDeferred = { - resolve: resolve, - reject: reject - }; - }); - hotUpdate = {}; - /*foreachInstalledChunks*/ - { // eslint-disable-line no-lone-blocks - /*globals chunkId */ - hotEnsureUpdateChunk(chunkId); - } - if(hotStatus === "prepare" && hotChunksLoading === 0 && hotWaitingFiles === 0) { - hotUpdateDownloaded(); - } - return promise; - }); - } - - function hotAddUpdateChunk(chunkId, moreModules) { // eslint-disable-line no-unused-vars - if(!hotAvailableFilesMap[chunkId] || !hotRequestedFilesMap[chunkId]) - return; - hotRequestedFilesMap[chunkId] = false; - for(var moduleId in moreModules) { - if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) { - hotUpdate[moduleId] = moreModules[moduleId]; - } - } - if(--hotWaitingFiles === 0 && hotChunksLoading === 0) { - hotUpdateDownloaded(); - } - } - - function hotEnsureUpdateChunk(chunkId) { - if(!hotAvailableFilesMap[chunkId]) { - hotWaitingFilesMap[chunkId] = true; - } else { - hotRequestedFilesMap[chunkId] = true; - hotWaitingFiles++; - hotDownloadUpdateChunk(chunkId); - } - } - - function hotUpdateDownloaded() { - hotSetStatus("ready"); - var deferred = hotDeferred; - hotDeferred = null; - if(!deferred) return; - if(hotApplyOnUpdate) { - // Wrap deferred object in Promise to mark it as a well-handled Promise to - // avoid triggering uncaught exception warning in Chrome. - // See https://bugs.chromium.org/p/chromium/issues/detail?id=465666 - Promise.resolve().then(function() { - return hotApply(hotApplyOnUpdate); - }).then( - function(result) { - deferred.resolve(result); - }, - function(err) { - deferred.reject(err); - } - ); - } else { - var outdatedModules = []; - for(var id in hotUpdate) { - if(Object.prototype.hasOwnProperty.call(hotUpdate, id)) { - outdatedModules.push(toModuleId(id)); - } - } - deferred.resolve(outdatedModules); - } - } - - function hotApply(options) { - if(hotStatus !== "ready") throw new Error("apply() is only allowed in ready status"); - options = options || {}; - - var cb; - var i; - var j; - var module; - var moduleId; - - function getAffectedStuff(updateModuleId) { - var outdatedModules = [updateModuleId]; - var outdatedDependencies = {}; - - var queue = outdatedModules.slice().map(function(id) { - return { - chain: [id], - id: id - }; - }); - while(queue.length > 0) { - var queueItem = queue.pop(); - var moduleId = queueItem.id; - var chain = queueItem.chain; - module = installedModules[moduleId]; - if(!module || module.hot._selfAccepted) - continue; - if(module.hot._selfDeclined) { - return { - type: "self-declined", - chain: chain, - moduleId: moduleId - }; - } - if(module.hot._main) { - return { - type: "unaccepted", - chain: chain, - moduleId: moduleId - }; - } - for(var i = 0; i < module.parents.length; i++) { - var parentId = module.parents[i]; - var parent = installedModules[parentId]; - if(!parent) continue; - if(parent.hot._declinedDependencies[moduleId]) { - return { - type: "declined", - chain: chain.concat([parentId]), - moduleId: moduleId, - parentId: parentId - }; - } - if(outdatedModules.indexOf(parentId) >= 0) continue; - if(parent.hot._acceptedDependencies[moduleId]) { - if(!outdatedDependencies[parentId]) - outdatedDependencies[parentId] = []; - addAllToSet(outdatedDependencies[parentId], [moduleId]); - continue; - } - delete outdatedDependencies[parentId]; - outdatedModules.push(parentId); - queue.push({ - chain: chain.concat([parentId]), - id: parentId - }); - } - } - - return { - type: "accepted", - moduleId: updateModuleId, - outdatedModules: outdatedModules, - outdatedDependencies: outdatedDependencies - }; - } - - function addAllToSet(a, b) { - for(var i = 0; i < b.length; i++) { - var item = b[i]; - if(a.indexOf(item) < 0) - a.push(item); - } - } - - // at begin all updates modules are outdated - // the "outdated" status can propagate to parents if they don't accept the children - var outdatedDependencies = {}; - var outdatedModules = []; - var appliedUpdate = {}; - - var warnUnexpectedRequire = function warnUnexpectedRequire() { - console.warn("[HMR] unexpected require(" + result.moduleId + ") to disposed module"); - }; - - for(var id in hotUpdate) { - if(Object.prototype.hasOwnProperty.call(hotUpdate, id)) { - moduleId = toModuleId(id); - var result; - if(hotUpdate[id]) { - result = getAffectedStuff(moduleId); - } else { - result = { - type: "disposed", - moduleId: id - }; - } - var abortError = false; - var doApply = false; - var doDispose = false; - var chainInfo = ""; - if(result.chain) { - chainInfo = "\nUpdate propagation: " + result.chain.join(" -> "); - } - switch(result.type) { - case "self-declined": - if(options.onDeclined) - options.onDeclined(result); - if(!options.ignoreDeclined) - abortError = new Error("Aborted because of self decline: " + result.moduleId + chainInfo); - break; - case "declined": - if(options.onDeclined) - options.onDeclined(result); - if(!options.ignoreDeclined) - abortError = new Error("Aborted because of declined dependency: " + result.moduleId + " in " + result.parentId + chainInfo); - break; - case "unaccepted": - if(options.onUnaccepted) - options.onUnaccepted(result); - if(!options.ignoreUnaccepted) - abortError = new Error("Aborted because " + moduleId + " is not accepted" + chainInfo); - break; - case "accepted": - if(options.onAccepted) - options.onAccepted(result); - doApply = true; - break; - case "disposed": - if(options.onDisposed) - options.onDisposed(result); - doDispose = true; - break; - default: - throw new Error("Unexception type " + result.type); - } - if(abortError) { - hotSetStatus("abort"); - return Promise.reject(abortError); - } - if(doApply) { - appliedUpdate[moduleId] = hotUpdate[moduleId]; - addAllToSet(outdatedModules, result.outdatedModules); - for(moduleId in result.outdatedDependencies) { - if(Object.prototype.hasOwnProperty.call(result.outdatedDependencies, moduleId)) { - if(!outdatedDependencies[moduleId]) - outdatedDependencies[moduleId] = []; - addAllToSet(outdatedDependencies[moduleId], result.outdatedDependencies[moduleId]); - } - } - } - if(doDispose) { - addAllToSet(outdatedModules, [result.moduleId]); - appliedUpdate[moduleId] = warnUnexpectedRequire; - } - } - } - - // Store self accepted outdated modules to require them later by the module system - var outdatedSelfAcceptedModules = []; - for(i = 0; i < outdatedModules.length; i++) { - moduleId = outdatedModules[i]; - if(installedModules[moduleId] && installedModules[moduleId].hot._selfAccepted) - outdatedSelfAcceptedModules.push({ - module: moduleId, - errorHandler: installedModules[moduleId].hot._selfAccepted - }); - } - - // Now in "dispose" phase - hotSetStatus("dispose"); - Object.keys(hotAvailableFilesMap).forEach(function(chunkId) { - if(hotAvailableFilesMap[chunkId] === false) { - hotDisposeChunk(chunkId); - } - }); - - var idx; - var queue = outdatedModules.slice(); - while(queue.length > 0) { - moduleId = queue.pop(); - module = installedModules[moduleId]; - if(!module) continue; - - var data = {}; - - // Call dispose handlers - var disposeHandlers = module.hot._disposeHandlers; - for(j = 0; j < disposeHandlers.length; j++) { - cb = disposeHandlers[j]; - cb(data); - } - hotCurrentModuleData[moduleId] = data; - - // disable module (this disables requires from this module) - module.hot.active = false; - - // remove module from cache - delete installedModules[moduleId]; - - // when disposing there is no need to call dispose handler - delete outdatedDependencies[moduleId]; - - // remove "parents" references from all children - for(j = 0; j < module.children.length; j++) { - var child = installedModules[module.children[j]]; - if(!child) continue; - idx = child.parents.indexOf(moduleId); - if(idx >= 0) { - child.parents.splice(idx, 1); - } - } - } - - // remove outdated dependency from module children - var dependency; - var moduleOutdatedDependencies; - for(moduleId in outdatedDependencies) { - if(Object.prototype.hasOwnProperty.call(outdatedDependencies, moduleId)) { - module = installedModules[moduleId]; - if(module) { - moduleOutdatedDependencies = outdatedDependencies[moduleId]; - for(j = 0; j < moduleOutdatedDependencies.length; j++) { - dependency = moduleOutdatedDependencies[j]; - idx = module.children.indexOf(dependency); - if(idx >= 0) module.children.splice(idx, 1); - } - } - } - } - - // Not in "apply" phase - hotSetStatus("apply"); - - hotCurrentHash = hotUpdateNewHash; - - // insert new code - for(moduleId in appliedUpdate) { - if(Object.prototype.hasOwnProperty.call(appliedUpdate, moduleId)) { - modules[moduleId] = appliedUpdate[moduleId]; - } - } - - // call accept handlers - var error = null; - for(moduleId in outdatedDependencies) { - if(Object.prototype.hasOwnProperty.call(outdatedDependencies, moduleId)) { - module = installedModules[moduleId]; - if(module) { - moduleOutdatedDependencies = outdatedDependencies[moduleId]; - var callbacks = []; - for(i = 0; i < moduleOutdatedDependencies.length; i++) { - dependency = moduleOutdatedDependencies[i]; - cb = module.hot._acceptedDependencies[dependency]; - if(cb) { - if(callbacks.indexOf(cb) >= 0) continue; - callbacks.push(cb); - } - } - for(i = 0; i < callbacks.length; i++) { - cb = callbacks[i]; - try { - cb(moduleOutdatedDependencies); - } catch(err) { - if(options.onErrored) { - options.onErrored({ - type: "accept-errored", - moduleId: moduleId, - dependencyId: moduleOutdatedDependencies[i], - error: err - }); - } - if(!options.ignoreErrored) { - if(!error) - error = err; - } - } - } - } - } - } - - // Load self accepted modules - for(i = 0; i < outdatedSelfAcceptedModules.length; i++) { - var item = outdatedSelfAcceptedModules[i]; - moduleId = item.module; - hotCurrentParents = [moduleId]; - try { - $require$(moduleId); - } catch(err) { - if(typeof item.errorHandler === "function") { - try { - item.errorHandler(err); - } catch(err2) { - if(options.onErrored) { - options.onErrored({ - type: "self-accept-error-handler-errored", - moduleId: moduleId, - error: err2, - orginalError: err, // TODO remove in webpack 4 - originalError: err - }); - } - if(!options.ignoreErrored) { - if(!error) - error = err2; - } - if(!error) - error = err; - } - } else { - if(options.onErrored) { - options.onErrored({ - type: "self-accept-errored", - moduleId: moduleId, - error: err - }); - } - if(!options.ignoreErrored) { - if(!error) - error = err; - } - } - } - } - - // handle errors in accept handlers and self accepted module load - if(error) { - hotSetStatus("fail"); - return Promise.reject(error); - } - - hotSetStatus("idle"); - return new Promise(function(resolve) { - resolve(outdatedModules); - }); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +/*global $hash$ $requestTimeout$ installedModules $require$ hotDownloadManifest hotDownloadUpdateChunk hotDisposeChunk modules */ +module.exports = function() { + var hotApplyOnUpdate = true; + // eslint-disable-next-line no-unused-vars + var hotCurrentHash = $hash$; + var hotRequestTimeout = $requestTimeout$; + var hotCurrentModuleData = {}; + var hotCurrentChildModule; + // eslint-disable-next-line no-unused-vars + var hotCurrentParents = []; + // eslint-disable-next-line no-unused-vars + var hotCurrentParentsTemp = []; + + // eslint-disable-next-line no-unused-vars + function hotCreateRequire(moduleId) { + var me = installedModules[moduleId]; + if (!me) return $require$; + var fn = function(request) { + if (me.hot.active) { + if (installedModules[request]) { + if (installedModules[request].parents.indexOf(moduleId) === -1) { + installedModules[request].parents.push(moduleId); + } + } else { + hotCurrentParents = [moduleId]; + hotCurrentChildModule = request; + } + if (me.children.indexOf(request) === -1) { + me.children.push(request); + } + } else { + console.warn( + "[HMR] unexpected require(" + + request + + ") from disposed module " + + moduleId + ); + hotCurrentParents = []; + } + return $require$(request); + }; + var ObjectFactory = function ObjectFactory(name) { + return { + configurable: true, + enumerable: true, + get: function() { + return $require$[name]; + }, + set: function(value) { + $require$[name] = value; + } + }; + }; + for (var name in $require$) { + if ( + Object.prototype.hasOwnProperty.call($require$, name) && + name !== "e" && + name !== "t" + ) { + Object.defineProperty(fn, name, ObjectFactory(name)); + } + } + fn.e = function(chunkId) { + if (hotStatus === "ready") hotSetStatus("prepare"); + hotChunksLoading++; + return $require$.e(chunkId).then(finishChunkLoading, function(err) { + finishChunkLoading(); + throw err; + }); + + function finishChunkLoading() { + hotChunksLoading--; + if (hotStatus === "prepare") { + if (!hotWaitingFilesMap[chunkId]) { + hotEnsureUpdateChunk(chunkId); + } + if (hotChunksLoading === 0 && hotWaitingFiles === 0) { + hotUpdateDownloaded(); + } + } + } + }; + fn.t = function(value, mode) { + if (mode & 1) value = fn(value); + return $require$.t(value, mode & ~1); + }; + return fn; + } + + // eslint-disable-next-line no-unused-vars + function hotCreateModule(moduleId) { + var hot = { + // private stuff + _acceptedDependencies: {}, + _declinedDependencies: {}, + _selfAccepted: false, + _selfDeclined: false, + _disposeHandlers: [], + _main: hotCurrentChildModule !== moduleId, + + // Module API + active: true, + accept: function(dep, callback) { + if (dep === undefined) hot._selfAccepted = true; + else if (typeof dep === "function") hot._selfAccepted = dep; + else if (typeof dep === "object") + for (var i = 0; i < dep.length; i++) + hot._acceptedDependencies[dep[i]] = callback || function() {}; + else hot._acceptedDependencies[dep] = callback || function() {}; + }, + decline: function(dep) { + if (dep === undefined) hot._selfDeclined = true; + else if (typeof dep === "object") + for (var i = 0; i < dep.length; i++) + hot._declinedDependencies[dep[i]] = true; + else hot._declinedDependencies[dep] = true; + }, + dispose: function(callback) { + hot._disposeHandlers.push(callback); + }, + addDisposeHandler: function(callback) { + hot._disposeHandlers.push(callback); + }, + removeDisposeHandler: function(callback) { + var idx = hot._disposeHandlers.indexOf(callback); + if (idx >= 0) hot._disposeHandlers.splice(idx, 1); + }, + + // Management API + check: hotCheck, + apply: hotApply, + status: function(l) { + if (!l) return hotStatus; + hotStatusHandlers.push(l); + }, + addStatusHandler: function(l) { + hotStatusHandlers.push(l); + }, + removeStatusHandler: function(l) { + var idx = hotStatusHandlers.indexOf(l); + if (idx >= 0) hotStatusHandlers.splice(idx, 1); + }, + + //inherit from previous dispose call + data: hotCurrentModuleData[moduleId] + }; + hotCurrentChildModule = undefined; + return hot; + } + + var hotStatusHandlers = []; + var hotStatus = "idle"; + + function hotSetStatus(newStatus) { + hotStatus = newStatus; + for (var i = 0; i < hotStatusHandlers.length; i++) + hotStatusHandlers[i].call(null, newStatus); + } + + // while downloading + var hotWaitingFiles = 0; + var hotChunksLoading = 0; + var hotWaitingFilesMap = {}; + var hotRequestedFilesMap = {}; + var hotAvailableFilesMap = {}; + var hotDeferred; + + // The update info + var hotUpdate, hotUpdateNewHash; + + function toModuleId(id) { + var isNumber = +id + "" === id; + return isNumber ? +id : id; + } + + function hotCheck(apply) { + if (hotStatus !== "idle") { + throw new Error("check() is only allowed in idle status"); + } + hotApplyOnUpdate = apply; + hotSetStatus("check"); + return hotDownloadManifest(hotRequestTimeout).then(function(update) { + if (!update) { + hotSetStatus("idle"); + return null; + } + hotRequestedFilesMap = {}; + hotWaitingFilesMap = {}; + hotAvailableFilesMap = update.c; + hotUpdateNewHash = update.h; + + hotSetStatus("prepare"); + var promise = new Promise(function(resolve, reject) { + hotDeferred = { + resolve: resolve, + reject: reject + }; + }); + hotUpdate = {}; + /*foreachInstalledChunks*/ + // eslint-disable-next-line no-lone-blocks + { + /*globals chunkId */ + hotEnsureUpdateChunk(chunkId); + } + if ( + hotStatus === "prepare" && + hotChunksLoading === 0 && + hotWaitingFiles === 0 + ) { + hotUpdateDownloaded(); + } + return promise; + }); + } + + // eslint-disable-next-line no-unused-vars + function hotAddUpdateChunk(chunkId, moreModules) { + if (!hotAvailableFilesMap[chunkId] || !hotRequestedFilesMap[chunkId]) + return; + hotRequestedFilesMap[chunkId] = false; + for (var moduleId in moreModules) { + if (Object.prototype.hasOwnProperty.call(moreModules, moduleId)) { + hotUpdate[moduleId] = moreModules[moduleId]; + } + } + if (--hotWaitingFiles === 0 && hotChunksLoading === 0) { + hotUpdateDownloaded(); + } + } + + function hotEnsureUpdateChunk(chunkId) { + if (!hotAvailableFilesMap[chunkId]) { + hotWaitingFilesMap[chunkId] = true; + } else { + hotRequestedFilesMap[chunkId] = true; + hotWaitingFiles++; + hotDownloadUpdateChunk(chunkId); + } + } + + function hotUpdateDownloaded() { + hotSetStatus("ready"); + var deferred = hotDeferred; + hotDeferred = null; + if (!deferred) return; + if (hotApplyOnUpdate) { + // Wrap deferred object in Promise to mark it as a well-handled Promise to + // avoid triggering uncaught exception warning in Chrome. + // See https://bugs.chromium.org/p/chromium/issues/detail?id=465666 + Promise.resolve() + .then(function() { + return hotApply(hotApplyOnUpdate); + }) + .then( + function(result) { + deferred.resolve(result); + }, + function(err) { + deferred.reject(err); + } + ); + } else { + var outdatedModules = []; + for (var id in hotUpdate) { + if (Object.prototype.hasOwnProperty.call(hotUpdate, id)) { + outdatedModules.push(toModuleId(id)); + } + } + deferred.resolve(outdatedModules); + } + } + + function hotApply(options) { + if (hotStatus !== "ready") + throw new Error("apply() is only allowed in ready status"); + options = options || {}; + + var cb; + var i; + var j; + var module; + var moduleId; + + function getAffectedStuff(updateModuleId) { + var outdatedModules = [updateModuleId]; + var outdatedDependencies = {}; + + var queue = outdatedModules.slice().map(function(id) { + return { + chain: [id], + id: id + }; + }); + while (queue.length > 0) { + var queueItem = queue.pop(); + var moduleId = queueItem.id; + var chain = queueItem.chain; + module = installedModules[moduleId]; + if (!module || module.hot._selfAccepted) continue; + if (module.hot._selfDeclined) { + return { + type: "self-declined", + chain: chain, + moduleId: moduleId + }; + } + if (module.hot._main) { + return { + type: "unaccepted", + chain: chain, + moduleId: moduleId + }; + } + for (var i = 0; i < module.parents.length; i++) { + var parentId = module.parents[i]; + var parent = installedModules[parentId]; + if (!parent) continue; + if (parent.hot._declinedDependencies[moduleId]) { + return { + type: "declined", + chain: chain.concat([parentId]), + moduleId: moduleId, + parentId: parentId + }; + } + if (outdatedModules.indexOf(parentId) !== -1) continue; + if (parent.hot._acceptedDependencies[moduleId]) { + if (!outdatedDependencies[parentId]) + outdatedDependencies[parentId] = []; + addAllToSet(outdatedDependencies[parentId], [moduleId]); + continue; + } + delete outdatedDependencies[parentId]; + outdatedModules.push(parentId); + queue.push({ + chain: chain.concat([parentId]), + id: parentId + }); + } + } + + return { + type: "accepted", + moduleId: updateModuleId, + outdatedModules: outdatedModules, + outdatedDependencies: outdatedDependencies + }; + } + + function addAllToSet(a, b) { + for (var i = 0; i < b.length; i++) { + var item = b[i]; + if (a.indexOf(item) === -1) a.push(item); + } + } + + // at begin all updates modules are outdated + // the "outdated" status can propagate to parents if they don't accept the children + var outdatedDependencies = {}; + var outdatedModules = []; + var appliedUpdate = {}; + + var warnUnexpectedRequire = function warnUnexpectedRequire() { + console.warn( + "[HMR] unexpected require(" + result.moduleId + ") to disposed module" + ); + }; + + for (var id in hotUpdate) { + if (Object.prototype.hasOwnProperty.call(hotUpdate, id)) { + moduleId = toModuleId(id); + /** @type {TODO} */ + var result; + if (hotUpdate[id]) { + result = getAffectedStuff(moduleId); + } else { + result = { + type: "disposed", + moduleId: id + }; + } + /** @type {Error|false} */ + var abortError = false; + var doApply = false; + var doDispose = false; + var chainInfo = ""; + if (result.chain) { + chainInfo = "\nUpdate propagation: " + result.chain.join(" -> "); + } + switch (result.type) { + case "self-declined": + if (options.onDeclined) options.onDeclined(result); + if (!options.ignoreDeclined) + abortError = new Error( + "Aborted because of self decline: " + + result.moduleId + + chainInfo + ); + break; + case "declined": + if (options.onDeclined) options.onDeclined(result); + if (!options.ignoreDeclined) + abortError = new Error( + "Aborted because of declined dependency: " + + result.moduleId + + " in " + + result.parentId + + chainInfo + ); + break; + case "unaccepted": + if (options.onUnaccepted) options.onUnaccepted(result); + if (!options.ignoreUnaccepted) + abortError = new Error( + "Aborted because " + moduleId + " is not accepted" + chainInfo + ); + break; + case "accepted": + if (options.onAccepted) options.onAccepted(result); + doApply = true; + break; + case "disposed": + if (options.onDisposed) options.onDisposed(result); + doDispose = true; + break; + default: + throw new Error("Unexception type " + result.type); + } + if (abortError) { + hotSetStatus("abort"); + return Promise.reject(abortError); + } + if (doApply) { + appliedUpdate[moduleId] = hotUpdate[moduleId]; + addAllToSet(outdatedModules, result.outdatedModules); + for (moduleId in result.outdatedDependencies) { + if ( + Object.prototype.hasOwnProperty.call( + result.outdatedDependencies, + moduleId + ) + ) { + if (!outdatedDependencies[moduleId]) + outdatedDependencies[moduleId] = []; + addAllToSet( + outdatedDependencies[moduleId], + result.outdatedDependencies[moduleId] + ); + } + } + } + if (doDispose) { + addAllToSet(outdatedModules, [result.moduleId]); + appliedUpdate[moduleId] = warnUnexpectedRequire; + } + } + } + + // Store self accepted outdated modules to require them later by the module system + var outdatedSelfAcceptedModules = []; + for (i = 0; i < outdatedModules.length; i++) { + moduleId = outdatedModules[i]; + if ( + installedModules[moduleId] && + installedModules[moduleId].hot._selfAccepted + ) + outdatedSelfAcceptedModules.push({ + module: moduleId, + errorHandler: installedModules[moduleId].hot._selfAccepted + }); + } + + // Now in "dispose" phase + hotSetStatus("dispose"); + Object.keys(hotAvailableFilesMap).forEach(function(chunkId) { + if (hotAvailableFilesMap[chunkId] === false) { + hotDisposeChunk(chunkId); + } + }); + + var idx; + var queue = outdatedModules.slice(); + while (queue.length > 0) { + moduleId = queue.pop(); + module = installedModules[moduleId]; + if (!module) continue; + + var data = {}; + + // Call dispose handlers + var disposeHandlers = module.hot._disposeHandlers; + for (j = 0; j < disposeHandlers.length; j++) { + cb = disposeHandlers[j]; + cb(data); + } + hotCurrentModuleData[moduleId] = data; + + // disable module (this disables requires from this module) + module.hot.active = false; + + // remove module from cache + delete installedModules[moduleId]; + + // when disposing there is no need to call dispose handler + delete outdatedDependencies[moduleId]; + + // remove "parents" references from all children + for (j = 0; j < module.children.length; j++) { + var child = installedModules[module.children[j]]; + if (!child) continue; + idx = child.parents.indexOf(moduleId); + if (idx >= 0) { + child.parents.splice(idx, 1); + } + } + } + + // remove outdated dependency from module children + var dependency; + var moduleOutdatedDependencies; + for (moduleId in outdatedDependencies) { + if ( + Object.prototype.hasOwnProperty.call(outdatedDependencies, moduleId) + ) { + module = installedModules[moduleId]; + if (module) { + moduleOutdatedDependencies = outdatedDependencies[moduleId]; + for (j = 0; j < moduleOutdatedDependencies.length; j++) { + dependency = moduleOutdatedDependencies[j]; + idx = module.children.indexOf(dependency); + if (idx >= 0) module.children.splice(idx, 1); + } + } + } + } + + // Not in "apply" phase + hotSetStatus("apply"); + + hotCurrentHash = hotUpdateNewHash; + + // insert new code + for (moduleId in appliedUpdate) { + if (Object.prototype.hasOwnProperty.call(appliedUpdate, moduleId)) { + modules[moduleId] = appliedUpdate[moduleId]; + } + } + + // call accept handlers + var error = null; + for (moduleId in outdatedDependencies) { + if ( + Object.prototype.hasOwnProperty.call(outdatedDependencies, moduleId) + ) { + module = installedModules[moduleId]; + if (module) { + moduleOutdatedDependencies = outdatedDependencies[moduleId]; + var callbacks = []; + for (i = 0; i < moduleOutdatedDependencies.length; i++) { + dependency = moduleOutdatedDependencies[i]; + cb = module.hot._acceptedDependencies[dependency]; + if (cb) { + if (callbacks.indexOf(cb) !== -1) continue; + callbacks.push(cb); + } + } + for (i = 0; i < callbacks.length; i++) { + cb = callbacks[i]; + try { + cb(moduleOutdatedDependencies); + } catch (err) { + if (options.onErrored) { + options.onErrored({ + type: "accept-errored", + moduleId: moduleId, + dependencyId: moduleOutdatedDependencies[i], + error: err + }); + } + if (!options.ignoreErrored) { + if (!error) error = err; + } + } + } + } + } + } + + // Load self accepted modules + for (i = 0; i < outdatedSelfAcceptedModules.length; i++) { + var item = outdatedSelfAcceptedModules[i]; + moduleId = item.module; + hotCurrentParents = [moduleId]; + try { + $require$(moduleId); + } catch (err) { + if (typeof item.errorHandler === "function") { + try { + item.errorHandler(err); + } catch (err2) { + if (options.onErrored) { + options.onErrored({ + type: "self-accept-error-handler-errored", + moduleId: moduleId, + error: err2, + originalError: err + }); + } + if (!options.ignoreErrored) { + if (!error) error = err2; + } + if (!error) error = err; + } + } else { + if (options.onErrored) { + options.onErrored({ + type: "self-accept-errored", + moduleId: moduleId, + error: err + }); + } + if (!options.ignoreErrored) { + if (!error) error = err; + } + } + } + } + + // handle errors in accept handlers and self accepted module load + if (error) { + hotSetStatus("fail"); + return Promise.reject(error); + } + + hotSetStatus("idle"); + return new Promise(function(resolve) { + resolve(outdatedModules); + }); + } +}; diff --git a/node_modules/webpack/lib/HotModuleReplacementPlugin.js b/node_modules/webpack/lib/HotModuleReplacementPlugin.js index f3cc63b94..365a2443a 100644 --- a/node_modules/webpack/lib/HotModuleReplacementPlugin.js +++ b/node_modules/webpack/lib/HotModuleReplacementPlugin.js @@ -1,251 +1,407 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const Template = require("./Template"); -const ModuleHotAcceptDependency = require("./dependencies/ModuleHotAcceptDependency"); -const ModuleHotDeclineDependency = require("./dependencies/ModuleHotDeclineDependency"); -const RawSource = require("webpack-sources").RawSource; -const ConstDependency = require("./dependencies/ConstDependency"); -const NullFactory = require("./NullFactory"); -const ParserHelpers = require("./ParserHelpers"); - -module.exports = class HotModuleReplacementPlugin { - constructor(options) { - this.options = options || {}; - this.multiStep = this.options.multiStep; - this.fullBuildTimeout = this.options.fullBuildTimeout || 200; - this.requestTimeout = this.options.requestTimeout || 10000; - } - - apply(compiler) { - const multiStep = this.multiStep; - const fullBuildTimeout = this.fullBuildTimeout; - const requestTimeout = this.requestTimeout; - const hotUpdateChunkFilename = compiler.options.output.hotUpdateChunkFilename; - const hotUpdateMainFilename = compiler.options.output.hotUpdateMainFilename; - compiler.plugin("additional-pass", callback => { - if(multiStep) - return setTimeout(callback, fullBuildTimeout); - return callback(); - }); - compiler.plugin("compilation", (compilation, params) => { - const hotUpdateChunkTemplate = compilation.hotUpdateChunkTemplate; - if(!hotUpdateChunkTemplate) return; - - const normalModuleFactory = params.normalModuleFactory; - - compilation.dependencyFactories.set(ConstDependency, new NullFactory()); - compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template()); - - compilation.dependencyFactories.set(ModuleHotAcceptDependency, normalModuleFactory); - compilation.dependencyTemplates.set(ModuleHotAcceptDependency, new ModuleHotAcceptDependency.Template()); - - compilation.dependencyFactories.set(ModuleHotDeclineDependency, normalModuleFactory); - compilation.dependencyTemplates.set(ModuleHotDeclineDependency, new ModuleHotDeclineDependency.Template()); - - compilation.plugin("record", function(compilation, records) { - if(records.hash === this.hash) return; - records.hash = compilation.hash; - records.moduleHashs = {}; - this.modules.forEach(module => { - const identifier = module.identifier(); - const hash = require("crypto").createHash("md5"); - module.updateHash(hash); - records.moduleHashs[identifier] = hash.digest("hex"); - }); - records.chunkHashs = {}; - this.chunks.forEach(chunk => { - records.chunkHashs[chunk.id] = chunk.hash; - }); - records.chunkModuleIds = {}; - this.chunks.forEach(chunk => { - records.chunkModuleIds[chunk.id] = chunk.mapModules(m => m.id); - }); - }); - let initialPass = false; - let recompilation = false; - compilation.plugin("after-hash", function() { - let records = this.records; - if(!records) { - initialPass = true; - return; - } - if(!records.hash) - initialPass = true; - const preHash = records.preHash || "x"; - const prepreHash = records.prepreHash || "x"; - if(preHash === this.hash) { - recompilation = true; - this.modifyHash(prepreHash); - return; - } - records.prepreHash = records.hash || "x"; - records.preHash = this.hash; - this.modifyHash(records.prepreHash); - }); - compilation.plugin("should-generate-chunk-assets", () => { - if(multiStep && !recompilation && !initialPass) - return false; - }); - compilation.plugin("need-additional-pass", () => { - if(multiStep && !recompilation && !initialPass) - return true; - }); - compilation.plugin("additional-chunk-assets", function() { - const records = this.records; - if(records.hash === this.hash) return; - if(!records.moduleHashs || !records.chunkHashs || !records.chunkModuleIds) return; - this.modules.forEach(module => { - const identifier = module.identifier(); - let hash = require("crypto").createHash("md5"); - module.updateHash(hash); - hash = hash.digest("hex"); - module.hotUpdate = records.moduleHashs[identifier] !== hash; - }); - const hotUpdateMainContent = { - h: this.hash, - c: {}, - }; - Object.keys(records.chunkHashs).forEach(function(chunkId) { - chunkId = isNaN(+chunkId) ? chunkId : +chunkId; - const currentChunk = this.chunks.find(chunk => chunk.id === chunkId); - if(currentChunk) { - const newModules = currentChunk.getModules().filter(module => module.hotUpdate); - const allModules = {}; - currentChunk.forEachModule(module => { - allModules[module.id] = true; - }); - const removedModules = records.chunkModuleIds[chunkId].filter(id => !allModules[id]); - if(newModules.length > 0 || removedModules.length > 0) { - const source = hotUpdateChunkTemplate.render(chunkId, newModules, removedModules, this.hash, this.moduleTemplate, this.dependencyTemplates); - const filename = this.getPath(hotUpdateChunkFilename, { - hash: records.hash, - chunk: currentChunk - }); - this.additionalChunkAssets.push(filename); - this.assets[filename] = source; - hotUpdateMainContent.c[chunkId] = true; - currentChunk.files.push(filename); - this.applyPlugins("chunk-asset", currentChunk, filename); - } - } else { - hotUpdateMainContent.c[chunkId] = false; - } - }, this); - const source = new RawSource(JSON.stringify(hotUpdateMainContent)); - const filename = this.getPath(hotUpdateMainFilename, { - hash: records.hash - }); - this.assets[filename] = source; - }); - - compilation.mainTemplate.plugin("hash", hash => { - hash.update("HotMainTemplateDecorator"); - }); - - compilation.mainTemplate.plugin("module-require", (_, chunk, hash, varModuleId) => { - return `hotCreateRequire(${varModuleId})`; - }); - - compilation.mainTemplate.plugin("require-extensions", function(source) { - const buf = [source]; - buf.push(""); - buf.push("// __webpack_hash__"); - buf.push(this.requireFn + ".h = function() { return hotCurrentHash; };"); - return this.asString(buf); - }); - - compilation.mainTemplate.plugin("bootstrap", function(source, chunk, hash) { - source = this.applyPluginsWaterfall("hot-bootstrap", source, chunk, hash); - return this.asString([ - source, - "", - hotInitCode - .replace(/\$require\$/g, this.requireFn) - .replace(/\$hash\$/g, JSON.stringify(hash)) - .replace(/\$requestTimeout\$/g, requestTimeout) - .replace(/\/\*foreachInstalledChunks\*\//g, chunk.chunks.length > 0 ? "for(var chunkId in installedChunks)" : `var chunkId = ${JSON.stringify(chunk.id)};`) - ]); - }); - - compilation.mainTemplate.plugin("global-hash", () => true); - - compilation.mainTemplate.plugin("current-hash", (_, length) => { - if(isFinite(length)) - return `hotCurrentHash.substr(0, ${length})`; - else - return "hotCurrentHash"; - }); - - compilation.mainTemplate.plugin("module-obj", function(source, chunk, hash, varModuleId) { - return this.asString([ - `${source},`, - `hot: hotCreateModule(${varModuleId}),`, - "parents: (hotCurrentParentsTemp = hotCurrentParents, hotCurrentParents = [], hotCurrentParentsTemp),", - "children: []" - ]); - }); - - params.normalModuleFactory.plugin("parser", (parser, parserOptions) => { - parser.plugin("expression __webpack_hash__", ParserHelpers.toConstantDependency("__webpack_require__.h()")); - parser.plugin("evaluate typeof __webpack_hash__", ParserHelpers.evaluateToString("string")); - parser.plugin("evaluate Identifier module.hot", function(expr) { - return ParserHelpers.evaluateToIdentifier("module.hot", !!this.state.compilation.hotUpdateChunkTemplate)(expr); - }); - parser.plugin("call module.hot.accept", function(expr) { - if(!this.state.compilation.hotUpdateChunkTemplate) return false; - if(expr.arguments.length >= 1) { - const arg = this.evaluateExpression(expr.arguments[0]); - let params = []; - let requests = []; - if(arg.isString()) { - params = [arg]; - } else if(arg.isArray()) { - params = arg.items.filter(param => param.isString()); - } - if(params.length > 0) { - params.forEach((param, idx) => { - const request = param.string; - const dep = new ModuleHotAcceptDependency(request, param.range); - dep.optional = true; - dep.loc = Object.create(expr.loc); - dep.loc.index = idx; - this.state.module.addDependency(dep); - requests.push(request); - }); - if(expr.arguments.length > 1) - this.applyPluginsBailResult("hot accept callback", expr.arguments[1], requests); - else - this.applyPluginsBailResult("hot accept without callback", expr, requests); - } - } - }); - parser.plugin("call module.hot.decline", function(expr) { - if(!this.state.compilation.hotUpdateChunkTemplate) return false; - if(expr.arguments.length === 1) { - const arg = this.evaluateExpression(expr.arguments[0]); - let params = []; - if(arg.isString()) { - params = [arg]; - } else if(arg.isArray()) { - params = arg.items.filter(param => param.isString()); - } - params.forEach((param, idx) => { - const dep = new ModuleHotDeclineDependency(param.string, param.range); - dep.optional = true; - dep.loc = Object.create(expr.loc); - dep.loc.index = idx; - this.state.module.addDependency(dep); - }); - } - }); - parser.plugin("expression module.hot", ParserHelpers.skipTraversal); - }); - }); - } - -}; - -const hotInitCode = Template.getFunctionContent(require("./HotModuleReplacement.runtime.js")); +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const { SyncBailHook } = require("tapable"); +const { RawSource } = require("webpack-sources"); +const Template = require("./Template"); +const ModuleHotAcceptDependency = require("./dependencies/ModuleHotAcceptDependency"); +const ModuleHotDeclineDependency = require("./dependencies/ModuleHotDeclineDependency"); +const ConstDependency = require("./dependencies/ConstDependency"); +const NullFactory = require("./NullFactory"); +const ParserHelpers = require("./ParserHelpers"); + +module.exports = class HotModuleReplacementPlugin { + constructor(options) { + this.options = options || {}; + this.multiStep = this.options.multiStep; + this.fullBuildTimeout = this.options.fullBuildTimeout || 200; + this.requestTimeout = this.options.requestTimeout || 10000; + } + + apply(compiler) { + const multiStep = this.multiStep; + const fullBuildTimeout = this.fullBuildTimeout; + const requestTimeout = this.requestTimeout; + const hotUpdateChunkFilename = + compiler.options.output.hotUpdateChunkFilename; + const hotUpdateMainFilename = compiler.options.output.hotUpdateMainFilename; + compiler.hooks.additionalPass.tapAsync( + "HotModuleReplacementPlugin", + callback => { + if (multiStep) return setTimeout(callback, fullBuildTimeout); + return callback(); + } + ); + + const addParserPlugins = (parser, parserOptions) => { + parser.hooks.expression + .for("__webpack_hash__") + .tap( + "HotModuleReplacementPlugin", + ParserHelpers.toConstantDependencyWithWebpackRequire( + parser, + "__webpack_require__.h()" + ) + ); + parser.hooks.evaluateTypeof + .for("__webpack_hash__") + .tap( + "HotModuleReplacementPlugin", + ParserHelpers.evaluateToString("string") + ); + parser.hooks.evaluateIdentifier.for("module.hot").tap( + { + name: "HotModuleReplacementPlugin", + before: "NodeStuffPlugin" + }, + expr => { + return ParserHelpers.evaluateToIdentifier( + "module.hot", + !!parser.state.compilation.hotUpdateChunkTemplate + )(expr); + } + ); + // TODO webpack 5: refactor this, no custom hooks + if (!parser.hooks.hotAcceptCallback) { + parser.hooks.hotAcceptCallback = new SyncBailHook([ + "expression", + "requests" + ]); + } + if (!parser.hooks.hotAcceptWithoutCallback) { + parser.hooks.hotAcceptWithoutCallback = new SyncBailHook([ + "expression", + "requests" + ]); + } + parser.hooks.call + .for("module.hot.accept") + .tap("HotModuleReplacementPlugin", expr => { + if (!parser.state.compilation.hotUpdateChunkTemplate) { + return false; + } + if (expr.arguments.length >= 1) { + const arg = parser.evaluateExpression(expr.arguments[0]); + let params = []; + let requests = []; + if (arg.isString()) { + params = [arg]; + } else if (arg.isArray()) { + params = arg.items.filter(param => param.isString()); + } + if (params.length > 0) { + params.forEach((param, idx) => { + const request = param.string; + const dep = new ModuleHotAcceptDependency(request, param.range); + dep.optional = true; + dep.loc = Object.create(expr.loc); + dep.loc.index = idx; + parser.state.module.addDependency(dep); + requests.push(request); + }); + if (expr.arguments.length > 1) { + parser.hooks.hotAcceptCallback.call( + expr.arguments[1], + requests + ); + parser.walkExpression(expr.arguments[1]); // other args are ignored + return true; + } else { + parser.hooks.hotAcceptWithoutCallback.call(expr, requests); + return true; + } + } + } + }); + parser.hooks.call + .for("module.hot.decline") + .tap("HotModuleReplacementPlugin", expr => { + if (!parser.state.compilation.hotUpdateChunkTemplate) { + return false; + } + if (expr.arguments.length === 1) { + const arg = parser.evaluateExpression(expr.arguments[0]); + let params = []; + if (arg.isString()) { + params = [arg]; + } else if (arg.isArray()) { + params = arg.items.filter(param => param.isString()); + } + params.forEach((param, idx) => { + const dep = new ModuleHotDeclineDependency( + param.string, + param.range + ); + dep.optional = true; + dep.loc = Object.create(expr.loc); + dep.loc.index = idx; + parser.state.module.addDependency(dep); + }); + } + }); + parser.hooks.expression + .for("module.hot") + .tap("HotModuleReplacementPlugin", ParserHelpers.skipTraversal); + }; + + compiler.hooks.compilation.tap( + "HotModuleReplacementPlugin", + (compilation, { normalModuleFactory }) => { + const hotUpdateChunkTemplate = compilation.hotUpdateChunkTemplate; + if (!hotUpdateChunkTemplate) return; + + compilation.dependencyFactories.set(ConstDependency, new NullFactory()); + compilation.dependencyTemplates.set( + ConstDependency, + new ConstDependency.Template() + ); + + compilation.dependencyFactories.set( + ModuleHotAcceptDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + ModuleHotAcceptDependency, + new ModuleHotAcceptDependency.Template() + ); + + compilation.dependencyFactories.set( + ModuleHotDeclineDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + ModuleHotDeclineDependency, + new ModuleHotDeclineDependency.Template() + ); + + compilation.hooks.record.tap( + "HotModuleReplacementPlugin", + (compilation, records) => { + if (records.hash === compilation.hash) return; + records.hash = compilation.hash; + records.moduleHashs = {}; + for (const module of compilation.modules) { + const identifier = module.identifier(); + records.moduleHashs[identifier] = module.hash; + } + records.chunkHashs = {}; + for (const chunk of compilation.chunks) { + records.chunkHashs[chunk.id] = chunk.hash; + } + records.chunkModuleIds = {}; + for (const chunk of compilation.chunks) { + records.chunkModuleIds[chunk.id] = Array.from( + chunk.modulesIterable, + m => m.id + ); + } + } + ); + let initialPass = false; + let recompilation = false; + compilation.hooks.afterHash.tap("HotModuleReplacementPlugin", () => { + let records = compilation.records; + if (!records) { + initialPass = true; + return; + } + if (!records.hash) initialPass = true; + const preHash = records.preHash || "x"; + const prepreHash = records.prepreHash || "x"; + if (preHash === compilation.hash) { + recompilation = true; + compilation.modifyHash(prepreHash); + return; + } + records.prepreHash = records.hash || "x"; + records.preHash = compilation.hash; + compilation.modifyHash(records.prepreHash); + }); + compilation.hooks.shouldGenerateChunkAssets.tap( + "HotModuleReplacementPlugin", + () => { + if (multiStep && !recompilation && !initialPass) return false; + } + ); + compilation.hooks.needAdditionalPass.tap( + "HotModuleReplacementPlugin", + () => { + if (multiStep && !recompilation && !initialPass) return true; + } + ); + compilation.hooks.additionalChunkAssets.tap( + "HotModuleReplacementPlugin", + () => { + const records = compilation.records; + if (records.hash === compilation.hash) return; + if ( + !records.moduleHashs || + !records.chunkHashs || + !records.chunkModuleIds + ) + return; + for (const module of compilation.modules) { + const identifier = module.identifier(); + let hash = module.hash; + module.hotUpdate = records.moduleHashs[identifier] !== hash; + } + const hotUpdateMainContent = { + h: compilation.hash, + c: {} + }; + for (const key of Object.keys(records.chunkHashs)) { + const chunkId = isNaN(+key) ? key : +key; + const currentChunk = compilation.chunks.find( + chunk => chunk.id === chunkId + ); + if (currentChunk) { + const newModules = currentChunk + .getModules() + .filter(module => module.hotUpdate); + const allModules = new Set(); + for (const module of currentChunk.modulesIterable) { + allModules.add(module.id); + } + const removedModules = records.chunkModuleIds[chunkId].filter( + id => !allModules.has(id) + ); + if (newModules.length > 0 || removedModules.length > 0) { + const source = hotUpdateChunkTemplate.render( + chunkId, + newModules, + removedModules, + compilation.hash, + compilation.moduleTemplates.javascript, + compilation.dependencyTemplates + ); + const filename = compilation.getPath(hotUpdateChunkFilename, { + hash: records.hash, + chunk: currentChunk + }); + compilation.additionalChunkAssets.push(filename); + compilation.assets[filename] = source; + hotUpdateMainContent.c[chunkId] = true; + currentChunk.files.push(filename); + compilation.hooks.chunkAsset.call(currentChunk, filename); + } + } else { + hotUpdateMainContent.c[chunkId] = false; + } + } + const source = new RawSource(JSON.stringify(hotUpdateMainContent)); + const filename = compilation.getPath(hotUpdateMainFilename, { + hash: records.hash + }); + compilation.assets[filename] = source; + } + ); + + const mainTemplate = compilation.mainTemplate; + + mainTemplate.hooks.hash.tap("HotModuleReplacementPlugin", hash => { + hash.update("HotMainTemplateDecorator"); + }); + + mainTemplate.hooks.moduleRequire.tap( + "HotModuleReplacementPlugin", + (_, chunk, hash, varModuleId) => { + return `hotCreateRequire(${varModuleId})`; + } + ); + + mainTemplate.hooks.requireExtensions.tap( + "HotModuleReplacementPlugin", + source => { + const buf = [source]; + buf.push(""); + buf.push("// __webpack_hash__"); + buf.push( + mainTemplate.requireFn + + ".h = function() { return hotCurrentHash; };" + ); + return Template.asString(buf); + } + ); + + const needChunkLoadingCode = chunk => { + for (const chunkGroup of chunk.groupsIterable) { + if (chunkGroup.chunks.length > 1) return true; + if (chunkGroup.getNumberOfChildren() > 0) return true; + } + return false; + }; + + mainTemplate.hooks.bootstrap.tap( + "HotModuleReplacementPlugin", + (source, chunk, hash) => { + source = mainTemplate.hooks.hotBootstrap.call(source, chunk, hash); + return Template.asString([ + source, + "", + hotInitCode + .replace(/\$require\$/g, mainTemplate.requireFn) + .replace(/\$hash\$/g, JSON.stringify(hash)) + .replace(/\$requestTimeout\$/g, requestTimeout) + .replace( + /\/\*foreachInstalledChunks\*\//g, + needChunkLoadingCode(chunk) + ? "for(var chunkId in installedChunks)" + : `var chunkId = ${JSON.stringify(chunk.id)};` + ) + ]); + } + ); + + mainTemplate.hooks.globalHash.tap( + "HotModuleReplacementPlugin", + () => true + ); + + mainTemplate.hooks.currentHash.tap( + "HotModuleReplacementPlugin", + (_, length) => { + if (isFinite(length)) { + return `hotCurrentHash.substr(0, ${length})`; + } else { + return "hotCurrentHash"; + } + } + ); + + mainTemplate.hooks.moduleObj.tap( + "HotModuleReplacementPlugin", + (source, chunk, hash, varModuleId) => { + return Template.asString([ + `${source},`, + `hot: hotCreateModule(${varModuleId}),`, + "parents: (hotCurrentParentsTemp = hotCurrentParents, hotCurrentParents = [], hotCurrentParentsTemp),", + "children: []" + ]); + } + ); + + // TODO add HMR support for javascript/esm + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("HotModuleReplacementPlugin", addParserPlugins); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("HotModuleReplacementPlugin", addParserPlugins); + + compilation.hooks.normalModuleLoader.tap( + "HotModuleReplacementPlugin", + context => { + context.hot = true; + } + ); + } + ); + } +}; + +const hotInitCode = Template.getFunctionContent( + require("./HotModuleReplacement.runtime") +); diff --git a/node_modules/webpack/lib/HotUpdateChunkTemplate.js b/node_modules/webpack/lib/HotUpdateChunkTemplate.js index 0a83c9a85..92ab8db08 100644 --- a/node_modules/webpack/lib/HotUpdateChunkTemplate.js +++ b/node_modules/webpack/lib/HotUpdateChunkTemplate.js @@ -1,31 +1,78 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const Template = require("./Template"); -const Chunk = require("./Chunk"); - -module.exports = class HotUpdateChunkTemplate extends Template { - constructor(outputOptions) { - super(outputOptions); - } - - render(id, modules, removedModules, hash, moduleTemplate, dependencyTemplates) { - const hotUpdateChunk = new Chunk(); - hotUpdateChunk.id = id; - hotUpdateChunk.setModules(modules); - hotUpdateChunk.removedModules = removedModules; - const modulesSource = this.renderChunkModules(hotUpdateChunk, moduleTemplate, dependencyTemplates); - const core = this.applyPluginsWaterfall("modules", modulesSource, modules, removedModules, moduleTemplate, dependencyTemplates); - const source = this.applyPluginsWaterfall("render", core, modules, removedModules, hash, id, moduleTemplate, dependencyTemplates); - return source; - } - - updateHash(hash) { - hash.update("HotUpdateChunkTemplate"); - hash.update("1"); - this.applyPlugins("hash", hash); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const Template = require("./Template"); +const HotUpdateChunk = require("./HotUpdateChunk"); +const { Tapable, SyncWaterfallHook, SyncHook } = require("tapable"); + +module.exports = class HotUpdateChunkTemplate extends Tapable { + constructor(outputOptions) { + super(); + this.outputOptions = outputOptions || {}; + this.hooks = { + modules: new SyncWaterfallHook([ + "source", + "modules", + "removedModules", + "moduleTemplate", + "dependencyTemplates" + ]), + render: new SyncWaterfallHook([ + "source", + "modules", + "removedModules", + "hash", + "id", + "moduleTemplate", + "dependencyTemplates" + ]), + hash: new SyncHook(["hash"]) + }; + } + + render( + id, + modules, + removedModules, + hash, + moduleTemplate, + dependencyTemplates + ) { + const hotUpdateChunk = new HotUpdateChunk(); + hotUpdateChunk.id = id; + hotUpdateChunk.setModules(modules); + hotUpdateChunk.removedModules = removedModules; + const modulesSource = Template.renderChunkModules( + hotUpdateChunk, + m => typeof m.source === "function", + moduleTemplate, + dependencyTemplates + ); + const core = this.hooks.modules.call( + modulesSource, + modules, + removedModules, + moduleTemplate, + dependencyTemplates + ); + const source = this.hooks.render.call( + core, + modules, + removedModules, + hash, + id, + moduleTemplate, + dependencyTemplates + ); + return source; + } + + updateHash(hash) { + hash.update("HotUpdateChunkTemplate"); + hash.update("1"); + this.hooks.hash.call(hash); + } +}; diff --git a/node_modules/webpack/lib/IgnorePlugin.js b/node_modules/webpack/lib/IgnorePlugin.js index d8f2db018..6e803e8ff 100644 --- a/node_modules/webpack/lib/IgnorePlugin.js +++ b/node_modules/webpack/lib/IgnorePlugin.js @@ -1,69 +1,109 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class IgnorePlugin { - constructor(resourceRegExp, contextRegExp) { - this.resourceRegExp = resourceRegExp; - this.contextRegExp = contextRegExp; - - this.checkIgnore = this.checkIgnore.bind(this); - } - - /* - * Only returns true if a "resourceRegExp" exists - * and the resource given matches the regexp. - */ - checkResource(resource) { - if(!this.resourceRegExp) { - return false; - } - return this.resourceRegExp.test(resource); - } - - /* - * Returns true if contextRegExp does not exist - * or if context matches the given regexp. - */ - checkContext(context) { - if(!this.contextRegExp) { - return true; - } - return this.contextRegExp.test(context); - } - - /* - * Returns true if result should be ignored. - * false if it shouldn't. - * - * Not that if "contextRegExp" is given, both the "resourceRegExp" - * and "contextRegExp" have to match. - */ - checkResult(result) { - if(!result) { - return true; - } - return this.checkResource(result.request) && this.checkContext(result.context); - } - - checkIgnore(result, callback) { - // check if result is ignored - if(this.checkResult(result)) { - return callback(); - } - return callback(null, result); - } - - apply(compiler) { - compiler.plugin("normal-module-factory", (nmf) => { - nmf.plugin("before-resolve", this.checkIgnore); - }); - compiler.plugin("context-module-factory", (cmf) => { - cmf.plugin("before-resolve", this.checkIgnore); - }); - } -} - -module.exports = IgnorePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const validateOptions = require("schema-utils"); +const schema = require("../schemas/plugins/IgnorePlugin.json"); + +/** @typedef {import("./Compiler")} Compiler */ + +class IgnorePlugin { + /** + * @param {object} options IgnorePlugin options + * @param {RegExp} options.resourceRegExp - A RegExp to test the request against + * @param {RegExp} options.contextRegExp - A RegExp to test the context (directory) against + * @param {function(string): boolean=} options.checkResource - A filter function for resource + * @param {function(string): boolean=} options.checkContext - A filter function for context + */ + constructor(options) { + // TODO webpack 5 remove this compat-layer + if (arguments.length > 1 || options instanceof RegExp) { + options = { + resourceRegExp: arguments[0], + contextRegExp: arguments[1] + }; + } + + validateOptions(schema, options, "IgnorePlugin"); + this.options = options; + + /** @private @type {Function} */ + this.checkIgnore = this.checkIgnore.bind(this); + } + + /** + * @param {string} resource resource + * @returns {boolean} returns true if a "resourceRegExp" exists + * and the resource given matches the regexp. + */ + checkResource(resource) { + if (this.options.checkResource) { + return this.options.checkResource(resource); + } + if (!this.options.resourceRegExp) { + return false; + } + return this.options.resourceRegExp.test(resource); + } + + /** + * @param {string} context context + * @returns {boolean} returns true if "contextRegExp" does not exist + * or if context matches the given regexp. + */ + checkContext(context) { + if (this.options.checkContext) { + return this.options.checkContext(context); + } + + if (!this.options.contextRegExp) { + return true; + } + return this.options.contextRegExp.test(context); + } + + /** + * Note that if "contextRegExp" is given, both the "resourceRegExp" + * and "contextRegExp" have to match. + * + * @param {TODO} result result + * @returns {boolean} returns true if result should be ignored + */ + checkResult(result) { + if (!result) { + return true; + } + return ( + this.checkResource(result.request) && this.checkContext(result.context) + ); + } + + /** + * @param {TODO} result result + * @returns {TODO|null} returns result or null if result should be ignored + */ + checkIgnore(result) { + // check if result is ignored + if (this.checkResult(result)) { + return null; + } + return result; + } + + /** + * @param {Compiler} compiler Webpack Compiler + * @returns {void} + */ + apply(compiler) { + compiler.hooks.normalModuleFactory.tap("IgnorePlugin", nmf => { + nmf.hooks.beforeResolve.tap("IgnorePlugin", this.checkIgnore); + }); + compiler.hooks.contextModuleFactory.tap("IgnorePlugin", cmf => { + cmf.hooks.beforeResolve.tap("IgnorePlugin", this.checkIgnore); + }); + } +} + +module.exports = IgnorePlugin; diff --git a/node_modules/webpack/lib/JsonpChunkTemplatePlugin.js b/node_modules/webpack/lib/JsonpChunkTemplatePlugin.js deleted file mode 100644 index ceeb95406..000000000 --- a/node_modules/webpack/lib/JsonpChunkTemplatePlugin.js +++ /dev/null @@ -1,31 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ConcatSource = require("webpack-sources").ConcatSource; - -class JsonpChunkTemplatePlugin { - apply(chunkTemplate) { - chunkTemplate.plugin("render", function(modules, chunk) { - const jsonpFunction = this.outputOptions.jsonpFunction; - const source = new ConcatSource(); - source.add(`${jsonpFunction}(${JSON.stringify(chunk.ids)},`); - source.add(modules); - const entries = [chunk.entryModule].filter(Boolean).map(m => m.id); - if(entries.length > 0) { - source.add(`,${JSON.stringify(entries)}`); - } - source.add(")"); - return source; - }); - chunkTemplate.plugin("hash", function(hash) { - hash.update("JsonpChunkTemplatePlugin"); - hash.update("3"); - hash.update(`${this.outputOptions.jsonpFunction}`); - hash.update(`${this.outputOptions.library}`); - }); - } -} -module.exports = JsonpChunkTemplatePlugin; diff --git a/node_modules/webpack/lib/JsonpExportMainTemplatePlugin.js b/node_modules/webpack/lib/JsonpExportMainTemplatePlugin.js deleted file mode 100644 index 8bbab2e04..000000000 --- a/node_modules/webpack/lib/JsonpExportMainTemplatePlugin.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ConcatSource = require("webpack-sources").ConcatSource; - -class JsonpExportMainTemplatePlugin { - constructor(name) { - this.name = name; - } - - apply(compilation) { - const mainTemplate = compilation.mainTemplate; - - compilation.templatesPlugin("render-with-entry", (source, chunk, hash) => { - const name = mainTemplate.applyPluginsWaterfall("asset-path", this.name || "", { - hash: hash, - chunk: chunk - }); - return new ConcatSource(`${name}(`, source, ");"); - }); - - mainTemplate.plugin("global-hash-paths", paths => { - if(this.name) paths.push(this.name); - return paths; - }); - - mainTemplate.plugin("hash", hash => { - hash.update("jsonp export"); - hash.update(`${this.name}`); - }); - } -} - -module.exports = JsonpExportMainTemplatePlugin; diff --git a/node_modules/webpack/lib/JsonpHotUpdateChunkTemplatePlugin.js b/node_modules/webpack/lib/JsonpHotUpdateChunkTemplatePlugin.js deleted file mode 100644 index 407110e93..000000000 --- a/node_modules/webpack/lib/JsonpHotUpdateChunkTemplatePlugin.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ConcatSource = require("webpack-sources").ConcatSource; - -class JsonpHotUpdateChunkTemplatePlugin { - apply(hotUpdateChunkTemplate) { - hotUpdateChunkTemplate.plugin("render", function(modulesSource, modules, removedModules, hash, id) { - const source = new ConcatSource(); - source.add(`${this.outputOptions.hotUpdateFunction}(${JSON.stringify(id)},`); - source.add(modulesSource); - source.add(")"); - return source; - }); - hotUpdateChunkTemplate.plugin("hash", function(hash) { - hash.update("JsonpHotUpdateChunkTemplatePlugin"); - hash.update("3"); - hash.update(`${this.outputOptions.hotUpdateFunction}`); - hash.update(`${this.outputOptions.library}`); - }); - } -} - -module.exports = JsonpHotUpdateChunkTemplatePlugin; diff --git a/node_modules/webpack/lib/JsonpMainTemplate.runtime.js b/node_modules/webpack/lib/JsonpMainTemplate.runtime.js deleted file mode 100644 index ed5fba098..000000000 --- a/node_modules/webpack/lib/JsonpMainTemplate.runtime.js +++ /dev/null @@ -1,60 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -/*globals hotAddUpdateChunk parentHotUpdateCallback document XMLHttpRequest $require$ $hotChunkFilename$ $hotMainFilename$ $crossOriginLoading$ */ -module.exports = function() { - function webpackHotUpdateCallback(chunkId, moreModules) { // eslint-disable-line no-unused-vars - hotAddUpdateChunk(chunkId, moreModules); - if(parentHotUpdateCallback) parentHotUpdateCallback(chunkId, moreModules); - } //$semicolon - - function hotDownloadUpdateChunk(chunkId) { // eslint-disable-line no-unused-vars - var head = document.getElementsByTagName("head")[0]; - var script = document.createElement("script"); - script.type = "text/javascript"; - script.charset = "utf-8"; - script.src = $require$.p + $hotChunkFilename$; - $crossOriginLoading$; - head.appendChild(script); - } - - function hotDownloadManifest(requestTimeout) { // eslint-disable-line no-unused-vars - requestTimeout = requestTimeout || 10000; - return new Promise(function(resolve, reject) { - if(typeof XMLHttpRequest === "undefined") - return reject(new Error("No browser support")); - try { - var request = new XMLHttpRequest(); - var requestPath = $require$.p + $hotMainFilename$; - request.open("GET", requestPath, true); - request.timeout = requestTimeout; - request.send(null); - } catch(err) { - return reject(err); - } - request.onreadystatechange = function() { - if(request.readyState !== 4) return; - if(request.status === 0) { - // timeout - reject(new Error("Manifest request to " + requestPath + " timed out.")); - } else if(request.status === 404) { - // no update available - resolve(); - } else if(request.status !== 200 && request.status !== 304) { - // other failure - reject(new Error("Manifest request to " + requestPath + " failed.")); - } else { - // success - try { - var update = JSON.parse(request.responseText); - } catch(e) { - reject(e); - return; - } - resolve(update); - } - }; - }); - } -}; diff --git a/node_modules/webpack/lib/JsonpMainTemplatePlugin.js b/node_modules/webpack/lib/JsonpMainTemplatePlugin.js deleted file mode 100644 index e713f3879..000000000 --- a/node_modules/webpack/lib/JsonpMainTemplatePlugin.js +++ /dev/null @@ -1,211 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const Template = require("./Template"); - -class JsonpMainTemplatePlugin { - - apply(mainTemplate) { - mainTemplate.plugin("local-vars", function(source, chunk) { - if(chunk.chunks.length > 0) { - return this.asString([ - source, - "", - "// objects to store loaded and loading chunks", - "var installedChunks = {", - this.indent( - chunk.ids.map(id => `${JSON.stringify(id)}: 0`).join(",\n") - ), - "};" - ]); - } - return source; - }); - mainTemplate.plugin("jsonp-script", function(_, chunk, hash) { - const chunkFilename = this.outputOptions.chunkFilename; - const chunkMaps = chunk.getChunkMaps(); - const crossOriginLoading = this.outputOptions.crossOriginLoading; - const chunkLoadTimeout = this.outputOptions.chunkLoadTimeout; - const scriptSrcPath = this.applyPluginsWaterfall("asset-path", JSON.stringify(chunkFilename), { - hash: `" + ${this.renderCurrentHashCode(hash)} + "`, - hashWithLength: length => `" + ${this.renderCurrentHashCode(hash, length)} + "`, - chunk: { - id: "\" + chunkId + \"", - hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`, - hashWithLength(length) { - const shortChunkHashMap = Object.create(null); - Object.keys(chunkMaps.hash).forEach(chunkId => { - if(typeof chunkMaps.hash[chunkId] === "string") - shortChunkHashMap[chunkId] = chunkMaps.hash[chunkId].substr(0, length); - }); - return `" + ${JSON.stringify(shortChunkHashMap)}[chunkId] + "`; - }, - name: `" + (${JSON.stringify(chunkMaps.name)}[chunkId]||chunkId) + "` - } - }); - return this.asString([ - "var script = document.createElement('script');", - "script.type = 'text/javascript';", - "script.charset = 'utf-8';", - "script.async = true;", - `script.timeout = ${chunkLoadTimeout};`, - crossOriginLoading ? `script.crossOrigin = ${JSON.stringify(crossOriginLoading)};` : "", - `if (${this.requireFn}.nc) {`, - this.indent(`script.setAttribute("nonce", ${this.requireFn}.nc);`), - "}", - `script.src = ${this.requireFn}.p + ${scriptSrcPath};`, - `var timeout = setTimeout(onScriptComplete, ${chunkLoadTimeout});`, - "script.onerror = script.onload = onScriptComplete;", - "function onScriptComplete() {", - this.indent([ - "// avoid mem leaks in IE.", - "script.onerror = script.onload = null;", - "clearTimeout(timeout);", - "var chunk = installedChunks[chunkId];", - "if(chunk !== 0) {", - this.indent([ - "if(chunk) {", - this.indent("chunk[1](new Error('Loading chunk ' + chunkId + ' failed.'));"), - "}", - "installedChunks[chunkId] = undefined;" - ]), - "}" - ]), - "};", - ]); - }); - mainTemplate.plugin("require-ensure", function(_, chunk, hash) { - return this.asString([ - "var installedChunkData = installedChunks[chunkId];", - "if(installedChunkData === 0) {", - this.indent([ - "return new Promise(function(resolve) { resolve(); });" - ]), - "}", - "", - "// a Promise means \"currently loading\".", - "if(installedChunkData) {", - this.indent([ - "return installedChunkData[2];" - ]), - "}", - "", - "// setup Promise in chunk cache", - "var promise = new Promise(function(resolve, reject) {", - this.indent([ - "installedChunkData = installedChunks[chunkId] = [resolve, reject];" - ]), - "});", - "installedChunkData[2] = promise;", - "", - "// start chunk loading", - "var head = document.getElementsByTagName('head')[0];", - this.applyPluginsWaterfall("jsonp-script", "", chunk, hash), - "head.appendChild(script);", - "", - "return promise;" - ]); - }); - mainTemplate.plugin("require-extensions", function(source, chunk) { - if(chunk.chunks.length === 0) return source; - - return this.asString([ - source, - "", - "// on error function for async loading", - `${this.requireFn}.oe = function(err) { console.error(err); throw err; };` - ]); - }); - mainTemplate.plugin("bootstrap", function(source, chunk, hash) { - if(chunk.chunks.length > 0) { - var jsonpFunction = this.outputOptions.jsonpFunction; - return this.asString([ - source, - "", - "// install a JSONP callback for chunk loading", - `var parentJsonpFunction = window[${JSON.stringify(jsonpFunction)}];`, - `window[${JSON.stringify(jsonpFunction)}] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {`, - this.indent([ - "// add \"moreModules\" to the modules object,", - "// then flag all \"chunkIds\" as loaded and fire callback", - "var moduleId, chunkId, i = 0, resolves = [], result;", - "for(;i < chunkIds.length; i++) {", - this.indent([ - "chunkId = chunkIds[i];", - "if(installedChunks[chunkId]) {", - this.indent("resolves.push(installedChunks[chunkId][0]);"), - "}", - "installedChunks[chunkId] = 0;" - ]), - "}", - "for(moduleId in moreModules) {", - this.indent([ - "if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {", - this.indent(this.renderAddModule(hash, chunk, "moduleId", "moreModules[moduleId]")), - "}" - ]), - "}", - "if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);", - "while(resolves.length) {", - this.indent("resolves.shift()();"), - "}", - this.entryPointInChildren(chunk) ? [ - "if(executeModules) {", - this.indent([ - "for(i=0; i < executeModules.length; i++) {", - this.indent(`result = ${this.requireFn}(${this.requireFn}.s = executeModules[i]);`), - "}" - ]), - "}", - "return result;", - ] : "" - ]), - "};" - ]); - } - return source; - }); - mainTemplate.plugin("hot-bootstrap", function(source, chunk, hash) { - const hotUpdateChunkFilename = this.outputOptions.hotUpdateChunkFilename; - const hotUpdateMainFilename = this.outputOptions.hotUpdateMainFilename; - const crossOriginLoading = this.outputOptions.crossOriginLoading; - const hotUpdateFunction = this.outputOptions.hotUpdateFunction; - const currentHotUpdateChunkFilename = this.applyPluginsWaterfall("asset-path", JSON.stringify(hotUpdateChunkFilename), { - hash: `" + ${this.renderCurrentHashCode(hash)} + "`, - hashWithLength: length => `" + ${this.renderCurrentHashCode(hash, length)} + "`, - chunk: { - id: "\" + chunkId + \"" - } - }); - const currentHotUpdateMainFilename = this.applyPluginsWaterfall("asset-path", JSON.stringify(hotUpdateMainFilename), { - hash: `" + ${this.renderCurrentHashCode(hash)} + "`, - hashWithLength: length => `" + ${this.renderCurrentHashCode(hash, length)} + "` - }); - const runtimeSource = Template.getFunctionContent(require("./JsonpMainTemplate.runtime.js")) - .replace(/\/\/\$semicolon/g, ";") - .replace(/\$require\$/g, this.requireFn) - .replace(/\$crossOriginLoading\$/g, crossOriginLoading ? `script.crossOrigin = ${JSON.stringify(crossOriginLoading)}` : "") - .replace(/\$hotMainFilename\$/g, currentHotUpdateMainFilename) - .replace(/\$hotChunkFilename\$/g, currentHotUpdateChunkFilename) - .replace(/\$hash\$/g, JSON.stringify(hash)); - return `${source} -function hotDisposeChunk(chunkId) { - delete installedChunks[chunkId]; -} -var parentHotUpdateCallback = window[${JSON.stringify(hotUpdateFunction)}]; -window[${JSON.stringify(hotUpdateFunction)}] = ${runtimeSource}`; - }); - mainTemplate.plugin("hash", function(hash) { - hash.update("jsonp"); - hash.update("4"); - hash.update(`${this.outputOptions.filename}`); - hash.update(`${this.outputOptions.chunkFilename}`); - hash.update(`${this.outputOptions.jsonpFunction}`); - hash.update(`${this.outputOptions.hotUpdateFunction}`); - }); - } -} -module.exports = JsonpMainTemplatePlugin; diff --git a/node_modules/webpack/lib/JsonpTemplatePlugin.js b/node_modules/webpack/lib/JsonpTemplatePlugin.js deleted file mode 100644 index a141891f7..000000000 --- a/node_modules/webpack/lib/JsonpTemplatePlugin.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const JsonpMainTemplatePlugin = require("./JsonpMainTemplatePlugin"); -const JsonpChunkTemplatePlugin = require("./JsonpChunkTemplatePlugin"); -const JsonpHotUpdateChunkTemplatePlugin = require("./JsonpHotUpdateChunkTemplatePlugin"); - -class JsonpTemplatePlugin { - apply(compiler) { - compiler.plugin("this-compilation", (compilation) => { - compilation.mainTemplate.apply(new JsonpMainTemplatePlugin()); - compilation.chunkTemplate.apply(new JsonpChunkTemplatePlugin()); - compilation.hotUpdateChunkTemplate.apply(new JsonpHotUpdateChunkTemplatePlugin()); - }); - } -} - -module.exports = JsonpTemplatePlugin; diff --git a/node_modules/webpack/lib/LibManifestPlugin.js b/node_modules/webpack/lib/LibManifestPlugin.js index dc2f0ae14..54dbf10a0 100644 --- a/node_modules/webpack/lib/LibManifestPlugin.js +++ b/node_modules/webpack/lib/LibManifestPlugin.js @@ -1,63 +1,86 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const path = require("path"); -const asyncLib = require("async"); - -class LibManifestPlugin { - constructor(options) { - this.options = options; - } - - apply(compiler) { - compiler.plugin("emit", (compilation, callback) => { - asyncLib.forEach(compilation.chunks, (chunk, callback) => { - if(!chunk.isInitial()) { - callback(); - return; - } - const targetPath = compilation.getPath(this.options.path, { - hash: compilation.hash, - chunk - }); - const name = this.options.name && compilation.getPath(this.options.name, { - hash: compilation.hash, - chunk - }); - const manifest = { - name, - type: this.options.type, - content: chunk.mapModules(module => { - if(module.libIdent) { - const ident = module.libIdent({ - context: this.options.context || compiler.options.context - }); - if(ident) { - return { - ident, - data: { - id: module.id, - meta: module.meta, - exports: Array.isArray(module.providedExports) ? module.providedExports : undefined - } - }; - } - } - }).filter(Boolean).reduce((obj, item) => { - obj[item.ident] = item.data; - return obj; - }, Object.create(null)) - }; - const content = new Buffer(JSON.stringify(manifest), "utf8"); //eslint-disable-line - compiler.outputFileSystem.mkdirp(path.dirname(targetPath), err => { - if(err) return callback(err); - compiler.outputFileSystem.writeFile(targetPath, content, callback); - }); - }, callback); - }); - } -} -module.exports = LibManifestPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const path = require("path"); +const asyncLib = require("neo-async"); +const SingleEntryDependency = require("./dependencies/SingleEntryDependency"); + +class LibManifestPlugin { + constructor(options) { + this.options = options; + } + + apply(compiler) { + compiler.hooks.emit.tapAsync( + "LibManifestPlugin", + (compilation, callback) => { + asyncLib.forEach( + compilation.chunks, + (chunk, callback) => { + if (!chunk.isOnlyInitial()) { + callback(); + return; + } + const targetPath = compilation.getPath(this.options.path, { + hash: compilation.hash, + chunk + }); + const name = + this.options.name && + compilation.getPath(this.options.name, { + hash: compilation.hash, + chunk + }); + const manifest = { + name, + type: this.options.type, + content: Array.from(chunk.modulesIterable, module => { + if ( + this.options.entryOnly && + !module.reasons.some( + r => r.dependency instanceof SingleEntryDependency + ) + ) { + return; + } + if (module.libIdent) { + const ident = module.libIdent({ + context: this.options.context || compiler.options.context + }); + if (ident) { + return { + ident, + data: { + id: module.id, + buildMeta: module.buildMeta + } + }; + } + } + }) + .filter(Boolean) + .reduce((obj, item) => { + obj[item.ident] = item.data; + return obj; + }, Object.create(null)) + }; + const content = Buffer.from(JSON.stringify(manifest), "utf8"); + compiler.outputFileSystem.mkdirp(path.dirname(targetPath), err => { + if (err) return callback(err); + compiler.outputFileSystem.writeFile( + targetPath, + content, + callback + ); + }); + }, + callback + ); + } + ); + } +} +module.exports = LibManifestPlugin; diff --git a/node_modules/webpack/lib/LibraryTemplatePlugin.js b/node_modules/webpack/lib/LibraryTemplatePlugin.js index 11ab06074..c871994fa 100644 --- a/node_modules/webpack/lib/LibraryTemplatePlugin.js +++ b/node_modules/webpack/lib/LibraryTemplatePlugin.js @@ -1,92 +1,153 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const SetVarMainTemplatePlugin = require("./SetVarMainTemplatePlugin"); - -function accessorToObjectAccess(accessor) { - return accessor.map((a) => { - return `[${JSON.stringify(a)}]`; - }).join(""); -} - -function accessorAccess(base, accessor, joinWith) { - accessor = [].concat(accessor); - return accessor.map((a, idx) => { - a = base ? - base + accessorToObjectAccess(accessor.slice(0, idx + 1)) : - accessor[0] + accessorToObjectAccess(accessor.slice(1, idx + 1)); - if(idx === accessor.length - 1) return a; - if(idx === 0 && typeof base === "undefined") return `${a} = typeof ${a} === "object" ? ${a} : {}`; - return `${a} = ${a} || {}`; - }).join(joinWith || "; "); -} - -class LibraryTemplatePlugin { - - constructor(name, target, umdNamedDefine, auxiliaryComment, exportProperty) { - this.name = name; - this.target = target; - this.umdNamedDefine = umdNamedDefine; - this.auxiliaryComment = auxiliaryComment; - this.exportProperty = exportProperty; - } - - apply(compiler) { - compiler.plugin("this-compilation", (compilation) => { - if(this.exportProperty) { - var ExportPropertyMainTemplatePlugin = require("./ExportPropertyMainTemplatePlugin"); - compilation.apply(new ExportPropertyMainTemplatePlugin(this.exportProperty)); - } - switch(this.target) { - case "var": - compilation.apply(new SetVarMainTemplatePlugin(`var ${accessorAccess(false, this.name)}`)); - break; - case "assign": - compilation.apply(new SetVarMainTemplatePlugin(accessorAccess(undefined, this.name))); - break; - case "this": - case "window": - case "global": - if(this.name) - compilation.apply(new SetVarMainTemplatePlugin(accessorAccess(this.target, this.name))); - else - compilation.apply(new SetVarMainTemplatePlugin(this.target, true)); - break; - case "commonjs": - if(this.name) - compilation.apply(new SetVarMainTemplatePlugin(accessorAccess("exports", this.name))); - else - compilation.apply(new SetVarMainTemplatePlugin("exports", true)); - break; - case "commonjs2": - case "commonjs-module": - compilation.apply(new SetVarMainTemplatePlugin("module.exports")); - break; - case "amd": - var AmdMainTemplatePlugin = require("./AmdMainTemplatePlugin"); - compilation.apply(new AmdMainTemplatePlugin(this.name)); - break; - case "umd": - case "umd2": - var UmdMainTemplatePlugin = require("./UmdMainTemplatePlugin"); - compilation.apply(new UmdMainTemplatePlugin(this.name, { - optionalAmdExternalAsGlobal: this.target === "umd2", - namedDefine: this.umdNamedDefine, - auxiliaryComment: this.auxiliaryComment - })); - break; - case "jsonp": - var JsonpExportMainTemplatePlugin = require("./JsonpExportMainTemplatePlugin"); - compilation.apply(new JsonpExportMainTemplatePlugin(this.name)); - break; - default: - throw new Error(`${this.target} is not a valid Library target`); - } - }); - } -} - -module.exports = LibraryTemplatePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const SetVarMainTemplatePlugin = require("./SetVarMainTemplatePlugin"); + +/** @typedef {import("./Compiler")} Compiler */ + +/** + * @param {string[]} accessor the accessor to convert to path + * @returns {string} the path + */ +const accessorToObjectAccess = accessor => { + return accessor.map(a => `[${JSON.stringify(a)}]`).join(""); +}; + +/** + * @param {string=} base the path prefix + * @param {string|string[]} accessor the accessor + * @param {string=} joinWith the element separator + * @returns {string} the path + */ +const accessorAccess = (base, accessor, joinWith = "; ") => { + const accessors = Array.isArray(accessor) ? accessor : [accessor]; + return accessors + .map((_, idx) => { + const a = base + ? base + accessorToObjectAccess(accessors.slice(0, idx + 1)) + : accessors[0] + accessorToObjectAccess(accessors.slice(1, idx + 1)); + if (idx === accessors.length - 1) return a; + if (idx === 0 && base === undefined) { + return `${a} = typeof ${a} === "object" ? ${a} : {}`; + } + return `${a} = ${a} || {}`; + }) + .join(joinWith); +}; + +class LibraryTemplatePlugin { + /** + * @param {string} name name of library + * @param {string} target type of library + * @param {boolean} umdNamedDefine setting this to true will name the UMD module + * @param {string|TODO} auxiliaryComment comment in the UMD wrapper + * @param {string|string[]} exportProperty which export should be exposed as library + */ + constructor(name, target, umdNamedDefine, auxiliaryComment, exportProperty) { + this.name = name; + this.target = target; + this.umdNamedDefine = umdNamedDefine; + this.auxiliaryComment = auxiliaryComment; + this.exportProperty = exportProperty; + } + + /** + * @param {Compiler} compiler the compiler instance + * @returns {void} + */ + apply(compiler) { + compiler.hooks.thisCompilation.tap("LibraryTemplatePlugin", compilation => { + if (this.exportProperty) { + const ExportPropertyMainTemplatePlugin = require("./ExportPropertyMainTemplatePlugin"); + new ExportPropertyMainTemplatePlugin(this.exportProperty).apply( + compilation + ); + } + switch (this.target) { + case "var": + new SetVarMainTemplatePlugin( + `var ${accessorAccess(undefined, this.name)}`, + false + ).apply(compilation); + break; + case "assign": + new SetVarMainTemplatePlugin( + accessorAccess(undefined, this.name), + false + ).apply(compilation); + break; + case "this": + case "self": + case "window": + if (this.name) { + new SetVarMainTemplatePlugin( + accessorAccess(this.target, this.name), + false + ).apply(compilation); + } else { + new SetVarMainTemplatePlugin(this.target, true).apply(compilation); + } + break; + case "global": + if (this.name) { + new SetVarMainTemplatePlugin( + accessorAccess( + compilation.runtimeTemplate.outputOptions.globalObject, + this.name + ), + false + ).apply(compilation); + } else { + new SetVarMainTemplatePlugin( + compilation.runtimeTemplate.outputOptions.globalObject, + true + ).apply(compilation); + } + break; + case "commonjs": + if (this.name) { + new SetVarMainTemplatePlugin( + accessorAccess("exports", this.name), + false + ).apply(compilation); + } else { + new SetVarMainTemplatePlugin("exports", true).apply(compilation); + } + break; + case "commonjs2": + case "commonjs-module": + new SetVarMainTemplatePlugin("module.exports", false).apply( + compilation + ); + break; + case "amd": { + const AmdMainTemplatePlugin = require("./AmdMainTemplatePlugin"); + new AmdMainTemplatePlugin(this.name).apply(compilation); + break; + } + case "umd": + case "umd2": { + const UmdMainTemplatePlugin = require("./UmdMainTemplatePlugin"); + new UmdMainTemplatePlugin(this.name, { + optionalAmdExternalAsGlobal: this.target === "umd2", + namedDefine: this.umdNamedDefine, + auxiliaryComment: this.auxiliaryComment + }).apply(compilation); + break; + } + case "jsonp": { + const JsonpExportMainTemplatePlugin = require("./web/JsonpExportMainTemplatePlugin"); + new JsonpExportMainTemplatePlugin(this.name).apply(compilation); + break; + } + default: + throw new Error(`${this.target} is not a valid Library target`); + } + }); + } +} + +module.exports = LibraryTemplatePlugin; diff --git a/node_modules/webpack/lib/LoaderOptionsPlugin.js b/node_modules/webpack/lib/LoaderOptionsPlugin.js index b3d3ef7f4..5d13e2c06 100644 --- a/node_modules/webpack/lib/LoaderOptionsPlugin.js +++ b/node_modules/webpack/lib/LoaderOptionsPlugin.js @@ -1,36 +1,53 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ModuleFilenameHelpers = require("./ModuleFilenameHelpers"); - -class LoaderOptionsPlugin { - constructor(options) { - if(typeof options !== "object") options = {}; - if(!options.test) options.test = { - test: () => true - }; - this.options = options; - } - - apply(compiler) { - const options = this.options; - compiler.plugin("compilation", (compilation) => { - compilation.plugin("normal-module-loader", (context, module) => { - const resource = module.resource; - if(!resource) return; - const i = resource.indexOf("?"); - if(ModuleFilenameHelpers.matchObject(options, i < 0 ? resource : resource.substr(0, i))) { - const filterSet = new Set(["include", "exclude", "test"]); - Object.keys(options) - .filter((key) => !filterSet.has(key)) - .forEach((key) => context[key] = options[key]); - } - }); - }); - } -} - -module.exports = LoaderOptionsPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const ModuleFilenameHelpers = require("./ModuleFilenameHelpers"); + +const validateOptions = require("schema-utils"); +const schema = require("../schemas/plugins/LoaderOptionsPlugin.json"); + +class LoaderOptionsPlugin { + constructor(options) { + validateOptions(schema, options || {}, "Loader Options Plugin"); + + if (typeof options !== "object") options = {}; + if (!options.test) { + options.test = { + test: () => true + }; + } + this.options = options; + } + + apply(compiler) { + const options = this.options; + compiler.hooks.compilation.tap("LoaderOptionsPlugin", compilation => { + compilation.hooks.normalModuleLoader.tap( + "LoaderOptionsPlugin", + (context, module) => { + const resource = module.resource; + if (!resource) return; + const i = resource.indexOf("?"); + if ( + ModuleFilenameHelpers.matchObject( + options, + i < 0 ? resource : resource.substr(0, i) + ) + ) { + for (const key of Object.keys(options)) { + if (key === "include" || key === "exclude" || key === "test") { + continue; + } + context[key] = options[key]; + } + } + } + ); + }); + } +} + +module.exports = LoaderOptionsPlugin; diff --git a/node_modules/webpack/lib/LoaderTargetPlugin.js b/node_modules/webpack/lib/LoaderTargetPlugin.js index c7f5f59b4..99ffbc997 100644 --- a/node_modules/webpack/lib/LoaderTargetPlugin.js +++ b/node_modules/webpack/lib/LoaderTargetPlugin.js @@ -1,19 +1,24 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class LoaderTargetPlugin { - constructor(target) { - this.target = target; - } - - apply(compiler) { - compiler.plugin("compilation", (compilation) => { - compilation.plugin("normal-module-loader", (loaderContext) => loaderContext.target = this.target); - }); - } -} - -module.exports = LoaderTargetPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +class LoaderTargetPlugin { + constructor(target) { + this.target = target; + } + + apply(compiler) { + compiler.hooks.compilation.tap("LoaderTargetPlugin", compilation => { + compilation.hooks.normalModuleLoader.tap( + "LoaderTargetPlugin", + loaderContext => { + loaderContext.target = this.target; + } + ); + }); + } +} + +module.exports = LoaderTargetPlugin; diff --git a/node_modules/webpack/lib/MainTemplate.js b/node_modules/webpack/lib/MainTemplate.js index 58a3409d5..0243a4a30 100644 --- a/node_modules/webpack/lib/MainTemplate.js +++ b/node_modules/webpack/lib/MainTemplate.js @@ -1,231 +1,535 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ConcatSource = require("webpack-sources").ConcatSource; -const OriginalSource = require("webpack-sources").OriginalSource; -const PrefixSource = require("webpack-sources").PrefixSource; -const Template = require("./Template"); - -// require function shortcuts: -// __webpack_require__.s = the module id of the entry point -// __webpack_require__.c = the module cache -// __webpack_require__.m = the module functions -// __webpack_require__.p = the bundle public path -// __webpack_require__.i = the identity function used for harmony imports -// __webpack_require__.e = the chunk ensure function -// __webpack_require__.d = the exported propery define getter function -// __webpack_require__.o = Object.prototype.hasOwnProperty.call -// __webpack_require__.n = compatibility get default export -// __webpack_require__.h = the webpack hash -// __webpack_require__.oe = the uncatched error handler for the webpack runtime -// __webpack_require__.nc = the script nonce - -module.exports = class MainTemplate extends Template { - constructor(outputOptions) { - super(outputOptions); - this.plugin("startup", (source, chunk, hash) => { - const buf = []; - if(chunk.entryModule) { - buf.push("// Load entry module and return exports"); - buf.push(`return ${this.renderRequireFunctionForModule(hash, chunk, JSON.stringify(chunk.entryModule.id))}(${this.requireFn}.s = ${JSON.stringify(chunk.entryModule.id)});`); - } - return this.asString(buf); - }); - this.plugin("render", (bootstrapSource, chunk, hash, moduleTemplate, dependencyTemplates) => { - const source = new ConcatSource(); - source.add("/******/ (function(modules) { // webpackBootstrap\n"); - source.add(new PrefixSource("/******/", bootstrapSource)); - source.add("/******/ })\n"); - source.add("/************************************************************************/\n"); - source.add("/******/ ("); - const modules = this.renderChunkModules(chunk, moduleTemplate, dependencyTemplates, "/******/ "); - source.add(this.applyPluginsWaterfall("modules", modules, chunk, hash, moduleTemplate, dependencyTemplates)); - source.add(")"); - return source; - }); - this.plugin("local-vars", (source, chunk, hash) => { - return this.asString([ - source, - "// The module cache", - "var installedModules = {};" - ]); - }); - this.plugin("require", (source, chunk, hash) => { - return this.asString([ - source, - "// Check if module is in cache", - "if(installedModules[moduleId]) {", - this.indent("return installedModules[moduleId].exports;"), - "}", - "// Create a new module (and put it into the cache)", - "var module = installedModules[moduleId] = {", - this.indent(this.applyPluginsWaterfall("module-obj", "", chunk, hash, "moduleId")), - "};", - "", - this.asString(outputOptions.strictModuleExceptionHandling ? [ - "// Execute the module function", - "var threw = true;", - "try {", - this.indent([ - `modules[moduleId].call(module.exports, module, module.exports, ${this.renderRequireFunctionForModule(hash, chunk, "moduleId")});`, - "threw = false;" - ]), - "} finally {", - this.indent([ - "if(threw) delete installedModules[moduleId];" - ]), - "}" - ] : [ - "// Execute the module function", - `modules[moduleId].call(module.exports, module, module.exports, ${this.renderRequireFunctionForModule(hash, chunk, "moduleId")});`, - ]), - "", - "// Flag the module as loaded", - "module.l = true;", - "", - "// Return the exports of the module", - "return module.exports;" - ]); - }); - this.plugin("module-obj", (source, chunk, hash, varModuleId) => { - return this.asString([ - "i: moduleId,", - "l: false,", - "exports: {}" - ]); - }); - this.plugin("require-extensions", (source, chunk, hash) => { - const buf = []; - if(chunk.chunks.length > 0) { - buf.push("// This file contains only the entry chunk."); - buf.push("// The chunk loading function for additional chunks"); - buf.push(`${this.requireFn}.e = function requireEnsure(chunkId) {`); - buf.push(this.indent(this.applyPluginsWaterfall("require-ensure", "throw new Error('Not chunk loading available');", chunk, hash, "chunkId"))); - buf.push("};"); - } - buf.push(""); - buf.push("// expose the modules object (__webpack_modules__)"); - buf.push(`${this.requireFn}.m = modules;`); - - buf.push(""); - buf.push("// expose the module cache"); - buf.push(`${this.requireFn}.c = installedModules;`); - - buf.push(""); - buf.push("// define getter function for harmony exports"); - buf.push(`${this.requireFn}.d = function(exports, name, getter) {`); - buf.push(this.indent([ - `if(!${this.requireFn}.o(exports, name)) {`, - this.indent([ - "Object.defineProperty(exports, name, {", - this.indent([ - "configurable: false,", - "enumerable: true,", - "get: getter" - ]), - "});" - ]), - "}" - ])); - buf.push("};"); - - buf.push(""); - buf.push("// getDefaultExport function for compatibility with non-harmony modules"); - buf.push(this.requireFn + ".n = function(module) {"); - buf.push(this.indent([ - "var getter = module && module.__esModule ?", - this.indent([ - "function getDefault() { return module['default']; } :", - "function getModuleExports() { return module; };" - ]), - `${this.requireFn}.d(getter, 'a', getter);`, - "return getter;" - ])); - buf.push("};"); - - buf.push(""); - buf.push("// Object.prototype.hasOwnProperty.call"); - buf.push(`${this.requireFn}.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };`); - - const publicPath = this.getPublicPath({ - hash: hash - }); - buf.push(""); - buf.push("// __webpack_public_path__"); - buf.push(`${this.requireFn}.p = ${JSON.stringify(publicPath)};`); - return this.asString(buf); - }); - - this.requireFn = "__webpack_require__"; - } - - render(hash, chunk, moduleTemplate, dependencyTemplates) { - const buf = []; - buf.push(this.applyPluginsWaterfall("bootstrap", "", chunk, hash, moduleTemplate, dependencyTemplates)); - buf.push(this.applyPluginsWaterfall("local-vars", "", chunk, hash)); - buf.push(""); - buf.push("// The require function"); - buf.push(`function ${this.requireFn}(moduleId) {`); - buf.push(this.indent(this.applyPluginsWaterfall("require", "", chunk, hash))); - buf.push("}"); - buf.push(""); - buf.push(this.asString(this.applyPluginsWaterfall("require-extensions", "", chunk, hash))); - buf.push(""); - buf.push(this.asString(this.applyPluginsWaterfall("startup", "", chunk, hash))); - let source = this.applyPluginsWaterfall("render", new OriginalSource(this.prefix(buf, " \t") + "\n", `webpack/bootstrap ${hash}`), chunk, hash, moduleTemplate, dependencyTemplates); - if(chunk.hasEntryModule()) { - source = this.applyPluginsWaterfall("render-with-entry", source, chunk, hash); - } - if(!source) throw new Error("Compiler error: MainTemplate plugin 'render' should return something"); - chunk.rendered = true; - return new ConcatSource(source, ";"); - } - - renderRequireFunctionForModule(hash, chunk, varModuleId) { - return this.applyPluginsWaterfall("module-require", this.requireFn, chunk, hash, varModuleId); - } - - renderAddModule(hash, chunk, varModuleId, varModule) { - return this.applyPluginsWaterfall("add-module", `modules[${varModuleId}] = ${varModule};`, chunk, hash, varModuleId, varModule); - } - - renderCurrentHashCode(hash, length) { - length = length || Infinity; - return this.applyPluginsWaterfall("current-hash", JSON.stringify(hash.substr(0, length)), length); - } - - entryPointInChildren(chunk) { - const checkChildren = (chunk, alreadyCheckedChunks) => { - return chunk.chunks.some((child) => { - if(alreadyCheckedChunks.indexOf(child) >= 0) return; - alreadyCheckedChunks.push(child); - return child.hasEntryModule() || checkChildren(child, alreadyCheckedChunks); - }); - }; - return checkChildren(chunk, []); - } - - getPublicPath(options) { - return this.applyPluginsWaterfall("asset-path", this.outputOptions.publicPath || "", options); - } - - updateHash(hash) { - hash.update("maintemplate"); - hash.update("3"); - hash.update(this.outputOptions.publicPath + ""); - this.applyPlugins("hash", hash); - } - - updateHashForChunk(hash, chunk) { - this.updateHash(hash); - this.applyPlugins("hash-for-chunk", hash, chunk); - } - - useChunkHash(chunk) { - const paths = this.applyPluginsWaterfall("global-hash-paths", []); - return !this.applyPluginsBailResult("global-hash", chunk, paths); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const { + ConcatSource, + OriginalSource, + PrefixSource, + RawSource +} = require("webpack-sources"); +const { + Tapable, + SyncWaterfallHook, + SyncHook, + SyncBailHook +} = require("tapable"); +const Template = require("./Template"); + +/** @typedef {import("webpack-sources").ConcatSource} ConcatSource */ +/** @typedef {import("webpack-sources").Source} Source */ +/** @typedef {import("./ModuleTemplate")} ModuleTemplate */ +/** @typedef {import("./Chunk")} Chunk */ +/** @typedef {import("./Module")} Module} */ +/** @typedef {import("./util/createHash").Hash} Hash} */ +/** @typedef {import("./Dependency").DependencyTemplate} DependencyTemplate} */ + +/** + * @typedef {Object} RenderManifestOptions + * @property {Chunk} chunk the chunk used to render + * @property {string} hash + * @property {string} fullHash + * @property {TODO} outputOptions + * @property {{javascript: ModuleTemplate, webassembly: ModuleTemplate}} moduleTemplates + * @property {Map} dependencyTemplates + */ + +// require function shortcuts: +// __webpack_require__.s = the module id of the entry point +// __webpack_require__.c = the module cache +// __webpack_require__.m = the module functions +// __webpack_require__.p = the bundle public path +// __webpack_require__.i = the identity function used for harmony imports +// __webpack_require__.e = the chunk ensure function +// __webpack_require__.d = the exported property define getter function +// __webpack_require__.o = Object.prototype.hasOwnProperty.call +// __webpack_require__.r = define compatibility on export +// __webpack_require__.t = create a fake namespace object +// __webpack_require__.n = compatibility get default export +// __webpack_require__.h = the webpack hash +// __webpack_require__.w = an object containing all installed WebAssembly.Instance export objects keyed by module id +// __webpack_require__.oe = the uncaught error handler for the webpack runtime +// __webpack_require__.nc = the script nonce + +module.exports = class MainTemplate extends Tapable { + /** + * + * @param {TODO=} outputOptions output options for the MainTemplate + */ + constructor(outputOptions) { + super(); + /** @type {TODO?} */ + this.outputOptions = outputOptions || {}; + this.hooks = { + /** @type {SyncWaterfallHook} */ + renderManifest: new SyncWaterfallHook(["result", "options"]), + modules: new SyncWaterfallHook([ + "modules", + "chunk", + "hash", + "moduleTemplate", + "dependencyTemplates" + ]), + moduleObj: new SyncWaterfallHook([ + "source", + "chunk", + "hash", + "moduleIdExpression" + ]), + requireEnsure: new SyncWaterfallHook([ + "source", + "chunk", + "hash", + "chunkIdExpression" + ]), + bootstrap: new SyncWaterfallHook([ + "source", + "chunk", + "hash", + "moduleTemplate", + "dependencyTemplates" + ]), + localVars: new SyncWaterfallHook(["source", "chunk", "hash"]), + require: new SyncWaterfallHook(["source", "chunk", "hash"]), + requireExtensions: new SyncWaterfallHook(["source", "chunk", "hash"]), + /** @type {SyncWaterfallHook} */ + beforeStartup: new SyncWaterfallHook(["source", "chunk", "hash"]), + /** @type {SyncWaterfallHook} */ + startup: new SyncWaterfallHook(["source", "chunk", "hash"]), + render: new SyncWaterfallHook([ + "source", + "chunk", + "hash", + "moduleTemplate", + "dependencyTemplates" + ]), + renderWithEntry: new SyncWaterfallHook(["source", "chunk", "hash"]), + moduleRequire: new SyncWaterfallHook([ + "source", + "chunk", + "hash", + "moduleIdExpression" + ]), + addModule: new SyncWaterfallHook([ + "source", + "chunk", + "hash", + "moduleIdExpression", + "moduleExpression" + ]), + currentHash: new SyncWaterfallHook(["source", "requestedLength"]), + assetPath: new SyncWaterfallHook(["path", "options"]), + hash: new SyncHook(["hash"]), + hashForChunk: new SyncHook(["hash", "chunk"]), + globalHashPaths: new SyncWaterfallHook(["paths"]), + globalHash: new SyncBailHook(["chunk", "paths"]), + + // TODO this should be moved somewhere else + // It's weird here + hotBootstrap: new SyncWaterfallHook(["source", "chunk", "hash"]) + }; + this.hooks.startup.tap("MainTemplate", (source, chunk, hash) => { + /** @type {string[]} */ + const buf = []; + if (chunk.entryModule) { + buf.push("// Load entry module and return exports"); + buf.push( + `return ${this.renderRequireFunctionForModule( + hash, + chunk, + JSON.stringify(chunk.entryModule.id) + )}(${this.requireFn}.s = ${JSON.stringify(chunk.entryModule.id)});` + ); + } + return Template.asString(buf); + }); + this.hooks.render.tap( + "MainTemplate", + (bootstrapSource, chunk, hash, moduleTemplate, dependencyTemplates) => { + const source = new ConcatSource(); + source.add("/******/ (function(modules) { // webpackBootstrap\n"); + source.add(new PrefixSource("/******/", bootstrapSource)); + source.add("/******/ })\n"); + source.add( + "/************************************************************************/\n" + ); + source.add("/******/ ("); + source.add( + this.hooks.modules.call( + new RawSource(""), + chunk, + hash, + moduleTemplate, + dependencyTemplates + ) + ); + source.add(")"); + return source; + } + ); + this.hooks.localVars.tap("MainTemplate", (source, chunk, hash) => { + return Template.asString([ + source, + "// The module cache", + "var installedModules = {};" + ]); + }); + this.hooks.require.tap("MainTemplate", (source, chunk, hash) => { + return Template.asString([ + source, + "// Check if module is in cache", + "if(installedModules[moduleId]) {", + Template.indent("return installedModules[moduleId].exports;"), + "}", + "// Create a new module (and put it into the cache)", + "var module = installedModules[moduleId] = {", + Template.indent(this.hooks.moduleObj.call("", chunk, hash, "moduleId")), + "};", + "", + Template.asString( + outputOptions.strictModuleExceptionHandling + ? [ + "// Execute the module function", + "var threw = true;", + "try {", + Template.indent([ + `modules[moduleId].call(module.exports, module, module.exports, ${this.renderRequireFunctionForModule( + hash, + chunk, + "moduleId" + )});`, + "threw = false;" + ]), + "} finally {", + Template.indent([ + "if(threw) delete installedModules[moduleId];" + ]), + "}" + ] + : [ + "// Execute the module function", + `modules[moduleId].call(module.exports, module, module.exports, ${this.renderRequireFunctionForModule( + hash, + chunk, + "moduleId" + )});` + ] + ), + "", + "// Flag the module as loaded", + "module.l = true;", + "", + "// Return the exports of the module", + "return module.exports;" + ]); + }); + this.hooks.moduleObj.tap( + "MainTemplate", + (source, chunk, hash, varModuleId) => { + return Template.asString(["i: moduleId,", "l: false,", "exports: {}"]); + } + ); + this.hooks.requireExtensions.tap("MainTemplate", (source, chunk, hash) => { + const buf = []; + const chunkMaps = chunk.getChunkMaps(); + // Check if there are non initial chunks which need to be imported using require-ensure + if (Object.keys(chunkMaps.hash).length) { + buf.push("// This file contains only the entry chunk."); + buf.push("// The chunk loading function for additional chunks"); + buf.push(`${this.requireFn}.e = function requireEnsure(chunkId) {`); + buf.push(Template.indent("var promises = [];")); + buf.push( + Template.indent( + this.hooks.requireEnsure.call("", chunk, hash, "chunkId") + ) + ); + buf.push(Template.indent("return Promise.all(promises);")); + buf.push("};"); + } + buf.push(""); + buf.push("// expose the modules object (__webpack_modules__)"); + buf.push(`${this.requireFn}.m = modules;`); + + buf.push(""); + buf.push("// expose the module cache"); + buf.push(`${this.requireFn}.c = installedModules;`); + + buf.push(""); + buf.push("// define getter function for harmony exports"); + buf.push(`${this.requireFn}.d = function(exports, name, getter) {`); + buf.push( + Template.indent([ + `if(!${this.requireFn}.o(exports, name)) {`, + Template.indent([ + "Object.defineProperty(exports, name, { enumerable: true, get: getter });" + ]), + "}" + ]) + ); + buf.push("};"); + + buf.push(""); + buf.push("// define __esModule on exports"); + buf.push(`${this.requireFn}.r = function(exports) {`); + buf.push( + Template.indent([ + "if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {", + Template.indent([ + "Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });" + ]), + "}", + "Object.defineProperty(exports, '__esModule', { value: true });" + ]) + ); + buf.push("};"); + + buf.push(""); + buf.push("// create a fake namespace object"); + buf.push("// mode & 1: value is a module id, require it"); + buf.push("// mode & 2: merge all properties of value into the ns"); + buf.push("// mode & 4: return value when already ns object"); + buf.push("// mode & 8|1: behave like require"); + buf.push(`${this.requireFn}.t = function(value, mode) {`); + buf.push( + Template.indent([ + `if(mode & 1) value = ${this.requireFn}(value);`, + `if(mode & 8) return value;`, + "if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;", + "var ns = Object.create(null);", + `${this.requireFn}.r(ns);`, + "Object.defineProperty(ns, 'default', { enumerable: true, value: value });", + "if(mode & 2 && typeof value != 'string') for(var key in value) " + + `${this.requireFn}.d(ns, key, function(key) { ` + + "return value[key]; " + + "}.bind(null, key));", + "return ns;" + ]) + ); + buf.push("};"); + + buf.push(""); + buf.push( + "// getDefaultExport function for compatibility with non-harmony modules" + ); + buf.push(this.requireFn + ".n = function(module) {"); + buf.push( + Template.indent([ + "var getter = module && module.__esModule ?", + Template.indent([ + "function getDefault() { return module['default']; } :", + "function getModuleExports() { return module; };" + ]), + `${this.requireFn}.d(getter, 'a', getter);`, + "return getter;" + ]) + ); + buf.push("};"); + + buf.push(""); + buf.push("// Object.prototype.hasOwnProperty.call"); + buf.push( + `${ + this.requireFn + }.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };` + ); + + const publicPath = this.getPublicPath({ + hash: hash + }); + buf.push(""); + buf.push("// __webpack_public_path__"); + buf.push(`${this.requireFn}.p = ${JSON.stringify(publicPath)};`); + return Template.asString(buf); + }); + + this.requireFn = "__webpack_require__"; + } + + /** + * + * @param {RenderManifestOptions} options render manifest options + * @returns {TODO[]} returns render manifest + */ + getRenderManifest(options) { + const result = []; + + this.hooks.renderManifest.call(result, options); + + return result; + } + + /** + * TODO webpack 5: remove moduleTemplate and dependencyTemplates + * @param {string} hash hash to be used for render call + * @param {Chunk} chunk Chunk instance + * @param {ModuleTemplate} moduleTemplate ModuleTemplate instance for render + * @param {Map} dependencyTemplates dependency templates + * @returns {string[]} the generated source of the bootstrap code + */ + renderBootstrap(hash, chunk, moduleTemplate, dependencyTemplates) { + const buf = []; + buf.push( + this.hooks.bootstrap.call( + "", + chunk, + hash, + moduleTemplate, + dependencyTemplates + ) + ); + buf.push(this.hooks.localVars.call("", chunk, hash)); + buf.push(""); + buf.push("// The require function"); + buf.push(`function ${this.requireFn}(moduleId) {`); + buf.push(Template.indent(this.hooks.require.call("", chunk, hash))); + buf.push("}"); + buf.push(""); + buf.push( + Template.asString(this.hooks.requireExtensions.call("", chunk, hash)) + ); + buf.push(""); + buf.push(Template.asString(this.hooks.beforeStartup.call("", chunk, hash))); + buf.push(Template.asString(this.hooks.startup.call("", chunk, hash))); + return buf; + } + + /** + * @param {string} hash hash to be used for render call + * @param {Chunk} chunk Chunk instance + * @param {ModuleTemplate} moduleTemplate ModuleTemplate instance for render + * @param {Map} dependencyTemplates dependency templates + * @returns {ConcatSource} the newly generated source from rendering + */ + render(hash, chunk, moduleTemplate, dependencyTemplates) { + const buf = this.renderBootstrap( + hash, + chunk, + moduleTemplate, + dependencyTemplates + ); + let source = this.hooks.render.call( + new OriginalSource( + Template.prefix(buf, " \t") + "\n", + "webpack/bootstrap" + ), + chunk, + hash, + moduleTemplate, + dependencyTemplates + ); + if (chunk.hasEntryModule()) { + source = this.hooks.renderWithEntry.call(source, chunk, hash); + } + if (!source) { + throw new Error( + "Compiler error: MainTemplate plugin 'render' should return something" + ); + } + chunk.rendered = true; + return new ConcatSource(source, ";"); + } + + /** + * + * @param {string} hash hash for render fn + * @param {Chunk} chunk Chunk instance for require + * @param {(number|string)=} varModuleId module id + * @returns {TODO} the moduleRequire hook call return signature + */ + renderRequireFunctionForModule(hash, chunk, varModuleId) { + return this.hooks.moduleRequire.call( + this.requireFn, + chunk, + hash, + varModuleId + ); + } + + /** + * + * @param {string} hash hash for render add fn + * @param {Chunk} chunk Chunk instance for require add fn + * @param {(string|number)=} varModuleId module id + * @param {Module} varModule Module instance + * @returns {TODO} renderAddModule call + */ + renderAddModule(hash, chunk, varModuleId, varModule) { + return this.hooks.addModule.call( + `modules[${varModuleId}] = ${varModule};`, + chunk, + hash, + varModuleId, + varModule + ); + } + + /** + * + * @param {string} hash string hash + * @param {number=} length length + * @returns {string} call hook return + */ + renderCurrentHashCode(hash, length) { + length = length || Infinity; + return this.hooks.currentHash.call( + JSON.stringify(hash.substr(0, length)), + length + ); + } + + /** + * + * @param {object} options get public path options + * @returns {string} hook call + */ + getPublicPath(options) { + return this.hooks.assetPath.call( + this.outputOptions.publicPath || "", + options + ); + } + + getAssetPath(path, options) { + return this.hooks.assetPath.call(path, options); + } + + /** + * Updates hash with information from this template + * @param {Hash} hash the hash to update + * @returns {void} + */ + updateHash(hash) { + hash.update("maintemplate"); + hash.update("3"); + this.hooks.hash.call(hash); + } + + /** + * TODO webpack 5: remove moduleTemplate and dependencyTemplates + * Updates hash with chunk-specific information from this template + * @param {Hash} hash the hash to update + * @param {Chunk} chunk the chunk + * @param {ModuleTemplate} moduleTemplate ModuleTemplate instance for render + * @param {Map} dependencyTemplates dependency templates + * @returns {void} + */ + updateHashForChunk(hash, chunk, moduleTemplate, dependencyTemplates) { + this.updateHash(hash); + this.hooks.hashForChunk.call(hash, chunk); + for (const line of this.renderBootstrap( + "0000", + chunk, + moduleTemplate, + dependencyTemplates + )) { + hash.update(line); + } + } + + useChunkHash(chunk) { + const paths = this.hooks.globalHashPaths.call([]); + return !this.hooks.globalHash.call(chunk, paths); + } +}; diff --git a/node_modules/webpack/lib/MemoryOutputFileSystem.js b/node_modules/webpack/lib/MemoryOutputFileSystem.js index bc0769369..847614888 100644 --- a/node_modules/webpack/lib/MemoryOutputFileSystem.js +++ b/node_modules/webpack/lib/MemoryOutputFileSystem.js @@ -1,5 +1,5 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -module.exports = require("memory-fs"); +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +module.exports = require("memory-fs"); diff --git a/node_modules/webpack/lib/Module.js b/node_modules/webpack/lib/Module.js index fb259d863..7685740ab 100644 --- a/node_modules/webpack/lib/Module.js +++ b/node_modules/webpack/lib/Module.js @@ -1,250 +1,431 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const util = require("util"); - -const DependenciesBlock = require("./DependenciesBlock"); -const ModuleReason = require("./ModuleReason"); -const SortableSet = require("./util/SortableSet"); -const Template = require("./Template"); - -let debugId = 1000; - -const sortById = (a, b) => { - return a.id - b.id; -}; - -const sortByDebugId = (a, b) => { - return a.debugId - b.debugId; -}; - -class Module extends DependenciesBlock { - - constructor() { - super(); - this.context = null; - this.reasons = []; - this.debugId = debugId++; - this.id = null; - this.portableId = null; - this.index = null; - this.index2 = null; - this.depth = null; - this.used = null; - this.usedExports = null; - this.providedExports = null; - this._chunks = new SortableSet(undefined, sortById); - this._chunksDebugIdent = undefined; - this.warnings = []; - this.dependenciesWarnings = []; - this.errors = []; - this.dependenciesErrors = []; - this.strict = false; - this.meta = {}; - this.optimizationBailout = []; - } - - disconnect() { - this.reasons.length = 0; - this.id = null; - this.index = null; - this.index2 = null; - this.depth = null; - this.used = null; - this.usedExports = null; - this.providedExports = null; - this._chunks.clear(); - this._chunksDebugIdent = undefined; - this.optimizationBailout.length = 0; - super.disconnect(); - } - - unseal() { - this.id = null; - this.index = null; - this.index2 = null; - this.depth = null; - this._chunks.clear(); - this._chunksDebugIdent = undefined; - super.unseal(); - } - - setChunks(chunks) { - this._chunks = new SortableSet(chunks, sortById); - this._chunksDebugIdent = undefined; - } - - addChunk(chunk) { - this._chunks.add(chunk); - this._chunksDebugIdent = undefined; - } - - removeChunk(chunk) { - if(this._chunks.delete(chunk)) { - this._chunksDebugIdent = undefined; - chunk.removeModule(this); - return true; - } - return false; - } - - isInChunk(chunk) { - return this._chunks.has(chunk); - } - - getChunkIdsIdent() { - if(this._chunksDebugIdent !== undefined) return this._chunksDebugIdent; - this._chunks.sortWith(sortByDebugId); - const chunks = this._chunks; - const list = []; - for(const chunk of chunks) { - const debugId = chunk.debugId; - - if(typeof debugId !== "number") { - return this._chunksDebugIdent = null; - } - - list.push(debugId); - } - - return this._chunksDebugIdent = list.join(","); - } - - forEachChunk(fn) { - this._chunks.forEach(fn); - } - - mapChunks(fn) { - return Array.from(this._chunks, fn); - } - - getChunks() { - return Array.from(this._chunks); - } - - getNumberOfChunks() { - return this._chunks.size; - } - - hasEqualsChunks(otherModule) { - if(this._chunks.size !== otherModule._chunks.size) return false; - this._chunks.sortWith(sortByDebugId); - otherModule._chunks.sortWith(sortByDebugId); - const a = this._chunks[Symbol.iterator](); - const b = otherModule._chunks[Symbol.iterator](); - while(true) { // eslint-disable-line - const aItem = a.next(); - const bItem = b.next(); - if(aItem.done) return true; - if(aItem.value !== bItem.value) return false; - } - } - - addReason(module, dependency) { - this.reasons.push(new ModuleReason(module, dependency)); - } - - removeReason(module, dependency) { - for(let i = 0; i < this.reasons.length; i++) { - let r = this.reasons[i]; - if(r.module === module && r.dependency === dependency) { - this.reasons.splice(i, 1); - return true; - } - } - return false; - } - - hasReasonForChunk(chunk) { - for(let i = 0; i < this.reasons.length; i++) { - if(this.reasons[i].hasChunk(chunk)) - return true; - } - return false; - } - - rewriteChunkInReasons(oldChunk, newChunks) { - for(let i = 0; i < this.reasons.length; i++) { - this.reasons[i].rewriteChunks(oldChunk, newChunks); - } - } - - isUsed(exportName) { - if(this.used === null) return exportName; - if(!exportName) return !!this.used; - if(!this.used) return false; - if(!this.usedExports) return false; - if(this.usedExports === true) return exportName; - let idx = this.usedExports.indexOf(exportName); - if(idx < 0) return false; - if(this.isProvided(exportName)) - return Template.numberToIdentifer(idx); - return exportName; - } - - isProvided(exportName) { - if(!Array.isArray(this.providedExports)) - return null; - return this.providedExports.indexOf(exportName) >= 0; - } - - toString() { - return `Module[${this.id || this.debugId}]`; - } - - needRebuild(fileTimestamps, contextTimestamps) { - return true; - } - - updateHash(hash) { - hash.update(this.id + "" + this.used); - hash.update(JSON.stringify(this.usedExports)); - super.updateHash(hash); - } - - sortItems(sortChunks) { - super.sortItems(); - if(sortChunks) - this._chunks.sort(); - this.reasons.sort((a, b) => sortById(a.module, b.module)); - if(Array.isArray(this.usedExports)) { - this.usedExports.sort(); - } - } - - unbuild() { - this.disconnect(); - } -} - -Object.defineProperty(Module.prototype, "entry", { - configurable: false, - get() { - throw new Error("Module.entry was removed. Use Chunk.entryModule"); - }, - set() { - throw new Error("Module.entry was removed. Use Chunk.entryModule"); - } -}); - -Object.defineProperty(Module.prototype, "chunks", { - configurable: false, - get: util.deprecate(function() { - return Array.from(this._chunks); - }, "Module.chunks: Use Module.forEachChunk/mapChunks/getNumberOfChunks/isInChunk/addChunk/removeChunk instead"), - set() { - throw new Error("Readonly. Use Module.addChunk/removeChunk to modify chunks."); - } -}); - -Module.prototype.identifier = null; -Module.prototype.readableIdentifier = null; -Module.prototype.build = null; -Module.prototype.source = null; -Module.prototype.size = null; -Module.prototype.nameForCondition = null; - -module.exports = Module; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const util = require("util"); + +const DependenciesBlock = require("./DependenciesBlock"); +const ModuleReason = require("./ModuleReason"); +const SortableSet = require("./util/SortableSet"); +const Template = require("./Template"); + +/** @typedef {import("./Chunk")} Chunk */ +/** @typedef {import("./RequestShortener")} RequestShortener */ +/** @typedef {import("./WebpackError")} WebpackError */ +/** @typedef {import("./util/createHash").Hash} Hash */ + +const EMPTY_RESOLVE_OPTIONS = {}; + +let debugId = 1000; + +const sortById = (a, b) => { + return a.id - b.id; +}; + +const sortByDebugId = (a, b) => { + return a.debugId - b.debugId; +}; + +/** @typedef {(requestShortener: RequestShortener) => string} OptimizationBailoutFunction */ + +class Module extends DependenciesBlock { + constructor(type, context = null) { + super(); + /** @type {string} */ + this.type = type; + /** @type {string} */ + this.context = context; + + // Unique Id + /** @type {number} */ + this.debugId = debugId++; + + // Hash + /** @type {string} */ + this.hash = undefined; + /** @type {string} */ + this.renderedHash = undefined; + + // Info from Factory + /** @type {TODO} */ + this.resolveOptions = EMPTY_RESOLVE_OPTIONS; + /** @type {object} */ + this.factoryMeta = {}; + + // Info from Build + /** @type {WebpackError[]} */ + this.warnings = []; + /** @type {WebpackError[]} */ + this.errors = []; + /** @type {object} */ + this.buildMeta = undefined; + /** @type {object} */ + this.buildInfo = undefined; + + // Graph (per Compilation) + /** @type {ModuleReason[]} */ + this.reasons = []; + /** @type {SortableSet} */ + this._chunks = new SortableSet(undefined, sortById); + + // Info from Compilation (per Compilation) + /** @type {number|string} */ + this.id = null; + /** @type {number} */ + this.index = null; + /** @type {number} */ + this.index2 = null; + /** @type {number} */ + this.depth = null; + /** @type {Module} */ + this.issuer = null; + /** @type {undefined | object} */ + this.profile = undefined; + /** @type {boolean} */ + this.prefetched = false; + /** @type {boolean} */ + this.built = false; + + // Info from Optimization (per Compilation) + /** @type {null | boolean} */ + this.used = null; + /** @type {false | true | string[]} */ + this.usedExports = null; + /** @type {(string | OptimizationBailoutFunction)[]} */ + this.optimizationBailout = []; + + // delayed operations + /** @type {undefined | {oldChunk: Chunk, newChunks: Chunk[]}[] } */ + this._rewriteChunkInReasons = undefined; + + /** @type {boolean} */ + this.useSourceMap = false; + + // info from build + this._source = null; + } + + get exportsArgument() { + return (this.buildInfo && this.buildInfo.exportsArgument) || "exports"; + } + + get moduleArgument() { + return (this.buildInfo && this.buildInfo.moduleArgument) || "module"; + } + + disconnect() { + this.hash = undefined; + this.renderedHash = undefined; + + this.reasons.length = 0; + this._rewriteChunkInReasons = undefined; + this._chunks.clear(); + + this.id = null; + this.index = null; + this.index2 = null; + this.depth = null; + this.issuer = null; + this.profile = undefined; + this.prefetched = false; + this.built = false; + + this.used = null; + this.usedExports = null; + this.optimizationBailout.length = 0; + super.disconnect(); + } + + unseal() { + this.id = null; + this.index = null; + this.index2 = null; + this.depth = null; + this._chunks.clear(); + super.unseal(); + } + + setChunks(chunks) { + this._chunks = new SortableSet(chunks, sortById); + } + + addChunk(chunk) { + if (this._chunks.has(chunk)) return false; + this._chunks.add(chunk); + return true; + } + + removeChunk(chunk) { + if (this._chunks.delete(chunk)) { + chunk.removeModule(this); + return true; + } + return false; + } + + isInChunk(chunk) { + return this._chunks.has(chunk); + } + + isEntryModule() { + for (const chunk of this._chunks) { + if (chunk.entryModule === this) return true; + } + return false; + } + + get optional() { + return ( + this.reasons.length > 0 && + this.reasons.every(r => r.dependency && r.dependency.optional) + ); + } + + /** + * @returns {Chunk[]} all chunks which contain the module + */ + getChunks() { + return Array.from(this._chunks); + } + + getNumberOfChunks() { + return this._chunks.size; + } + + get chunksIterable() { + return this._chunks; + } + + hasEqualsChunks(otherModule) { + if (this._chunks.size !== otherModule._chunks.size) return false; + this._chunks.sortWith(sortByDebugId); + otherModule._chunks.sortWith(sortByDebugId); + const a = this._chunks[Symbol.iterator](); + const b = otherModule._chunks[Symbol.iterator](); + // eslint-disable-next-line no-constant-condition + while (true) { + const aItem = a.next(); + const bItem = b.next(); + if (aItem.done) return true; + if (aItem.value !== bItem.value) return false; + } + } + + addReason(module, dependency, explanation) { + this.reasons.push(new ModuleReason(module, dependency, explanation)); + } + + removeReason(module, dependency) { + for (let i = 0; i < this.reasons.length; i++) { + let r = this.reasons[i]; + if (r.module === module && r.dependency === dependency) { + this.reasons.splice(i, 1); + return true; + } + } + return false; + } + + hasReasonForChunk(chunk) { + if (this._rewriteChunkInReasons) { + for (const operation of this._rewriteChunkInReasons) { + this._doRewriteChunkInReasons(operation.oldChunk, operation.newChunks); + } + this._rewriteChunkInReasons = undefined; + } + for (let i = 0; i < this.reasons.length; i++) { + if (this.reasons[i].hasChunk(chunk)) return true; + } + return false; + } + + hasReasons() { + return this.reasons.length > 0; + } + + rewriteChunkInReasons(oldChunk, newChunks) { + // This is expensive. Delay operation until we really need the data + if (this._rewriteChunkInReasons === undefined) { + this._rewriteChunkInReasons = []; + } + this._rewriteChunkInReasons.push({ + oldChunk, + newChunks + }); + } + + _doRewriteChunkInReasons(oldChunk, newChunks) { + for (let i = 0; i < this.reasons.length; i++) { + this.reasons[i].rewriteChunks(oldChunk, newChunks); + } + } + + isUsed(exportName) { + if (!exportName) return this.used !== false; + if (this.used === null || this.usedExports === null) return exportName; + if (!this.used) return false; + if (!this.usedExports) return false; + if (this.usedExports === true) return exportName; + let idx = this.usedExports.indexOf(exportName); + if (idx < 0) return false; + + // Mangle export name if possible + if (this.isProvided(exportName)) { + if (this.buildMeta.exportsType === "namespace") { + return Template.numberToIdentifer(idx); + } + if ( + this.buildMeta.exportsType === "named" && + !this.usedExports.includes("default") + ) { + return Template.numberToIdentifer(idx); + } + } + return exportName; + } + + isProvided(exportName) { + if (!Array.isArray(this.buildMeta.providedExports)) return null; + return this.buildMeta.providedExports.includes(exportName); + } + + toString() { + return `Module[${this.id || this.debugId}]`; + } + + needRebuild(fileTimestamps, contextTimestamps) { + return true; + } + + /** + * @param {Hash} hash the hash used to track dependencies + * @returns {void} + */ + updateHash(hash) { + hash.update(`${this.id}`); + hash.update(JSON.stringify(this.usedExports)); + super.updateHash(hash); + } + + sortItems(sortChunks) { + super.sortItems(); + if (sortChunks) this._chunks.sort(); + this.reasons.sort((a, b) => { + if (a.module === b.module) return 0; + if (!a.module) return -1; + if (!b.module) return 1; + return sortById(a.module, b.module); + }); + if (Array.isArray(this.usedExports)) { + this.usedExports.sort(); + } + } + + unbuild() { + this.dependencies.length = 0; + this.blocks.length = 0; + this.variables.length = 0; + this.buildMeta = undefined; + this.buildInfo = undefined; + this.disconnect(); + } + + get arguments() { + throw new Error("Module.arguments was removed, there is no replacement."); + } + + set arguments(value) { + throw new Error("Module.arguments was removed, there is no replacement."); + } +} + +// TODO remove in webpack 5 +Object.defineProperty(Module.prototype, "forEachChunk", { + configurable: false, + value: util.deprecate( + /** + * @deprecated + * @param {function(any, any, Set): void} fn callback function + * @returns {void} + * @this {Module} + */ + function(fn) { + this._chunks.forEach(fn); + }, + "Module.forEachChunk: Use for(const chunk of module.chunksIterable) instead" + ) +}); + +// TODO remove in webpack 5 +Object.defineProperty(Module.prototype, "mapChunks", { + configurable: false, + value: util.deprecate( + /** + * @deprecated + * @param {function(any, any): void} fn Mapper function + * @returns {Array} Array of chunks mapped + * @this {Module} + */ + function(fn) { + return Array.from(this._chunks, fn); + }, + "Module.mapChunks: Use Array.from(module.chunksIterable, fn) instead" + ) +}); + +// TODO remove in webpack 5 +Object.defineProperty(Module.prototype, "entry", { + configurable: false, + get() { + throw new Error("Module.entry was removed. Use Chunk.entryModule"); + }, + set() { + throw new Error("Module.entry was removed. Use Chunk.entryModule"); + } +}); + +// TODO remove in webpack 5 +Object.defineProperty(Module.prototype, "meta", { + configurable: false, + get: util.deprecate( + /** + * @deprecated + * @returns {void} + * @this {Module} + */ + function() { + return this.buildMeta; + }, + "Module.meta was renamed to Module.buildMeta" + ), + set: util.deprecate( + /** + * @deprecated + * @param {TODO} value Value + * @returns {void} + * @this {Module} + */ + function(value) { + this.buildMeta = value; + }, + "Module.meta was renamed to Module.buildMeta" + ) +}); + +/** @type {function(): string} */ +Module.prototype.identifier = null; + +/** @type {function(RequestShortener): string} */ +Module.prototype.readableIdentifier = null; + +Module.prototype.build = null; +Module.prototype.source = null; +Module.prototype.size = null; +Module.prototype.nameForCondition = null; +/** @type {null | function(Chunk): boolean} */ +Module.prototype.chunkCondition = null; +Module.prototype.updateCacheModule = null; + +module.exports = Module; diff --git a/node_modules/webpack/lib/ModuleBuildError.js b/node_modules/webpack/lib/ModuleBuildError.js index 09158f697..d6b498eef 100644 --- a/node_modules/webpack/lib/ModuleBuildError.js +++ b/node_modules/webpack/lib/ModuleBuildError.js @@ -1,42 +1,52 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const WebpackError = require("./WebpackError"); -const cutOffLoaderExecution = require("./ErrorHelpers").cutOffLoaderExecution; - -class ModuleBuildError extends WebpackError { - constructor(module, err) { - super(); - - this.name = "ModuleBuildError"; - this.message = "Module build failed: "; - if(err !== null && typeof err === "object") { - if(typeof err.stack === "string" && err.stack) { - var stack = cutOffLoaderExecution(err.stack); - if(!err.hideStack) { - this.message += stack; - } else { - this.details = stack; - if(typeof err.message === "string" && err.message) { - this.message += err.message; - } else { - this.message += err; - } - } - } else if(typeof err.message === "string" && err.message) { - this.message += err.message; - } else { - this.message += err; - } - } - this.module = module; - this.error = err; - - Error.captureStackTrace(this, this.constructor); - } -} - -module.exports = ModuleBuildError; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const WebpackError = require("./WebpackError"); +const { cutOffLoaderExecution } = require("./ErrorHelpers"); + +class ModuleBuildError extends WebpackError { + constructor(module, err, { from = null } = {}) { + let message = "Module build failed"; + let details = undefined; + if (from) { + message += ` (from ${from}):\n`; + } else { + message += ": "; + } + if (err !== null && typeof err === "object") { + if (typeof err.stack === "string" && err.stack) { + const stack = cutOffLoaderExecution(err.stack); + if (!err.hideStack) { + message += stack; + } else { + details = stack; + if (typeof err.message === "string" && err.message) { + message += err.message; + } else { + message += err; + } + } + } else if (typeof err.message === "string" && err.message) { + message += err.message; + } else { + message += err; + } + } else { + message = err; + } + + super(message); + + this.name = "ModuleBuildError"; + this.details = details; + this.module = module; + this.error = err; + + Error.captureStackTrace(this, this.constructor); + } +} + +module.exports = ModuleBuildError; diff --git a/node_modules/webpack/lib/ModuleDependencyError.js b/node_modules/webpack/lib/ModuleDependencyError.js index 582b6b2ab..cb16cc34a 100644 --- a/node_modules/webpack/lib/ModuleDependencyError.js +++ b/node_modules/webpack/lib/ModuleDependencyError.js @@ -1,22 +1,35 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const WebpackError = require("./WebpackError"); -const formatLocation = require("./formatLocation"); - -module.exports = class ModuleDependencyError extends WebpackError { - constructor(module, err, loc) { - super(); - - this.name = "ModuleDependencyError"; - this.message = `${formatLocation(loc)} ${err.message}`; - this.details = err.stack.split("\n").slice(1).join("\n"); - this.origin = this.module = module; - this.error = err; - - Error.captureStackTrace(this, this.constructor); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const WebpackError = require("./WebpackError"); + +/** @typedef {import("./Module")} Module */ + +class ModuleDependencyError extends WebpackError { + /** + * Creates an instance of ModuleDependencyError. + * @param {Module} module module tied to dependency + * @param {Error} err error thrown + * @param {TODO} loc location of dependency + */ + constructor(module, err, loc) { + super(err.message); + + this.name = "ModuleDependencyError"; + this.details = err.stack + .split("\n") + .slice(1) + .join("\n"); + this.module = module; + this.loc = loc; + this.error = err; + this.origin = module.issuer; + + Error.captureStackTrace(this, this.constructor); + } +} + +module.exports = ModuleDependencyError; diff --git a/node_modules/webpack/lib/ModuleDependencyWarning.js b/node_modules/webpack/lib/ModuleDependencyWarning.js index 235fa1bb2..be62791cb 100644 --- a/node_modules/webpack/lib/ModuleDependencyWarning.js +++ b/node_modules/webpack/lib/ModuleDependencyWarning.js @@ -1,22 +1,25 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const WebpackError = require("./WebpackError"); -const formatLocation = require("./formatLocation"); - -module.exports = class ModuleDependencyWarning extends WebpackError { - constructor(module, err, loc) { - super(); - - this.name = "ModuleDependencyWarning"; - this.message = `${formatLocation(loc)} ${err.message}`; - this.details = err.stack.split("\n").slice(1).join("\n"); - this.origin = this.module = module; - this.error = err; - - Error.captureStackTrace(this, this.constructor); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const WebpackError = require("./WebpackError"); + +module.exports = class ModuleDependencyWarning extends WebpackError { + constructor(module, err, loc) { + super(err.message); + + this.name = "ModuleDependencyWarning"; + this.details = err.stack + .split("\n") + .slice(1) + .join("\n"); + this.module = module; + this.loc = loc; + this.error = err; + this.origin = module.issuer; + + Error.captureStackTrace(this, this.constructor); + } +}; diff --git a/node_modules/webpack/lib/ModuleError.js b/node_modules/webpack/lib/ModuleError.js index 9e9be7683..7079d6132 100644 --- a/node_modules/webpack/lib/ModuleError.js +++ b/node_modules/webpack/lib/ModuleError.js @@ -1,24 +1,36 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const WebpackError = require("./WebpackError"); -const cleanUp = require("./ErrorHelpers").cleanUp; - -class ModuleError extends WebpackError { - constructor(module, err) { - super(); - - this.name = "ModuleError"; - this.module = module; - this.message = err && typeof err === "object" && err.message ? err.message : err; - this.error = err; - this.details = err && typeof err === "object" && err.stack ? cleanUp(err.stack, this.message) : undefined; - - Error.captureStackTrace(this, this.constructor); - } -} - -module.exports = ModuleError; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const WebpackError = require("./WebpackError"); +const { cleanUp } = require("./ErrorHelpers"); + +class ModuleError extends WebpackError { + constructor(module, err, { from = null } = {}) { + let message = "Module Error"; + if (from) { + message += ` (from ${from}):\n`; + } else { + message += ": "; + } + if (err && typeof err === "object" && err.message) { + message += err.message; + } else if (err) { + message += err; + } + super(message); + this.name = "ModuleError"; + this.module = module; + this.error = err; + this.details = + err && typeof err === "object" && err.stack + ? cleanUp(err.stack, this.message) + : undefined; + + Error.captureStackTrace(this, this.constructor); + } +} + +module.exports = ModuleError; diff --git a/node_modules/webpack/lib/ModuleFilenameHelpers.js b/node_modules/webpack/lib/ModuleFilenameHelpers.js index f61358b07..105e89e3f 100644 --- a/node_modules/webpack/lib/ModuleFilenameHelpers.js +++ b/node_modules/webpack/lib/ModuleFilenameHelpers.js @@ -1,162 +1,178 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ModuleFilenameHelpers = exports; - -ModuleFilenameHelpers.ALL_LOADERS_RESOURCE = "[all-loaders][resource]"; -ModuleFilenameHelpers.REGEXP_ALL_LOADERS_RESOURCE = /\[all-?loaders\]\[resource\]/gi; -ModuleFilenameHelpers.LOADERS_RESOURCE = "[loaders][resource]"; -ModuleFilenameHelpers.REGEXP_LOADERS_RESOURCE = /\[loaders\]\[resource\]/gi; -ModuleFilenameHelpers.RESOURCE = "[resource]"; -ModuleFilenameHelpers.REGEXP_RESOURCE = /\[resource\]/gi; -ModuleFilenameHelpers.ABSOLUTE_RESOURCE_PATH = "[absolute-resource-path]"; -ModuleFilenameHelpers.REGEXP_ABSOLUTE_RESOURCE_PATH = /\[abs(olute)?-?resource-?path\]/gi; -ModuleFilenameHelpers.RESOURCE_PATH = "[resource-path]"; -ModuleFilenameHelpers.REGEXP_RESOURCE_PATH = /\[resource-?path\]/gi; -ModuleFilenameHelpers.ALL_LOADERS = "[all-loaders]"; -ModuleFilenameHelpers.REGEXP_ALL_LOADERS = /\[all-?loaders\]/gi; -ModuleFilenameHelpers.LOADERS = "[loaders]"; -ModuleFilenameHelpers.REGEXP_LOADERS = /\[loaders\]/gi; -ModuleFilenameHelpers.QUERY = "[query]"; -ModuleFilenameHelpers.REGEXP_QUERY = /\[query\]/gi; -ModuleFilenameHelpers.ID = "[id]"; -ModuleFilenameHelpers.REGEXP_ID = /\[id\]/gi; -ModuleFilenameHelpers.HASH = "[hash]"; -ModuleFilenameHelpers.REGEXP_HASH = /\[hash\]/gi; - -function getAfter(str, token) { - const idx = str.indexOf(token); - return idx < 0 ? "" : str.substr(idx); -} - -function getBefore(str, token) { - const idx = str.lastIndexOf(token); - return idx < 0 ? "" : str.substr(0, idx); -} - -function getHash(str) { - const hash = require("crypto").createHash("md5"); - hash.update(str); - return hash.digest("hex").substr(0, 4); -} - -function asRegExp(test) { - if(typeof test === "string") test = new RegExp("^" + test.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&")); - return test; -} - -ModuleFilenameHelpers.createFilename = function createFilename(module, moduleFilenameTemplate, requestShortener) { - let absoluteResourcePath; - let hash; - let identifier; - let moduleId; - let shortIdentifier; - if(module === undefined) module = ""; - if(typeof module === "string") { - shortIdentifier = requestShortener.shorten(module); - identifier = shortIdentifier; - moduleId = ""; - absoluteResourcePath = module.split("!").pop(); - hash = getHash(identifier); - } else { - shortIdentifier = module.readableIdentifier(requestShortener); - identifier = requestShortener.shorten(module.identifier()); - moduleId = module.id; - absoluteResourcePath = module.identifier().split("!").pop(); - hash = getHash(identifier); - } - const resource = shortIdentifier.split("!").pop(); - const loaders = getBefore(shortIdentifier, "!"); - const allLoaders = getBefore(identifier, "!"); - const query = getAfter(resource, "?"); - const resourcePath = resource.substr(0, resource.length - query.length); - if(typeof moduleFilenameTemplate === "function") { - return moduleFilenameTemplate({ - identifier: identifier, - shortIdentifier: shortIdentifier, - resource: resource, - resourcePath: resourcePath, - absoluteResourcePath: absoluteResourcePath, - allLoaders: allLoaders, - query: query, - moduleId: moduleId, - hash: hash - }); - } - return moduleFilenameTemplate - .replace(ModuleFilenameHelpers.REGEXP_ALL_LOADERS_RESOURCE, identifier) - .replace(ModuleFilenameHelpers.REGEXP_LOADERS_RESOURCE, shortIdentifier) - .replace(ModuleFilenameHelpers.REGEXP_RESOURCE, resource) - .replace(ModuleFilenameHelpers.REGEXP_RESOURCE_PATH, resourcePath) - .replace(ModuleFilenameHelpers.REGEXP_ABSOLUTE_RESOURCE_PATH, absoluteResourcePath) - .replace(ModuleFilenameHelpers.REGEXP_ALL_LOADERS, allLoaders) - .replace(ModuleFilenameHelpers.REGEXP_LOADERS, loaders) - .replace(ModuleFilenameHelpers.REGEXP_QUERY, query) - .replace(ModuleFilenameHelpers.REGEXP_ID, moduleId) - .replace(ModuleFilenameHelpers.REGEXP_HASH, hash); -}; - -ModuleFilenameHelpers.createFooter = function createFooter(module, requestShortener) { - if(!module) module = ""; - if(typeof module === "string") { - return [ - "// WEBPACK FOOTER //", - `// ${requestShortener.shorten(module)}` - ].join("\n"); - } else { - return [ - "//////////////////", - "// WEBPACK FOOTER", - `// ${module.readableIdentifier(requestShortener)}`, - `// module id = ${module.id}`, - `// module chunks = ${module.mapChunks(c => c.id).join(" ")}` - ].join("\n"); - } -}; - -ModuleFilenameHelpers.replaceDuplicates = function replaceDuplicates(array, fn, comparator) { - const countMap = Object.create(null); - const posMap = Object.create(null); - array.forEach((item, idx) => { - countMap[item] = (countMap[item] || []); - countMap[item].push(idx); - posMap[item] = 0; - }); - if(comparator) { - Object.keys(countMap).forEach(item => { - countMap[item].sort(comparator); - }); - } - return array.map((item, i) => { - if(countMap[item].length > 1) { - if(comparator && countMap[item][0] === i) - return item; - return fn(item, i, posMap[item]++); - } else return item; - }); -}; - -ModuleFilenameHelpers.matchPart = function matchPart(str, test) { - if(!test) return true; - test = asRegExp(test); - if(Array.isArray(test)) { - return test.map(asRegExp).filter(function(regExp) { - return regExp.test(str); - }).length > 0; - } else { - return test.test(str); - } -}; - -ModuleFilenameHelpers.matchObject = function matchObject(obj, str) { - if(obj.test) - if(!ModuleFilenameHelpers.matchPart(str, obj.test)) return false; - if(obj.include) - if(!ModuleFilenameHelpers.matchPart(str, obj.include)) return false; - if(obj.exclude) - if(ModuleFilenameHelpers.matchPart(str, obj.exclude)) return false; - return true; -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const createHash = require("./util/createHash"); + +const ModuleFilenameHelpers = exports; + +ModuleFilenameHelpers.ALL_LOADERS_RESOURCE = "[all-loaders][resource]"; +ModuleFilenameHelpers.REGEXP_ALL_LOADERS_RESOURCE = /\[all-?loaders\]\[resource\]/gi; +ModuleFilenameHelpers.LOADERS_RESOURCE = "[loaders][resource]"; +ModuleFilenameHelpers.REGEXP_LOADERS_RESOURCE = /\[loaders\]\[resource\]/gi; +ModuleFilenameHelpers.RESOURCE = "[resource]"; +ModuleFilenameHelpers.REGEXP_RESOURCE = /\[resource\]/gi; +ModuleFilenameHelpers.ABSOLUTE_RESOURCE_PATH = "[absolute-resource-path]"; +ModuleFilenameHelpers.REGEXP_ABSOLUTE_RESOURCE_PATH = /\[abs(olute)?-?resource-?path\]/gi; +ModuleFilenameHelpers.RESOURCE_PATH = "[resource-path]"; +ModuleFilenameHelpers.REGEXP_RESOURCE_PATH = /\[resource-?path\]/gi; +ModuleFilenameHelpers.ALL_LOADERS = "[all-loaders]"; +ModuleFilenameHelpers.REGEXP_ALL_LOADERS = /\[all-?loaders\]/gi; +ModuleFilenameHelpers.LOADERS = "[loaders]"; +ModuleFilenameHelpers.REGEXP_LOADERS = /\[loaders\]/gi; +ModuleFilenameHelpers.QUERY = "[query]"; +ModuleFilenameHelpers.REGEXP_QUERY = /\[query\]/gi; +ModuleFilenameHelpers.ID = "[id]"; +ModuleFilenameHelpers.REGEXP_ID = /\[id\]/gi; +ModuleFilenameHelpers.HASH = "[hash]"; +ModuleFilenameHelpers.REGEXP_HASH = /\[hash\]/gi; +ModuleFilenameHelpers.NAMESPACE = "[namespace]"; +ModuleFilenameHelpers.REGEXP_NAMESPACE = /\[namespace\]/gi; + +const getAfter = (str, token) => { + const idx = str.indexOf(token); + return idx < 0 ? "" : str.substr(idx); +}; + +const getBefore = (str, token) => { + const idx = str.lastIndexOf(token); + return idx < 0 ? "" : str.substr(0, idx); +}; + +const getHash = str => { + const hash = createHash("md4"); + hash.update(str); + return hash.digest("hex").substr(0, 4); +}; + +const asRegExp = test => { + if (typeof test === "string") { + test = new RegExp("^" + test.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&")); + } + return test; +}; + +ModuleFilenameHelpers.createFilename = (module, options, requestShortener) => { + const opts = Object.assign( + { + namespace: "", + moduleFilenameTemplate: "" + }, + typeof options === "object" + ? options + : { + moduleFilenameTemplate: options + } + ); + + let absoluteResourcePath; + let hash; + let identifier; + let moduleId; + let shortIdentifier; + if (module === undefined) module = ""; + if (typeof module === "string") { + shortIdentifier = requestShortener.shorten(module); + identifier = shortIdentifier; + moduleId = ""; + absoluteResourcePath = module.split("!").pop(); + hash = getHash(identifier); + } else { + shortIdentifier = module.readableIdentifier(requestShortener); + identifier = requestShortener.shorten(module.identifier()); + moduleId = module.id; + absoluteResourcePath = module + .identifier() + .split("!") + .pop(); + hash = getHash(identifier); + } + const resource = shortIdentifier.split("!").pop(); + const loaders = getBefore(shortIdentifier, "!"); + const allLoaders = getBefore(identifier, "!"); + const query = getAfter(resource, "?"); + const resourcePath = resource.substr(0, resource.length - query.length); + if (typeof opts.moduleFilenameTemplate === "function") { + return opts.moduleFilenameTemplate({ + identifier: identifier, + shortIdentifier: shortIdentifier, + resource: resource, + resourcePath: resourcePath, + absoluteResourcePath: absoluteResourcePath, + allLoaders: allLoaders, + query: query, + moduleId: moduleId, + hash: hash, + namespace: opts.namespace + }); + } + return opts.moduleFilenameTemplate + .replace(ModuleFilenameHelpers.REGEXP_ALL_LOADERS_RESOURCE, identifier) + .replace(ModuleFilenameHelpers.REGEXP_LOADERS_RESOURCE, shortIdentifier) + .replace(ModuleFilenameHelpers.REGEXP_RESOURCE, resource) + .replace(ModuleFilenameHelpers.REGEXP_RESOURCE_PATH, resourcePath) + .replace( + ModuleFilenameHelpers.REGEXP_ABSOLUTE_RESOURCE_PATH, + absoluteResourcePath + ) + .replace(ModuleFilenameHelpers.REGEXP_ALL_LOADERS, allLoaders) + .replace(ModuleFilenameHelpers.REGEXP_LOADERS, loaders) + .replace(ModuleFilenameHelpers.REGEXP_QUERY, query) + .replace(ModuleFilenameHelpers.REGEXP_ID, moduleId) + .replace(ModuleFilenameHelpers.REGEXP_HASH, hash) + .replace(ModuleFilenameHelpers.REGEXP_NAMESPACE, opts.namespace); +}; + +ModuleFilenameHelpers.replaceDuplicates = (array, fn, comparator) => { + const countMap = Object.create(null); + const posMap = Object.create(null); + array.forEach((item, idx) => { + countMap[item] = countMap[item] || []; + countMap[item].push(idx); + posMap[item] = 0; + }); + if (comparator) { + Object.keys(countMap).forEach(item => { + countMap[item].sort(comparator); + }); + } + return array.map((item, i) => { + if (countMap[item].length > 1) { + if (comparator && countMap[item][0] === i) return item; + return fn(item, i, posMap[item]++); + } else { + return item; + } + }); +}; + +ModuleFilenameHelpers.matchPart = (str, test) => { + if (!test) return true; + test = asRegExp(test); + if (Array.isArray(test)) { + return test.map(asRegExp).some(regExp => regExp.test(str)); + } else { + return test.test(str); + } +}; + +ModuleFilenameHelpers.matchObject = (obj, str) => { + if (obj.test) { + if (!ModuleFilenameHelpers.matchPart(str, obj.test)) { + return false; + } + } + if (obj.include) { + if (!ModuleFilenameHelpers.matchPart(str, obj.include)) { + return false; + } + } + if (obj.exclude) { + if (ModuleFilenameHelpers.matchPart(str, obj.exclude)) { + return false; + } + } + return true; +}; diff --git a/node_modules/webpack/lib/ModuleNotFoundError.js b/node_modules/webpack/lib/ModuleNotFoundError.js index 454cd48bf..cdfc3147b 100644 --- a/node_modules/webpack/lib/ModuleNotFoundError.js +++ b/node_modules/webpack/lib/ModuleNotFoundError.js @@ -1,26 +1,23 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const WebpackError = require("./WebpackError"); - -class ModuleNotFoundError extends WebpackError { - constructor(module, err, dependencies) { - super(); - - this.name = "ModuleNotFoundError"; - this.message = "Module not found: " + err; - this.details = err.details; - this.missing = err.missing; - this.module = module; - this.origin = module; - this.dependencies = dependencies; - this.error = err; - - Error.captureStackTrace(this, this.constructor); - } -} - -module.exports = ModuleNotFoundError; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const WebpackError = require("./WebpackError"); + +class ModuleNotFoundError extends WebpackError { + constructor(module, err) { + super("Module not found: " + err); + + this.name = "ModuleNotFoundError"; + this.details = err.details; + this.missing = err.missing; + this.module = module; + this.error = err; + + Error.captureStackTrace(this, this.constructor); + } +} + +module.exports = ModuleNotFoundError; diff --git a/node_modules/webpack/lib/ModuleParseError.js b/node_modules/webpack/lib/ModuleParseError.js index 3431d477b..32c7a69c1 100644 --- a/node_modules/webpack/lib/ModuleParseError.js +++ b/node_modules/webpack/lib/ModuleParseError.js @@ -1,34 +1,57 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const WebpackError = require("./WebpackError"); - -class ModuleParseError extends WebpackError { - constructor(module, source, err) { - super(); - - this.name = "ModuleParseError"; - this.message = "Module parse failed: " + err.message; - this.message += "\nYou may need an appropriate loader to handle this file type."; - if(err.loc && typeof err.loc === "object" && typeof err.loc.line === "number") { - var lineNumber = err.loc.line; - if(/[\0\u0001\u0002\u0003\u0004\u0005\u0006\u0007]/.test(source)) { // binary file - this.message += "\n(Source code omitted for this binary file)"; - } else { - source = source.split("\n"); - this.message += "\n| " + source.slice(Math.max(0, lineNumber - 3), lineNumber + 2).join("\n| "); - } - } else { - this.message += "\n" + err.stack; - } - this.module = module; - this.error = err; - - Error.captureStackTrace(this, this.constructor); - } -} - -module.exports = ModuleParseError; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const WebpackError = require("./WebpackError"); + +/** @typedef {import("./Module")} Module */ + +class ModuleParseError extends WebpackError { + /** + * @param {Module} module the errored module + * @param {string} source source code + * @param {Error&any} err the parse error + */ + constructor(module, source, err) { + let message = "Module parse failed: " + err.message; + let loc = undefined; + message += "\nYou may need an appropriate loader to handle this file type."; + if ( + err.loc && + typeof err.loc === "object" && + typeof err.loc.line === "number" + ) { + var lineNumber = err.loc.line; + if (/[\0\u0001\u0002\u0003\u0004\u0005\u0006\u0007]/.test(source)) { + // binary file + message += "\n(Source code omitted for this binary file)"; + } else { + const sourceLines = source.split("\n"); + const start = Math.max(0, lineNumber - 3); + const linesBefore = sourceLines.slice(start, lineNumber - 1); + const theLine = sourceLines[lineNumber - 1]; + const linesAfter = sourceLines.slice(lineNumber, lineNumber + 2); + message += + linesBefore.map(l => `\n| ${l}`).join("") + + `\n> ${theLine}` + + linesAfter.map(l => `\n| ${l}`).join(""); + } + loc = err.loc; + } else { + message += "\n" + err.stack; + } + + super(message); + + this.name = "ModuleParseError"; + this.module = module; + this.loc = loc; + this.error = err; + + Error.captureStackTrace(this, this.constructor); + } +} + +module.exports = ModuleParseError; diff --git a/node_modules/webpack/lib/ModuleReason.js b/node_modules/webpack/lib/ModuleReason.js index 52f539d01..3697f8495 100644 --- a/node_modules/webpack/lib/ModuleReason.js +++ b/node_modules/webpack/lib/ModuleReason.js @@ -1,50 +1,48 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const util = require("util"); - -class ModuleReason { - constructor(module, dependency) { - this.module = module; - this.dependency = dependency; - this._chunks = null; - } - - hasChunk(chunk) { - if(this._chunks) { - if(this._chunks.has(chunk)) - return true; - } else if(this.module._chunks.has(chunk)) - return true; - return false; - } - - rewriteChunks(oldChunk, newChunks) { - if(!this._chunks) { - if(!this.module._chunks.has(oldChunk)) - return; - this._chunks = new Set(this.module._chunks); - } - if(this._chunks.has(oldChunk)) { - this._chunks.delete(oldChunk); - for(let i = 0; i < newChunks.length; i++) { - this._chunks.add(newChunks[i]); - } - } - } -} - -Object.defineProperty(ModuleReason.prototype, "chunks", { - configurable: false, - get: util.deprecate(function() { - return this._chunks ? Array.from(this._chunks) : null; - }, "ModuleReason.chunks: Use ModuleReason.hasChunk/rewriteChunks instead"), - set() { - throw new Error("Readonly. Use ModuleReason.rewriteChunks to modify chunks."); - } -}); - -module.exports = ModuleReason; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +/** @typedef {import("./Module")} Module */ +/** @typedef {import("./Dependency")} Dependency */ + +class ModuleReason { + /** + * @param {Module} module the referencing module + * @param {Dependency} dependency the referencing dependency + * @param {string=} explanation some extra detail + */ + constructor(module, dependency, explanation) { + this.module = module; + this.dependency = dependency; + this.explanation = explanation; + this._chunks = null; + } + + hasChunk(chunk) { + if (this._chunks) { + if (this._chunks.has(chunk)) return true; + } else if (this.module && this.module._chunks.has(chunk)) return true; + return false; + } + + rewriteChunks(oldChunk, newChunks) { + if (!this._chunks) { + if (this.module) { + if (!this.module._chunks.has(oldChunk)) return; + this._chunks = new Set(this.module._chunks); + } else { + this._chunks = new Set(); + } + } + if (this._chunks.has(oldChunk)) { + this._chunks.delete(oldChunk); + for (let i = 0; i < newChunks.length; i++) { + this._chunks.add(newChunks[i]); + } + } + } +} + +module.exports = ModuleReason; diff --git a/node_modules/webpack/lib/ModuleTemplate.js b/node_modules/webpack/lib/ModuleTemplate.js index 69834df48..06e787ed9 100644 --- a/node_modules/webpack/lib/ModuleTemplate.js +++ b/node_modules/webpack/lib/ModuleTemplate.js @@ -1,23 +1,93 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const Template = require("./Template"); - -module.exports = class ModuleTemplate extends Template { - constructor(outputOptions) { - super(outputOptions); - } - render(module, dependencyTemplates, chunk) { - const moduleSource = module.source(dependencyTemplates, this.outputOptions, this.requestShortener); - const moduleSourcePostModule = this.applyPluginsWaterfall("module", moduleSource, module, chunk, dependencyTemplates); - const moduleSourcePostRender = this.applyPluginsWaterfall("render", moduleSourcePostModule, module, chunk, dependencyTemplates); - return this.applyPluginsWaterfall("package", moduleSourcePostRender, module, chunk, dependencyTemplates); - } - updateHash(hash) { - hash.update("1"); - this.applyPlugins("hash", hash); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const { Tapable, SyncWaterfallHook, SyncHook } = require("tapable"); + +/** @typedef {import("webpack-sources").Source} Source */ +/** @typedef {import("./Module")} Module */ + +module.exports = class ModuleTemplate extends Tapable { + constructor(runtimeTemplate, type) { + super(); + this.runtimeTemplate = runtimeTemplate; + this.type = type; + this.hooks = { + content: new SyncWaterfallHook([ + "source", + "module", + "options", + "dependencyTemplates" + ]), + module: new SyncWaterfallHook([ + "source", + "module", + "options", + "dependencyTemplates" + ]), + render: new SyncWaterfallHook([ + "source", + "module", + "options", + "dependencyTemplates" + ]), + package: new SyncWaterfallHook([ + "source", + "module", + "options", + "dependencyTemplates" + ]), + hash: new SyncHook(["hash"]) + }; + } + + /** + * @param {Module} module the module + * @param {TODO} dependencyTemplates templates for dependencies + * @param {TODO} options render options + * @returns {Source} the source + */ + render(module, dependencyTemplates, options) { + try { + const moduleSource = module.source( + dependencyTemplates, + this.runtimeTemplate, + this.type + ); + const moduleSourcePostContent = this.hooks.content.call( + moduleSource, + module, + options, + dependencyTemplates + ); + const moduleSourcePostModule = this.hooks.module.call( + moduleSourcePostContent, + module, + options, + dependencyTemplates + ); + const moduleSourcePostRender = this.hooks.render.call( + moduleSourcePostModule, + module, + options, + dependencyTemplates + ); + return this.hooks.package.call( + moduleSourcePostRender, + module, + options, + dependencyTemplates + ); + } catch (e) { + e.message = `${module.identifier()}\n${e.message}`; + throw e; + } + } + + updateHash(hash) { + hash.update("1"); + this.hooks.hash.call(hash); + } +}; diff --git a/node_modules/webpack/lib/ModuleWarning.js b/node_modules/webpack/lib/ModuleWarning.js index 2bda197a6..13068192c 100644 --- a/node_modules/webpack/lib/ModuleWarning.js +++ b/node_modules/webpack/lib/ModuleWarning.js @@ -1,24 +1,36 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const WebpackError = require("./WebpackError"); -const cleanUp = require("./ErrorHelpers").cleanUp; - -class ModuleWarning extends WebpackError { - constructor(module, warning) { - super(); - - this.name = "ModuleWarning"; - this.module = module; - this.message = warning && typeof warning === "object" && warning.message ? warning.message : warning; - this.warning = warning; - this.details = warning && typeof warning === "object" && warning.stack ? cleanUp(warning.stack, this.message) : undefined; - - Error.captureStackTrace(this, this.constructor); - } -} - -module.exports = ModuleWarning; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const WebpackError = require("./WebpackError"); +const { cleanUp } = require("./ErrorHelpers"); + +class ModuleWarning extends WebpackError { + constructor(module, warning, { from = null } = {}) { + let message = "Module Warning"; + if (from) { + message += ` (from ${from}):\n`; + } else { + message += ": "; + } + if (warning && typeof warning === "object" && warning.message) { + message += warning.message; + } else if (warning) { + message += warning; + } + super(message); + this.name = "ModuleWarning"; + this.module = module; + this.warning = warning; + this.details = + warning && typeof warning === "object" && warning.stack + ? cleanUp(warning.stack, this.message) + : undefined; + + Error.captureStackTrace(this, this.constructor); + } +} + +module.exports = ModuleWarning; diff --git a/node_modules/webpack/lib/MovedToPluginWarningPlugin.js b/node_modules/webpack/lib/MovedToPluginWarningPlugin.js deleted file mode 100644 index e4198d1ca..000000000 --- a/node_modules/webpack/lib/MovedToPluginWarningPlugin.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -module.exports = class MovedToPluginWarningPlugin { - constructor(optionName, pluginName) { - this.optionName = optionName; - this.pluginName = pluginName; - } - apply(compiler) { - const optionName = this.optionName; - const pluginName = this.pluginName; - compiler.plugin("compilation", (compilation) => { - compilation.warnings.push(new Error `webpack options: - DEPRECATED option ${optionName} will be moved to the ${pluginName}. - Use this instead. - For more info about the usage of the ${pluginName} see https://webpack.js.org/plugins/`); - }); - } -}; diff --git a/node_modules/webpack/lib/MultiCompiler.js b/node_modules/webpack/lib/MultiCompiler.js index 8c9b8c183..cdc7fb508 100644 --- a/node_modules/webpack/lib/MultiCompiler.js +++ b/node_modules/webpack/lib/MultiCompiler.js @@ -1,164 +1,283 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const Tapable = require("tapable"); -const asyncLib = require("async"); -const MultiWatching = require("./MultiWatching"); -const MultiStats = require("./MultiStats"); - -module.exports = class MultiCompiler extends Tapable { - constructor(compilers) { - super(); - if(!Array.isArray(compilers)) { - compilers = Object.keys(compilers).map((name) => { - compilers[name].name = name; - return compilers[name]; - }); - } - this.compilers = compilers; - let doneCompilers = 0; - let compilerStats = []; - this.compilers.forEach((compiler, idx) => { - let compilerDone = false; - compiler.plugin("done", stats => { - if(!compilerDone) { - compilerDone = true; - doneCompilers++; - } - compilerStats[idx] = stats; - if(doneCompilers === this.compilers.length) { - this.applyPlugins("done", new MultiStats(compilerStats)); - } - }); - compiler.plugin("invalid", () => { - if(compilerDone) { - compilerDone = false; - doneCompilers--; - } - this.applyPlugins("invalid"); - }); - }, this); - } - - get outputPath() { - let commonPath = this.compilers[0].outputPath; - for(const compiler of this.compilers) { - while(compiler.outputPath.indexOf(commonPath) !== 0 && /[/\\]/.test(commonPath)) { - commonPath = commonPath.replace(/[/\\][^/\\]*$/, ""); - } - } - - if(!commonPath && this.compilers[0].outputPath[0] === "/") return "/"; - return commonPath; - } - - get inputFileSystem() { - throw new Error("Cannot read inputFileSystem of a MultiCompiler"); - } - - get outputFileSystem() { - throw new Error("Cannot read outputFileSystem of a MultiCompiler"); - } - - set inputFileSystem(value) { - this.compilers.forEach(compiler => { - compiler.inputFileSystem = value; - }); - } - - set outputFileSystem(value) { - this.compilers.forEach(compiler => { - compiler.outputFileSystem = value; - }); - } - - runWithDependencies(compilers, fn, callback) { - let fulfilledNames = {}; - let remainingCompilers = compilers; - const isDependencyFulfilled = (d) => fulfilledNames[d]; - const getReadyCompilers = () => { - let readyCompilers = []; - let list = remainingCompilers; - remainingCompilers = []; - for(const c of list) { - const ready = !c.dependencies || c.dependencies.every(isDependencyFulfilled); - if(ready) - readyCompilers.push(c); - else - remainingCompilers.push(c); - } - return readyCompilers; - }; - const runCompilers = (callback) => { - if(remainingCompilers.length === 0) return callback(); - asyncLib.map(getReadyCompilers(), (compiler, callback) => { - fn(compiler, (err) => { - if(err) return callback(err); - fulfilledNames[compiler.name] = true; - runCompilers(callback); - }); - }, callback); - }; - runCompilers(callback); - } - - watch(watchOptions, handler) { - let watchings = []; - let allStats = this.compilers.map(() => null); - let compilerStatus = this.compilers.map(() => false); - this.runWithDependencies(this.compilers, (compiler, callback) => { - const compilerIdx = this.compilers.indexOf(compiler); - let firstRun = true; - let watching = compiler.watch(Array.isArray(watchOptions) ? watchOptions[compilerIdx] : watchOptions, (err, stats) => { - if(err) - handler(err); - if(stats) { - allStats[compilerIdx] = stats; - compilerStatus[compilerIdx] = "new"; - if(compilerStatus.every(Boolean)) { - const freshStats = allStats.filter((s, idx) => { - return compilerStatus[idx] === "new"; - }); - compilerStatus.fill(true); - const multiStats = new MultiStats(freshStats); - handler(null, multiStats); - } - } - if(firstRun && !err) { - firstRun = false; - callback(); - } - }); - watchings.push(watching); - }, () => { - // ignore - }); - - return new MultiWatching(watchings, this); - } - - run(callback) { - const allStats = this.compilers.map(() => null); - this.runWithDependencies(this.compilers, ((compiler, callback) => { - const compilerIdx = this.compilers.indexOf(compiler); - compiler.run((err, stats) => { - if(err) return callback(err); - allStats[compilerIdx] = stats; - callback(); - }); - }), (err) => { - if(err) return callback(err); - callback(null, new MultiStats(allStats)); - }); - } - - purgeInputFileSystem() { - this.compilers.forEach((compiler) => { - if(compiler.inputFileSystem && compiler.inputFileSystem.purge) - compiler.inputFileSystem.purge(); - }); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const { Tapable, SyncHook, MultiHook } = require("tapable"); +const asyncLib = require("neo-async"); +const MultiWatching = require("./MultiWatching"); +const MultiStats = require("./MultiStats"); +const ConcurrentCompilationError = require("./ConcurrentCompilationError"); + +module.exports = class MultiCompiler extends Tapable { + constructor(compilers) { + super(); + this.hooks = { + done: new SyncHook(["stats"]), + invalid: new MultiHook(compilers.map(c => c.hooks.invalid)), + run: new MultiHook(compilers.map(c => c.hooks.run)), + watchClose: new SyncHook([]), + watchRun: new MultiHook(compilers.map(c => c.hooks.watchRun)) + }; + if (!Array.isArray(compilers)) { + compilers = Object.keys(compilers).map(name => { + compilers[name].name = name; + return compilers[name]; + }); + } + this.compilers = compilers; + let doneCompilers = 0; + let compilerStats = []; + let index = 0; + for (const compiler of this.compilers) { + let compilerDone = false; + const compilerIndex = index++; + // eslint-disable-next-line no-loop-func + compiler.hooks.done.tap("MultiCompiler", stats => { + if (!compilerDone) { + compilerDone = true; + doneCompilers++; + } + compilerStats[compilerIndex] = stats; + if (doneCompilers === this.compilers.length) { + this.hooks.done.call(new MultiStats(compilerStats)); + } + }); + // eslint-disable-next-line no-loop-func + compiler.hooks.invalid.tap("MultiCompiler", () => { + if (compilerDone) { + compilerDone = false; + doneCompilers--; + } + }); + } + this.running = false; + } + + get outputPath() { + let commonPath = this.compilers[0].outputPath; + for (const compiler of this.compilers) { + while ( + compiler.outputPath.indexOf(commonPath) !== 0 && + /[/\\]/.test(commonPath) + ) { + commonPath = commonPath.replace(/[/\\][^/\\]*$/, ""); + } + } + + if (!commonPath && this.compilers[0].outputPath[0] === "/") return "/"; + return commonPath; + } + + get inputFileSystem() { + throw new Error("Cannot read inputFileSystem of a MultiCompiler"); + } + + get outputFileSystem() { + throw new Error("Cannot read outputFileSystem of a MultiCompiler"); + } + + set inputFileSystem(value) { + for (const compiler of this.compilers) { + compiler.inputFileSystem = value; + } + } + + set outputFileSystem(value) { + for (const compiler of this.compilers) { + compiler.outputFileSystem = value; + } + } + + validateDependencies(callback) { + const edges = new Set(); + const missing = []; + const targetFound = compiler => { + for (const edge of edges) { + if (edge.target === compiler) { + return true; + } + } + return false; + }; + const sortEdges = (e1, e2) => { + return ( + e1.source.name.localeCompare(e2.source.name) || + e1.target.name.localeCompare(e2.target.name) + ); + }; + for (const source of this.compilers) { + if (source.dependencies) { + for (const dep of source.dependencies) { + const target = this.compilers.find(c => c.name === dep); + if (!target) { + missing.push(dep); + } else { + edges.add({ + source, + target + }); + } + } + } + } + const errors = missing.map(m => `Compiler dependency \`${m}\` not found.`); + const stack = this.compilers.filter(c => !targetFound(c)); + while (stack.length > 0) { + const current = stack.pop(); + for (const edge of edges) { + if (edge.source === current) { + edges.delete(edge); + const target = edge.target; + if (!targetFound(target)) { + stack.push(target); + } + } + } + } + if (edges.size > 0) { + const lines = Array.from(edges) + .sort(sortEdges) + .map(edge => `${edge.source.name} -> ${edge.target.name}`); + lines.unshift("Circular dependency found in compiler dependencies."); + errors.unshift(lines.join("\n")); + } + if (errors.length > 0) { + const message = errors.join("\n"); + callback(new Error(message)); + return false; + } + return true; + } + + runWithDependencies(compilers, fn, callback) { + const fulfilledNames = new Set(); + let remainingCompilers = compilers; + const isDependencyFulfilled = d => fulfilledNames.has(d); + const getReadyCompilers = () => { + let readyCompilers = []; + let list = remainingCompilers; + remainingCompilers = []; + for (const c of list) { + const ready = + !c.dependencies || c.dependencies.every(isDependencyFulfilled); + if (ready) { + readyCompilers.push(c); + } else { + remainingCompilers.push(c); + } + } + return readyCompilers; + }; + const runCompilers = callback => { + if (remainingCompilers.length === 0) return callback(); + asyncLib.map( + getReadyCompilers(), + (compiler, callback) => { + fn(compiler, err => { + if (err) return callback(err); + fulfilledNames.add(compiler.name); + runCompilers(callback); + }); + }, + callback + ); + }; + runCompilers(callback); + } + + watch(watchOptions, handler) { + if (this.running) return handler(new ConcurrentCompilationError()); + + let watchings = []; + let allStats = this.compilers.map(() => null); + let compilerStatus = this.compilers.map(() => false); + if (this.validateDependencies(handler)) { + this.running = true; + this.runWithDependencies( + this.compilers, + (compiler, callback) => { + const compilerIdx = this.compilers.indexOf(compiler); + let firstRun = true; + let watching = compiler.watch( + Array.isArray(watchOptions) + ? watchOptions[compilerIdx] + : watchOptions, + (err, stats) => { + if (err) handler(err); + if (stats) { + allStats[compilerIdx] = stats; + compilerStatus[compilerIdx] = "new"; + if (compilerStatus.every(Boolean)) { + const freshStats = allStats.filter((s, idx) => { + return compilerStatus[idx] === "new"; + }); + compilerStatus.fill(true); + const multiStats = new MultiStats(freshStats); + handler(null, multiStats); + } + } + if (firstRun && !err) { + firstRun = false; + callback(); + } + } + ); + watchings.push(watching); + }, + () => { + // ignore + } + ); + } + + return new MultiWatching(watchings, this); + } + + run(callback) { + if (this.running) { + return callback(new ConcurrentCompilationError()); + } + + const finalCallback = (err, stats) => { + this.running = false; + + if (callback !== undefined) { + return callback(err, stats); + } + }; + + const allStats = this.compilers.map(() => null); + if (this.validateDependencies(callback)) { + this.running = true; + this.runWithDependencies( + this.compilers, + (compiler, callback) => { + const compilerIdx = this.compilers.indexOf(compiler); + compiler.run((err, stats) => { + if (err) { + return callback(err); + } + allStats[compilerIdx] = stats; + callback(); + }); + }, + err => { + if (err) { + return finalCallback(err); + } + finalCallback(null, new MultiStats(allStats)); + } + ); + } + } + + purgeInputFileSystem() { + for (const compiler of this.compilers) { + if (compiler.inputFileSystem && compiler.inputFileSystem.purge) { + compiler.inputFileSystem.purge(); + } + } + } +}; diff --git a/node_modules/webpack/lib/MultiEntryPlugin.js b/node_modules/webpack/lib/MultiEntryPlugin.js index e7ca65189..b38a82399 100644 --- a/node_modules/webpack/lib/MultiEntryPlugin.js +++ b/node_modules/webpack/lib/MultiEntryPlugin.js @@ -1,39 +1,80 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const MultiEntryDependency = require("./dependencies/MultiEntryDependency"); -const SingleEntryDependency = require("./dependencies/SingleEntryDependency"); -const MultiModuleFactory = require("./MultiModuleFactory"); - -module.exports = class MultiEntryPlugin { - constructor(context, entries, name) { - this.context = context; - this.entries = entries; - this.name = name; - } - - apply(compiler) { - compiler.plugin("compilation", (compilation, params) => { - const multiModuleFactory = new MultiModuleFactory(); - const normalModuleFactory = params.normalModuleFactory; - - compilation.dependencyFactories.set(MultiEntryDependency, multiModuleFactory); - compilation.dependencyFactories.set(SingleEntryDependency, normalModuleFactory); - }); - compiler.plugin("make", (compilation, callback) => { - const dep = MultiEntryPlugin.createDependency(this.entries, this.name); - compilation.addEntry(this.context, dep, this.name, callback); - }); - } - - static createDependency(entries, name) { - return new MultiEntryDependency(entries.map((e, idx) => { - const dep = new SingleEntryDependency(e); - dep.loc = name + ":" + (100000 + idx); - return dep; - }), name); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const MultiEntryDependency = require("./dependencies/MultiEntryDependency"); +const SingleEntryDependency = require("./dependencies/SingleEntryDependency"); +const MultiModuleFactory = require("./MultiModuleFactory"); + +/** @typedef {import("./Compiler")} Compiler */ + +class MultiEntryPlugin { + /** + * The MultiEntryPlugin is invoked whenever this.options.entry value is an array of paths + * @param {string} context context path + * @param {string[]} entries array of entry paths + * @param {string} name entry key name + */ + constructor(context, entries, name) { + this.context = context; + this.entries = entries; + this.name = name; + } + + /** + * @param {Compiler} compiler the compiler instance + * @returns {void} + */ + apply(compiler) { + compiler.hooks.compilation.tap( + "MultiEntryPlugin", + (compilation, { normalModuleFactory }) => { + const multiModuleFactory = new MultiModuleFactory(); + + compilation.dependencyFactories.set( + MultiEntryDependency, + multiModuleFactory + ); + compilation.dependencyFactories.set( + SingleEntryDependency, + normalModuleFactory + ); + } + ); + + compiler.hooks.make.tapAsync( + "MultiEntryPlugin", + (compilation, callback) => { + const { context, entries, name } = this; + + const dep = MultiEntryPlugin.createDependency(entries, name); + compilation.addEntry(context, dep, name, callback); + } + ); + } + + /** + * @param {string[]} entries each entry path string + * @param {string} name name of the entry + * @returns {MultiEntryDependency} returns a constructed Dependency + */ + static createDependency(entries, name) { + return new MultiEntryDependency( + entries.map((e, idx) => { + const dep = new SingleEntryDependency(e); + // Because entrypoints are not dependencies found in an + // existing module, we give it a synthetic id + dep.loc = { + name, + index: idx + }; + return dep; + }), + name + ); + } +} + +module.exports = MultiEntryPlugin; diff --git a/node_modules/webpack/lib/MultiModule.js b/node_modules/webpack/lib/MultiModule.js index b6a91e34f..c8e5d5757 100644 --- a/node_modules/webpack/lib/MultiModule.js +++ b/node_modules/webpack/lib/MultiModule.js @@ -1,75 +1,87 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const Module = require("./Module"); -const RawSource = require("webpack-sources").RawSource; - -class MultiModule extends Module { - - constructor(context, dependencies, name) { - super(); - this.context = context; - this.dependencies = dependencies; - this.name = name; - this.built = false; - this.cacheable = true; - } - - identifier() { - return `multi ${this.dependencies.map((d) => d.request).join(" ")}`; - } - - readableIdentifier(requestShortener) { - return `multi ${this.dependencies.map((d) => requestShortener.shorten(d.request)).join(" ")}`; - } - - disconnect() { - this.built = false; - super.disconnect(); - } - - build(options, compilation, resolver, fs, callback) { - this.built = true; - return callback(); - } - - needRebuild() { - return false; - } - - size() { - return 16 + this.dependencies.length * 12; - } - - updateHash(hash) { - hash.update("multi module"); - hash.update(this.name || ""); - super.updateHash(hash); - } - - source(dependencyTemplates, outputOptions) { - const str = []; - this.dependencies.forEach(function(dep, idx) { - if(dep.module) { - if(idx === this.dependencies.length - 1) - str.push("module.exports = "); - str.push("__webpack_require__("); - if(outputOptions.pathinfo) - str.push(`/*! ${dep.request} */`); - str.push(`${JSON.stringify(dep.module.id)}`); - str.push(")"); - } else { - str.push("(function webpackMissingModule() { throw new Error("); - str.push(JSON.stringify(`Cannot find module "${dep.request}"`)); - str.push("); }())"); - } - str.push(";\n"); - }, this); - return new RawSource(str.join("")); - } -} - -module.exports = MultiModule; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const Module = require("./Module"); +const Template = require("./Template"); +const { RawSource } = require("webpack-sources"); + +/** @typedef {import("./util/createHash").Hash} Hash */ + +class MultiModule extends Module { + constructor(context, dependencies, name) { + super("javascript/dynamic", context); + + // Info from Factory + this.dependencies = dependencies; + this.name = name; + this._identifier = `multi ${this.dependencies + .map(d => d.request) + .join(" ")}`; + } + + identifier() { + return this._identifier; + } + + readableIdentifier(requestShortener) { + return `multi ${this.dependencies + .map(d => requestShortener.shorten(d.request)) + .join(" ")}`; + } + + build(options, compilation, resolver, fs, callback) { + this.built = true; + this.buildMeta = {}; + this.buildInfo = {}; + return callback(); + } + + needRebuild() { + return false; + } + + size() { + return 16 + this.dependencies.length * 12; + } + + /** + * @param {Hash} hash the hash used to track dependencies + * @returns {void} + */ + updateHash(hash) { + hash.update("multi module"); + hash.update(this.name || ""); + super.updateHash(hash); + } + + source(dependencyTemplates, runtimeTemplate) { + const str = []; + let idx = 0; + for (const dep of this.dependencies) { + if (dep.module) { + if (idx === this.dependencies.length - 1) { + str.push("module.exports = "); + } + str.push("__webpack_require__("); + if (runtimeTemplate.outputOptions.pathinfo) { + str.push(Template.toComment(dep.request)); + } + str.push(`${JSON.stringify(dep.module.id)}`); + str.push(")"); + } else { + const content = require("./dependencies/WebpackMissingModule").module( + dep.request + ); + str.push(content); + } + str.push(";\n"); + idx++; + } + return new RawSource(str.join("")); + } +} + +module.exports = MultiModule; diff --git a/node_modules/webpack/lib/MultiModuleFactory.js b/node_modules/webpack/lib/MultiModuleFactory.js index d28bfb551..5d29b2056 100644 --- a/node_modules/webpack/lib/MultiModuleFactory.js +++ b/node_modules/webpack/lib/MultiModuleFactory.js @@ -1,19 +1,23 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const Tapable = require("tapable"); -const MultiModule = require("./MultiModule"); - -module.exports = class MultiModuleFactory extends Tapable { - constructor() { - super(); - } - - create(data, callback) { - const dependency = data.dependencies[0]; - callback(null, new MultiModule(data.context, dependency.dependencies, dependency.name)); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const { Tapable } = require("tapable"); +const MultiModule = require("./MultiModule"); + +module.exports = class MultiModuleFactory extends Tapable { + constructor() { + super(); + this.hooks = {}; + } + + create(data, callback) { + const dependency = data.dependencies[0]; + callback( + null, + new MultiModule(data.context, dependency.dependencies, dependency.name) + ); + } +}; diff --git a/node_modules/webpack/lib/MultiStats.js b/node_modules/webpack/lib/MultiStats.js index 3401c9d30..1a5fcf2b0 100644 --- a/node_modules/webpack/lib/MultiStats.js +++ b/node_modules/webpack/lib/MultiStats.js @@ -1,79 +1,92 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const Stats = require("./Stats"); - -const optionOrFallback = (optionValue, fallbackValue) => optionValue !== undefined ? optionValue : fallbackValue; - -class MultiStats { - constructor(stats) { - this.stats = stats; - this.hash = stats.map(stat => stat.hash).join(""); - } - - hasErrors() { - return this.stats.map((stat) => stat.hasErrors()).reduce((a, b) => a || b, false); - } - - hasWarnings() { - return this.stats.map((stat) => stat.hasWarnings()).reduce((a, b) => a || b, false); - } - - toJson(options, forToString) { - if(typeof options === "boolean" || typeof options === "string") { - options = Stats.presetToOptions(options); - } else if(!options) { - options = {}; - } - const jsons = this.stats.map((stat, idx) => { - const childOptions = Stats.getChildOptions(options, idx); - const obj = stat.toJson(childOptions, forToString); - obj.name = stat.compilation && stat.compilation.name; - return obj; - }); - const showVersion = typeof options.version === "undefined" ? jsons.every(j => j.version) : options.version !== false; - const showHash = typeof options.hash === "undefined" ? jsons.every(j => j.hash) : options.hash !== false; - jsons.forEach(j => { - if(showVersion) - delete j.version; - }); - const obj = { - errors: jsons.reduce((arr, j) => { - return arr.concat(j.errors.map(msg => { - return `(${j.name}) ${msg}`; - })); - }, []), - warnings: jsons.reduce((arr, j) => { - return arr.concat(j.warnings.map(msg => { - return `(${j.name}) ${msg}`; - })); - }, []) - }; - if(showVersion) - obj.version = require("../package.json").version; - if(showHash) - obj.hash = this.hash; - if(options.children !== false) - obj.children = jsons; - return obj; - } - - toString(options) { - if(typeof options === "boolean" || typeof options === "string") { - options = Stats.presetToOptions(options); - } else if(!options) { - options = {}; - } - - const useColors = optionOrFallback(options.colors, false); - - const obj = this.toJson(options, true); - - return Stats.jsonToString(obj, useColors); - } -} - -module.exports = MultiStats; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const Stats = require("./Stats"); + +const optionOrFallback = (optionValue, fallbackValue) => + optionValue !== undefined ? optionValue : fallbackValue; + +class MultiStats { + constructor(stats) { + this.stats = stats; + this.hash = stats.map(stat => stat.hash).join(""); + } + + hasErrors() { + return this.stats + .map(stat => stat.hasErrors()) + .reduce((a, b) => a || b, false); + } + + hasWarnings() { + return this.stats + .map(stat => stat.hasWarnings()) + .reduce((a, b) => a || b, false); + } + + toJson(options, forToString) { + if (typeof options === "boolean" || typeof options === "string") { + options = Stats.presetToOptions(options); + } else if (!options) { + options = {}; + } + const jsons = this.stats.map((stat, idx) => { + const childOptions = Stats.getChildOptions(options, idx); + const obj = stat.toJson(childOptions, forToString); + obj.name = stat.compilation && stat.compilation.name; + return obj; + }); + const showVersion = + options.version === undefined + ? jsons.every(j => j.version) + : options.version !== false; + const showHash = + options.hash === undefined + ? jsons.every(j => j.hash) + : options.hash !== false; + if (showVersion) { + for (const j of jsons) { + delete j.version; + } + } + const obj = { + errors: jsons.reduce((arr, j) => { + return arr.concat( + j.errors.map(msg => { + return `(${j.name}) ${msg}`; + }) + ); + }, []), + warnings: jsons.reduce((arr, j) => { + return arr.concat( + j.warnings.map(msg => { + return `(${j.name}) ${msg}`; + }) + ); + }, []) + }; + if (showVersion) obj.version = require("../package.json").version; + if (showHash) obj.hash = this.hash; + if (options.children !== false) obj.children = jsons; + return obj; + } + + toString(options) { + if (typeof options === "boolean" || typeof options === "string") { + options = Stats.presetToOptions(options); + } else if (!options) { + options = {}; + } + + const useColors = optionOrFallback(options.colors, false); + + const obj = this.toJson(options, true); + + return Stats.jsonToString(obj, useColors); + } +} + +module.exports = MultiStats; diff --git a/node_modules/webpack/lib/MultiWatching.js b/node_modules/webpack/lib/MultiWatching.js index 95fd4075f..48e012c87 100644 --- a/node_modules/webpack/lib/MultiWatching.js +++ b/node_modules/webpack/lib/MultiWatching.js @@ -1,32 +1,38 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const asyncLib = require("async"); - -class MultiWatching { - constructor(watchings, compiler) { - this.watchings = watchings; - this.compiler = compiler; - } - - invalidate() { - this.watchings.forEach((watching) => watching.invalidate()); - } - - close(callback) { - if(callback === undefined) callback = () => { /*do nothing*/ }; - - asyncLib.forEach(this.watchings, (watching, finishedCallback) => { - watching.close(finishedCallback); - }, err => { - this.compiler.applyPlugins("watch-close"); - callback(err); - }); - - } -} - -module.exports = MultiWatching; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const asyncLib = require("neo-async"); + +class MultiWatching { + constructor(watchings, compiler) { + this.watchings = watchings; + this.compiler = compiler; + } + + invalidate() { + for (const watching of this.watchings) { + watching.invalidate(); + } + } + + close(callback) { + asyncLib.forEach( + this.watchings, + (watching, finishedCallback) => { + watching.close(finishedCallback); + }, + err => { + this.compiler.hooks.watchClose.call(); + if (typeof callback === "function") { + this.compiler.running = false; + callback(err); + } + } + ); + } +} + +module.exports = MultiWatching; diff --git a/node_modules/webpack/lib/NamedChunksPlugin.js b/node_modules/webpack/lib/NamedChunksPlugin.js index 10f99530f..0cb5b6bf3 100644 --- a/node_modules/webpack/lib/NamedChunksPlugin.js +++ b/node_modules/webpack/lib/NamedChunksPlugin.js @@ -1,30 +1,29 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class NamedChunksPlugin { - - static defaultNameResolver(chunk) { - return chunk.name || null; - } - - constructor(nameResolver) { - this.nameResolver = nameResolver || NamedChunksPlugin.defaultNameResolver; - } - - apply(compiler) { - compiler.plugin("compilation", (compilation) => { - compilation.plugin("before-chunk-ids", (chunks) => { - chunks.forEach((chunk) => { - if(chunk.id === null) { - chunk.id = this.nameResolver(chunk); - } - }); - }); - }); - } -} - -module.exports = NamedChunksPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +class NamedChunksPlugin { + static defaultNameResolver(chunk) { + return chunk.name || null; + } + + constructor(nameResolver) { + this.nameResolver = nameResolver || NamedChunksPlugin.defaultNameResolver; + } + + apply(compiler) { + compiler.hooks.compilation.tap("NamedChunksPlugin", compilation => { + compilation.hooks.beforeChunkIds.tap("NamedChunksPlugin", chunks => { + for (const chunk of chunks) { + if (chunk.id === null) { + chunk.id = this.nameResolver(chunk); + } + } + }); + }); + } +} + +module.exports = NamedChunksPlugin; diff --git a/node_modules/webpack/lib/NamedModulesPlugin.js b/node_modules/webpack/lib/NamedModulesPlugin.js index 37c12a9cf..a3857ac8e 100644 --- a/node_modules/webpack/lib/NamedModulesPlugin.js +++ b/node_modules/webpack/lib/NamedModulesPlugin.js @@ -1,27 +1,57 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class NamedModulesPlugin { - constructor(options) { - this.options = options || {}; - } - - apply(compiler) { - compiler.plugin("compilation", (compilation) => { - compilation.plugin("before-module-ids", (modules) => { - modules.forEach((module) => { - if(module.id === null && module.libIdent) { - module.id = module.libIdent({ - context: this.options.context || compiler.options.context - }); - } - }); - }); - }); - } -} - -module.exports = NamedModulesPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const createHash = require("./util/createHash"); +const RequestShortener = require("./RequestShortener"); + +const getHash = str => { + const hash = createHash("md4"); + hash.update(str); + return hash.digest("hex").substr(0, 4); +}; + +class NamedModulesPlugin { + constructor(options) { + this.options = options || {}; + } + + apply(compiler) { + compiler.hooks.compilation.tap("NamedModulesPlugin", compilation => { + compilation.hooks.beforeModuleIds.tap("NamedModulesPlugin", modules => { + const namedModules = new Map(); + const context = this.options.context || compiler.options.context; + + for (const module of modules) { + if (module.id === null && module.libIdent) { + module.id = module.libIdent({ context }); + } + + if (module.id !== null) { + const namedModule = namedModules.get(module.id); + if (namedModule !== undefined) { + namedModule.push(module); + } else { + namedModules.set(module.id, [module]); + } + } + } + + for (const namedModule of namedModules.values()) { + if (namedModule.length > 1) { + for (const module of namedModule) { + const requestShortener = new RequestShortener(context); + module.id = `${module.id}?${getHash( + requestShortener.shorten(module.identifier()) + )}`; + } + } + } + }); + }); + } +} + +module.exports = NamedModulesPlugin; diff --git a/node_modules/webpack/lib/NewWatchingPlugin.js b/node_modules/webpack/lib/NewWatchingPlugin.js deleted file mode 100644 index 29e2fa326..000000000 --- a/node_modules/webpack/lib/NewWatchingPlugin.js +++ /dev/null @@ -1,15 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class NewWatchingPlugin { - apply(compiler) { - compiler.plugin("compilation", function(compilation) { - compilation.warnings.push(new Error("The 'NewWatchingPlugin' is no longer necessary (now default)")); - }); - } -} - -module.exports = NewWatchingPlugin; diff --git a/node_modules/webpack/lib/NoEmitOnErrorsPlugin.js b/node_modules/webpack/lib/NoEmitOnErrorsPlugin.js index c650253e5..2c37c4979 100644 --- a/node_modules/webpack/lib/NoEmitOnErrorsPlugin.js +++ b/node_modules/webpack/lib/NoEmitOnErrorsPlugin.js @@ -1,22 +1,20 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class NoEmitOnErrorsPlugin { - apply(compiler) { - compiler.plugin("should-emit", (compilation) => { - if(compilation.errors.length > 0) - return false; - }); - compiler.plugin("compilation", (compilation) => { - compilation.plugin("should-record", () => { - if(compilation.errors.length > 0) - return false; - }); - }); - } -} - -module.exports = NoEmitOnErrorsPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +class NoEmitOnErrorsPlugin { + apply(compiler) { + compiler.hooks.shouldEmit.tap("NoEmitOnErrorsPlugin", compilation => { + if (compilation.getStats().hasErrors()) return false; + }); + compiler.hooks.compilation.tap("NoEmitOnErrorsPlugin", compilation => { + compilation.hooks.shouldRecord.tap("NoEmitOnErrorsPlugin", () => { + if (compilation.getStats().hasErrors()) return false; + }); + }); + } +} + +module.exports = NoEmitOnErrorsPlugin; diff --git a/node_modules/webpack/lib/NoErrorsPlugin.js b/node_modules/webpack/lib/NoErrorsPlugin.js deleted file mode 100644 index 0922f72f9..000000000 --- a/node_modules/webpack/lib/NoErrorsPlugin.js +++ /dev/null @@ -1,29 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -let deprecationReported = false; - -class NoErrorsPlugin { - apply(compiler) { - compiler.plugin("should-emit", (compilation) => { - if(!deprecationReported) { - compilation.warnings.push("webpack: Using NoErrorsPlugin is deprecated.\n" + - "Use NoEmitOnErrorsPlugin instead.\n"); - deprecationReported = true; - } - if(compilation.errors.length > 0) - return false; - }); - compiler.plugin("compilation", (compilation) => { - compilation.plugin("should-record", () => { - if(compilation.errors.length > 0) - return false; - }); - }); - } -} - -module.exports = NoErrorsPlugin; diff --git a/node_modules/webpack/lib/NodeStuffPlugin.js b/node_modules/webpack/lib/NodeStuffPlugin.js index b18ed173c..75d2e73b0 100644 --- a/node_modules/webpack/lib/NodeStuffPlugin.js +++ b/node_modules/webpack/lib/NodeStuffPlugin.js @@ -1,97 +1,197 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const path = require("path"); -const ParserHelpers = require("./ParserHelpers"); -const ConstDependency = require("./dependencies/ConstDependency"); - -const NullFactory = require("./NullFactory"); - -class NodeStuffPlugin { - constructor(options) { - this.options = options; - } - - apply(compiler) { - const options = this.options; - compiler.plugin("compilation", (compilation, params) => { - compilation.dependencyFactories.set(ConstDependency, new NullFactory()); - compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template()); - - params.normalModuleFactory.plugin("parser", (parser, parserOptions) => { - - if(parserOptions.node === false) - return; - - let localOptions = options; - if(parserOptions.node) - localOptions = Object.assign({}, localOptions, parserOptions.node); - - function setConstant(expressionName, value) { - parser.plugin(`expression ${expressionName}`, function() { - this.state.current.addVariable(expressionName, JSON.stringify(value)); - return true; - }); - } - - function setModuleConstant(expressionName, fn) { - parser.plugin(`expression ${expressionName}`, function() { - this.state.current.addVariable(expressionName, JSON.stringify(fn(this.state.module))); - return true; - }); - } - const context = compiler.context; - if(localOptions.__filename === "mock") { - setConstant("__filename", "/index.js"); - } else if(localOptions.__filename) { - setModuleConstant("__filename", module => path.relative(context, module.resource)); - } - parser.plugin("evaluate Identifier __filename", function(expr) { - if(!this.state.module) return; - const resource = this.state.module.resource; - const i = resource.indexOf("?"); - return ParserHelpers.evaluateToString(i < 0 ? resource : resource.substr(0, i))(expr); - }); - if(localOptions.__dirname === "mock") { - setConstant("__dirname", "/"); - } else if(localOptions.__dirname) { - setModuleConstant("__dirname", module => path.relative(context, module.context)); - } - parser.plugin("evaluate Identifier __dirname", function(expr) { - if(!this.state.module) return; - return ParserHelpers.evaluateToString(this.state.module.context)(expr); - }); - parser.plugin("expression require.main", ParserHelpers.toConstantDependency("__webpack_require__.c[__webpack_require__.s]")); - parser.plugin( - "expression require.extensions", - ParserHelpers.expressionIsUnsupported("require.extensions is not supported by webpack. Use a loader instead.") - ); - parser.plugin("expression module.loaded", ParserHelpers.toConstantDependency("module.l")); - parser.plugin("expression module.id", ParserHelpers.toConstantDependency("module.i")); - parser.plugin("expression module.exports", function() { - const module = this.state.module; - const isHarmony = module.meta && module.meta.harmonyModule; - if(!isHarmony) - return true; - }); - parser.plugin("evaluate Identifier module.hot", ParserHelpers.evaluateToIdentifier("module.hot", false)); - parser.plugin("expression module", function() { - const module = this.state.module; - const isHarmony = module.meta && module.meta.harmonyModule; - let moduleJsPath = path.join(__dirname, "..", "buildin", isHarmony ? "harmony-module.js" : "module.js"); - if(module.context) { - moduleJsPath = path.relative(this.state.module.context, moduleJsPath); - if(!/^[A-Z]:/i.test(moduleJsPath)) { - moduleJsPath = `./${moduleJsPath.replace(/\\/g, "/")}`; - } - } - return ParserHelpers.addParsedVariableToModule(this, "module", `require(${JSON.stringify(moduleJsPath)})(module)`); - }); - }); - }); - } -} -module.exports = NodeStuffPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const path = require("path"); +const ParserHelpers = require("./ParserHelpers"); +const ConstDependency = require("./dependencies/ConstDependency"); + +const NullFactory = require("./NullFactory"); + +class NodeStuffPlugin { + constructor(options) { + this.options = options; + } + + apply(compiler) { + const options = this.options; + compiler.hooks.compilation.tap( + "NodeStuffPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set(ConstDependency, new NullFactory()); + compilation.dependencyTemplates.set( + ConstDependency, + new ConstDependency.Template() + ); + + const handler = (parser, parserOptions) => { + if (parserOptions.node === false) return; + + let localOptions = options; + if (parserOptions.node) { + localOptions = Object.assign({}, localOptions, parserOptions.node); + } + + const setConstant = (expressionName, value) => { + parser.hooks.expression + .for(expressionName) + .tap("NodeStuffPlugin", () => { + parser.state.current.addVariable( + expressionName, + JSON.stringify(value) + ); + return true; + }); + }; + + const setModuleConstant = (expressionName, fn) => { + parser.hooks.expression + .for(expressionName) + .tap("NodeStuffPlugin", () => { + parser.state.current.addVariable( + expressionName, + JSON.stringify(fn(parser.state.module)) + ); + return true; + }); + }; + const context = compiler.context; + if (localOptions.__filename === "mock") { + setConstant("__filename", "/index.js"); + } else if (localOptions.__filename) { + setModuleConstant("__filename", module => + path.relative(context, module.resource) + ); + } + parser.hooks.evaluateIdentifier + .for("__filename") + .tap("NodeStuffPlugin", expr => { + if (!parser.state.module) return; + const resource = parser.state.module.resource; + const i = resource.indexOf("?"); + return ParserHelpers.evaluateToString( + i < 0 ? resource : resource.substr(0, i) + )(expr); + }); + if (localOptions.__dirname === "mock") { + setConstant("__dirname", "/"); + } else if (localOptions.__dirname) { + setModuleConstant("__dirname", module => + path.relative(context, module.context) + ); + } + parser.hooks.evaluateIdentifier + .for("__dirname") + .tap("NodeStuffPlugin", expr => { + if (!parser.state.module) return; + return ParserHelpers.evaluateToString( + parser.state.module.context + )(expr); + }); + parser.hooks.expression + .for("require.main") + .tap( + "NodeStuffPlugin", + ParserHelpers.toConstantDependencyWithWebpackRequire( + parser, + "__webpack_require__.c[__webpack_require__.s]" + ) + ); + parser.hooks.expression + .for("require.extensions") + .tap( + "NodeStuffPlugin", + ParserHelpers.expressionIsUnsupported( + parser, + "require.extensions is not supported by webpack. Use a loader instead." + ) + ); + parser.hooks.expression + .for("require.main.require") + .tap( + "NodeStuffPlugin", + ParserHelpers.expressionIsUnsupported( + parser, + "require.main.require is not supported by webpack." + ) + ); + parser.hooks.expression + .for("module.parent.require") + .tap( + "NodeStuffPlugin", + ParserHelpers.expressionIsUnsupported( + parser, + "module.parent.require is not supported by webpack." + ) + ); + parser.hooks.expression + .for("module.loaded") + .tap("NodeStuffPlugin", expr => { + parser.state.module.buildMeta.moduleConcatenationBailout = + "module.loaded"; + return ParserHelpers.toConstantDependency(parser, "module.l")( + expr + ); + }); + parser.hooks.expression + .for("module.id") + .tap("NodeStuffPlugin", expr => { + parser.state.module.buildMeta.moduleConcatenationBailout = + "module.id"; + return ParserHelpers.toConstantDependency(parser, "module.i")( + expr + ); + }); + parser.hooks.expression + .for("module.exports") + .tap("NodeStuffPlugin", () => { + const module = parser.state.module; + const isHarmony = + module.buildMeta && module.buildMeta.exportsType; + if (!isHarmony) return true; + }); + parser.hooks.evaluateIdentifier + .for("module.hot") + .tap( + "NodeStuffPlugin", + ParserHelpers.evaluateToIdentifier("module.hot", false) + ); + parser.hooks.expression.for("module").tap("NodeStuffPlugin", () => { + const module = parser.state.module; + const isHarmony = module.buildMeta && module.buildMeta.exportsType; + let moduleJsPath = path.join( + __dirname, + "..", + "buildin", + isHarmony ? "harmony-module.js" : "module.js" + ); + if (module.context) { + moduleJsPath = path.relative( + parser.state.module.context, + moduleJsPath + ); + if (!/^[A-Z]:/i.test(moduleJsPath)) { + moduleJsPath = `./${moduleJsPath.replace(/\\/g, "/")}`; + } + } + return ParserHelpers.addParsedVariableToModule( + parser, + "module", + `require(${JSON.stringify(moduleJsPath)})(module)` + ); + }); + }; + + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("NodeStuffPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("NodeStuffPlugin", handler); + } + ); + } +} +module.exports = NodeStuffPlugin; diff --git a/node_modules/webpack/lib/NormalModule.js b/node_modules/webpack/lib/NormalModule.js index c3288bf0d..fdabc3000 100644 --- a/node_modules/webpack/lib/NormalModule.js +++ b/node_modules/webpack/lib/NormalModule.js @@ -1,556 +1,542 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const path = require("path"); -const NativeModule = require("module"); -const crypto = require("crypto"); - -const SourceMapSource = require("webpack-sources").SourceMapSource; -const OriginalSource = require("webpack-sources").OriginalSource; -const RawSource = require("webpack-sources").RawSource; -const ReplaceSource = require("webpack-sources").ReplaceSource; -const CachedSource = require("webpack-sources").CachedSource; -const LineToLineMappedSource = require("webpack-sources").LineToLineMappedSource; - -const WebpackError = require("./WebpackError"); -const Module = require("./Module"); -const ModuleParseError = require("./ModuleParseError"); -const ModuleBuildError = require("./ModuleBuildError"); -const ModuleError = require("./ModuleError"); -const ModuleWarning = require("./ModuleWarning"); - -const runLoaders = require("loader-runner").runLoaders; -const getContext = require("loader-runner").getContext; - -function asString(buf) { - if(Buffer.isBuffer(buf)) { - return buf.toString("utf-8"); - } - return buf; -} - -function contextify(context, request) { - return request.split("!").map(function(r) { - const splitPath = r.split("?"); - splitPath[0] = path.relative(context, splitPath[0]); - if(path.sep === "\\") - splitPath[0] = splitPath[0].replace(/\\/g, "/"); - if(splitPath[0].indexOf("../") !== 0) - splitPath[0] = "./" + splitPath[0]; - return splitPath.join("?"); - }).join("!"); -} - -class NonErrorEmittedError extends WebpackError { - constructor(error) { - super(); - - this.name = "NonErrorEmittedError"; - this.message = "(Emitted value instead of an instance of Error) " + error; - - Error.captureStackTrace(this, this.constructor); - } -} - -const dependencyTemplatesHashMap = new WeakMap(); - -class NormalModule extends Module { - - constructor(request, userRequest, rawRequest, loaders, resource, parser) { - super(); - this.request = request; - this.userRequest = userRequest; - this.rawRequest = rawRequest; - this.parser = parser; - this.resource = resource; - this.context = getContext(resource); - this.loaders = loaders; - this.fileDependencies = []; - this.contextDependencies = []; - this.warnings = []; - this.errors = []; - this.error = null; - this._source = null; - this.assets = {}; - this.built = false; - this._cachedSource = null; - } - - identifier() { - return this.request; - } - - readableIdentifier(requestShortener) { - return requestShortener.shorten(this.userRequest); - } - - libIdent(options) { - return contextify(options.context, this.userRequest); - } - - nameForCondition() { - const idx = this.resource.indexOf("?"); - if(idx >= 0) return this.resource.substr(0, idx); - return this.resource; - } - - createSourceForAsset(name, content, sourceMap) { - if(!sourceMap) { - return new RawSource(content); - } - - if(typeof sourceMap === "string") { - return new OriginalSource(content, sourceMap); - } - - return new SourceMapSource(content, name, sourceMap); - } - - createLoaderContext(resolver, options, compilation, fs) { - const loaderContext = { - version: 2, - emitWarning: (warning) => { - if(!(warning instanceof Error)) - warning = new NonErrorEmittedError(warning); - this.warnings.push(new ModuleWarning(this, warning)); - }, - emitError: (error) => { - if(!(error instanceof Error)) - error = new NonErrorEmittedError(error); - this.errors.push(new ModuleError(this, error)); - }, - exec: (code, filename) => { - const module = new NativeModule(filename, this); - module.paths = NativeModule._nodeModulePaths(this.context); - module.filename = filename; - module._compile(code, filename); - return module.exports; - }, - resolve(context, request, callback) { - resolver.resolve({}, context, request, callback); - }, - resolveSync(context, request) { - return resolver.resolveSync({}, context, request); - }, - emitFile: (name, content, sourceMap) => { - this.assets[name] = this.createSourceForAsset(name, content, sourceMap); - }, - options: options, - webpack: true, - sourceMap: !!this.useSourceMap, - _module: this, - _compilation: compilation, - _compiler: compilation.compiler, - fs: fs, - }; - - compilation.applyPlugins("normal-module-loader", loaderContext, this); - if(options.loader) - Object.assign(loaderContext, options.loader); - - return loaderContext; - } - - createSource(source, resourceBuffer, sourceMap) { - // if there is no identifier return raw source - if(!this.identifier) { - return new RawSource(source); - } - - // from here on we assume we have an identifier - const identifier = this.identifier(); - - if(this.lineToLine && resourceBuffer) { - return new LineToLineMappedSource( - source, identifier, asString(resourceBuffer)); - } - - if(this.useSourceMap && sourceMap) { - return new SourceMapSource(source, identifier, sourceMap); - } - - return new OriginalSource(source, identifier); - } - - doBuild(options, compilation, resolver, fs, callback) { - this.cacheable = false; - const loaderContext = this.createLoaderContext(resolver, options, compilation, fs); - - runLoaders({ - resource: this.resource, - loaders: this.loaders, - context: loaderContext, - readResource: fs.readFile.bind(fs) - }, (err, result) => { - if(result) { - this.cacheable = result.cacheable; - this.fileDependencies = result.fileDependencies; - this.contextDependencies = result.contextDependencies; - } - - if(err) { - const error = new ModuleBuildError(this, err); - return callback(error); - } - - const resourceBuffer = result.resourceBuffer; - const source = result.result[0]; - const sourceMap = result.result[1]; - - if(!Buffer.isBuffer(source) && typeof source !== "string") { - const error = new ModuleBuildError(this, new Error("Final loader didn't return a Buffer or String")); - return callback(error); - } - - this._source = this.createSource(asString(source), resourceBuffer, sourceMap); - return callback(); - }); - } - - disconnect() { - this.built = false; - super.disconnect(); - } - - markModuleAsErrored(error) { - this.meta = null; - this.error = error; - this.errors.push(this.error); - this._source = new RawSource("throw new Error(" + JSON.stringify(this.error.message) + ");"); - } - - applyNoParseRule(rule, content) { - // must start with "rule" if rule is a string - if(typeof rule === "string") { - return content.indexOf(rule) === 0; - } - - if(typeof rule === "function") { - return rule(content); - } - // we assume rule is a regexp - return rule.test(content); - } - - // check if module should not be parsed - // returns "true" if the module should !not! be parsed - // returns "false" if the module !must! be parsed - shouldPreventParsing(noParseRule, request) { - // if no noParseRule exists, return false - // the module !must! be parsed. - if(!noParseRule) { - return false; - } - - // we only have one rule to check - if(!Array.isArray(noParseRule)) { - // returns "true" if the module is !not! to be parsed - return this.applyNoParseRule(noParseRule, request); - } - - for(let i = 0; i < noParseRule.length; i++) { - const rule = noParseRule[i]; - // early exit on first truthy match - // this module is !not! to be parsed - if(this.applyNoParseRule(rule, request)) { - return true; - } - } - // no match found, so this module !should! be parsed - return false; - } - - build(options, compilation, resolver, fs, callback) { - this.buildTimestamp = Date.now(); - this.built = true; - this._source = null; - this.error = null; - this.errors.length = 0; - this.warnings.length = 0; - this.meta = {}; - - return this.doBuild(options, compilation, resolver, fs, (err) => { - this.dependencies.length = 0; - this.variables.length = 0; - this.blocks.length = 0; - this._cachedSource = null; - - // if we have an error mark module as failed and exit - if(err) { - this.markModuleAsErrored(err); - return callback(); - } - - // check if this module should !not! be parsed. - // if so, exit here; - const noParseRule = options.module && options.module.noParse; - if(this.shouldPreventParsing(noParseRule, this.request)) { - return callback(); - } - - try { - this.parser.parse(this._source.source(), { - current: this, - module: this, - compilation: compilation, - options: options - }); - } catch(e) { - const source = this._source.source(); - const error = new ModuleParseError(this, source, e); - this.markModuleAsErrored(error); - return callback(); - } - return callback(); - }); - } - - getHashDigest(dependencyTemplates) { - let dtHash = dependencyTemplatesHashMap.get("hash"); - const hash = crypto.createHash("md5"); - this.updateHash(hash); - hash.update(`${dtHash}`); - return hash.digest("hex"); - } - - sourceDependency(dependency, dependencyTemplates, source, outputOptions, requestShortener) { - const template = dependencyTemplates.get(dependency.constructor); - if(!template) throw new Error("No template for dependency: " + dependency.constructor.name); - template.apply(dependency, source, outputOptions, requestShortener, dependencyTemplates); - } - - sourceVariables(variable, availableVars, dependencyTemplates, outputOptions, requestShortener) { - const name = variable.name; - const expr = variable.expressionSource(dependencyTemplates, outputOptions, requestShortener); - - if(availableVars.some(v => v.name === name && v.expression.source() === expr.source())) { - return; - } - return { - name: name, - expression: expr - }; - } - - /* - * creates the start part of a IIFE around the module to inject a variable name - * (function(...){ <- this part - * }.call(...)) - */ - variableInjectionFunctionWrapperStartCode(varNames) { - const args = varNames.join(", "); - return `/* WEBPACK VAR INJECTION */(function(${args}) {`; - } - - contextArgument(block) { - if(this === block) { - return this.exportsArgument || "exports"; - } - return "this"; - } - - /* - * creates the end part of a IIFE around the module to inject a variable name - * (function(...){ - * }.call(...)) <- this part - */ - variableInjectionFunctionWrapperEndCode(varExpressions, block) { - const firstParam = this.contextArgument(block); - const furtherParams = varExpressions.map(e => e.source()).join(", "); - return `}.call(${firstParam}, ${furtherParams}))`; - } - - splitVariablesInUniqueNamedChunks(vars) { - const startState = [ - [] - ]; - return vars.reduce((chunks, variable) => { - const current = chunks[chunks.length - 1]; - // check if variable with same name exists already - // if so create a new chunk of variables. - const variableNameAlreadyExists = current.some(v => v.name === variable.name); - - if(variableNameAlreadyExists) { - // start new chunk with current variable - chunks.push([variable]); - } else { - // else add it to current chunk - current.push(variable); - } - return chunks; - }, startState); - } - - sourceBlock(block, availableVars, dependencyTemplates, source, outputOptions, requestShortener) { - block.dependencies.forEach((dependency) => this.sourceDependency( - dependency, dependencyTemplates, source, outputOptions, requestShortener)); - - /** - * Get the variables of all blocks that we need to inject. - * These will contain the variable name and its expression. - * The name will be added as a paramter in a IIFE the expression as its value. - */ - const vars = block.variables.reduce((result, value) => { - const variable = this.sourceVariables( - value, availableVars, dependencyTemplates, outputOptions, requestShortener); - - if(variable) { - result.push(variable); - } - - return result; - }, []); - - /** - * if we actually have variables - * this is important as how #splitVariablesInUniqueNamedChunks works - * it will always return an array in an array which would lead to a IIFE wrapper around - * a module if we do this with an empty vars array. - */ - if(vars.length > 0) { - /** - * Split all variables up into chunks of unique names. - * e.g. imagine you have the following variable names that need to be injected: - * [foo, bar, baz, foo, some, more] - * we can not inject "foo" twice, therefore we just make two IIFEs like so: - * (function(foo, bar, baz){ - * (function(foo, some, more){ - * ... - * }(...)); - * }(...)); - * - * "splitVariablesInUniqueNamedChunks" splits the variables shown above up to this: - * [[foo, bar, baz], [foo, some, more]] - */ - const injectionVariableChunks = this.splitVariablesInUniqueNamedChunks(vars); - - // create all the beginnings of IIFEs - const functionWrapperStarts = injectionVariableChunks.map((variableChunk) => { - return this.variableInjectionFunctionWrapperStartCode( - variableChunk.map(variable => variable.name) - ); - }); - - // and all the ends - const functionWrapperEnds = injectionVariableChunks.map((variableChunk) => { - return this.variableInjectionFunctionWrapperEndCode( - variableChunk.map(variable => variable.expression), block - ); - }); - - // join them to one big string - const varStartCode = functionWrapperStarts.join(""); - - // reverse the ends first before joining them, as the last added must be the inner most - const varEndCode = functionWrapperEnds.reverse().join(""); - - // if we have anything, add it to the source - if(varStartCode && varEndCode) { - const start = block.range ? block.range[0] : -10; - const end = block.range ? block.range[1] : (this._source.size() + 1); - source.insert(start + 0.5, varStartCode); - source.insert(end + 0.5, "\n/* WEBPACK VAR INJECTION */" + varEndCode); - } - } - - block.blocks.forEach((block) => - this.sourceBlock( - block, - availableVars.concat(vars), - dependencyTemplates, - source, - outputOptions, - requestShortener - ) - ); - } - - source(dependencyTemplates, outputOptions, requestShortener) { - const hashDigest = this.getHashDigest(dependencyTemplates); - if(this._cachedSource && this._cachedSource.hash === hashDigest) { - return this._cachedSource.source; - } - - if(!this._source) { - return new RawSource("throw new Error('No source available');"); - } - - const source = new ReplaceSource(this._source); - this._cachedSource = { - source: source, - hash: hashDigest - }; - - this.sourceBlock(this, [], dependencyTemplates, source, outputOptions, requestShortener); - return new CachedSource(source); - } - - originalSource() { - return this._source; - } - - getHighestTimestamp(keys, timestampsByKey) { - let highestTimestamp = 0; - for(let i = 0; i < keys.length; i++) { - const key = keys[i]; - const timestamp = timestampsByKey[key]; - // if there is no timestamp yet, early return with Infinity - if(!timestamp) return Infinity; - highestTimestamp = Math.max(highestTimestamp, timestamp); - } - return highestTimestamp; - } - - needRebuild(fileTimestamps, contextTimestamps) { - const highestFileDepTimestamp = this.getHighestTimestamp( - this.fileDependencies, fileTimestamps); - // if the hightest is Infinity, we need a rebuild - // exit early here. - if(highestFileDepTimestamp === Infinity) { - return true; - } - - const highestContextDepTimestamp = this.getHighestTimestamp( - this.contextDependencies, contextTimestamps); - - // Again if the hightest is Infinity, we need a rebuild - // exit early here. - if(highestContextDepTimestamp === Infinity) { - return true; - } - - // else take the highest of file and context timestamps and compare - // to last build timestamp - return Math.max(highestContextDepTimestamp, highestFileDepTimestamp) >= this.buildTimestamp; - } - - size() { - return this._source ? this._source.size() : -1; - } - - updateHashWithSource(hash) { - if(!this._source) { - hash.update("null"); - return; - } - hash.update("source"); - this._source.updateHash(hash); - } - - updateHashWithMeta(hash) { - hash.update("meta"); - hash.update(JSON.stringify(this.meta)); - } - - updateHash(hash) { - this.updateHashWithSource(hash); - this.updateHashWithMeta(hash); - super.updateHash(hash); - } - -} - -module.exports = NormalModule; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const NativeModule = require("module"); + +const { + CachedSource, + LineToLineMappedSource, + OriginalSource, + RawSource, + SourceMapSource +} = require("webpack-sources"); +const { getContext, runLoaders } = require("loader-runner"); + +const WebpackError = require("./WebpackError"); +const Module = require("./Module"); +const ModuleParseError = require("./ModuleParseError"); +const ModuleBuildError = require("./ModuleBuildError"); +const ModuleError = require("./ModuleError"); +const ModuleWarning = require("./ModuleWarning"); +const createHash = require("./util/createHash"); +const contextify = require("./util/identifier").contextify; + +/** @typedef {import("./util/createHash").Hash} Hash */ + +const asString = buf => { + if (Buffer.isBuffer(buf)) { + return buf.toString("utf-8"); + } + return buf; +}; + +const asBuffer = str => { + if (!Buffer.isBuffer(str)) { + return Buffer.from(str, "utf-8"); + } + return str; +}; + +class NonErrorEmittedError extends WebpackError { + constructor(error) { + super(); + + this.name = "NonErrorEmittedError"; + this.message = "(Emitted value instead of an instance of Error) " + error; + + Error.captureStackTrace(this, this.constructor); + } +} + +/** + * @typedef {Object} CachedSourceEntry + * @property {TODO} source the generated source + * @property {string} hash the hash value + */ + +class NormalModule extends Module { + constructor({ + type, + request, + userRequest, + rawRequest, + loaders, + resource, + matchResource, + parser, + generator, + resolveOptions + }) { + super(type, getContext(resource)); + + // Info from Factory + this.request = request; + this.userRequest = userRequest; + this.rawRequest = rawRequest; + this.binary = type.startsWith("webassembly"); + this.parser = parser; + this.generator = generator; + this.resource = resource; + this.matchResource = matchResource; + this.loaders = loaders; + if (resolveOptions !== undefined) this.resolveOptions = resolveOptions; + + // Info from Build + this.error = null; + this._source = null; + this._buildHash = ""; + this.buildTimestamp = undefined; + /** @private @type {Map} */ + this._cachedSources = new Map(); + + // Options for the NormalModule set by plugins + // TODO refactor this -> options object filled from Factory + this.useSourceMap = false; + this.lineToLine = false; + + // Cache + this._lastSuccessfulBuildMeta = {}; + } + + identifier() { + return this.request; + } + + readableIdentifier(requestShortener) { + return requestShortener.shorten(this.userRequest); + } + + libIdent(options) { + return contextify(options.context, this.userRequest); + } + + nameForCondition() { + const resource = this.matchResource || this.resource; + const idx = resource.indexOf("?"); + if (idx >= 0) return resource.substr(0, idx); + return resource; + } + + updateCacheModule(module) { + this.type = module.type; + this.request = module.request; + this.userRequest = module.userRequest; + this.rawRequest = module.rawRequest; + this.parser = module.parser; + this.generator = module.generator; + this.resource = module.resource; + this.matchResource = module.matchResource; + this.loaders = module.loaders; + this.resolveOptions = module.resolveOptions; + } + + createSourceForAsset(name, content, sourceMap) { + if (!sourceMap) { + return new RawSource(content); + } + + if (typeof sourceMap === "string") { + return new OriginalSource(content, sourceMap); + } + + return new SourceMapSource(content, name, sourceMap); + } + + createLoaderContext(resolver, options, compilation, fs) { + const requestShortener = compilation.runtimeTemplate.requestShortener; + const loaderContext = { + version: 2, + emitWarning: warning => { + if (!(warning instanceof Error)) { + warning = new NonErrorEmittedError(warning); + } + const currentLoader = this.getCurrentLoader(loaderContext); + this.warnings.push( + new ModuleWarning(this, warning, { + from: requestShortener.shorten(currentLoader.loader) + }) + ); + }, + emitError: error => { + if (!(error instanceof Error)) { + error = new NonErrorEmittedError(error); + } + const currentLoader = this.getCurrentLoader(loaderContext); + this.errors.push( + new ModuleError(this, error, { + from: requestShortener.shorten(currentLoader.loader) + }) + ); + }, + // TODO remove in webpack 5 + exec: (code, filename) => { + // @ts-ignore Argument of type 'this' is not assignable to parameter of type 'Module'. + const module = new NativeModule(filename, this); + // @ts-ignore _nodeModulePaths is deprecated and undocumented Node.js API + module.paths = NativeModule._nodeModulePaths(this.context); + module.filename = filename; + module._compile(code, filename); + return module.exports; + }, + resolve(context, request, callback) { + resolver.resolve({}, context, request, {}, callback); + }, + emitFile: (name, content, sourceMap) => { + if (!this.buildInfo.assets) { + this.buildInfo.assets = Object.create(null); + } + this.buildInfo.assets[name] = this.createSourceForAsset( + name, + content, + sourceMap + ); + }, + rootContext: options.context, + webpack: true, + sourceMap: !!this.useSourceMap, + _module: this, + _compilation: compilation, + _compiler: compilation.compiler, + fs: fs + }; + + compilation.hooks.normalModuleLoader.call(loaderContext, this); + if (options.loader) { + Object.assign(loaderContext, options.loader); + } + + return loaderContext; + } + + getCurrentLoader(loaderContext, index = loaderContext.loaderIndex) { + if ( + this.loaders && + this.loaders.length && + index < this.loaders.length && + index >= 0 && + this.loaders[index] + ) { + return this.loaders[index]; + } + return null; + } + + createSource(source, resourceBuffer, sourceMap) { + // if there is no identifier return raw source + if (!this.identifier) { + return new RawSource(source); + } + + // from here on we assume we have an identifier + const identifier = this.identifier(); + + if (this.lineToLine && resourceBuffer) { + return new LineToLineMappedSource( + source, + identifier, + asString(resourceBuffer) + ); + } + + if (this.useSourceMap && sourceMap) { + return new SourceMapSource(source, identifier, sourceMap); + } + + if (Buffer.isBuffer(source)) { + // @ts-ignore + // TODO We need to fix @types/webpack-sources to allow RawSource to take a Buffer | string + return new RawSource(source); + } + + return new OriginalSource(source, identifier); + } + + doBuild(options, compilation, resolver, fs, callback) { + const loaderContext = this.createLoaderContext( + resolver, + options, + compilation, + fs + ); + + runLoaders( + { + resource: this.resource, + loaders: this.loaders, + context: loaderContext, + readResource: fs.readFile.bind(fs) + }, + (err, result) => { + if (result) { + this.buildInfo.cacheable = result.cacheable; + this.buildInfo.fileDependencies = new Set(result.fileDependencies); + this.buildInfo.contextDependencies = new Set( + result.contextDependencies + ); + } + + if (err) { + if (!(err instanceof Error)) { + err = new NonErrorEmittedError(err); + } + const currentLoader = this.getCurrentLoader(loaderContext); + const error = new ModuleBuildError(this, err, { + from: + currentLoader && + compilation.runtimeTemplate.requestShortener.shorten( + currentLoader.loader + ) + }); + return callback(error); + } + + const resourceBuffer = result.resourceBuffer; + const source = result.result[0]; + const sourceMap = result.result.length >= 1 ? result.result[1] : null; + const extraInfo = result.result.length >= 2 ? result.result[2] : null; + + if (!Buffer.isBuffer(source) && typeof source !== "string") { + const currentLoader = this.getCurrentLoader(loaderContext, 0); + const err = new Error( + `Final loader (${ + currentLoader + ? compilation.runtimeTemplate.requestShortener.shorten( + currentLoader.loader + ) + : "unknown" + }) didn't return a Buffer or String` + ); + const error = new ModuleBuildError(this, err); + return callback(error); + } + + this._source = this.createSource( + this.binary ? asBuffer(source) : asString(source), + resourceBuffer, + sourceMap + ); + this._ast = + typeof extraInfo === "object" && + extraInfo !== null && + extraInfo.webpackAST !== undefined + ? extraInfo.webpackAST + : null; + return callback(); + } + ); + } + + markModuleAsErrored(error) { + // Restore build meta from successful build to keep importing state + this.buildMeta = Object.assign({}, this._lastSuccessfulBuildMeta); + + this.error = error; + this.errors.push(this.error); + this._source = new RawSource( + "throw new Error(" + JSON.stringify(this.error.message) + ");" + ); + this._ast = null; + } + + applyNoParseRule(rule, content) { + // must start with "rule" if rule is a string + if (typeof rule === "string") { + return content.indexOf(rule) === 0; + } + + if (typeof rule === "function") { + return rule(content); + } + // we assume rule is a regexp + return rule.test(content); + } + + // check if module should not be parsed + // returns "true" if the module should !not! be parsed + // returns "false" if the module !must! be parsed + shouldPreventParsing(noParseRule, request) { + // if no noParseRule exists, return false + // the module !must! be parsed. + if (!noParseRule) { + return false; + } + + // we only have one rule to check + if (!Array.isArray(noParseRule)) { + // returns "true" if the module is !not! to be parsed + return this.applyNoParseRule(noParseRule, request); + } + + for (let i = 0; i < noParseRule.length; i++) { + const rule = noParseRule[i]; + // early exit on first truthy match + // this module is !not! to be parsed + if (this.applyNoParseRule(rule, request)) { + return true; + } + } + // no match found, so this module !should! be parsed + return false; + } + + _initBuildHash(compilation) { + const hash = createHash(compilation.outputOptions.hashFunction); + if (this._source) { + hash.update("source"); + this._source.updateHash(hash); + } + hash.update("meta"); + hash.update(JSON.stringify(this.buildMeta)); + this._buildHash = hash.digest("hex"); + } + + build(options, compilation, resolver, fs, callback) { + this.buildTimestamp = Date.now(); + this.built = true; + this._source = null; + this._ast = null; + this._buildHash = ""; + this.error = null; + this.errors.length = 0; + this.warnings.length = 0; + this.buildMeta = {}; + this.buildInfo = { + cacheable: false, + fileDependencies: new Set(), + contextDependencies: new Set() + }; + + return this.doBuild(options, compilation, resolver, fs, err => { + this._cachedSources.clear(); + + // if we have an error mark module as failed and exit + if (err) { + this.markModuleAsErrored(err); + this._initBuildHash(compilation); + return callback(); + } + + // check if this module should !not! be parsed. + // if so, exit here; + const noParseRule = options.module && options.module.noParse; + if (this.shouldPreventParsing(noParseRule, this.request)) { + this._initBuildHash(compilation); + return callback(); + } + + const handleParseError = e => { + const source = this._source.source(); + const error = new ModuleParseError(this, source, e); + this.markModuleAsErrored(error); + this._initBuildHash(compilation); + return callback(); + }; + + const handleParseResult = result => { + this._lastSuccessfulBuildMeta = this.buildMeta; + this._initBuildHash(compilation); + return callback(); + }; + + try { + const result = this.parser.parse( + this._ast || this._source.source(), + { + current: this, + module: this, + compilation: compilation, + options: options + }, + (err, result) => { + if (err) { + handleParseError(err); + } else { + handleParseResult(result); + } + } + ); + if (result !== undefined) { + // parse is sync + handleParseResult(result); + } + } catch (e) { + handleParseError(e); + } + }); + } + + getHashDigest(dependencyTemplates) { + // TODO webpack 5 refactor + let dtHash = dependencyTemplates.get("hash"); + return `${this.hash}-${dtHash}`; + } + + source(dependencyTemplates, runtimeTemplate, type = "javascript") { + const hashDigest = this.getHashDigest(dependencyTemplates); + const cacheEntry = this._cachedSources.get(type); + if (cacheEntry !== undefined && cacheEntry.hash === hashDigest) { + // We can reuse the cached source + return cacheEntry.source; + } + + const source = this.generator.generate( + this, + dependencyTemplates, + runtimeTemplate, + type + ); + + const cachedSource = new CachedSource(source); + this._cachedSources.set(type, { + source: cachedSource, + hash: hashDigest + }); + return cachedSource; + } + + originalSource() { + return this._source; + } + + needRebuild(fileTimestamps, contextTimestamps) { + // always try to rebuild in case of an error + if (this.error) return true; + + // always rebuild when module is not cacheable + if (!this.buildInfo.cacheable) return true; + + // Check timestamps of all dependencies + // Missing timestamp -> need rebuild + // Timestamp bigger than buildTimestamp -> need rebuild + for (const file of this.buildInfo.fileDependencies) { + const timestamp = fileTimestamps.get(file); + if (!timestamp) return true; + if (timestamp >= this.buildTimestamp) return true; + } + for (const file of this.buildInfo.contextDependencies) { + const timestamp = contextTimestamps.get(file); + if (!timestamp) return true; + if (timestamp >= this.buildTimestamp) return true; + } + // elsewise -> no rebuild needed + return false; + } + + size() { + return this._source ? this._source.size() : -1; + } + + /** + * @param {Hash} hash the hash used to track dependencies + * @returns {void} + */ + updateHash(hash) { + hash.update(this._buildHash); + super.updateHash(hash); + } +} + +module.exports = NormalModule; diff --git a/node_modules/webpack/lib/NormalModuleFactory.js b/node_modules/webpack/lib/NormalModuleFactory.js index 138b87d18..23ef0ae1d 100644 --- a/node_modules/webpack/lib/NormalModuleFactory.js +++ b/node_modules/webpack/lib/NormalModuleFactory.js @@ -1,292 +1,526 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra - */ -"use strict"; - -const asyncLib = require("async"); -const Tapable = require("tapable"); -const NormalModule = require("./NormalModule"); -const RawModule = require("./RawModule"); -const Parser = require("./Parser"); -const RuleSet = require("./RuleSet"); - -function loaderToIdent(data) { - if(!data.options) - return data.loader; - if(typeof data.options === "string") - return data.loader + "?" + data.options; - if(typeof data.options !== "object") - throw new Error("loader options must be string or object"); - if(data.ident) - return data.loader + "??" + data.ident; - return data.loader + "?" + JSON.stringify(data.options); -} - -function identToLoaderRequest(resultString) { - const idx = resultString.indexOf("?"); - let options; - - if(idx >= 0) { - options = resultString.substr(idx + 1); - resultString = resultString.substr(0, idx); - - return { - loader: resultString, - options - }; - } else { - return { - loader: resultString - }; - } -} - -class NormalModuleFactory extends Tapable { - constructor(context, resolvers, options) { - super(); - this.resolvers = resolvers; - this.ruleSet = new RuleSet(options.rules || options.loaders); - this.cachePredicate = typeof options.unsafeCache === "function" ? options.unsafeCache : Boolean.bind(null, options.unsafeCache); - this.context = context || ""; - this.parserCache = {}; - this.plugin("factory", () => (result, callback) => { - let resolver = this.applyPluginsWaterfall0("resolver", null); - - // Ignored - if(!resolver) return callback(); - - resolver(result, (err, data) => { - if(err) return callback(err); - - // Ignored - if(!data) return callback(); - - // direct module - if(typeof data.source === "function") - return callback(null, data); - - this.applyPluginsAsyncWaterfall("after-resolve", data, (err, result) => { - if(err) return callback(err); - - // Ignored - if(!result) return callback(); - - let createdModule = this.applyPluginsBailResult("create-module", result); - if(!createdModule) { - - if(!result.request) { - return callback(new Error("Empty dependency (no request)")); - } - - createdModule = new NormalModule( - result.request, - result.userRequest, - result.rawRequest, - result.loaders, - result.resource, - result.parser - ); - } - - createdModule = this.applyPluginsWaterfall0("module", createdModule); - - return callback(null, createdModule); - }); - }); - }); - this.plugin("resolver", () => (data, callback) => { - const contextInfo = data.contextInfo; - const context = data.context; - const request = data.request; - - const noAutoLoaders = /^-?!/.test(request); - const noPrePostAutoLoaders = /^!!/.test(request); - const noPostAutoLoaders = /^-!/.test(request); - let elements = request.replace(/^-?!+/, "").replace(/!!+/g, "!").split("!"); - let resource = elements.pop(); - elements = elements.map(identToLoaderRequest); - - asyncLib.parallel([ - callback => this.resolveRequestArray(contextInfo, context, elements, this.resolvers.loader, callback), - callback => { - if(resource === "" || resource[0] === "?") - return callback(null, { - resource - }); - - this.resolvers.normal.resolve(contextInfo, context, resource, (err, resource, resourceResolveData) => { - if(err) return callback(err); - callback(null, { - resourceResolveData, - resource - }); - }); - } - ], (err, results) => { - if(err) return callback(err); - let loaders = results[0]; - const resourceResolveData = results[1].resourceResolveData; - resource = results[1].resource; - - // translate option idents - try { - loaders.forEach(item => { - if(typeof item.options === "string" && /^\?/.test(item.options)) { - item.options = this.ruleSet.findOptionsByIdent(item.options.substr(1)); - } - }); - } catch(e) { - return callback(e); - } - - if(resource === false) { - // ignored - return callback(null, - new RawModule( - "/* (ignored) */", - `ignored ${context} ${request}`, - `${request} (ignored)` - ) - ); - } - - const userRequest = loaders.map(loaderToIdent).concat([resource]).join("!"); - - let resourcePath = resource; - let resourceQuery = ""; - const queryIndex = resourcePath.indexOf("?"); - if(queryIndex >= 0) { - resourceQuery = resourcePath.substr(queryIndex); - resourcePath = resourcePath.substr(0, queryIndex); - } - - const result = this.ruleSet.exec({ - resource: resourcePath, - resourceQuery, - issuer: contextInfo.issuer, - compiler: contextInfo.compiler - }); - const settings = {}; - const useLoadersPost = []; - const useLoaders = []; - const useLoadersPre = []; - result.forEach(r => { - if(r.type === "use") { - if(r.enforce === "post" && !noPostAutoLoaders && !noPrePostAutoLoaders) - useLoadersPost.push(r.value); - else if(r.enforce === "pre" && !noPrePostAutoLoaders) - useLoadersPre.push(r.value); - else if(!r.enforce && !noAutoLoaders && !noPrePostAutoLoaders) - useLoaders.push(r.value); - } else { - settings[r.type] = r.value; - } - }); - asyncLib.parallel([ - this.resolveRequestArray.bind(this, contextInfo, this.context, useLoadersPost, this.resolvers.loader), - this.resolveRequestArray.bind(this, contextInfo, this.context, useLoaders, this.resolvers.loader), - this.resolveRequestArray.bind(this, contextInfo, this.context, useLoadersPre, this.resolvers.loader) - ], (err, results) => { - if(err) return callback(err); - loaders = results[0].concat(loaders, results[1], results[2]); - process.nextTick(() => { - callback(null, { - context: context, - request: loaders.map(loaderToIdent).concat([resource]).join("!"), - dependencies: data.dependencies, - userRequest, - rawRequest: request, - loaders, - resource, - resourceResolveData, - parser: this.getParser(settings.parser) - }); - }); - }); - }); - }); - } - - create(data, callback) { - const dependencies = data.dependencies; - const cacheEntry = dependencies[0].__NormalModuleFactoryCache; - if(cacheEntry) return callback(null, cacheEntry); - const context = data.context || this.context; - const request = dependencies[0].request; - const contextInfo = data.contextInfo || {}; - this.applyPluginsAsyncWaterfall("before-resolve", { - contextInfo, - context, - request, - dependencies - }, (err, result) => { - if(err) return callback(err); - - // Ignored - if(!result) return callback(); - - const factory = this.applyPluginsWaterfall0("factory", null); - - // Ignored - if(!factory) return callback(); - - factory(result, (err, module) => { - if(err) return callback(err); - - if(module && this.cachePredicate(module)) { - dependencies.forEach(d => d.__NormalModuleFactoryCache = module); - } - - callback(null, module); - }); - }); - } - - resolveRequestArray(contextInfo, context, array, resolver, callback) { - if(array.length === 0) return callback(null, []); - asyncLib.map(array, (item, callback) => { - resolver.resolve(contextInfo, context, item.loader, (err, result) => { - if(err && /^[^/]*$/.test(item.loader) && !/-loader$/.test(item.loader)) { - return resolver.resolve(contextInfo, context, item.loader + "-loader", err2 => { - if(!err2) { - err.message = err.message + "\n" + - "BREAKING CHANGE: It's no longer allowed to omit the '-loader' suffix when using loaders.\n" + - ` You need to specify '${item.loader}-loader' instead of '${item.loader}',\n` + - " see https://webpack.js.org/guides/migrating/#automatic-loader-module-name-extension-removed"; - } - callback(err); - }); - } - if(err) return callback(err); - - const optionsOnly = item.options ? { - options: item.options - } : undefined; - return callback(null, Object.assign({}, item, identToLoaderRequest(result), optionsOnly)); - }); - }, callback); - } - - getParser(parserOptions) { - let ident = "null"; - if(parserOptions) { - if(parserOptions.ident) - ident = parserOptions.ident; - else - ident = JSON.stringify(parserOptions); - } - const parser = this.parserCache[ident]; - if(parser) - return parser; - return this.parserCache[ident] = this.createParser(parserOptions); - } - - createParser(parserOptions) { - const parser = new Parser(); - this.applyPlugins2("parser", parser, parserOptions || {}); - return parser; - } -} - -module.exports = NormalModuleFactory; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra + */ +"use strict"; + +const path = require("path"); +const asyncLib = require("neo-async"); +const { + Tapable, + AsyncSeriesWaterfallHook, + SyncWaterfallHook, + SyncBailHook, + SyncHook, + HookMap +} = require("tapable"); +const NormalModule = require("./NormalModule"); +const RawModule = require("./RawModule"); +const RuleSet = require("./RuleSet"); +const cachedMerge = require("./util/cachedMerge"); + +const EMPTY_RESOLVE_OPTIONS = {}; + +const MATCH_RESOURCE_REGEX = /^([^!]+)!=!/; + +const loaderToIdent = data => { + if (!data.options) { + return data.loader; + } + if (typeof data.options === "string") { + return data.loader + "?" + data.options; + } + if (typeof data.options !== "object") { + throw new Error("loader options must be string or object"); + } + if (data.ident) { + return data.loader + "??" + data.ident; + } + return data.loader + "?" + JSON.stringify(data.options); +}; + +const identToLoaderRequest = resultString => { + const idx = resultString.indexOf("?"); + if (idx >= 0) { + const loader = resultString.substr(0, idx); + const options = resultString.substr(idx + 1); + return { + loader, + options + }; + } else { + return { + loader: resultString, + options: undefined + }; + } +}; + +const dependencyCache = new WeakMap(); + +class NormalModuleFactory extends Tapable { + constructor(context, resolverFactory, options) { + super(); + this.hooks = { + resolver: new SyncWaterfallHook(["resolver"]), + factory: new SyncWaterfallHook(["factory"]), + beforeResolve: new AsyncSeriesWaterfallHook(["data"]), + afterResolve: new AsyncSeriesWaterfallHook(["data"]), + createModule: new SyncBailHook(["data"]), + module: new SyncWaterfallHook(["module", "data"]), + createParser: new HookMap(() => new SyncBailHook(["parserOptions"])), + parser: new HookMap(() => new SyncHook(["parser", "parserOptions"])), + createGenerator: new HookMap( + () => new SyncBailHook(["generatorOptions"]) + ), + generator: new HookMap( + () => new SyncHook(["generator", "generatorOptions"]) + ) + }; + this._pluginCompat.tap("NormalModuleFactory", options => { + switch (options.name) { + case "before-resolve": + case "after-resolve": + options.async = true; + break; + case "parser": + this.hooks.parser + .for("javascript/auto") + .tap(options.fn.name || "unnamed compat plugin", options.fn); + return true; + } + let match; + match = /^parser (.+)$/.exec(options.name); + if (match) { + this.hooks.parser + .for(match[1]) + .tap( + options.fn.name || "unnamed compat plugin", + options.fn.bind(this) + ); + return true; + } + match = /^create-parser (.+)$/.exec(options.name); + if (match) { + this.hooks.createParser + .for(match[1]) + .tap( + options.fn.name || "unnamed compat plugin", + options.fn.bind(this) + ); + return true; + } + }); + this.resolverFactory = resolverFactory; + this.ruleSet = new RuleSet(options.defaultRules.concat(options.rules)); + this.cachePredicate = + typeof options.unsafeCache === "function" + ? options.unsafeCache + : Boolean.bind(null, options.unsafeCache); + this.context = context || ""; + this.parserCache = Object.create(null); + this.generatorCache = Object.create(null); + this.hooks.factory.tap("NormalModuleFactory", () => (result, callback) => { + let resolver = this.hooks.resolver.call(null); + + // Ignored + if (!resolver) return callback(); + + resolver(result, (err, data) => { + if (err) return callback(err); + + // Ignored + if (!data) return callback(); + + // direct module + if (typeof data.source === "function") return callback(null, data); + + this.hooks.afterResolve.callAsync(data, (err, result) => { + if (err) return callback(err); + + // Ignored + if (!result) return callback(); + + let createdModule = this.hooks.createModule.call(result); + if (!createdModule) { + if (!result.request) { + return callback(new Error("Empty dependency (no request)")); + } + + createdModule = new NormalModule(result); + } + + createdModule = this.hooks.module.call(createdModule, result); + + return callback(null, createdModule); + }); + }); + }); + this.hooks.resolver.tap("NormalModuleFactory", () => (data, callback) => { + const contextInfo = data.contextInfo; + const context = data.context; + const request = data.request; + + const loaderResolver = this.getResolver("loader"); + const normalResolver = this.getResolver("normal", data.resolveOptions); + + let matchResource = undefined; + let requestWithoutMatchResource = request; + const matchResourceMatch = MATCH_RESOURCE_REGEX.exec(request); + if (matchResourceMatch) { + matchResource = matchResourceMatch[1]; + if (/^\.\.?\//.test(matchResource)) { + matchResource = path.join(context, matchResource); + } + requestWithoutMatchResource = request.substr( + matchResourceMatch[0].length + ); + } + + const noPreAutoLoaders = requestWithoutMatchResource.startsWith("-!"); + const noAutoLoaders = + noPreAutoLoaders || requestWithoutMatchResource.startsWith("!"); + const noPrePostAutoLoaders = requestWithoutMatchResource.startsWith("!!"); + let elements = requestWithoutMatchResource + .replace(/^-?!+/, "") + .replace(/!!+/g, "!") + .split("!"); + let resource = elements.pop(); + elements = elements.map(identToLoaderRequest); + + asyncLib.parallel( + [ + callback => + this.resolveRequestArray( + contextInfo, + context, + elements, + loaderResolver, + callback + ), + callback => { + if (resource === "" || resource[0] === "?") { + return callback(null, { + resource + }); + } + + normalResolver.resolve( + contextInfo, + context, + resource, + {}, + (err, resource, resourceResolveData) => { + if (err) return callback(err); + callback(null, { + resourceResolveData, + resource + }); + } + ); + } + ], + (err, results) => { + if (err) return callback(err); + let loaders = results[0]; + const resourceResolveData = results[1].resourceResolveData; + resource = results[1].resource; + + // translate option idents + try { + for (const item of loaders) { + if (typeof item.options === "string" && item.options[0] === "?") { + const ident = item.options.substr(1); + item.options = this.ruleSet.findOptionsByIdent(ident); + item.ident = ident; + } + } + } catch (e) { + return callback(e); + } + + if (resource === false) { + // ignored + return callback( + null, + new RawModule( + "/* (ignored) */", + `ignored ${context} ${request}`, + `${request} (ignored)` + ) + ); + } + + const userRequest = + (matchResource !== undefined ? `${matchResource}!=!` : "") + + loaders + .map(loaderToIdent) + .concat([resource]) + .join("!"); + + let resourcePath = + matchResource !== undefined ? matchResource : resource; + let resourceQuery = ""; + const queryIndex = resourcePath.indexOf("?"); + if (queryIndex >= 0) { + resourceQuery = resourcePath.substr(queryIndex); + resourcePath = resourcePath.substr(0, queryIndex); + } + + const result = this.ruleSet.exec({ + resource: resourcePath, + realResource: + matchResource !== undefined + ? resource.replace(/\?.*/, "") + : resourcePath, + resourceQuery, + issuer: contextInfo.issuer, + compiler: contextInfo.compiler + }); + const settings = {}; + const useLoadersPost = []; + const useLoaders = []; + const useLoadersPre = []; + for (const r of result) { + if (r.type === "use") { + if (r.enforce === "post" && !noPrePostAutoLoaders) { + useLoadersPost.push(r.value); + } else if ( + r.enforce === "pre" && + !noPreAutoLoaders && + !noPrePostAutoLoaders + ) { + useLoadersPre.push(r.value); + } else if ( + !r.enforce && + !noAutoLoaders && + !noPrePostAutoLoaders + ) { + useLoaders.push(r.value); + } + } else if ( + typeof r.value === "object" && + r.value !== null && + typeof settings[r.type] === "object" && + settings[r.type] !== null + ) { + settings[r.type] = cachedMerge(settings[r.type], r.value); + } else { + settings[r.type] = r.value; + } + } + asyncLib.parallel( + [ + this.resolveRequestArray.bind( + this, + contextInfo, + this.context, + useLoadersPost, + loaderResolver + ), + this.resolveRequestArray.bind( + this, + contextInfo, + this.context, + useLoaders, + loaderResolver + ), + this.resolveRequestArray.bind( + this, + contextInfo, + this.context, + useLoadersPre, + loaderResolver + ) + ], + (err, results) => { + if (err) return callback(err); + loaders = results[0].concat(loaders, results[1], results[2]); + process.nextTick(() => { + const type = settings.type; + const resolveOptions = settings.resolve; + callback(null, { + context: context, + request: loaders + .map(loaderToIdent) + .concat([resource]) + .join("!"), + dependencies: data.dependencies, + userRequest, + rawRequest: request, + loaders, + resource, + matchResource, + resourceResolveData, + settings, + type, + parser: this.getParser(type, settings.parser), + generator: this.getGenerator(type, settings.generator), + resolveOptions + }); + }); + } + ); + } + ); + }); + } + + create(data, callback) { + const dependencies = data.dependencies; + const cacheEntry = dependencyCache.get(dependencies[0]); + if (cacheEntry) return callback(null, cacheEntry); + const context = data.context || this.context; + const resolveOptions = data.resolveOptions || EMPTY_RESOLVE_OPTIONS; + const request = dependencies[0].request; + const contextInfo = data.contextInfo || {}; + this.hooks.beforeResolve.callAsync( + { + contextInfo, + resolveOptions, + context, + request, + dependencies + }, + (err, result) => { + if (err) return callback(err); + + // Ignored + if (!result) return callback(); + + const factory = this.hooks.factory.call(null); + + // Ignored + if (!factory) return callback(); + + factory(result, (err, module) => { + if (err) return callback(err); + + if (module && this.cachePredicate(module)) { + for (const d of dependencies) { + dependencyCache.set(d, module); + } + } + + callback(null, module); + }); + } + ); + } + + resolveRequestArray(contextInfo, context, array, resolver, callback) { + if (array.length === 0) return callback(null, []); + asyncLib.map( + array, + (item, callback) => { + resolver.resolve( + contextInfo, + context, + item.loader, + {}, + (err, result) => { + if ( + err && + /^[^/]*$/.test(item.loader) && + !/-loader$/.test(item.loader) + ) { + return resolver.resolve( + contextInfo, + context, + item.loader + "-loader", + {}, + err2 => { + if (!err2) { + err.message = + err.message + + "\n" + + "BREAKING CHANGE: It's no longer allowed to omit the '-loader' suffix when using loaders.\n" + + ` You need to specify '${ + item.loader + }-loader' instead of '${item.loader}',\n` + + " see https://webpack.js.org/migrate/3/#automatic-loader-module-name-extension-removed"; + } + callback(err); + } + ); + } + if (err) return callback(err); + + const optionsOnly = item.options + ? { + options: item.options + } + : undefined; + return callback( + null, + Object.assign({}, item, identToLoaderRequest(result), optionsOnly) + ); + } + ); + }, + callback + ); + } + + getParser(type, parserOptions) { + let ident = type; + if (parserOptions) { + if (parserOptions.ident) { + ident = `${type}|${parserOptions.ident}`; + } else { + ident = JSON.stringify([type, parserOptions]); + } + } + if (ident in this.parserCache) { + return this.parserCache[ident]; + } + return (this.parserCache[ident] = this.createParser(type, parserOptions)); + } + + createParser(type, parserOptions = {}) { + const parser = this.hooks.createParser.for(type).call(parserOptions); + if (!parser) { + throw new Error(`No parser registered for ${type}`); + } + this.hooks.parser.for(type).call(parser, parserOptions); + return parser; + } + + getGenerator(type, generatorOptions) { + let ident = type; + if (generatorOptions) { + if (generatorOptions.ident) { + ident = `${type}|${generatorOptions.ident}`; + } else { + ident = JSON.stringify([type, generatorOptions]); + } + } + if (ident in this.generatorCache) { + return this.generatorCache[ident]; + } + return (this.generatorCache[ident] = this.createGenerator( + type, + generatorOptions + )); + } + + createGenerator(type, generatorOptions = {}) { + const generator = this.hooks.createGenerator + .for(type) + .call(generatorOptions); + if (!generator) { + throw new Error(`No generator registered for ${type}`); + } + this.hooks.generator.for(type).call(generator, generatorOptions); + return generator; + } + + getResolver(type, resolveOptions) { + return this.resolverFactory.get( + type, + resolveOptions || EMPTY_RESOLVE_OPTIONS + ); + } +} + +module.exports = NormalModuleFactory; diff --git a/node_modules/webpack/lib/NormalModuleReplacementPlugin.js b/node_modules/webpack/lib/NormalModuleReplacementPlugin.js index 46a662d68..d4f23a58b 100644 --- a/node_modules/webpack/lib/NormalModuleReplacementPlugin.js +++ b/node_modules/webpack/lib/NormalModuleReplacementPlugin.js @@ -1,45 +1,51 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const path = require("path"); - -class NormalModuleReplacementPlugin { - constructor(resourceRegExp, newResource) { - this.resourceRegExp = resourceRegExp; - this.newResource = newResource; - } - - apply(compiler) { - const resourceRegExp = this.resourceRegExp; - const newResource = this.newResource; - compiler.plugin("normal-module-factory", (nmf) => { - nmf.plugin("before-resolve", (result, callback) => { - if(!result) return callback(); - if(resourceRegExp.test(result.request)) { - if(typeof newResource === "function") { - newResource(result); - } else { - result.request = newResource; - } - } - return callback(null, result); - }); - nmf.plugin("after-resolve", (result, callback) => { - if(!result) return callback(); - if(resourceRegExp.test(result.resource)) { - if(typeof newResource === "function") { - newResource(result); - } else { - result.resource = path.resolve(path.dirname(result.resource), newResource); - } - } - return callback(null, result); - }); - }); - } -} - -module.exports = NormalModuleReplacementPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const path = require("path"); + +class NormalModuleReplacementPlugin { + constructor(resourceRegExp, newResource) { + this.resourceRegExp = resourceRegExp; + this.newResource = newResource; + } + + apply(compiler) { + const resourceRegExp = this.resourceRegExp; + const newResource = this.newResource; + compiler.hooks.normalModuleFactory.tap( + "NormalModuleReplacementPlugin", + nmf => { + nmf.hooks.beforeResolve.tap("NormalModuleReplacementPlugin", result => { + if (!result) return; + if (resourceRegExp.test(result.request)) { + if (typeof newResource === "function") { + newResource(result); + } else { + result.request = newResource; + } + } + return result; + }); + nmf.hooks.afterResolve.tap("NormalModuleReplacementPlugin", result => { + if (!result) return; + if (resourceRegExp.test(result.resource)) { + if (typeof newResource === "function") { + newResource(result); + } else { + result.resource = path.resolve( + path.dirname(result.resource), + newResource + ); + } + } + return result; + }); + } + ); + } +} + +module.exports = NormalModuleReplacementPlugin; diff --git a/node_modules/webpack/lib/NullFactory.js b/node_modules/webpack/lib/NullFactory.js index 9ff4cb58e..90ede1fe3 100644 --- a/node_modules/webpack/lib/NullFactory.js +++ b/node_modules/webpack/lib/NullFactory.js @@ -1,12 +1,12 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class NullFactory { - create(data, callback) { - return callback(); - } -} -module.exports = NullFactory; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +class NullFactory { + create(data, callback) { + return callback(); + } +} +module.exports = NullFactory; diff --git a/node_modules/webpack/lib/OptionsApply.js b/node_modules/webpack/lib/OptionsApply.js index 022506360..3b1ec3164 100644 --- a/node_modules/webpack/lib/OptionsApply.js +++ b/node_modules/webpack/lib/OptionsApply.js @@ -1,10 +1,10 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class OptionsApply { - process(options, compiler) {} -} -module.exports = OptionsApply; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +class OptionsApply { + process(options, compiler) {} +} +module.exports = OptionsApply; diff --git a/node_modules/webpack/lib/OptionsDefaulter.js b/node_modules/webpack/lib/OptionsDefaulter.js index 42120689d..cad07ea06 100644 --- a/node_modules/webpack/lib/OptionsDefaulter.js +++ b/node_modules/webpack/lib/OptionsDefaulter.js @@ -1,73 +1,83 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -function getProperty(obj, name) { - name = name.split("."); - for(let i = 0; i < name.length - 1; i++) { - obj = obj[name[i]]; - if(typeof obj !== "object" || !obj) return; - } - return obj[name.pop()]; -} - -function setProperty(obj, name, value) { - name = name.split("."); - for(let i = 0; i < name.length - 1; i++) { - if(typeof obj[name[i]] !== "object" && typeof obj[name[i]] !== "undefined") return; - if(!obj[name[i]]) obj[name[i]] = {}; - obj = obj[name[i]]; - } - obj[name.pop()] = value; -} - -class OptionsDefaulter { - constructor() { - this.defaults = {}; - this.config = {}; - } - - process(options) { - // TODO: change this for webpack 4: options = Object.assign({}, options); - for(let name in this.defaults) { - switch(this.config[name]) { - case undefined: - if(getProperty(options, name) === undefined) - setProperty(options, name, this.defaults[name]); - break; - case "call": - setProperty(options, name, this.defaults[name].call(this, getProperty(options, name), options), options); - break; - case "make": - if(getProperty(options, name) === undefined) - setProperty(options, name, this.defaults[name].call(this, options), options); - break; - case "append": - { - let oldValue = getProperty(options, name); - if(!Array.isArray(oldValue)) oldValue = []; - oldValue.push.apply(oldValue, this.defaults[name]); - setProperty(options, name, oldValue); - break; - } - default: - throw new Error("OptionsDefaulter cannot process " + this.config[name]); - } - } - // TODO: change this for webpack 4: return options; - } - - set(name, config, def) { - if(arguments.length === 3) { - this.defaults[name] = def; - this.config[name] = config; - } else { - this.defaults[name] = config; - delete this.config[name]; - } - } -} - -module.exports = OptionsDefaulter; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const getProperty = (obj, name) => { + name = name.split("."); + for (let i = 0; i < name.length - 1; i++) { + obj = obj[name[i]]; + if (typeof obj !== "object" || !obj || Array.isArray(obj)) return; + } + return obj[name.pop()]; +}; + +const setProperty = (obj, name, value) => { + name = name.split("."); + for (let i = 0; i < name.length - 1; i++) { + if (typeof obj[name[i]] !== "object" && obj[name[i]] !== undefined) return; + if (Array.isArray(obj[name[i]])) return; + if (!obj[name[i]]) obj[name[i]] = {}; + obj = obj[name[i]]; + } + obj[name.pop()] = value; +}; + +class OptionsDefaulter { + constructor() { + this.defaults = {}; + this.config = {}; + } + + process(options) { + options = Object.assign({}, options); + for (let name in this.defaults) { + switch (this.config[name]) { + case undefined: + if (getProperty(options, name) === undefined) { + setProperty(options, name, this.defaults[name]); + } + break; + case "call": + setProperty( + options, + name, + this.defaults[name].call(this, getProperty(options, name), options) + ); + break; + case "make": + if (getProperty(options, name) === undefined) { + setProperty(options, name, this.defaults[name].call(this, options)); + } + break; + case "append": { + let oldValue = getProperty(options, name); + if (!Array.isArray(oldValue)) { + oldValue = []; + } + oldValue.push(...this.defaults[name]); + setProperty(options, name, oldValue); + break; + } + default: + throw new Error( + "OptionsDefaulter cannot process " + this.config[name] + ); + } + } + return options; + } + + set(name, config, def) { + if (def !== undefined) { + this.defaults[name] = def; + this.config[name] = config; + } else { + this.defaults[name] = config; + delete this.config[name]; + } + } +} + +module.exports = OptionsDefaulter; diff --git a/node_modules/webpack/lib/Parser.js b/node_modules/webpack/lib/Parser.js index 3150f847a..787f67d61 100644 --- a/node_modules/webpack/lib/Parser.js +++ b/node_modules/webpack/lib/Parser.js @@ -1,1462 +1,2202 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -// Syntax: https://developer.mozilla.org/en/SpiderMonkey/Parser_API - -const acorn = require("acorn-dynamic-import").default; -const Tapable = require("tapable"); -const json5 = require("json5"); -const BasicEvaluatedExpression = require("./BasicEvaluatedExpression"); - -function joinRanges(startRange, endRange) { - if(!endRange) return startRange; - if(!startRange) return endRange; - return [startRange[0], endRange[1]]; -} - -const ECMA_VERSION = 2017; - -const POSSIBLE_AST_OPTIONS = [{ - ranges: true, - locations: true, - ecmaVersion: ECMA_VERSION, - sourceType: "module", - plugins: { - dynamicImport: true - } -}, { - ranges: true, - locations: true, - ecmaVersion: ECMA_VERSION, - sourceType: "script", - plugins: { - dynamicImport: true - } -}]; - -class Parser extends Tapable { - constructor(options) { - super(); - this.options = options; - this.scope = undefined; - this.state = undefined; - this.comments = undefined; - this.initializeEvaluating(); - } - - initializeEvaluating() { - this.plugin("evaluate Literal", expr => { - switch(typeof expr.value) { - case "number": - return new BasicEvaluatedExpression().setNumber(expr.value).setRange(expr.range); - case "string": - return new BasicEvaluatedExpression().setString(expr.value).setRange(expr.range); - case "boolean": - return new BasicEvaluatedExpression().setBoolean(expr.value).setRange(expr.range); - } - if(expr.value === null) - return new BasicEvaluatedExpression().setNull().setRange(expr.range); - if(expr.value instanceof RegExp) - return new BasicEvaluatedExpression().setRegExp(expr.value).setRange(expr.range); - }); - this.plugin("evaluate LogicalExpression", function(expr) { - let left; - let leftAsBool; - let right; - if(expr.operator === "&&") { - left = this.evaluateExpression(expr.left); - leftAsBool = left && left.asBool(); - if(leftAsBool === false) return left.setRange(expr.range); - if(leftAsBool !== true) return; - right = this.evaluateExpression(expr.right); - return right.setRange(expr.range); - } else if(expr.operator === "||") { - left = this.evaluateExpression(expr.left); - leftAsBool = left && left.asBool(); - if(leftAsBool === true) return left.setRange(expr.range); - if(leftAsBool !== false) return; - right = this.evaluateExpression(expr.right); - return right.setRange(expr.range); - } - }); - this.plugin("evaluate BinaryExpression", function(expr) { - let left; - let right; - let res; - if(expr.operator === "+") { - left = this.evaluateExpression(expr.left); - right = this.evaluateExpression(expr.right); - if(!left || !right) return; - res = new BasicEvaluatedExpression(); - if(left.isString()) { - if(right.isString()) { - res.setString(left.string + right.string); - } else if(right.isNumber()) { - res.setString(left.string + right.number); - } else if(right.isWrapped() && right.prefix && right.prefix.isString()) { - res.setWrapped( - new BasicEvaluatedExpression() - .setString(left.string + right.prefix.string) - .setRange(joinRanges(left.range, right.prefix.range)), - right.postfix); - } else if(right.isWrapped()) { - res.setWrapped( - new BasicEvaluatedExpression() - .setString(left.string) - .setRange(left.range), - right.postfix); - } else { - res.setWrapped(left, null); - } - } else if(left.isNumber()) { - if(right.isString()) { - res.setString(left.number + right.string); - } else if(right.isNumber()) { - res.setNumber(left.number + right.number); - } - } else if(left.isWrapped()) { - if(left.postfix && left.postfix.isString() && right.isString()) { - res.setWrapped(left.prefix, - new BasicEvaluatedExpression() - .setString(left.postfix.string + right.string) - .setRange(joinRanges(left.postfix.range, right.range)) - ); - } else if(left.postfix && left.postfix.isString() && right.isNumber()) { - res.setWrapped(left.prefix, - new BasicEvaluatedExpression() - .setString(left.postfix.string + right.number) - .setRange(joinRanges(left.postfix.range, right.range)) - ); - } else if(right.isString()) { - res.setWrapped(left.prefix, right); - } else if(right.isNumber()) { - res.setWrapped(left.prefix, - new BasicEvaluatedExpression() - .setString(right.number + "") - .setRange(right.range)); - } else { - res.setWrapped(left.prefix, new BasicEvaluatedExpression()); - } - } else { - if(right.isString()) { - res.setWrapped(null, right); - } - } - res.setRange(expr.range); - return res; - } else if(expr.operator === "-") { - left = this.evaluateExpression(expr.left); - right = this.evaluateExpression(expr.right); - if(!left || !right) return; - if(!left.isNumber() || !right.isNumber()) return; - res = new BasicEvaluatedExpression(); - res.setNumber(left.number - right.number); - res.setRange(expr.range); - return res; - } else if(expr.operator === "*") { - left = this.evaluateExpression(expr.left); - right = this.evaluateExpression(expr.right); - if(!left || !right) return; - if(!left.isNumber() || !right.isNumber()) return; - res = new BasicEvaluatedExpression(); - res.setNumber(left.number * right.number); - res.setRange(expr.range); - return res; - } else if(expr.operator === "/") { - left = this.evaluateExpression(expr.left); - right = this.evaluateExpression(expr.right); - if(!left || !right) return; - if(!left.isNumber() || !right.isNumber()) return; - res = new BasicEvaluatedExpression(); - res.setNumber(left.number / right.number); - res.setRange(expr.range); - return res; - } else if(expr.operator === "==" || expr.operator === "===") { - left = this.evaluateExpression(expr.left); - right = this.evaluateExpression(expr.right); - if(!left || !right) return; - res = new BasicEvaluatedExpression(); - res.setRange(expr.range); - if(left.isString() && right.isString()) { - return res.setBoolean(left.string === right.string); - } else if(left.isNumber() && right.isNumber()) { - return res.setBoolean(left.number === right.number); - } else if(left.isBoolean() && right.isBoolean()) { - return res.setBoolean(left.bool === right.bool); - } - } else if(expr.operator === "!=" || expr.operator === "!==") { - left = this.evaluateExpression(expr.left); - right = this.evaluateExpression(expr.right); - if(!left || !right) return; - res = new BasicEvaluatedExpression(); - res.setRange(expr.range); - if(left.isString() && right.isString()) { - return res.setBoolean(left.string !== right.string); - } else if(left.isNumber() && right.isNumber()) { - return res.setBoolean(left.number !== right.number); - } else if(left.isBoolean() && right.isBoolean()) { - return res.setBoolean(left.bool !== right.bool); - } - } - }); - this.plugin("evaluate UnaryExpression", function(expr) { - if(expr.operator === "typeof") { - let res; - let name; - if(expr.argument.type === "Identifier") { - name = this.scope.renames["$" + expr.argument.name] || expr.argument.name; - if(this.scope.definitions.indexOf(name) === -1) { - res = this.applyPluginsBailResult1("evaluate typeof " + name, expr); - if(res !== undefined) return res; - } - } - if(expr.argument.type === "MemberExpression") { - const exprName = this.getNameForExpression(expr.argument); - if(exprName && exprName.free) { - res = this.applyPluginsBailResult1("evaluate typeof " + exprName.name, expr); - if(res !== undefined) return res; - } - } - if(expr.argument.type === "FunctionExpression") { - return new BasicEvaluatedExpression().setString("function").setRange(expr.range); - } - const arg = this.evaluateExpression(expr.argument); - if(arg.isString() || arg.isWrapped()) return new BasicEvaluatedExpression().setString("string").setRange(expr.range); - else if(arg.isNumber()) return new BasicEvaluatedExpression().setString("number").setRange(expr.range); - else if(arg.isBoolean()) return new BasicEvaluatedExpression().setString("boolean").setRange(expr.range); - else if(arg.isArray() || arg.isConstArray() || arg.isRegExp()) return new BasicEvaluatedExpression().setString("object").setRange(expr.range); - } else if(expr.operator === "!") { - const argument = this.evaluateExpression(expr.argument); - if(!argument) return; - if(argument.isBoolean()) { - return new BasicEvaluatedExpression().setBoolean(!argument.bool).setRange(expr.range); - } else if(argument.isTruthy()) { - return new BasicEvaluatedExpression().setBoolean(false).setRange(expr.range); - } else if(argument.isFalsy()) { - return new BasicEvaluatedExpression().setBoolean(true).setRange(expr.range); - } else if(argument.isString()) { - return new BasicEvaluatedExpression().setBoolean(!argument.string).setRange(expr.range); - } else if(argument.isNumber()) { - return new BasicEvaluatedExpression().setBoolean(!argument.number).setRange(expr.range); - } - } - }); - this.plugin("evaluate typeof undefined", function(expr) { - return new BasicEvaluatedExpression().setString("undefined").setRange(expr.range); - }); - this.plugin("evaluate Identifier", function(expr) { - const name = this.scope.renames["$" + expr.name] || expr.name; - if(this.scope.definitions.indexOf(expr.name) === -1) { - const result = this.applyPluginsBailResult1("evaluate Identifier " + name, expr); - if(result) return result; - return new BasicEvaluatedExpression().setIdentifier(name).setRange(expr.range); - } else { - return this.applyPluginsBailResult1("evaluate defined Identifier " + name, expr); - } - }); - this.plugin("evaluate ThisExpression", function(expr) { - const name = this.scope.renames.$this; - if(name) { - const result = this.applyPluginsBailResult1("evaluate Identifier " + name, expr); - if(result) return result; - return new BasicEvaluatedExpression().setIdentifier(name).setRange(expr.range); - } - }); - this.plugin("evaluate MemberExpression", function(expression) { - let exprName = this.getNameForExpression(expression); - if(exprName) { - if(exprName.free) { - const result = this.applyPluginsBailResult1("evaluate Identifier " + exprName.name, expression); - if(result) return result; - return new BasicEvaluatedExpression().setIdentifier(exprName.name).setRange(expression.range); - } else { - return this.applyPluginsBailResult1("evaluate defined Identifier " + exprName.name, expression); - } - } - }); - this.plugin("evaluate CallExpression", function(expr) { - if(expr.callee.type !== "MemberExpression") return; - if(expr.callee.property.type !== (expr.callee.computed ? "Literal" : "Identifier")) return; - const param = this.evaluateExpression(expr.callee.object); - if(!param) return; - const property = expr.callee.property.name || expr.callee.property.value; - return this.applyPluginsBailResult("evaluate CallExpression ." + property, expr, param); - }); - this.plugin("evaluate CallExpression .replace", function(expr, param) { - if(!param.isString()) return; - if(expr.arguments.length !== 2) return; - let arg1 = this.evaluateExpression(expr.arguments[0]); - let arg2 = this.evaluateExpression(expr.arguments[1]); - if(!arg1.isString() && !arg1.isRegExp()) return; - arg1 = arg1.regExp || arg1.string; - if(!arg2.isString()) return; - arg2 = arg2.string; - return new BasicEvaluatedExpression().setString(param.string.replace(arg1, arg2)).setRange(expr.range); - }); - ["substr", "substring"].forEach(fn => { - this.plugin("evaluate CallExpression ." + fn, function(expr, param) { - if(!param.isString()) return; - let arg1; - let result, str = param.string; - switch(expr.arguments.length) { - case 1: - arg1 = this.evaluateExpression(expr.arguments[0]); - if(!arg1.isNumber()) return; - result = str[fn](arg1.number); - break; - case 2: - { - arg1 = this.evaluateExpression(expr.arguments[0]); - const arg2 = this.evaluateExpression(expr.arguments[1]); - if(!arg1.isNumber()) return; - if(!arg2.isNumber()) return; - result = str[fn](arg1.number, arg2.number); - break; - } - default: - return; - } - return new BasicEvaluatedExpression().setString(result).setRange(expr.range); - }); - }); - - /** - * @param {string} kind "cooked" | "raw" - * @param {any[]} quasis quasis - * @param {any[]} expressions expressions - * @return {BasicEvaluatedExpression[]} Simplified template - */ - function getSimplifiedTemplateResult(kind, quasis, expressions) { - const parts = []; - - for(let i = 0; i < quasis.length; i++) { - parts.push(new BasicEvaluatedExpression().setString(quasis[i].value[kind]).setRange(quasis[i].range)); - - if(i > 0) { - const prevExpr = parts[parts.length - 2], - lastExpr = parts[parts.length - 1]; - const expr = this.evaluateExpression(expressions[i - 1]); - if(!(expr.isString() || expr.isNumber())) continue; - - prevExpr.setString(prevExpr.string + (expr.isString() ? expr.string : expr.number) + lastExpr.string); - prevExpr.setRange([prevExpr.range[0], lastExpr.range[1]]); - parts.pop(); - } - } - return parts; - } - - this.plugin("evaluate TemplateLiteral", function(node) { - const parts = getSimplifiedTemplateResult.call(this, "cooked", node.quasis, node.expressions); - if(parts.length === 1) { - return parts[0].setRange(node.range); - } - return new BasicEvaluatedExpression().setTemplateString(parts).setRange(node.range); - }); - this.plugin("evaluate TaggedTemplateExpression", function(node) { - if(this.evaluateExpression(node.tag).identifier !== "String.raw") return; - const parts = getSimplifiedTemplateResult.call(this, "raw", node.quasi.quasis, node.quasi.expressions); - return new BasicEvaluatedExpression().setTemplateString(parts).setRange(node.range); - }); - - this.plugin("evaluate CallExpression .concat", function(expr, param) { - if(!param.isString() && !param.isWrapped()) return; - - let stringSuffix = null; - let hasUnknownParams = false; - for(let i = expr.arguments.length - 1; i >= 0; i--) { - const argExpr = this.evaluateExpression(expr.arguments[i]); - if(!argExpr.isString() && !argExpr.isNumber()) { - hasUnknownParams = true; - break; - } - - const value = argExpr.isString() ? argExpr.string : "" + argExpr.number; - - const newString = value + (stringSuffix ? stringSuffix.string : ""); - const newRange = [argExpr.range[0], (stringSuffix || argExpr).range[1]]; - stringSuffix = new BasicEvaluatedExpression().setString(newString).setRange(newRange); - } - - if(hasUnknownParams) { - const prefix = param.isString() ? param : param.prefix; - return new BasicEvaluatedExpression().setWrapped(prefix, stringSuffix).setRange(expr.range); - } else if(param.isWrapped()) { - const postfix = stringSuffix || param.postfix; - return new BasicEvaluatedExpression().setWrapped(param.prefix, postfix).setRange(expr.range); - } else { - const newString = param.string + (stringSuffix ? stringSuffix.string : ""); - return new BasicEvaluatedExpression().setString(newString).setRange(expr.range); - } - }); - this.plugin("evaluate CallExpression .split", function(expr, param) { - if(!param.isString()) return; - if(expr.arguments.length !== 1) return; - let result; - const arg = this.evaluateExpression(expr.arguments[0]); - if(arg.isString()) { - result = param.string.split(arg.string); - } else if(arg.isRegExp()) { - result = param.string.split(arg.regExp); - } else return; - return new BasicEvaluatedExpression().setArray(result).setRange(expr.range); - }); - this.plugin("evaluate ConditionalExpression", function(expr) { - const condition = this.evaluateExpression(expr.test); - const conditionValue = condition.asBool(); - let res; - if(conditionValue === undefined) { - const consequent = this.evaluateExpression(expr.consequent); - const alternate = this.evaluateExpression(expr.alternate); - if(!consequent || !alternate) return; - res = new BasicEvaluatedExpression(); - if(consequent.isConditional()) - res.setOptions(consequent.options); - else - res.setOptions([consequent]); - if(alternate.isConditional()) - res.addOptions(alternate.options); - else - res.addOptions([alternate]); - } else { - res = this.evaluateExpression(conditionValue ? expr.consequent : expr.alternate); - } - res.setRange(expr.range); - return res; - }); - this.plugin("evaluate ArrayExpression", function(expr) { - const items = expr.elements.map(function(element) { - return element !== null && this.evaluateExpression(element); - }, this); - if(!items.every(Boolean)) return; - return new BasicEvaluatedExpression().setItems(items).setRange(expr.range); - }); - } - - getRenameIdentifier(expr) { - const result = this.evaluateExpression(expr); - if(!result) return; - if(result.isIdentifier()) return result.identifier; - return; - } - - walkClass(classy) { - if(classy.superClass) - this.walkExpression(classy.superClass); - if(classy.body && classy.body.type === "ClassBody") { - classy.body.body.forEach(methodDefinition => { - if(methodDefinition.type === "MethodDefinition") - this.walkMethodDefinition(methodDefinition); - }); - } - } - - walkMethodDefinition(methodDefinition) { - if(methodDefinition.computed && methodDefinition.key) - this.walkExpression(methodDefinition.key); - if(methodDefinition.value) - this.walkExpression(methodDefinition.value); - } - - // Prewalking iterates the scope for variable declarations - prewalkStatements(statements) { - for(let index = 0, len = statements.length; index < len; index++) { - const statement = statements[index]; - this.prewalkStatement(statement); - } - } - - // Walking iterates the statements and expressions and processes them - walkStatements(statements) { - for(let index = 0, len = statements.length; index < len; index++) { - const statement = statements[index]; - this.walkStatement(statement); - } - } - - prewalkStatement(statement) { - const handler = this["prewalk" + statement.type]; - if(handler) - handler.call(this, statement); - } - - walkStatement(statement) { - if(this.applyPluginsBailResult1("statement", statement) !== undefined) return; - const handler = this["walk" + statement.type]; - if(handler) - handler.call(this, statement); - } - - // Real Statements - prewalkBlockStatement(statement) { - this.prewalkStatements(statement.body); - } - - walkBlockStatement(statement) { - this.walkStatements(statement.body); - } - - walkExpressionStatement(statement) { - this.walkExpression(statement.expression); - } - - prewalkIfStatement(statement) { - this.prewalkStatement(statement.consequent); - if(statement.alternate) - this.prewalkStatement(statement.alternate); - } - - walkIfStatement(statement) { - const result = this.applyPluginsBailResult1("statement if", statement); - if(result === undefined) { - this.walkExpression(statement.test); - this.walkStatement(statement.consequent); - if(statement.alternate) - this.walkStatement(statement.alternate); - } else { - if(result) - this.walkStatement(statement.consequent); - else if(statement.alternate) - this.walkStatement(statement.alternate); - } - } - - prewalkLabeledStatement(statement) { - this.prewalkStatement(statement.body); - } - - walkLabeledStatement(statement) { - const result = this.applyPluginsBailResult1("label " + statement.label.name, statement); - if(result !== true) - this.walkStatement(statement.body); - } - - prewalkWithStatement(statement) { - this.prewalkStatement(statement.body); - } - - walkWithStatement(statement) { - this.walkExpression(statement.object); - this.walkStatement(statement.body); - } - - prewalkSwitchStatement(statement) { - this.prewalkSwitchCases(statement.cases); - } - - walkSwitchStatement(statement) { - this.walkExpression(statement.discriminant); - this.walkSwitchCases(statement.cases); - } - - walkTerminatingStatement(statement) { - if(statement.argument) - this.walkExpression(statement.argument); - } - - walkReturnStatement(statement) { - this.walkTerminatingStatement(statement); - } - - walkThrowStatement(statement) { - this.walkTerminatingStatement(statement); - } - - prewalkTryStatement(statement) { - this.prewalkStatement(statement.block); - } - - walkTryStatement(statement) { - if(this.scope.inTry) { - this.walkStatement(statement.block); - } else { - this.scope.inTry = true; - this.walkStatement(statement.block); - this.scope.inTry = false; - } - if(statement.handler) - this.walkCatchClause(statement.handler); - if(statement.finalizer) - this.walkStatement(statement.finalizer); - } - - prewalkWhileStatement(statement) { - this.prewalkStatement(statement.body); - } - - walkWhileStatement(statement) { - this.walkExpression(statement.test); - this.walkStatement(statement.body); - } - - prewalkDoWhileStatement(statement) { - this.prewalkStatement(statement.body); - } - - walkDoWhileStatement(statement) { - this.walkStatement(statement.body); - this.walkExpression(statement.test); - } - - prewalkForStatement(statement) { - if(statement.init) { - if(statement.init.type === "VariableDeclaration") - this.prewalkStatement(statement.init); - } - this.prewalkStatement(statement.body); - } - - walkForStatement(statement) { - if(statement.init) { - if(statement.init.type === "VariableDeclaration") - this.walkStatement(statement.init); - else - this.walkExpression(statement.init); - } - if(statement.test) - this.walkExpression(statement.test); - if(statement.update) - this.walkExpression(statement.update); - this.walkStatement(statement.body); - } - - prewalkForInStatement(statement) { - if(statement.left.type === "VariableDeclaration") - this.prewalkStatement(statement.left); - this.prewalkStatement(statement.body); - } - - walkForInStatement(statement) { - if(statement.left.type === "VariableDeclaration") - this.walkStatement(statement.left); - else - this.walkExpression(statement.left); - this.walkExpression(statement.right); - this.walkStatement(statement.body); - } - - prewalkForOfStatement(statement) { - if(statement.left.type === "VariableDeclaration") - this.prewalkStatement(statement.left); - this.prewalkStatement(statement.body); - } - - walkForOfStatement(statement) { - if(statement.left.type === "VariableDeclaration") - this.walkStatement(statement.left); - else - this.walkExpression(statement.left); - this.walkExpression(statement.right); - this.walkStatement(statement.body); - } - - // Declarations - prewalkFunctionDeclaration(statement) { - if(statement.id) { - this.scope.renames["$" + statement.id.name] = undefined; - this.scope.definitions.push(statement.id.name); - } - } - - walkFunctionDeclaration(statement) { - statement.params.forEach(param => { - this.walkPattern(param); - }); - this.inScope(statement.params, () => { - if(statement.body.type === "BlockStatement") { - this.prewalkStatement(statement.body); - this.walkStatement(statement.body); - } else { - this.walkExpression(statement.body); - } - }); - } - - prewalkImportDeclaration(statement) { - const source = statement.source.value; - this.applyPluginsBailResult("import", statement, source); - statement.specifiers.forEach(function(specifier) { - const name = specifier.local.name; - this.scope.renames["$" + name] = undefined; - this.scope.definitions.push(name); - switch(specifier.type) { - case "ImportDefaultSpecifier": - this.applyPluginsBailResult("import specifier", statement, source, "default", name); - break; - case "ImportSpecifier": - this.applyPluginsBailResult("import specifier", statement, source, specifier.imported.name, name); - break; - case "ImportNamespaceSpecifier": - this.applyPluginsBailResult("import specifier", statement, source, null, name); - break; - } - }, this); - } - - prewalkExportNamedDeclaration(statement) { - let source; - if(statement.source) { - source = statement.source.value; - this.applyPluginsBailResult("export import", statement, source); - } else { - this.applyPluginsBailResult1("export", statement); - } - if(statement.declaration) { - if(/Expression$/.test(statement.declaration.type)) { - throw new Error("Doesn't occur?"); - } else { - if(!this.applyPluginsBailResult("export declaration", statement, statement.declaration)) { - const pos = this.scope.definitions.length; - this.prewalkStatement(statement.declaration); - const newDefs = this.scope.definitions.slice(pos); - for(let index = newDefs.length - 1; index >= 0; index--) { - const def = newDefs[index]; - this.applyPluginsBailResult("export specifier", statement, def, def, index); - } - } - } - } - if(statement.specifiers) { - for(let specifierIndex = 0; specifierIndex < statement.specifiers.length; specifierIndex++) { - const specifier = statement.specifiers[specifierIndex]; - switch(specifier.type) { - case "ExportSpecifier": - { - const name = specifier.exported.name; - if(source) - this.applyPluginsBailResult("export import specifier", statement, source, specifier.local.name, name, specifierIndex); - else - this.applyPluginsBailResult("export specifier", statement, specifier.local.name, name, specifierIndex); - break; - } - } - } - } - } - - walkExportNamedDeclaration(statement) { - if(statement.declaration) { - this.walkStatement(statement.declaration); - } - } - - prewalkExportDefaultDeclaration(statement) { - if(/Declaration$/.test(statement.declaration.type)) { - const pos = this.scope.definitions.length; - this.prewalkStatement(statement.declaration); - const newDefs = this.scope.definitions.slice(pos); - for(let index = 0, len = newDefs.length; index < len; index++) { - const def = newDefs[index]; - this.applyPluginsBailResult("export specifier", statement, def, "default"); - } - } - } - - walkExportDefaultDeclaration(statement) { - this.applyPluginsBailResult1("export", statement); - if(/Declaration$/.test(statement.declaration.type)) { - if(!this.applyPluginsBailResult("export declaration", statement, statement.declaration)) { - this.walkStatement(statement.declaration); - } - } else { - this.walkExpression(statement.declaration); - if(!this.applyPluginsBailResult("export expression", statement, statement.declaration)) { - this.applyPluginsBailResult("export specifier", statement, statement.declaration, "default"); - } - } - } - - prewalkExportAllDeclaration(statement) { - const source = statement.source.value; - this.applyPluginsBailResult("export import", statement, source); - this.applyPluginsBailResult("export import specifier", statement, source, null, null, 0); - } - - prewalkVariableDeclaration(statement) { - if(statement.declarations) - this.prewalkVariableDeclarators(statement.declarations); - } - - walkVariableDeclaration(statement) { - if(statement.declarations) - this.walkVariableDeclarators(statement.declarations); - } - - prewalkClassDeclaration(statement) { - if(statement.id) { - this.scope.renames["$" + statement.id.name] = undefined; - this.scope.definitions.push(statement.id.name); - } - } - - walkClassDeclaration(statement) { - this.walkClass(statement); - } - - prewalkSwitchCases(switchCases) { - for(let index = 0, len = switchCases.length; index < len; index++) { - const switchCase = switchCases[index]; - this.prewalkStatements(switchCase.consequent); - } - } - - walkSwitchCases(switchCases) { - for(let index = 0, len = switchCases.length; index < len; index++) { - const switchCase = switchCases[index]; - - if(switchCase.test) { - this.walkExpression(switchCase.test); - } - this.walkStatements(switchCase.consequent); - } - } - - walkCatchClause(catchClause) { - this.inScope([catchClause.param], () => { - this.prewalkStatement(catchClause.body); - this.walkStatement(catchClause.body); - }); - } - - prewalkVariableDeclarators(declarators) { - declarators.forEach(declarator => { - switch(declarator.type) { - case "VariableDeclarator": - { - this.enterPattern(declarator.id, (name, decl) => { - if(!this.applyPluginsBailResult1("var-" + declarator.kind + " " + name, decl)) { - if(!this.applyPluginsBailResult1("var " + name, decl)) { - this.scope.renames["$" + name] = undefined; - if(this.scope.definitions.indexOf(name) < 0) - this.scope.definitions.push(name); - } - } - }); - break; - } - } - }); - } - - walkVariableDeclarators(declarators) { - declarators.forEach(declarator => { - switch(declarator.type) { - case "VariableDeclarator": - { - const renameIdentifier = declarator.init && this.getRenameIdentifier(declarator.init); - if(renameIdentifier && declarator.id.type === "Identifier" && this.applyPluginsBailResult1("can-rename " + renameIdentifier, declarator.init)) { - // renaming with "var a = b;" - if(!this.applyPluginsBailResult1("rename " + renameIdentifier, declarator.init)) { - this.scope.renames["$" + declarator.id.name] = this.scope.renames["$" + renameIdentifier] || renameIdentifier; - const idx = this.scope.definitions.indexOf(declarator.id.name); - if(idx >= 0) this.scope.definitions.splice(idx, 1); - } - } else { - this.walkPattern(declarator.id); - if(declarator.init) - this.walkExpression(declarator.init); - } - break; - } - } - }); - } - - walkPattern(pattern) { - if(pattern.type === "Identifier") - return; - if(this["walk" + pattern.type]) - this["walk" + pattern.type](pattern); - } - - walkAssignmentPattern(pattern) { - this.walkExpression(pattern.right); - this.walkPattern(pattern.left); - } - - walkObjectPattern(pattern) { - for(let i = 0, len = pattern.properties.length; i < len; i++) { - const prop = pattern.properties[i]; - if(prop) { - if(prop.computed) - this.walkExpression(prop.key); - if(prop.value) - this.walkPattern(prop.value); - } - } - } - - walkArrayPattern(pattern) { - for(let i = 0, len = pattern.elements.length; i < len; i++) { - const element = pattern.elements[i]; - if(element) - this.walkPattern(element); - } - } - - walkRestElement(pattern) { - this.walkPattern(pattern.argument); - } - - walkExpressions(expressions) { - for(let expressionsIndex = 0, len = expressions.length; expressionsIndex < len; expressionsIndex++) { - const expression = expressions[expressionsIndex]; - if(expression) - this.walkExpression(expression); - } - } - - walkExpression(expression) { - if(this["walk" + expression.type]) - return this["walk" + expression.type](expression); - } - - walkAwaitExpression(expression) { - const argument = expression.argument; - if(this["walk" + argument.type]) - return this["walk" + argument.type](argument); - } - - walkArrayExpression(expression) { - if(expression.elements) - this.walkExpressions(expression.elements); - } - - walkSpreadElement(expression) { - if(expression.argument) - this.walkExpression(expression.argument); - } - - walkObjectExpression(expression) { - for(let propIndex = 0, len = expression.properties.length; propIndex < len; propIndex++) { - const prop = expression.properties[propIndex]; - if(prop.computed) - this.walkExpression(prop.key); - if(prop.shorthand) - this.scope.inShorthand = true; - this.walkExpression(prop.value); - if(prop.shorthand) - this.scope.inShorthand = false; - } - } - - walkFunctionExpression(expression) { - expression.params.forEach(param => { - this.walkPattern(param); - }); - this.inScope(expression.params, () => { - if(expression.body.type === "BlockStatement") { - this.prewalkStatement(expression.body); - this.walkStatement(expression.body); - } else { - this.walkExpression(expression.body); - } - }); - } - - walkArrowFunctionExpression(expression) { - expression.params.forEach(param => { - this.walkPattern(param); - }); - this.inScope(expression.params, () => { - if(expression.body.type === "BlockStatement") { - this.prewalkStatement(expression.body); - this.walkStatement(expression.body); - } else { - this.walkExpression(expression.body); - } - }); - } - - walkSequenceExpression(expression) { - if(expression.expressions) - this.walkExpressions(expression.expressions); - } - - walkUpdateExpression(expression) { - this.walkExpression(expression.argument); - } - - walkUnaryExpression(expression) { - if(expression.operator === "typeof") { - const exprName = this.getNameForExpression(expression.argument); - if(exprName && exprName.free) { - const result = this.applyPluginsBailResult1("typeof " + exprName.name, expression); - if(result === true) - return; - } - } - this.walkExpression(expression.argument); - } - - walkLeftRightExpression(expression) { - this.walkExpression(expression.left); - this.walkExpression(expression.right); - } - - walkBinaryExpression(expression) { - this.walkLeftRightExpression(expression); - } - - walkLogicalExpression(expression) { - this.walkLeftRightExpression(expression); - } - - walkAssignmentExpression(expression) { - const renameIdentifier = this.getRenameIdentifier(expression.right); - if(expression.left.type === "Identifier" && renameIdentifier && this.applyPluginsBailResult1("can-rename " + renameIdentifier, expression.right)) { - // renaming "a = b;" - if(!this.applyPluginsBailResult1("rename " + renameIdentifier, expression.right)) { - this.scope.renames["$" + expression.left.name] = renameIdentifier; - const idx = this.scope.definitions.indexOf(expression.left.name); - if(idx >= 0) this.scope.definitions.splice(idx, 1); - } - } else if(expression.left.type === "Identifier") { - if(!this.applyPluginsBailResult1("assigned " + expression.left.name, expression)) { - this.walkExpression(expression.right); - } - this.scope.renames["$" + expression.left.name] = undefined; - if(!this.applyPluginsBailResult1("assign " + expression.left.name, expression)) { - this.walkExpression(expression.left); - } - } else { - this.walkExpression(expression.right); - this.walkPattern(expression.left); - this.enterPattern(expression.left, (name, decl) => { - this.scope.renames["$" + name] = undefined; - }); - } - } - - walkConditionalExpression(expression) { - const result = this.applyPluginsBailResult1("expression ?:", expression); - if(result === undefined) { - this.walkExpression(expression.test); - this.walkExpression(expression.consequent); - if(expression.alternate) - this.walkExpression(expression.alternate); - } else { - if(result) - this.walkExpression(expression.consequent); - else if(expression.alternate) - this.walkExpression(expression.alternate); - } - } - - walkNewExpression(expression) { - this.walkExpression(expression.callee); - if(expression.arguments) - this.walkExpressions(expression.arguments); - } - - walkYieldExpression(expression) { - if(expression.argument) - this.walkExpression(expression.argument); - } - - walkTemplateLiteral(expression) { - if(expression.expressions) - this.walkExpressions(expression.expressions); - } - - walkTaggedTemplateExpression(expression) { - if(expression.tag) - this.walkExpression(expression.tag); - if(expression.quasi && expression.quasi.expressions) - this.walkExpressions(expression.quasi.expressions); - } - - walkClassExpression(expression) { - this.walkClass(expression); - } - - walkCallExpression(expression) { - let result; - - function walkIIFE(functionExpression, options, currentThis) { - function renameArgOrThis(argOrThis) { - const renameIdentifier = this.getRenameIdentifier(argOrThis); - if(renameIdentifier && this.applyPluginsBailResult1("can-rename " + renameIdentifier, argOrThis)) { - if(!this.applyPluginsBailResult1("rename " + renameIdentifier, argOrThis)) - return renameIdentifier; - } - this.walkExpression(argOrThis); - } - const params = functionExpression.params; - const renameThis = currentThis ? renameArgOrThis.call(this, currentThis) : null; - const args = options.map(renameArgOrThis, this); - this.inScope(params.filter(function(identifier, idx) { - return !args[idx]; - }), () => { - if(renameThis) { - this.scope.renames.$this = renameThis; - } - for(let i = 0; i < args.length; i++) { - const param = args[i]; - if(!param) continue; - if(!params[i] || params[i].type !== "Identifier") continue; - this.scope.renames["$" + params[i].name] = param; - } - if(functionExpression.body.type === "BlockStatement") { - this.prewalkStatement(functionExpression.body); - this.walkStatement(functionExpression.body); - } else - this.walkExpression(functionExpression.body); - }); - } - if(expression.callee.type === "MemberExpression" && - expression.callee.object.type === "FunctionExpression" && - !expression.callee.computed && - (["call", "bind"]).indexOf(expression.callee.property.name) >= 0 && - expression.arguments && - expression.arguments.length > 0 - ) { - // (function(...) { }.call/bind(?, ...)) - walkIIFE.call(this, expression.callee.object, expression.arguments.slice(1), expression.arguments[0]); - } else if(expression.callee.type === "FunctionExpression" && expression.arguments) { - // (function(...) { }(...)) - walkIIFE.call(this, expression.callee, expression.arguments); - } else if(expression.callee.type === "Import") { - result = this.applyPluginsBailResult1("import-call", expression); - if(result === true) - return; - - if(expression.arguments) - this.walkExpressions(expression.arguments); - } else { - - const callee = this.evaluateExpression(expression.callee); - if(callee.isIdentifier()) { - result = this.applyPluginsBailResult1("call " + callee.identifier, expression); - if(result === true) - return; - let identifier = callee.identifier.replace(/\.[^.]+$/, ".*"); - if(identifier !== callee.identifier) { - result = this.applyPluginsBailResult1("call " + identifier, expression); - if(result === true) - return; - } - } - - if(expression.callee) - this.walkExpression(expression.callee); - if(expression.arguments) - this.walkExpressions(expression.arguments); - } - } - - walkMemberExpression(expression) { - const exprName = this.getNameForExpression(expression); - if(exprName && exprName.free) { - let result = this.applyPluginsBailResult1("expression " + exprName.name, expression); - if(result === true) - return; - result = this.applyPluginsBailResult1("expression " + exprName.nameGeneral, expression); - if(result === true) - return; - } - this.walkExpression(expression.object); - if(expression.computed === true) - this.walkExpression(expression.property); - } - - walkIdentifier(expression) { - if(this.scope.definitions.indexOf(expression.name) === -1) { - const result = this.applyPluginsBailResult1("expression " + (this.scope.renames["$" + expression.name] || expression.name), expression); - if(result === true) - return; - } - } - - inScope(params, fn) { - const oldScope = this.scope; - this.scope = { - inTry: false, - inShorthand: false, - definitions: oldScope.definitions.slice(), - renames: Object.create(oldScope.renames) - }; - - this.scope.renames.$this = undefined; - - for(let paramIndex = 0, len = params.length; paramIndex < len; paramIndex++) { - const param = params[paramIndex]; - - if(typeof param !== "string") { - this.enterPattern(param, param => { - this.scope.renames["$" + param] = undefined; - this.scope.definitions.push(param); - }); - } else { - this.scope.renames["$" + param] = undefined; - this.scope.definitions.push(param); - } - } - - fn(); - this.scope = oldScope; - } - - enterPattern(pattern, onIdent) { - if(pattern && this["enter" + pattern.type]) - this["enter" + pattern.type](pattern, onIdent); - } - - enterIdentifier(pattern, onIdent) { - onIdent(pattern.name, pattern); - } - - enterObjectPattern(pattern, onIdent) { - for(let propIndex = 0, len = pattern.properties.length; propIndex < len; propIndex++) { - const prop = pattern.properties[propIndex]; - this.enterPattern(prop.value, onIdent); - } - } - - enterArrayPattern(pattern, onIdent) { - for(let elementIndex = 0, len = pattern.elements.length; elementIndex < len; elementIndex++) { - const element = pattern.elements[elementIndex]; - this.enterPattern(element, onIdent); - } - } - - enterRestElement(pattern, onIdent) { - this.enterPattern(pattern.argument, onIdent); - } - - enterAssignmentPattern(pattern, onIdent) { - this.enterPattern(pattern.left, onIdent); - } - - evaluateExpression(expression) { - try { - const result = this.applyPluginsBailResult1("evaluate " + expression.type, expression); - if(result !== undefined) - return result; - } catch(e) { - console.warn(e); - // ignore error - } - return new BasicEvaluatedExpression().setRange(expression.range); - } - - parseString(expression) { - switch(expression.type) { - case "BinaryExpression": - if(expression.operator === "+") - return this.parseString(expression.left) + this.parseString(expression.right); - break; - case "Literal": - return expression.value + ""; - } - throw new Error(expression.type + " is not supported as parameter for require"); - } - - parseCalculatedString(expression) { - switch(expression.type) { - case "BinaryExpression": - if(expression.operator === "+") { - const left = this.parseCalculatedString(expression.left); - const right = this.parseCalculatedString(expression.right); - if(left.code) { - return { - range: left.range, - value: left.value, - code: true - }; - } else if(right.code) { - return { - range: [left.range[0], right.range ? right.range[1] : left.range[1]], - value: left.value + right.value, - code: true - }; - } else { - return { - range: [left.range[0], right.range[1]], - value: left.value + right.value - }; - } - } - break; - case "ConditionalExpression": - { - const consequent = this.parseCalculatedString(expression.consequent); - const alternate = this.parseCalculatedString(expression.alternate); - const items = []; - if(consequent.conditional) - Array.prototype.push.apply(items, consequent.conditional); - else if(!consequent.code) - items.push(consequent); - else break; - if(alternate.conditional) - Array.prototype.push.apply(items, alternate.conditional); - else if(!alternate.code) - items.push(alternate); - else break; - return { - value: "", - code: true, - conditional: items - }; - } - case "Literal": - return { - range: expression.range, - value: expression.value + "" - }; - } - return { - value: "", - code: true - }; - } - - parseStringArray(expression) { - if(expression.type !== "ArrayExpression") { - return [this.parseString(expression)]; - } - - const arr = []; - if(expression.elements) - expression.elements.forEach(function(expr) { - arr.push(this.parseString(expr)); - }, this); - return arr; - } - - parseCalculatedStringArray(expression) { - if(expression.type !== "ArrayExpression") { - return [this.parseCalculatedString(expression)]; - } - - const arr = []; - if(expression.elements) - expression.elements.forEach(function(expr) { - arr.push(this.parseCalculatedString(expr)); - }, this); - return arr; - } - - parse(source, initialState) { - let ast; - const comments = []; - for(let i = 0, len = POSSIBLE_AST_OPTIONS.length; i < len; i++) { - if(!ast) { - try { - comments.length = 0; - POSSIBLE_AST_OPTIONS[i].onComment = comments; - ast = acorn.parse(source, POSSIBLE_AST_OPTIONS[i]); - } catch(e) { - // ignore the error - } - } - } - if(!ast) { - // for the error - ast = acorn.parse(source, { - ranges: true, - locations: true, - ecmaVersion: ECMA_VERSION, - sourceType: "module", - plugins: { - dynamicImport: true - }, - onComment: comments - }); - } - if(!ast || typeof ast !== "object") - throw new Error("Source couldn't be parsed"); - const oldScope = this.scope; - const oldState = this.state; - const oldComments = this.comments; - this.scope = { - inTry: false, - definitions: [], - renames: {} - }; - const state = this.state = initialState || {}; - this.comments = comments; - if(this.applyPluginsBailResult("program", ast, comments) === undefined) { - this.prewalkStatements(ast.body); - this.walkStatements(ast.body); - } - this.scope = oldScope; - this.state = oldState; - this.comments = oldComments; - return state; - } - - evaluate(source) { - const ast = acorn.parse("(" + source + ")", { - ranges: true, - locations: true, - ecmaVersion: ECMA_VERSION, - sourceType: "module", - plugins: { - dynamicImport: true - } - }); - if(!ast || typeof ast !== "object" || ast.type !== "Program") - throw new Error("evaluate: Source couldn't be parsed"); - if(ast.body.length !== 1 || ast.body[0].type !== "ExpressionStatement") - throw new Error("evaluate: Source is not a expression"); - return this.evaluateExpression(ast.body[0].expression); - } - - getComments(range) { - return this.comments.filter(comment => comment.range[0] >= range[0] && comment.range[1] <= range[1]); - } - - getCommentOptions(range) { - const comments = this.getComments(range); - if(comments.length === 0) return null; - const options = comments.map(comment => { - try { - return json5.parse(`{${comment.value}}`); - } catch(e) { - return {}; - } - }); - return options.reduce((o, i) => Object.assign(o, i), {}); - } - - getNameForExpression(expression) { - let expr = expression; - const exprName = []; - while(expr.type === "MemberExpression" && expr.property.type === (expr.computed ? "Literal" : "Identifier")) { - exprName.push(expr.computed ? expr.property.value : expr.property.name); - expr = expr.object; - } - let free; - if(expr.type === "Identifier") { - free = this.scope.definitions.indexOf(expr.name) === -1; - exprName.push(this.scope.renames["$" + expr.name] || expr.name); - } else if(expr.type === "ThisExpression" && this.scope.renames.$this) { - free = true; - exprName.push(this.scope.renames.$this); - } else if(expr.type === "ThisExpression") { - free = false; - exprName.push("this"); - } else { - return null; - } - let prefix = ""; - for(let i = exprName.length - 1; i >= 1; i--) - prefix += exprName[i] + "."; - const name = prefix + exprName[0]; - const nameGeneral = prefix + "*"; - return { - name, - nameGeneral, - free - }; - } - -} - -Parser.ECMA_VERSION = ECMA_VERSION; - -module.exports = Parser; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +// Syntax: https://developer.mozilla.org/en/SpiderMonkey/Parser_API + +const acorn = require("acorn-dynamic-import").default; +const { Tapable, SyncBailHook, HookMap } = require("tapable"); +const util = require("util"); +const vm = require("vm"); +const BasicEvaluatedExpression = require("./BasicEvaluatedExpression"); +const StackedSetMap = require("./util/StackedSetMap"); +const TrackingSet = require("./util/TrackingSet"); + +const joinRanges = (startRange, endRange) => { + if (!endRange) return startRange; + if (!startRange) return endRange; + return [startRange[0], endRange[1]]; +}; + +const defaultParserOptions = { + ranges: true, + locations: true, + ecmaVersion: 2019, + sourceType: "module", + onComment: null, + plugins: { + dynamicImport: true + } +}; + +// regexp to match at lease one "magic comment" +const webpackCommentRegExp = new RegExp(/(^|\W)webpack[A-Z]{1,}[A-Za-z]{1,}:/); + +const EMPTY_ARRAY = []; + +const EMPTY_COMMENT_OPTIONS = { + options: null, + errors: null +}; + +class Parser extends Tapable { + constructor(options, sourceType = "auto") { + super(); + this.hooks = { + evaluateTypeof: new HookMap(() => new SyncBailHook(["expression"])), + evaluate: new HookMap(() => new SyncBailHook(["expression"])), + evaluateIdentifier: new HookMap(() => new SyncBailHook(["expression"])), + evaluateDefinedIdentifier: new HookMap( + () => new SyncBailHook(["expression"]) + ), + evaluateCallExpressionMember: new HookMap( + () => new SyncBailHook(["expression", "param"]) + ), + statement: new SyncBailHook(["statement"]), + statementIf: new SyncBailHook(["statement"]), + label: new HookMap(() => new SyncBailHook(["statement"])), + import: new SyncBailHook(["statement", "source"]), + importSpecifier: new SyncBailHook([ + "statement", + "source", + "exportName", + "identifierName" + ]), + export: new SyncBailHook(["statement"]), + exportImport: new SyncBailHook(["statement", "source"]), + exportDeclaration: new SyncBailHook(["statement", "declaration"]), + exportExpression: new SyncBailHook(["statement", "declaration"]), + exportSpecifier: new SyncBailHook([ + "statement", + "identifierName", + "exportName", + "index" + ]), + exportImportSpecifier: new SyncBailHook([ + "statement", + "source", + "identifierName", + "exportName", + "index" + ]), + varDeclaration: new HookMap(() => new SyncBailHook(["declaration"])), + varDeclarationLet: new HookMap(() => new SyncBailHook(["declaration"])), + varDeclarationConst: new HookMap(() => new SyncBailHook(["declaration"])), + varDeclarationVar: new HookMap(() => new SyncBailHook(["declaration"])), + canRename: new HookMap(() => new SyncBailHook(["initExpression"])), + rename: new HookMap(() => new SyncBailHook(["initExpression"])), + assigned: new HookMap(() => new SyncBailHook(["expression"])), + assign: new HookMap(() => new SyncBailHook(["expression"])), + typeof: new HookMap(() => new SyncBailHook(["expression"])), + importCall: new SyncBailHook(["expression"]), + call: new HookMap(() => new SyncBailHook(["expression"])), + callAnyMember: new HookMap(() => new SyncBailHook(["expression"])), + new: new HookMap(() => new SyncBailHook(["expression"])), + expression: new HookMap(() => new SyncBailHook(["expression"])), + expressionAnyMember: new HookMap(() => new SyncBailHook(["expression"])), + expressionConditionalOperator: new SyncBailHook(["expression"]), + program: new SyncBailHook(["ast", "comments"]) + }; + const HOOK_MAP_COMPAT_CONFIG = { + evaluateTypeof: /^evaluate typeof (.+)$/, + evaluateIdentifier: /^evaluate Identifier (.+)$/, + evaluateDefinedIdentifier: /^evaluate defined Identifier (.+)$/, + evaluateCallExpressionMember: /^evaluate CallExpression .(.+)$/, + evaluate: /^evaluate (.+)$/, + label: /^label (.+)$/, + varDeclarationLet: /^var-let (.+)$/, + varDeclarationConst: /^var-const (.+)$/, + varDeclarationVar: /^var-var (.+)$/, + varDeclaration: /^var (.+)$/, + canRename: /^can-rename (.+)$/, + rename: /^rename (.+)$/, + typeof: /^typeof (.+)$/, + assigned: /^assigned (.+)$/, + assign: /^assign (.+)$/, + callAnyMember: /^call (.+)\.\*$/, + call: /^call (.+)$/, + new: /^new (.+)$/, + expressionConditionalOperator: /^expression \?:$/, + expressionAnyMember: /^expression (.+)\.\*$/, + expression: /^expression (.+)$/ + }; + this._pluginCompat.tap("Parser", options => { + for (const name of Object.keys(HOOK_MAP_COMPAT_CONFIG)) { + const regexp = HOOK_MAP_COMPAT_CONFIG[name]; + const match = regexp.exec(options.name); + if (match) { + if (match[1]) { + this.hooks[name].tap( + match[1], + options.fn.name || "unnamed compat plugin", + options.fn.bind(this) + ); + } else { + this.hooks[name].tap( + options.fn.name || "unnamed compat plugin", + options.fn.bind(this) + ); + } + return true; + } + } + }); + this.options = options; + this.sourceType = sourceType; + this.scope = undefined; + this.state = undefined; + this.comments = undefined; + this.initializeEvaluating(); + } + + initializeEvaluating() { + this.hooks.evaluate.for("Literal").tap("Parser", expr => { + switch (typeof expr.value) { + case "number": + return new BasicEvaluatedExpression() + .setNumber(expr.value) + .setRange(expr.range); + case "string": + return new BasicEvaluatedExpression() + .setString(expr.value) + .setRange(expr.range); + case "boolean": + return new BasicEvaluatedExpression() + .setBoolean(expr.value) + .setRange(expr.range); + } + if (expr.value === null) { + return new BasicEvaluatedExpression().setNull().setRange(expr.range); + } + if (expr.value instanceof RegExp) { + return new BasicEvaluatedExpression() + .setRegExp(expr.value) + .setRange(expr.range); + } + }); + this.hooks.evaluate.for("LogicalExpression").tap("Parser", expr => { + let left; + let leftAsBool; + let right; + if (expr.operator === "&&") { + left = this.evaluateExpression(expr.left); + leftAsBool = left && left.asBool(); + if (leftAsBool === false) return left.setRange(expr.range); + if (leftAsBool !== true) return; + right = this.evaluateExpression(expr.right); + return right.setRange(expr.range); + } else if (expr.operator === "||") { + left = this.evaluateExpression(expr.left); + leftAsBool = left && left.asBool(); + if (leftAsBool === true) return left.setRange(expr.range); + if (leftAsBool !== false) return; + right = this.evaluateExpression(expr.right); + return right.setRange(expr.range); + } + }); + this.hooks.evaluate.for("BinaryExpression").tap("Parser", expr => { + let left; + let right; + let res; + if (expr.operator === "+") { + left = this.evaluateExpression(expr.left); + right = this.evaluateExpression(expr.right); + if (!left || !right) return; + res = new BasicEvaluatedExpression(); + if (left.isString()) { + if (right.isString()) { + res.setString(left.string + right.string); + } else if (right.isNumber()) { + res.setString(left.string + right.number); + } else if ( + right.isWrapped() && + right.prefix && + right.prefix.isString() + ) { + res.setWrapped( + new BasicEvaluatedExpression() + .setString(left.string + right.prefix.string) + .setRange(joinRanges(left.range, right.prefix.range)), + right.postfix + ); + } else if (right.isWrapped()) { + res.setWrapped( + new BasicEvaluatedExpression() + .setString(left.string) + .setRange(left.range), + right.postfix + ); + } else { + res.setWrapped(left, null); + } + } else if (left.isNumber()) { + if (right.isString()) { + res.setString(left.number + right.string); + } else if (right.isNumber()) { + res.setNumber(left.number + right.number); + } + } else if (left.isWrapped()) { + if (left.postfix && left.postfix.isString() && right.isString()) { + res.setWrapped( + left.prefix, + new BasicEvaluatedExpression() + .setString(left.postfix.string + right.string) + .setRange(joinRanges(left.postfix.range, right.range)) + ); + } else if ( + left.postfix && + left.postfix.isString() && + right.isNumber() + ) { + res.setWrapped( + left.prefix, + new BasicEvaluatedExpression() + .setString(left.postfix.string + right.number) + .setRange(joinRanges(left.postfix.range, right.range)) + ); + } else if (right.isString()) { + res.setWrapped(left.prefix, right); + } else if (right.isNumber()) { + res.setWrapped( + left.prefix, + new BasicEvaluatedExpression() + .setString(right.number + "") + .setRange(right.range) + ); + } else { + res.setWrapped(left.prefix, new BasicEvaluatedExpression()); + } + } else { + if (right.isString()) { + res.setWrapped(null, right); + } + } + res.setRange(expr.range); + return res; + } else if (expr.operator === "-") { + left = this.evaluateExpression(expr.left); + right = this.evaluateExpression(expr.right); + if (!left || !right) return; + if (!left.isNumber() || !right.isNumber()) return; + res = new BasicEvaluatedExpression(); + res.setNumber(left.number - right.number); + res.setRange(expr.range); + return res; + } else if (expr.operator === "*") { + left = this.evaluateExpression(expr.left); + right = this.evaluateExpression(expr.right); + if (!left || !right) return; + if (!left.isNumber() || !right.isNumber()) return; + res = new BasicEvaluatedExpression(); + res.setNumber(left.number * right.number); + res.setRange(expr.range); + return res; + } else if (expr.operator === "/") { + left = this.evaluateExpression(expr.left); + right = this.evaluateExpression(expr.right); + if (!left || !right) return; + if (!left.isNumber() || !right.isNumber()) return; + res = new BasicEvaluatedExpression(); + res.setNumber(left.number / right.number); + res.setRange(expr.range); + return res; + } else if (expr.operator === "**") { + left = this.evaluateExpression(expr.left); + right = this.evaluateExpression(expr.right); + if (!left || !right) return; + if (!left.isNumber() || !right.isNumber()) return; + res = new BasicEvaluatedExpression(); + res.setNumber(Math.pow(left.number, right.number)); + res.setRange(expr.range); + return res; + } else if (expr.operator === "==" || expr.operator === "===") { + left = this.evaluateExpression(expr.left); + right = this.evaluateExpression(expr.right); + if (!left || !right) return; + res = new BasicEvaluatedExpression(); + res.setRange(expr.range); + if (left.isString() && right.isString()) { + return res.setBoolean(left.string === right.string); + } else if (left.isNumber() && right.isNumber()) { + return res.setBoolean(left.number === right.number); + } else if (left.isBoolean() && right.isBoolean()) { + return res.setBoolean(left.bool === right.bool); + } + } else if (expr.operator === "!=" || expr.operator === "!==") { + left = this.evaluateExpression(expr.left); + right = this.evaluateExpression(expr.right); + if (!left || !right) return; + res = new BasicEvaluatedExpression(); + res.setRange(expr.range); + if (left.isString() && right.isString()) { + return res.setBoolean(left.string !== right.string); + } else if (left.isNumber() && right.isNumber()) { + return res.setBoolean(left.number !== right.number); + } else if (left.isBoolean() && right.isBoolean()) { + return res.setBoolean(left.bool !== right.bool); + } + } else if (expr.operator === "&") { + left = this.evaluateExpression(expr.left); + right = this.evaluateExpression(expr.right); + if (!left || !right) return; + if (!left.isNumber() || !right.isNumber()) return; + res = new BasicEvaluatedExpression(); + res.setNumber(left.number & right.number); + res.setRange(expr.range); + return res; + } else if (expr.operator === "|") { + left = this.evaluateExpression(expr.left); + right = this.evaluateExpression(expr.right); + if (!left || !right) return; + if (!left.isNumber() || !right.isNumber()) return; + res = new BasicEvaluatedExpression(); + res.setNumber(left.number | right.number); + res.setRange(expr.range); + return res; + } else if (expr.operator === "^") { + left = this.evaluateExpression(expr.left); + right = this.evaluateExpression(expr.right); + if (!left || !right) return; + if (!left.isNumber() || !right.isNumber()) return; + res = new BasicEvaluatedExpression(); + res.setNumber(left.number ^ right.number); + res.setRange(expr.range); + return res; + } else if (expr.operator === ">>>") { + left = this.evaluateExpression(expr.left); + right = this.evaluateExpression(expr.right); + if (!left || !right) return; + if (!left.isNumber() || !right.isNumber()) return; + res = new BasicEvaluatedExpression(); + res.setNumber(left.number >>> right.number); + res.setRange(expr.range); + return res; + } else if (expr.operator === ">>") { + left = this.evaluateExpression(expr.left); + right = this.evaluateExpression(expr.right); + if (!left || !right) return; + if (!left.isNumber() || !right.isNumber()) return; + res = new BasicEvaluatedExpression(); + res.setNumber(left.number >> right.number); + res.setRange(expr.range); + return res; + } else if (expr.operator === "<<") { + left = this.evaluateExpression(expr.left); + right = this.evaluateExpression(expr.right); + if (!left || !right) return; + if (!left.isNumber() || !right.isNumber()) return; + res = new BasicEvaluatedExpression(); + res.setNumber(left.number << right.number); + res.setRange(expr.range); + return res; + } + }); + this.hooks.evaluate.for("UnaryExpression").tap("Parser", expr => { + if (expr.operator === "typeof") { + let res; + let name; + if (expr.argument.type === "Identifier") { + name = + this.scope.renames.get(expr.argument.name) || expr.argument.name; + if (!this.scope.definitions.has(name)) { + const hook = this.hooks.evaluateTypeof.get(name); + if (hook !== undefined) { + res = hook.call(expr); + if (res !== undefined) return res; + } + } + } + if (expr.argument.type === "MemberExpression") { + const exprName = this.getNameForExpression(expr.argument); + if (exprName && exprName.free) { + const hook = this.hooks.evaluateTypeof.get(exprName.name); + if (hook !== undefined) { + res = hook.call(expr); + if (res !== undefined) return res; + } + } + } + if (expr.argument.type === "FunctionExpression") { + return new BasicEvaluatedExpression() + .setString("function") + .setRange(expr.range); + } + const arg = this.evaluateExpression(expr.argument); + if (arg.isString() || arg.isWrapped()) { + return new BasicEvaluatedExpression() + .setString("string") + .setRange(expr.range); + } + if (arg.isNumber()) { + return new BasicEvaluatedExpression() + .setString("number") + .setRange(expr.range); + } + if (arg.isBoolean()) { + return new BasicEvaluatedExpression() + .setString("boolean") + .setRange(expr.range); + } + if (arg.isArray() || arg.isConstArray() || arg.isRegExp()) { + return new BasicEvaluatedExpression() + .setString("object") + .setRange(expr.range); + } + } else if (expr.operator === "!") { + const argument = this.evaluateExpression(expr.argument); + if (!argument) return; + if (argument.isBoolean()) { + return new BasicEvaluatedExpression() + .setBoolean(!argument.bool) + .setRange(expr.range); + } + if (argument.isTruthy()) { + return new BasicEvaluatedExpression() + .setBoolean(false) + .setRange(expr.range); + } + if (argument.isFalsy()) { + return new BasicEvaluatedExpression() + .setBoolean(true) + .setRange(expr.range); + } + if (argument.isString()) { + return new BasicEvaluatedExpression() + .setBoolean(!argument.string) + .setRange(expr.range); + } + if (argument.isNumber()) { + return new BasicEvaluatedExpression() + .setBoolean(!argument.number) + .setRange(expr.range); + } + } else if (expr.operator === "~") { + const argument = this.evaluateExpression(expr.argument); + if (!argument) return; + if (!argument.isNumber()) return; + const res = new BasicEvaluatedExpression(); + res.setNumber(~argument.number); + res.setRange(expr.range); + return res; + } + }); + this.hooks.evaluateTypeof.for("undefined").tap("Parser", expr => { + return new BasicEvaluatedExpression() + .setString("undefined") + .setRange(expr.range); + }); + this.hooks.evaluate.for("Identifier").tap("Parser", expr => { + const name = this.scope.renames.get(expr.name) || expr.name; + if (!this.scope.definitions.has(expr.name)) { + const hook = this.hooks.evaluateIdentifier.get(name); + if (hook !== undefined) { + const result = hook.call(expr); + if (result) return result; + } + return new BasicEvaluatedExpression() + .setIdentifier(name) + .setRange(expr.range); + } else { + const hook = this.hooks.evaluateDefinedIdentifier.get(name); + if (hook !== undefined) { + return hook.call(expr); + } + } + }); + this.hooks.evaluate.for("ThisExpression").tap("Parser", expr => { + const name = this.scope.renames.get("this"); + if (name) { + const hook = this.hooks.evaluateIdentifier.get(name); + if (hook !== undefined) { + const result = hook.call(expr); + if (result) return result; + } + return new BasicEvaluatedExpression() + .setIdentifier(name) + .setRange(expr.range); + } + }); + this.hooks.evaluate.for("MemberExpression").tap("Parser", expression => { + let exprName = this.getNameForExpression(expression); + if (exprName) { + if (exprName.free) { + const hook = this.hooks.evaluateIdentifier.get(exprName.name); + if (hook !== undefined) { + const result = hook.call(expression); + if (result) return result; + } + return new BasicEvaluatedExpression() + .setIdentifier(exprName.name) + .setRange(expression.range); + } else { + const hook = this.hooks.evaluateDefinedIdentifier.get(exprName.name); + if (hook !== undefined) { + return hook.call(expression); + } + } + } + }); + this.hooks.evaluate.for("CallExpression").tap("Parser", expr => { + if (expr.callee.type !== "MemberExpression") return; + if ( + expr.callee.property.type !== + (expr.callee.computed ? "Literal" : "Identifier") + ) + return; + const param = this.evaluateExpression(expr.callee.object); + if (!param) return; + const property = expr.callee.property.name || expr.callee.property.value; + const hook = this.hooks.evaluateCallExpressionMember.get(property); + if (hook !== undefined) { + return hook.call(expr, param); + } + }); + this.hooks.evaluateCallExpressionMember + .for("replace") + .tap("Parser", (expr, param) => { + if (!param.isString()) return; + if (expr.arguments.length !== 2) return; + let arg1 = this.evaluateExpression(expr.arguments[0]); + let arg2 = this.evaluateExpression(expr.arguments[1]); + if (!arg1.isString() && !arg1.isRegExp()) return; + arg1 = arg1.regExp || arg1.string; + if (!arg2.isString()) return; + arg2 = arg2.string; + return new BasicEvaluatedExpression() + .setString(param.string.replace(arg1, arg2)) + .setRange(expr.range); + }); + ["substr", "substring"].forEach(fn => { + this.hooks.evaluateCallExpressionMember + .for(fn) + .tap("Parser", (expr, param) => { + if (!param.isString()) return; + let arg1; + let result, + str = param.string; + switch (expr.arguments.length) { + case 1: + arg1 = this.evaluateExpression(expr.arguments[0]); + if (!arg1.isNumber()) return; + result = str[fn](arg1.number); + break; + case 2: { + arg1 = this.evaluateExpression(expr.arguments[0]); + const arg2 = this.evaluateExpression(expr.arguments[1]); + if (!arg1.isNumber()) return; + if (!arg2.isNumber()) return; + result = str[fn](arg1.number, arg2.number); + break; + } + default: + return; + } + return new BasicEvaluatedExpression() + .setString(result) + .setRange(expr.range); + }); + }); + + /** + * @param {string} kind "cooked" | "raw" + * @param {TODO[]} quasis quasis + * @param {TODO[]} expressions expressions + * @returns {BasicEvaluatedExpression[]} Simplified template + */ + const getSimplifiedTemplateResult = (kind, quasis, expressions) => { + const parts = []; + + for (let i = 0; i < quasis.length; i++) { + parts.push( + new BasicEvaluatedExpression() + .setString(quasis[i].value[kind]) + .setRange(quasis[i].range) + ); + + if (i > 0) { + const prevExpr = parts[parts.length - 2], + lastExpr = parts[parts.length - 1]; + const expr = this.evaluateExpression(expressions[i - 1]); + if (!(expr.isString() || expr.isNumber())) continue; + + prevExpr.setString( + prevExpr.string + + (expr.isString() ? expr.string : expr.number) + + lastExpr.string + ); + prevExpr.setRange([prevExpr.range[0], lastExpr.range[1]]); + parts.pop(); + } + } + return parts; + }; + + this.hooks.evaluate.for("TemplateLiteral").tap("Parser", node => { + const parts = getSimplifiedTemplateResult.call( + this, + "cooked", + node.quasis, + node.expressions + ); + if (parts.length === 1) { + return parts[0].setRange(node.range); + } + return new BasicEvaluatedExpression() + .setTemplateString(parts) + .setRange(node.range); + }); + this.hooks.evaluate.for("TaggedTemplateExpression").tap("Parser", node => { + if (this.evaluateExpression(node.tag).identifier !== "String.raw") return; + const parts = getSimplifiedTemplateResult.call( + this, + "raw", + node.quasi.quasis, + node.quasi.expressions + ); + return new BasicEvaluatedExpression() + .setTemplateString(parts) + .setRange(node.range); + }); + + this.hooks.evaluateCallExpressionMember + .for("concat") + .tap("Parser", (expr, param) => { + if (!param.isString() && !param.isWrapped()) return; + + let stringSuffix = null; + let hasUnknownParams = false; + for (let i = expr.arguments.length - 1; i >= 0; i--) { + const argExpr = this.evaluateExpression(expr.arguments[i]); + if (!argExpr.isString() && !argExpr.isNumber()) { + hasUnknownParams = true; + break; + } + + const value = argExpr.isString() + ? argExpr.string + : "" + argExpr.number; + + const newString = value + (stringSuffix ? stringSuffix.string : ""); + const newRange = [ + argExpr.range[0], + (stringSuffix || argExpr).range[1] + ]; + stringSuffix = new BasicEvaluatedExpression() + .setString(newString) + .setRange(newRange); + } + + if (hasUnknownParams) { + const prefix = param.isString() ? param : param.prefix; + return new BasicEvaluatedExpression() + .setWrapped(prefix, stringSuffix) + .setRange(expr.range); + } else if (param.isWrapped()) { + const postfix = stringSuffix || param.postfix; + return new BasicEvaluatedExpression() + .setWrapped(param.prefix, postfix) + .setRange(expr.range); + } else { + const newString = + param.string + (stringSuffix ? stringSuffix.string : ""); + return new BasicEvaluatedExpression() + .setString(newString) + .setRange(expr.range); + } + }); + this.hooks.evaluateCallExpressionMember + .for("split") + .tap("Parser", (expr, param) => { + if (!param.isString()) return; + if (expr.arguments.length !== 1) return; + let result; + const arg = this.evaluateExpression(expr.arguments[0]); + if (arg.isString()) { + result = param.string.split(arg.string); + } else if (arg.isRegExp()) { + result = param.string.split(arg.regExp); + } else { + return; + } + return new BasicEvaluatedExpression() + .setArray(result) + .setRange(expr.range); + }); + this.hooks.evaluate.for("ConditionalExpression").tap("Parser", expr => { + const condition = this.evaluateExpression(expr.test); + const conditionValue = condition.asBool(); + let res; + if (conditionValue === undefined) { + const consequent = this.evaluateExpression(expr.consequent); + const alternate = this.evaluateExpression(expr.alternate); + if (!consequent || !alternate) return; + res = new BasicEvaluatedExpression(); + if (consequent.isConditional()) { + res.setOptions(consequent.options); + } else { + res.setOptions([consequent]); + } + if (alternate.isConditional()) { + res.addOptions(alternate.options); + } else { + res.addOptions([alternate]); + } + } else { + res = this.evaluateExpression( + conditionValue ? expr.consequent : expr.alternate + ); + } + res.setRange(expr.range); + return res; + }); + this.hooks.evaluate.for("ArrayExpression").tap("Parser", expr => { + const items = expr.elements.map(element => { + return element !== null && this.evaluateExpression(element); + }); + if (!items.every(Boolean)) return; + return new BasicEvaluatedExpression() + .setItems(items) + .setRange(expr.range); + }); + } + + getRenameIdentifier(expr) { + const result = this.evaluateExpression(expr); + if (result && result.isIdentifier()) { + return result.identifier; + } + } + + walkClass(classy) { + if (classy.superClass) this.walkExpression(classy.superClass); + if (classy.body && classy.body.type === "ClassBody") { + const wasTopLevel = this.scope.topLevelScope; + this.scope.topLevelScope = false; + for (const methodDefinition of classy.body.body) { + if (methodDefinition.type === "MethodDefinition") { + this.walkMethodDefinition(methodDefinition); + } + } + this.scope.topLevelScope = wasTopLevel; + } + } + + walkMethodDefinition(methodDefinition) { + if (methodDefinition.computed && methodDefinition.key) { + this.walkExpression(methodDefinition.key); + } + if (methodDefinition.value) { + this.walkExpression(methodDefinition.value); + } + } + + // Prewalking iterates the scope for variable declarations + prewalkStatements(statements) { + for (let index = 0, len = statements.length; index < len; index++) { + const statement = statements[index]; + this.prewalkStatement(statement); + } + } + + // Walking iterates the statements and expressions and processes them + walkStatements(statements) { + for (let index = 0, len = statements.length; index < len; index++) { + const statement = statements[index]; + this.walkStatement(statement); + } + } + + prewalkStatement(statement) { + switch (statement.type) { + case "BlockStatement": + this.prewalkBlockStatement(statement); + break; + case "ClassDeclaration": + this.prewalkClassDeclaration(statement); + break; + case "DoWhileStatement": + this.prewalkDoWhileStatement(statement); + break; + case "ExportAllDeclaration": + this.prewalkExportAllDeclaration(statement); + break; + case "ExportDefaultDeclaration": + this.prewalkExportDefaultDeclaration(statement); + break; + case "ExportNamedDeclaration": + this.prewalkExportNamedDeclaration(statement); + break; + case "ForInStatement": + this.prewalkForInStatement(statement); + break; + case "ForOfStatement": + this.prewalkForOfStatement(statement); + break; + case "ForStatement": + this.prewalkForStatement(statement); + break; + case "FunctionDeclaration": + this.prewalkFunctionDeclaration(statement); + break; + case "IfStatement": + this.prewalkIfStatement(statement); + break; + case "ImportDeclaration": + this.prewalkImportDeclaration(statement); + break; + case "LabeledStatement": + this.prewalkLabeledStatement(statement); + break; + case "SwitchStatement": + this.prewalkSwitchStatement(statement); + break; + case "TryStatement": + this.prewalkTryStatement(statement); + break; + case "VariableDeclaration": + this.prewalkVariableDeclaration(statement); + break; + case "WhileStatement": + this.prewalkWhileStatement(statement); + break; + case "WithStatement": + this.prewalkWithStatement(statement); + break; + } + } + + walkStatement(statement) { + if (this.hooks.statement.call(statement) !== undefined) return; + switch (statement.type) { + case "BlockStatement": + this.walkBlockStatement(statement); + break; + case "ClassDeclaration": + this.walkClassDeclaration(statement); + break; + case "DoWhileStatement": + this.walkDoWhileStatement(statement); + break; + case "ExportDefaultDeclaration": + this.walkExportDefaultDeclaration(statement); + break; + case "ExportNamedDeclaration": + this.walkExportNamedDeclaration(statement); + break; + case "ExpressionStatement": + this.walkExpressionStatement(statement); + break; + case "ForInStatement": + this.walkForInStatement(statement); + break; + case "ForOfStatement": + this.walkForOfStatement(statement); + break; + case "ForStatement": + this.walkForStatement(statement); + break; + case "FunctionDeclaration": + this.walkFunctionDeclaration(statement); + break; + case "IfStatement": + this.walkIfStatement(statement); + break; + case "LabeledStatement": + this.walkLabeledStatement(statement); + break; + case "ReturnStatement": + this.walkReturnStatement(statement); + break; + case "SwitchStatement": + this.walkSwitchStatement(statement); + break; + case "ThrowStatement": + this.walkThrowStatement(statement); + break; + case "TryStatement": + this.walkTryStatement(statement); + break; + case "VariableDeclaration": + this.walkVariableDeclaration(statement); + break; + case "WhileStatement": + this.walkWhileStatement(statement); + break; + case "WithStatement": + this.walkWithStatement(statement); + break; + } + } + + // Real Statements + prewalkBlockStatement(statement) { + this.prewalkStatements(statement.body); + } + + walkBlockStatement(statement) { + this.walkStatements(statement.body); + } + + walkExpressionStatement(statement) { + this.walkExpression(statement.expression); + } + + prewalkIfStatement(statement) { + this.prewalkStatement(statement.consequent); + if (statement.alternate) { + this.prewalkStatement(statement.alternate); + } + } + + walkIfStatement(statement) { + const result = this.hooks.statementIf.call(statement); + if (result === undefined) { + this.walkExpression(statement.test); + this.walkStatement(statement.consequent); + if (statement.alternate) { + this.walkStatement(statement.alternate); + } + } else { + if (result) { + this.walkStatement(statement.consequent); + } else if (statement.alternate) { + this.walkStatement(statement.alternate); + } + } + } + + prewalkLabeledStatement(statement) { + this.prewalkStatement(statement.body); + } + + walkLabeledStatement(statement) { + const hook = this.hooks.label.get(statement.label.name); + if (hook !== undefined) { + const result = hook.call(statement); + if (result === true) return; + } + this.walkStatement(statement.body); + } + + prewalkWithStatement(statement) { + this.prewalkStatement(statement.body); + } + + walkWithStatement(statement) { + this.walkExpression(statement.object); + this.walkStatement(statement.body); + } + + prewalkSwitchStatement(statement) { + this.prewalkSwitchCases(statement.cases); + } + + walkSwitchStatement(statement) { + this.walkExpression(statement.discriminant); + this.walkSwitchCases(statement.cases); + } + + walkTerminatingStatement(statement) { + if (statement.argument) this.walkExpression(statement.argument); + } + + walkReturnStatement(statement) { + this.walkTerminatingStatement(statement); + } + + walkThrowStatement(statement) { + this.walkTerminatingStatement(statement); + } + + prewalkTryStatement(statement) { + this.prewalkStatement(statement.block); + } + + walkTryStatement(statement) { + if (this.scope.inTry) { + this.walkStatement(statement.block); + } else { + this.scope.inTry = true; + this.walkStatement(statement.block); + this.scope.inTry = false; + } + if (statement.handler) this.walkCatchClause(statement.handler); + if (statement.finalizer) this.walkStatement(statement.finalizer); + } + + prewalkWhileStatement(statement) { + this.prewalkStatement(statement.body); + } + + walkWhileStatement(statement) { + this.walkExpression(statement.test); + this.walkStatement(statement.body); + } + + prewalkDoWhileStatement(statement) { + this.prewalkStatement(statement.body); + } + + walkDoWhileStatement(statement) { + this.walkStatement(statement.body); + this.walkExpression(statement.test); + } + + prewalkForStatement(statement) { + if (statement.init) { + if (statement.init.type === "VariableDeclaration") { + this.prewalkStatement(statement.init); + } + } + this.prewalkStatement(statement.body); + } + + walkForStatement(statement) { + if (statement.init) { + if (statement.init.type === "VariableDeclaration") { + this.walkStatement(statement.init); + } else { + this.walkExpression(statement.init); + } + } + if (statement.test) { + this.walkExpression(statement.test); + } + if (statement.update) { + this.walkExpression(statement.update); + } + this.walkStatement(statement.body); + } + + prewalkForInStatement(statement) { + if (statement.left.type === "VariableDeclaration") { + this.prewalkVariableDeclaration(statement.left); + } + this.prewalkStatement(statement.body); + } + + walkForInStatement(statement) { + if (statement.left.type === "VariableDeclaration") { + this.walkVariableDeclaration(statement.left); + } else { + this.walkPattern(statement.left); + } + this.walkExpression(statement.right); + this.walkStatement(statement.body); + } + + prewalkForOfStatement(statement) { + if (statement.left.type === "VariableDeclaration") { + this.prewalkVariableDeclaration(statement.left); + } + this.prewalkStatement(statement.body); + } + + walkForOfStatement(statement) { + if (statement.left.type === "VariableDeclaration") { + this.walkVariableDeclaration(statement.left); + } else { + this.walkPattern(statement.left); + } + this.walkExpression(statement.right); + this.walkStatement(statement.body); + } + + // Declarations + prewalkFunctionDeclaration(statement) { + if (statement.id) { + this.scope.renames.set(statement.id.name, null); + this.scope.definitions.add(statement.id.name); + } + } + + walkFunctionDeclaration(statement) { + const wasTopLevel = this.scope.topLevelScope; + this.scope.topLevelScope = false; + this.inScope(statement.params, () => { + for (const param of statement.params) { + this.walkPattern(param); + } + if (statement.body.type === "BlockStatement") { + this.detectStrictMode(statement.body.body); + this.prewalkStatement(statement.body); + this.walkStatement(statement.body); + } else { + this.walkExpression(statement.body); + } + }); + this.scope.topLevelScope = wasTopLevel; + } + + prewalkImportDeclaration(statement) { + const source = statement.source.value; + this.hooks.import.call(statement, source); + for (const specifier of statement.specifiers) { + const name = specifier.local.name; + this.scope.renames.set(name, null); + this.scope.definitions.add(name); + switch (specifier.type) { + case "ImportDefaultSpecifier": + this.hooks.importSpecifier.call(statement, source, "default", name); + break; + case "ImportSpecifier": + this.hooks.importSpecifier.call( + statement, + source, + specifier.imported.name, + name + ); + break; + case "ImportNamespaceSpecifier": + this.hooks.importSpecifier.call(statement, source, null, name); + break; + } + } + } + + prewalkExportNamedDeclaration(statement) { + let source; + if (statement.source) { + source = statement.source.value; + this.hooks.exportImport.call(statement, source); + } else { + this.hooks.export.call(statement); + } + if (statement.declaration) { + if ( + !this.hooks.exportDeclaration.call(statement, statement.declaration) + ) { + const originalDefinitions = this.scope.definitions; + const tracker = new TrackingSet(this.scope.definitions); + this.scope.definitions = tracker; + this.prewalkStatement(statement.declaration); + const newDefs = Array.from(tracker.getAddedItems()); + this.scope.definitions = originalDefinitions; + for (let index = newDefs.length - 1; index >= 0; index--) { + const def = newDefs[index]; + this.hooks.exportSpecifier.call(statement, def, def, index); + } + } + } + if (statement.specifiers) { + for ( + let specifierIndex = 0; + specifierIndex < statement.specifiers.length; + specifierIndex++ + ) { + const specifier = statement.specifiers[specifierIndex]; + switch (specifier.type) { + case "ExportSpecifier": { + const name = specifier.exported.name; + if (source) { + this.hooks.exportImportSpecifier.call( + statement, + source, + specifier.local.name, + name, + specifierIndex + ); + } else { + this.hooks.exportSpecifier.call( + statement, + specifier.local.name, + name, + specifierIndex + ); + } + break; + } + } + } + } + } + + walkExportNamedDeclaration(statement) { + if (statement.declaration) { + this.walkStatement(statement.declaration); + } + } + + prewalkExportDefaultDeclaration(statement) { + if (statement.declaration.id) { + const originalDefinitions = this.scope.definitions; + const tracker = new TrackingSet(this.scope.definitions); + this.scope.definitions = tracker; + this.prewalkStatement(statement.declaration); + const newDefs = Array.from(tracker.getAddedItems()); + this.scope.definitions = originalDefinitions; + for (let index = 0, len = newDefs.length; index < len; index++) { + const def = newDefs[index]; + this.hooks.exportSpecifier.call(statement, def, "default"); + } + } + } + + walkExportDefaultDeclaration(statement) { + this.hooks.export.call(statement); + if ( + statement.declaration.id && + statement.declaration.type !== "FunctionExpression" && + statement.declaration.type !== "ClassExpression" + ) { + if ( + !this.hooks.exportDeclaration.call(statement, statement.declaration) + ) { + this.walkStatement(statement.declaration); + } + } else { + // Acorn parses `export default function() {}` as `FunctionDeclaration` and + // `export default class {}` as `ClassDeclaration`, both with `id = null`. + // These nodes must be treated as expressions. + if (statement.declaration.type === "FunctionDeclaration") { + this.walkFunctionDeclaration(statement.declaration); + } else if (statement.declaration.type === "ClassDeclaration") { + this.walkClassDeclaration(statement.declaration); + } else { + this.walkExpression(statement.declaration); + } + if (!this.hooks.exportExpression.call(statement, statement.declaration)) { + this.hooks.exportSpecifier.call( + statement, + statement.declaration, + "default" + ); + } + } + } + + prewalkExportAllDeclaration(statement) { + const source = statement.source.value; + this.hooks.exportImport.call(statement, source); + this.hooks.exportImportSpecifier.call(statement, source, null, null, 0); + } + + prewalkVariableDeclaration(statement) { + const hookMap = + statement.kind === "const" + ? this.hooks.varDeclarationConst + : statement.kind === "let" + ? this.hooks.varDeclarationLet + : this.hooks.varDeclarationVar; + for (const declarator of statement.declarations) { + switch (declarator.type) { + case "VariableDeclarator": { + this.enterPattern(declarator.id, (name, decl) => { + let hook = hookMap.get(name); + if (hook === undefined || !hook.call(decl)) { + hook = this.hooks.varDeclaration.get(name); + if (hook === undefined || !hook.call(decl)) { + this.scope.renames.set(name, null); + this.scope.definitions.add(name); + } + } + }); + break; + } + } + } + } + + walkVariableDeclaration(statement) { + for (const declarator of statement.declarations) { + switch (declarator.type) { + case "VariableDeclarator": { + const renameIdentifier = + declarator.init && this.getRenameIdentifier(declarator.init); + if (renameIdentifier && declarator.id.type === "Identifier") { + const hook = this.hooks.canRename.get(renameIdentifier); + if (hook !== undefined && hook.call(declarator.init)) { + // renaming with "var a = b;" + const hook = this.hooks.rename.get(renameIdentifier); + if (hook === undefined || !hook.call(declarator.init)) { + this.scope.renames.set( + declarator.id.name, + this.scope.renames.get(renameIdentifier) || renameIdentifier + ); + this.scope.definitions.delete(declarator.id.name); + } + break; + } + } + this.walkPattern(declarator.id); + if (declarator.init) this.walkExpression(declarator.init); + break; + } + } + } + } + + prewalkClassDeclaration(statement) { + if (statement.id) { + this.scope.renames.set(statement.id.name, null); + this.scope.definitions.add(statement.id.name); + } + } + + walkClassDeclaration(statement) { + this.walkClass(statement); + } + + prewalkSwitchCases(switchCases) { + for (let index = 0, len = switchCases.length; index < len; index++) { + const switchCase = switchCases[index]; + this.prewalkStatements(switchCase.consequent); + } + } + + walkSwitchCases(switchCases) { + for (let index = 0, len = switchCases.length; index < len; index++) { + const switchCase = switchCases[index]; + + if (switchCase.test) { + this.walkExpression(switchCase.test); + } + this.walkStatements(switchCase.consequent); + } + } + + walkCatchClause(catchClause) { + // Error binding is optional in catch clause since ECMAScript 2019 + const errorBinding = + catchClause.param === null ? EMPTY_ARRAY : [catchClause.param]; + + this.inScope(errorBinding, () => { + this.prewalkStatement(catchClause.body); + this.walkStatement(catchClause.body); + }); + } + + walkPattern(pattern) { + switch (pattern.type) { + case "ArrayPattern": + this.walkArrayPattern(pattern); + break; + case "AssignmentPattern": + this.walkAssignmentPattern(pattern); + break; + case "MemberExpression": + this.walkMemberExpression(pattern); + break; + case "ObjectPattern": + this.walkObjectPattern(pattern); + break; + case "RestElement": + this.walkRestElement(pattern); + break; + } + } + + walkAssignmentPattern(pattern) { + this.walkExpression(pattern.right); + this.walkPattern(pattern.left); + } + + walkObjectPattern(pattern) { + for (let i = 0, len = pattern.properties.length; i < len; i++) { + const prop = pattern.properties[i]; + if (prop) { + if (prop.computed) this.walkExpression(prop.key); + if (prop.value) this.walkPattern(prop.value); + } + } + } + + walkArrayPattern(pattern) { + for (let i = 0, len = pattern.elements.length; i < len; i++) { + const element = pattern.elements[i]; + if (element) this.walkPattern(element); + } + } + + walkRestElement(pattern) { + this.walkPattern(pattern.argument); + } + + walkExpressions(expressions) { + for (const expression of expressions) { + if (expression) { + this.walkExpression(expression); + } + } + } + + walkExpression(expression) { + switch (expression.type) { + case "ArrayExpression": + this.walkArrayExpression(expression); + break; + case "ArrowFunctionExpression": + this.walkArrowFunctionExpression(expression); + break; + case "AssignmentExpression": + this.walkAssignmentExpression(expression); + break; + case "AwaitExpression": + this.walkAwaitExpression(expression); + break; + case "BinaryExpression": + this.walkBinaryExpression(expression); + break; + case "CallExpression": + this.walkCallExpression(expression); + break; + case "ClassExpression": + this.walkClassExpression(expression); + break; + case "ConditionalExpression": + this.walkConditionalExpression(expression); + break; + case "FunctionExpression": + this.walkFunctionExpression(expression); + break; + case "Identifier": + this.walkIdentifier(expression); + break; + case "LogicalExpression": + this.walkLogicalExpression(expression); + break; + case "MemberExpression": + this.walkMemberExpression(expression); + break; + case "NewExpression": + this.walkNewExpression(expression); + break; + case "ObjectExpression": + this.walkObjectExpression(expression); + break; + case "SequenceExpression": + this.walkSequenceExpression(expression); + break; + case "SpreadElement": + this.walkSpreadElement(expression); + break; + case "TaggedTemplateExpression": + this.walkTaggedTemplateExpression(expression); + break; + case "TemplateLiteral": + this.walkTemplateLiteral(expression); + break; + case "ThisExpression": + this.walkThisExpression(expression); + break; + case "UnaryExpression": + this.walkUnaryExpression(expression); + break; + case "UpdateExpression": + this.walkUpdateExpression(expression); + break; + case "YieldExpression": + this.walkYieldExpression(expression); + break; + } + } + + walkAwaitExpression(expression) { + this.walkExpression(expression.argument); + } + + walkArrayExpression(expression) { + if (expression.elements) { + this.walkExpressions(expression.elements); + } + } + + walkSpreadElement(expression) { + if (expression.argument) { + this.walkExpression(expression.argument); + } + } + + walkObjectExpression(expression) { + for ( + let propIndex = 0, len = expression.properties.length; + propIndex < len; + propIndex++ + ) { + const prop = expression.properties[propIndex]; + if (prop.type === "SpreadElement") { + this.walkExpression(prop.argument); + continue; + } + if (prop.computed) { + this.walkExpression(prop.key); + } + if (prop.shorthand) { + this.scope.inShorthand = true; + } + this.walkExpression(prop.value); + if (prop.shorthand) { + this.scope.inShorthand = false; + } + } + } + + walkFunctionExpression(expression) { + const wasTopLevel = this.scope.topLevelScope; + this.scope.topLevelScope = false; + this.inScope(expression.params, () => { + for (const param of expression.params) { + this.walkPattern(param); + } + if (expression.body.type === "BlockStatement") { + this.detectStrictMode(expression.body.body); + this.prewalkStatement(expression.body); + this.walkStatement(expression.body); + } else { + this.walkExpression(expression.body); + } + }); + this.scope.topLevelScope = wasTopLevel; + } + + walkArrowFunctionExpression(expression) { + this.inScope(expression.params, () => { + for (const param of expression.params) { + this.walkPattern(param); + } + if (expression.body.type === "BlockStatement") { + this.detectStrictMode(expression.body.body); + this.prewalkStatement(expression.body); + this.walkStatement(expression.body); + } else { + this.walkExpression(expression.body); + } + }); + } + + walkSequenceExpression(expression) { + if (expression.expressions) this.walkExpressions(expression.expressions); + } + + walkUpdateExpression(expression) { + this.walkExpression(expression.argument); + } + + walkUnaryExpression(expression) { + if (expression.operator === "typeof") { + const exprName = this.getNameForExpression(expression.argument); + if (exprName && exprName.free) { + const hook = this.hooks.typeof.get(exprName.name); + if (hook !== undefined) { + const result = hook.call(expression); + if (result === true) return; + } + } + } + this.walkExpression(expression.argument); + } + + walkLeftRightExpression(expression) { + this.walkExpression(expression.left); + this.walkExpression(expression.right); + } + + walkBinaryExpression(expression) { + this.walkLeftRightExpression(expression); + } + + walkLogicalExpression(expression) { + this.walkLeftRightExpression(expression); + } + + walkAssignmentExpression(expression) { + const renameIdentifier = this.getRenameIdentifier(expression.right); + if (expression.left.type === "Identifier" && renameIdentifier) { + const hook = this.hooks.canRename.get(renameIdentifier); + if (hook !== undefined && hook.call(expression.right)) { + // renaming "a = b;" + const hook = this.hooks.rename.get(renameIdentifier); + if (hook === undefined || !hook.call(expression.right)) { + this.scope.renames.set(expression.left.name, renameIdentifier); + this.scope.definitions.delete(expression.left.name); + } + return; + } + } + if (expression.left.type === "Identifier") { + const assignedHook = this.hooks.assigned.get(expression.left.name); + if (assignedHook === undefined || !assignedHook.call(expression)) { + this.walkExpression(expression.right); + } + this.scope.renames.set(expression.left.name, null); + const assignHook = this.hooks.assign.get(expression.left.name); + if (assignHook === undefined || !assignHook.call(expression)) { + this.walkExpression(expression.left); + } + return; + } + this.walkExpression(expression.right); + this.walkPattern(expression.left); + this.enterPattern(expression.left, (name, decl) => { + this.scope.renames.set(name, null); + }); + } + + walkConditionalExpression(expression) { + const result = this.hooks.expressionConditionalOperator.call(expression); + if (result === undefined) { + this.walkExpression(expression.test); + this.walkExpression(expression.consequent); + if (expression.alternate) { + this.walkExpression(expression.alternate); + } + } else { + if (result) { + this.walkExpression(expression.consequent); + } else if (expression.alternate) { + this.walkExpression(expression.alternate); + } + } + } + + walkNewExpression(expression) { + const callee = this.evaluateExpression(expression.callee); + if (callee.isIdentifier()) { + const hook = this.hooks.new.get(callee.identifier); + if (hook !== undefined) { + const result = hook.call(expression); + if (result === true) { + return; + } + } + } + + this.walkExpression(expression.callee); + if (expression.arguments) { + this.walkExpressions(expression.arguments); + } + } + + walkYieldExpression(expression) { + if (expression.argument) { + this.walkExpression(expression.argument); + } + } + + walkTemplateLiteral(expression) { + if (expression.expressions) { + this.walkExpressions(expression.expressions); + } + } + + walkTaggedTemplateExpression(expression) { + if (expression.tag) { + this.walkExpression(expression.tag); + } + if (expression.quasi && expression.quasi.expressions) { + this.walkExpressions(expression.quasi.expressions); + } + } + + walkClassExpression(expression) { + this.walkClass(expression); + } + + _walkIIFE(functionExpression, options, currentThis) { + const renameArgOrThis = argOrThis => { + const renameIdentifier = this.getRenameIdentifier(argOrThis); + if (renameIdentifier) { + const hook = this.hooks.canRename.get(renameIdentifier); + if (hook !== undefined && hook.call(argOrThis)) { + const hook = this.hooks.rename.get(renameIdentifier); + if (hook === undefined || !hook.call(argOrThis)) { + return renameIdentifier; + } + } + } + this.walkExpression(argOrThis); + }; + const params = functionExpression.params; + const renameThis = currentThis ? renameArgOrThis(currentThis) : null; + const args = options.map(renameArgOrThis); + const wasTopLevel = this.scope.topLevelScope; + this.scope.topLevelScope = false; + this.inScope(params.filter((identifier, idx) => !args[idx]), () => { + if (renameThis) { + this.scope.renames.set("this", renameThis); + } + for (let i = 0; i < args.length; i++) { + const param = args[i]; + if (!param) continue; + if (!params[i] || params[i].type !== "Identifier") continue; + this.scope.renames.set(params[i].name, param); + } + if (functionExpression.body.type === "BlockStatement") { + this.prewalkStatement(functionExpression.body); + this.walkStatement(functionExpression.body); + } else { + this.walkExpression(functionExpression.body); + } + }); + this.scope.topLevelScope = wasTopLevel; + } + + walkCallExpression(expression) { + if ( + expression.callee.type === "MemberExpression" && + expression.callee.object.type === "FunctionExpression" && + !expression.callee.computed && + (expression.callee.property.name === "call" || + expression.callee.property.name === "bind") && + expression.arguments.length > 0 + ) { + // (function(…) { }.call/bind(?, …)) + this._walkIIFE( + expression.callee.object, + expression.arguments.slice(1), + expression.arguments[0] + ); + } else if (expression.callee.type === "FunctionExpression") { + // (function(…) { }(…)) + this._walkIIFE(expression.callee, expression.arguments, null); + } else if (expression.callee.type === "Import") { + let result = this.hooks.importCall.call(expression); + if (result === true) return; + + if (expression.arguments) this.walkExpressions(expression.arguments); + } else { + const callee = this.evaluateExpression(expression.callee); + if (callee.isIdentifier()) { + const callHook = this.hooks.call.get(callee.identifier); + if (callHook !== undefined) { + let result = callHook.call(expression); + if (result === true) return; + } + let identifier = callee.identifier.replace(/\.[^.]+$/, ""); + if (identifier !== callee.identifier) { + const callAnyHook = this.hooks.callAnyMember.get(identifier); + if (callAnyHook !== undefined) { + let result = callAnyHook.call(expression); + if (result === true) return; + } + } + } + + if (expression.callee) this.walkExpression(expression.callee); + if (expression.arguments) this.walkExpressions(expression.arguments); + } + } + + walkMemberExpression(expression) { + const exprName = this.getNameForExpression(expression); + if (exprName && exprName.free) { + const expressionHook = this.hooks.expression.get(exprName.name); + if (expressionHook !== undefined) { + const result = expressionHook.call(expression); + if (result === true) return; + } + const expressionAnyMemberHook = this.hooks.expressionAnyMember.get( + exprName.nameGeneral + ); + if (expressionAnyMemberHook !== undefined) { + const result = expressionAnyMemberHook.call(expression); + if (result === true) return; + } + } + this.walkExpression(expression.object); + if (expression.computed === true) this.walkExpression(expression.property); + } + + walkThisExpression(expression) { + const expressionHook = this.hooks.expression.get("this"); + if (expressionHook !== undefined) { + expressionHook.call(expression); + } + } + + walkIdentifier(expression) { + if (!this.scope.definitions.has(expression.name)) { + const hook = this.hooks.expression.get( + this.scope.renames.get(expression.name) || expression.name + ); + if (hook !== undefined) { + const result = hook.call(expression); + if (result === true) return; + } + } + } + + inScope(params, fn) { + const oldScope = this.scope; + this.scope = { + topLevelScope: oldScope.topLevelScope, + inTry: false, + inShorthand: false, + isStrict: oldScope.isStrict, + definitions: oldScope.definitions.createChild(), + renames: oldScope.renames.createChild() + }; + + this.scope.renames.set("this", null); + + for (const param of params) { + if (typeof param !== "string") { + this.enterPattern(param, param => { + this.scope.renames.set(param, null); + this.scope.definitions.add(param); + }); + } else if (param) { + this.scope.renames.set(param, null); + this.scope.definitions.add(param); + } + } + + fn(); + this.scope = oldScope; + } + + detectStrictMode(statements) { + const isStrict = + statements.length >= 1 && + statements[0].type === "ExpressionStatement" && + statements[0].expression.type === "Literal" && + statements[0].expression.value === "use strict"; + if (isStrict) { + this.scope.isStrict = true; + } + } + + enterPattern(pattern, onIdent) { + if (!pattern) return; + switch (pattern.type) { + case "ArrayPattern": + this.enterArrayPattern(pattern, onIdent); + break; + case "AssignmentPattern": + this.enterAssignmentPattern(pattern, onIdent); + break; + case "Identifier": + this.enterIdentifier(pattern, onIdent); + break; + case "ObjectPattern": + this.enterObjectPattern(pattern, onIdent); + break; + case "RestElement": + this.enterRestElement(pattern, onIdent); + break; + } + } + + enterIdentifier(pattern, onIdent) { + onIdent(pattern.name, pattern); + } + + enterObjectPattern(pattern, onIdent) { + for ( + let propIndex = 0, len = pattern.properties.length; + propIndex < len; + propIndex++ + ) { + const prop = pattern.properties[propIndex]; + this.enterPattern(prop.value, onIdent); + } + } + + enterArrayPattern(pattern, onIdent) { + for ( + let elementIndex = 0, len = pattern.elements.length; + elementIndex < len; + elementIndex++ + ) { + const element = pattern.elements[elementIndex]; + this.enterPattern(element, onIdent); + } + } + + enterRestElement(pattern, onIdent) { + this.enterPattern(pattern.argument, onIdent); + } + + enterAssignmentPattern(pattern, onIdent) { + this.enterPattern(pattern.left, onIdent); + } + + evaluateExpression(expression) { + try { + const hook = this.hooks.evaluate.get(expression.type); + if (hook !== undefined) { + const result = hook.call(expression); + if (result !== undefined) return result; + } + } catch (e) { + console.warn(e); + // ignore error + } + return new BasicEvaluatedExpression().setRange(expression.range); + } + + parseString(expression) { + switch (expression.type) { + case "BinaryExpression": + if (expression.operator === "+") { + return ( + this.parseString(expression.left) + + this.parseString(expression.right) + ); + } + break; + case "Literal": + return expression.value + ""; + } + throw new Error( + expression.type + " is not supported as parameter for require" + ); + } + + parseCalculatedString(expression) { + switch (expression.type) { + case "BinaryExpression": + if (expression.operator === "+") { + const left = this.parseCalculatedString(expression.left); + const right = this.parseCalculatedString(expression.right); + if (left.code) { + return { + range: left.range, + value: left.value, + code: true, + conditional: false + }; + } else if (right.code) { + return { + range: [ + left.range[0], + right.range ? right.range[1] : left.range[1] + ], + value: left.value + right.value, + code: true, + conditional: false + }; + } else { + return { + range: [left.range[0], right.range[1]], + value: left.value + right.value, + code: false, + conditional: false + }; + } + } + break; + case "ConditionalExpression": { + const consequent = this.parseCalculatedString(expression.consequent); + const alternate = this.parseCalculatedString(expression.alternate); + const items = []; + if (consequent.conditional) { + items.push(...consequent.conditional); + } else if (!consequent.code) { + items.push(consequent); + } else { + break; + } + if (alternate.conditional) { + items.push(...alternate.conditional); + } else if (!alternate.code) { + items.push(alternate); + } else { + break; + } + return { + range: undefined, + value: "", + code: true, + conditional: items + }; + } + case "Literal": + return { + range: expression.range, + value: expression.value + "", + code: false, + conditional: false + }; + } + return { + range: undefined, + value: "", + code: true, + conditional: false + }; + } + + parse(source, initialState) { + let ast; + let comments; + if (typeof source === "object" && source !== null) { + ast = source; + comments = source.comments; + } else { + comments = []; + ast = Parser.parse(source, { + sourceType: this.sourceType, + onComment: comments + }); + } + + const oldScope = this.scope; + const oldState = this.state; + const oldComments = this.comments; + this.scope = { + topLevelScope: true, + inTry: false, + inShorthand: false, + isStrict: false, + definitions: new StackedSetMap(), + renames: new StackedSetMap() + }; + const state = (this.state = initialState || {}); + this.comments = comments; + if (this.hooks.program.call(ast, comments) === undefined) { + this.detectStrictMode(ast.body); + this.prewalkStatements(ast.body); + this.walkStatements(ast.body); + } + this.scope = oldScope; + this.state = oldState; + this.comments = oldComments; + return state; + } + + evaluate(source) { + const ast = Parser.parse("(" + source + ")", { + sourceType: this.sourceType, + locations: false + }); + if (ast.body.length !== 1 || ast.body[0].type !== "ExpressionStatement") { + throw new Error("evaluate: Source is not a expression"); + } + return this.evaluateExpression(ast.body[0].expression); + } + + getComments(range) { + return this.comments.filter( + comment => comment.range[0] >= range[0] && comment.range[1] <= range[1] + ); + } + + parseCommentOptions(range) { + const comments = this.getComments(range); + if (comments.length === 0) { + return EMPTY_COMMENT_OPTIONS; + } + let options = {}; + let errors = []; + for (const comment of comments) { + const { value } = comment; + if (value && webpackCommentRegExp.test(value)) { + // try compile only if webpack options comment is present + try { + const val = vm.runInNewContext(`(function(){return {${value}};})()`); + Object.assign(options, val); + } catch (e) { + e.comment = comment; + errors.push(e); + } + } + } + return { options, errors }; + } + + getNameForExpression(expression) { + let expr = expression; + const exprName = []; + while ( + expr.type === "MemberExpression" && + expr.property.type === (expr.computed ? "Literal" : "Identifier") + ) { + exprName.push(expr.computed ? expr.property.value : expr.property.name); + expr = expr.object; + } + let free; + if (expr.type === "Identifier") { + free = !this.scope.definitions.has(expr.name); + exprName.push(this.scope.renames.get(expr.name) || expr.name); + } else if ( + expr.type === "ThisExpression" && + this.scope.renames.get("this") + ) { + free = true; + exprName.push(this.scope.renames.get("this")); + } else if (expr.type === "ThisExpression") { + free = this.scope.topLevelScope; + exprName.push("this"); + } else { + return null; + } + let prefix = ""; + for (let i = exprName.length - 1; i >= 2; i--) { + prefix += exprName[i] + "."; + } + if (exprName.length > 1) { + prefix += exprName[1]; + } + const name = prefix ? prefix + "." + exprName[0] : exprName[0]; + const nameGeneral = prefix; + return { + name, + nameGeneral, + free + }; + } + + static parse(code, options) { + const type = options ? options.sourceType : "module"; + const parserOptions = Object.assign( + Object.create(null), + defaultParserOptions, + options + ); + + if (type === "auto") { + parserOptions.sourceType = "module"; + } + + let ast; + let error; + let threw = false; + try { + ast = acorn.parse(code, parserOptions); + } catch (e) { + error = e; + threw = true; + } + + if (threw && type === "auto") { + parserOptions.sourceType = "script"; + if (Array.isArray(parserOptions.onComment)) { + parserOptions.onComment.length = 0; + } + try { + ast = acorn.parse(code, parserOptions); + threw = false; + } catch (e) { + threw = true; + } + } + + if (threw) { + throw error; + } + + return ast; + } +} + +// TODO remove in webpack 5 +Object.defineProperty(Parser.prototype, "getCommentOptions", { + configurable: false, + value: util.deprecate( + /** + * @deprecated + * @param {TODO} range Range + * @returns {void} + * @this {Parser} + */ + function(range) { + return this.parseCommentOptions(range).options; + }, + "Parser.getCommentOptions: Use Parser.parseCommentOptions(range) instead" + ) +}); + +module.exports = Parser; diff --git a/node_modules/webpack/lib/ParserHelpers.js b/node_modules/webpack/lib/ParserHelpers.js index 64a0e9996..5248f12fe 100644 --- a/node_modules/webpack/lib/ParserHelpers.js +++ b/node_modules/webpack/lib/ParserHelpers.js @@ -1,85 +1,103 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const path = require("path"); - -const BasicEvaluatedExpression = require("./BasicEvaluatedExpression"); -const ConstDependency = require("./dependencies/ConstDependency"); -const UnsupportedFeatureWarning = require("./UnsupportedFeatureWarning"); - -const ParserHelpers = exports; - -ParserHelpers.addParsedVariableToModule = function(parser, name, expression) { - if(!parser.state.current.addVariable) return false; - var deps = []; - parser.parse(expression, { - current: { - addDependency: function(dep) { - dep.userRequest = name; - deps.push(dep); - } - }, - module: parser.state.module - }); - parser.state.current.addVariable(name, expression, deps); - return true; -}; - -ParserHelpers.requireFileAsExpression = function(context, pathToModule) { - var moduleJsPath = path.relative(context, pathToModule); - if(!/^[A-Z]:/i.test(moduleJsPath)) { - moduleJsPath = "./" + moduleJsPath.replace(/\\/g, "/"); - } - return "require(" + JSON.stringify(moduleJsPath) + ")"; -}; - -ParserHelpers.toConstantDependency = function(value) { - return function constDependency(expr) { - var dep = new ConstDependency(value, expr.range); - dep.loc = expr.loc; - this.state.current.addDependency(dep); - return true; - }; -}; - -ParserHelpers.evaluateToString = function(value) { - return function stringExpression(expr) { - return new BasicEvaluatedExpression().setString(value).setRange(expr.range); - }; -}; - -ParserHelpers.evaluateToBoolean = function(value) { - return function booleanExpression(expr) { - return new BasicEvaluatedExpression().setBoolean(value).setRange(expr.range); - }; -}; - -ParserHelpers.evaluateToIdentifier = function(identifier, truthy) { - return function identifierExpression(expr) { - let evex = new BasicEvaluatedExpression().setIdentifier(identifier).setRange(expr.range); - if(truthy === true) evex = evex.setTruthy(); - else if(truthy === false) evex = evex.setFalsy(); - return evex; - }; -}; - -ParserHelpers.expressionIsUnsupported = function(message) { - return function unsupportedExpression(expr) { - var dep = new ConstDependency("(void 0)", expr.range); - dep.loc = expr.loc; - this.state.current.addDependency(dep); - if(!this.state.module) return; - this.state.module.warnings.push(new UnsupportedFeatureWarning(this.state.module, message)); - return true; - }; -}; - -ParserHelpers.skipTraversal = function skipTraversal() { - return true; -}; - -ParserHelpers.approve = function approve() { - return true; -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const path = require("path"); + +const BasicEvaluatedExpression = require("./BasicEvaluatedExpression"); +const ConstDependency = require("./dependencies/ConstDependency"); +const UnsupportedFeatureWarning = require("./UnsupportedFeatureWarning"); + +const ParserHelpers = exports; + +ParserHelpers.addParsedVariableToModule = (parser, name, expression) => { + if (!parser.state.current.addVariable) return false; + var deps = []; + parser.parse(expression, { + current: { + addDependency: dep => { + dep.userRequest = name; + deps.push(dep); + } + }, + module: parser.state.module + }); + parser.state.current.addVariable(name, expression, deps); + return true; +}; + +ParserHelpers.requireFileAsExpression = (context, pathToModule) => { + var moduleJsPath = path.relative(context, pathToModule); + if (!/^[A-Z]:/i.test(moduleJsPath)) { + moduleJsPath = "./" + moduleJsPath.replace(/\\/g, "/"); + } + return "require(" + JSON.stringify(moduleJsPath) + ")"; +}; + +ParserHelpers.toConstantDependency = (parser, value) => { + return function constDependency(expr) { + var dep = new ConstDependency(value, expr.range, false); + dep.loc = expr.loc; + parser.state.current.addDependency(dep); + return true; + }; +}; + +ParserHelpers.toConstantDependencyWithWebpackRequire = (parser, value) => { + return function constDependencyWithWebpackRequire(expr) { + var dep = new ConstDependency(value, expr.range, true); + dep.loc = expr.loc; + parser.state.current.addDependency(dep); + return true; + }; +}; + +ParserHelpers.evaluateToString = value => { + return function stringExpression(expr) { + return new BasicEvaluatedExpression().setString(value).setRange(expr.range); + }; +}; + +ParserHelpers.evaluateToBoolean = value => { + return function booleanExpression(expr) { + return new BasicEvaluatedExpression() + .setBoolean(value) + .setRange(expr.range); + }; +}; + +ParserHelpers.evaluateToIdentifier = (identifier, truthy) => { + return function identifierExpression(expr) { + let evex = new BasicEvaluatedExpression() + .setIdentifier(identifier) + .setRange(expr.range); + if (truthy === true) { + evex = evex.setTruthy(); + } else if (truthy === false) { + evex = evex.setFalsy(); + } + return evex; + }; +}; + +ParserHelpers.expressionIsUnsupported = (parser, message) => { + return function unsupportedExpression(expr) { + var dep = new ConstDependency("(void 0)", expr.range, false); + dep.loc = expr.loc; + parser.state.current.addDependency(dep); + if (!parser.state.module) return; + parser.state.module.warnings.push( + new UnsupportedFeatureWarning(parser.state.module, message, expr.loc) + ); + return true; + }; +}; + +ParserHelpers.skipTraversal = function skipTraversal() { + return true; +}; + +ParserHelpers.approve = function approve() { + return true; +}; diff --git a/node_modules/webpack/lib/PrefetchPlugin.js b/node_modules/webpack/lib/PrefetchPlugin.js index 4f45d33f7..cc9d17c0c 100644 --- a/node_modules/webpack/lib/PrefetchPlugin.js +++ b/node_modules/webpack/lib/PrefetchPlugin.js @@ -1,31 +1,37 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const PrefetchDependency = require("./dependencies/PrefetchDependency"); - -class PrefetchPlugin { - - constructor(context, request) { - if(!request) { - this.request = context; - } else { - this.context = context; - this.request = request; - } - } - - apply(compiler) { - compiler.plugin("compilation", (compilation, params) => { - const normalModuleFactory = params.normalModuleFactory; - - compilation.dependencyFactories.set(PrefetchDependency, normalModuleFactory); - }); - compiler.plugin("make", (compilation, callback) => { - compilation.prefetch(this.context || compiler.context, new PrefetchDependency(this.request), callback); - }); - } - -} -module.exports = PrefetchPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const PrefetchDependency = require("./dependencies/PrefetchDependency"); + +class PrefetchPlugin { + constructor(context, request) { + if (!request) { + this.request = context; + } else { + this.context = context; + this.request = request; + } + } + + apply(compiler) { + compiler.hooks.compilation.tap( + "PrefetchPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set( + PrefetchDependency, + normalModuleFactory + ); + } + ); + compiler.hooks.make.tapAsync("PrefetchPlugin", (compilation, callback) => { + compilation.prefetch( + this.context || compiler.context, + new PrefetchDependency(this.request), + callback + ); + }); + } +} +module.exports = PrefetchPlugin; diff --git a/node_modules/webpack/lib/ProgressPlugin.js b/node_modules/webpack/lib/ProgressPlugin.js index b0828d8a8..a8612932d 100644 --- a/node_modules/webpack/lib/ProgressPlugin.js +++ b/node_modules/webpack/lib/ProgressPlugin.js @@ -1,192 +1,246 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class ProgressPlugin { - - constructor(options) { - if(typeof options === "function") { - options = { - handler: options - }; - } - options = options || {}; - this.profile = options.profile; - this.handler = options.handler; - } - - apply(compiler) { - const handler = this.handler || defaultHandler; - const profile = this.profile; - if(compiler.compilers) { - const states = new Array(compiler.compilers.length); - compiler.compilers.forEach(function(compiler, idx) { - compiler.apply(new ProgressPlugin(function(p, msg) { - states[idx] = Array.prototype.slice.apply(arguments); - handler.apply(null, [ - states.map(state => state && state[0] || 0).reduce((a, b) => a + b) / states.length, - `[${idx}] ${msg}` - ].concat(Array.prototype.slice.call(arguments, 2))); - })); - }); - } else { - let lastModulesCount = 0; - let moduleCount = 500; - let doneModules = 0; - const activeModules = []; - - const update = function update(module) { - handler( - 0.1 + (doneModules / Math.max(lastModulesCount, moduleCount)) * 0.6, - "building modules", - `${doneModules}/${moduleCount} modules`, - `${activeModules.length} active`, - activeModules[activeModules.length - 1] - ); - }; - - const moduleDone = function moduleDone(module) { - doneModules++; - const ident = module.identifier(); - if(ident) { - const idx = activeModules.indexOf(ident); - if(idx >= 0) activeModules.splice(idx, 1); - } - update(); - }; - compiler.plugin("compilation", function(compilation) { - if(compilation.compiler.isChild()) return; - lastModulesCount = moduleCount; - moduleCount = 0; - doneModules = 0; - handler(0, "compiling"); - compilation.plugin("build-module", function(module) { - moduleCount++; - const ident = module.identifier(); - if(ident) { - activeModules.push(ident); - } - update(); - }); - compilation.plugin("failed-module", moduleDone); - compilation.plugin("succeed-module", moduleDone); - const syncHooks = { - "seal": [0.71, "sealing"], - "optimize": [0.72, "optimizing"], - "optimize-modules-basic": [0.73, "basic module optimization"], - "optimize-modules": [0.74, "module optimization"], - "optimize-modules-advanced": [0.75, "advanced module optimization"], - "optimize-chunks-basic": [0.76, "basic chunk optimization"], - "optimize-chunks": [0.77, "chunk optimization"], - "optimize-chunks-advanced": [0.78, "advanced chunk optimization"], - // optimize-tree - "optimize-chunk-modules": [0.80, "chunk modules optimization"], - "optimize-chunk-modules-advanced": [0.81, "advanced chunk modules optimization"], - "revive-modules": [0.82, "module reviving"], - "optimize-module-order": [0.83, "module order optimization"], - "optimize-module-ids": [0.84, "module id optimization"], - "revive-chunks": [0.85, "chunk reviving"], - "optimize-chunk-order": [0.86, "chunk order optimization"], - "optimize-chunk-ids": [0.87, "chunk id optimization"], - "before-hash": [0.88, "hashing"], - "before-module-assets": [0.89, "module assets processing"], - "before-chunk-assets": [0.90, "chunk assets processing"], - "additional-chunk-assets": [0.91, "additional chunk assets processing"], - "record": [0.92, "recording"] - }; - Object.keys(syncHooks).forEach(name => { - let pass = 0; - const settings = syncHooks[name]; - compilation.plugin(name, () => { - if(pass++ > 0) - handler(settings[0], settings[1], `pass ${pass}`); - else - handler(settings[0], settings[1]); - }); - }); - compilation.plugin("optimize-tree", (chunks, modules, callback) => { - handler(0.79, "module and chunk tree optimization"); - callback(); - }); - compilation.plugin("additional-assets", callback => { - handler(0.91, "additional asset processing"); - callback(); - }); - compilation.plugin("optimize-chunk-assets", (chunks, callback) => { - handler(0.92, "chunk asset optimization"); - callback(); - }); - compilation.plugin("optimize-assets", (assets, callback) => { - handler(0.94, "asset optimization"); - callback(); - }); - }); - compiler.plugin("emit", (compilation, callback) => { - handler(0.95, "emitting"); - callback(); - }); - compiler.plugin("done", () => { - handler(1, ""); - }); - } - - let lineCaretPosition = 0, - lastState, lastStateTime; - - function defaultHandler(percentage, msg) { - let state = msg; - const details = Array.prototype.slice.call(arguments, 2); - if(percentage < 1) { - percentage = Math.floor(percentage * 100); - msg = `${percentage}% ${msg}`; - if(percentage < 100) { - msg = ` ${msg}`; - } - if(percentage < 10) { - msg = ` ${msg}`; - } - details.forEach(detail => { - if(!detail) return; - if(detail.length > 40) { - detail = `...${detail.substr(detail.length - 37)}`; - } - msg += ` ${detail}`; - }); - } - if(profile) { - state = state.replace(/^\d+\/\d+\s+/, ""); - if(percentage === 0) { - lastState = null; - lastStateTime = Date.now(); - } else if(state !== lastState || percentage === 1) { - const now = Date.now(); - if(lastState) { - const stateMsg = `${now - lastStateTime}ms ${lastState}`; - goToLineStart(stateMsg); - process.stderr.write(stateMsg + "\n"); - lineCaretPosition = 0; - } - lastState = state; - lastStateTime = now; - } - } - goToLineStart(msg); - process.stderr.write(msg); - } - - function goToLineStart(nextMessage) { - let str = ""; - for(; lineCaretPosition > nextMessage.length; lineCaretPosition--) { - str += "\b \b"; - } - for(var i = 0; i < lineCaretPosition; i++) { - str += "\b"; - } - lineCaretPosition = nextMessage.length; - if(str) process.stderr.write(str); - } - } -} -module.exports = ProgressPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const createDefaultHandler = profile => { + let lineCaretPosition = 0; + let lastState; + let lastStateTime; + + const defaultHandler = (percentage, msg, ...args) => { + let state = msg; + const details = args; + if (percentage < 1) { + percentage = Math.floor(percentage * 100); + msg = `${percentage}% ${msg}`; + if (percentage < 100) { + msg = ` ${msg}`; + } + if (percentage < 10) { + msg = ` ${msg}`; + } + for (let detail of details) { + if (!detail) continue; + if (detail.length > 40) { + detail = `...${detail.substr(detail.length - 39)}`; + } + msg += ` ${detail}`; + } + } + if (profile) { + state = state.replace(/^\d+\/\d+\s+/, ""); + if (percentage === 0) { + lastState = null; + lastStateTime = Date.now(); + } else if (state !== lastState || percentage === 1) { + const now = Date.now(); + if (lastState) { + const stateMsg = `${now - lastStateTime}ms ${lastState}`; + goToLineStart(stateMsg); + process.stderr.write(stateMsg + "\n"); + lineCaretPosition = 0; + } + lastState = state; + lastStateTime = now; + } + } + goToLineStart(msg); + process.stderr.write(msg); + }; + + const goToLineStart = nextMessage => { + let str = ""; + for (; lineCaretPosition > nextMessage.length; lineCaretPosition--) { + str += "\b \b"; + } + for (var i = 0; i < lineCaretPosition; i++) { + str += "\b"; + } + lineCaretPosition = nextMessage.length; + if (str) process.stderr.write(str); + }; + + return defaultHandler; +}; + +class ProgressPlugin { + constructor(options) { + if (typeof options === "function") { + options = { + handler: options + }; + } + options = options || {}; + this.profile = options.profile; + this.handler = options.handler; + } + + apply(compiler) { + const handler = this.handler || createDefaultHandler(this.profile); + if (compiler.compilers) { + const states = new Array(compiler.compilers.length); + compiler.compilers.forEach((compiler, idx) => { + new ProgressPlugin((p, msg, ...args) => { + states[idx] = [p, msg, ...args]; + handler( + states + .map(state => (state && state[0]) || 0) + .reduce((a, b) => a + b) / states.length, + `[${idx}] ${msg}`, + ...args + ); + }).apply(compiler); + }); + } else { + let lastModulesCount = 0; + let moduleCount = 500; + let doneModules = 0; + const activeModules = []; + + const update = module => { + handler( + 0.1 + (doneModules / Math.max(lastModulesCount, moduleCount)) * 0.6, + "building modules", + `${doneModules}/${moduleCount} modules`, + `${activeModules.length} active`, + activeModules[activeModules.length - 1] + ); + }; + + const moduleDone = module => { + doneModules++; + const ident = module.identifier(); + if (ident) { + const idx = activeModules.indexOf(ident); + if (idx >= 0) activeModules.splice(idx, 1); + } + update(); + }; + compiler.hooks.compilation.tap("ProgressPlugin", compilation => { + if (compilation.compiler.isChild()) return; + lastModulesCount = moduleCount; + moduleCount = 0; + doneModules = 0; + handler(0, "compiling"); + compilation.hooks.buildModule.tap("ProgressPlugin", module => { + moduleCount++; + const ident = module.identifier(); + if (ident) { + activeModules.push(ident); + } + update(); + }); + compilation.hooks.failedModule.tap("ProgressPlugin", moduleDone); + compilation.hooks.succeedModule.tap("ProgressPlugin", moduleDone); + const hooks = { + finishModules: "finish module graph", + seal: "sealing", + optimizeDependenciesBasic: "basic dependencies optimization", + optimizeDependencies: "dependencies optimization", + optimizeDependenciesAdvanced: "advanced dependencies optimization", + afterOptimizeDependencies: "after dependencies optimization", + optimize: "optimizing", + optimizeModulesBasic: "basic module optimization", + optimizeModules: "module optimization", + optimizeModulesAdvanced: "advanced module optimization", + afterOptimizeModules: "after module optimization", + optimizeChunksBasic: "basic chunk optimization", + optimizeChunks: "chunk optimization", + optimizeChunksAdvanced: "advanced chunk optimization", + afterOptimizeChunks: "after chunk optimization", + optimizeTree: "module and chunk tree optimization", + afterOptimizeTree: "after module and chunk tree optimization", + optimizeChunkModulesBasic: "basic chunk modules optimization", + optimizeChunkModules: "chunk modules optimization", + optimizeChunkModulesAdvanced: "advanced chunk modules optimization", + afterOptimizeChunkModules: "after chunk modules optimization", + reviveModules: "module reviving", + optimizeModuleOrder: "module order optimization", + advancedOptimizeModuleOrder: "advanced module order optimization", + beforeModuleIds: "before module ids", + moduleIds: "module ids", + optimizeModuleIds: "module id optimization", + afterOptimizeModuleIds: "module id optimization", + reviveChunks: "chunk reviving", + optimizeChunkOrder: "chunk order optimization", + beforeChunkIds: "before chunk ids", + optimizeChunkIds: "chunk id optimization", + afterOptimizeChunkIds: "after chunk id optimization", + recordModules: "record modules", + recordChunks: "record chunks", + beforeHash: "hashing", + afterHash: "after hashing", + recordHash: "record hash", + beforeModuleAssets: "module assets processing", + beforeChunkAssets: "chunk assets processing", + additionalChunkAssets: "additional chunk assets processing", + record: "recording", + additionalAssets: "additional asset processing", + optimizeChunkAssets: "chunk asset optimization", + afterOptimizeChunkAssets: "after chunk asset optimization", + optimizeAssets: "asset optimization", + afterOptimizeAssets: "after asset optimization", + afterSeal: "after seal" + }; + const numberOfHooks = Object.keys(hooks).length; + Object.keys(hooks).forEach((name, idx) => { + const title = hooks[name]; + const percentage = (idx / numberOfHooks) * 0.25 + 0.7; + compilation.hooks[name].intercept({ + name: "ProgressPlugin", + context: true, + call: () => { + handler(percentage, title); + }, + tap: (context, tap) => { + if (context) { + // p is percentage from 0 to 1 + // args is any number of messages in a hierarchical matter + context.reportProgress = (p, ...args) => { + handler(percentage, title, tap.name, ...args); + }; + } + handler(percentage, title, tap.name); + } + }); + }); + }); + compiler.hooks.emit.intercept({ + name: "ProgressPlugin", + context: true, + call: () => { + handler(0.95, "emitting"); + }, + tap: (context, tap) => { + if (context) { + context.reportProgress = (p, ...args) => { + handler(0.95, "emitting", tap.name, ...args); + }; + } + handler(0.95, "emitting", tap.name); + } + }); + compiler.hooks.afterEmit.intercept({ + name: "ProgressPlugin", + context: true, + call: () => { + handler(0.98, "after emitting"); + }, + tap: (context, tap) => { + if (context) { + context.reportProgress = (p, ...args) => { + handler(0.98, "after emitting", tap.name, ...args); + }; + } + handler(0.98, "after emitting", tap.name); + } + }); + compiler.hooks.done.tap("ProgressPlugin", () => { + handler(1, ""); + }); + } + } +} +module.exports = ProgressPlugin; diff --git a/node_modules/webpack/lib/ProvidePlugin.js b/node_modules/webpack/lib/ProvidePlugin.js index fff352a4b..b09d8c864 100644 --- a/node_modules/webpack/lib/ProvidePlugin.js +++ b/node_modules/webpack/lib/ProvidePlugin.js @@ -1,55 +1,86 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ParserHelpers = require("./ParserHelpers"); -const ConstDependency = require("./dependencies/ConstDependency"); - -const NullFactory = require("./NullFactory"); - -class ProvidePlugin { - constructor(definitions) { - this.definitions = definitions; - } - - apply(compiler) { - const definitions = this.definitions; - compiler.plugin("compilation", (compilation, params) => { - compilation.dependencyFactories.set(ConstDependency, new NullFactory()); - compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template()); - params.normalModuleFactory.plugin("parser", (parser, parserOptions) => { - Object.keys(definitions).forEach(name => { - var request = [].concat(definitions[name]); - var splittedName = name.split("."); - if(splittedName.length > 0) { - splittedName.slice(1).forEach((_, i) => { - const name = splittedName.slice(0, i + 1).join("."); - parser.plugin(`can-rename ${name}`, ParserHelpers.approve); - }); - } - parser.plugin(`expression ${name}`, function(expr) { - let nameIdentifier = name; - const scopedName = name.indexOf(".") >= 0; - let expression = `require(${JSON.stringify(request[0])})`; - if(scopedName) { - nameIdentifier = `__webpack_provided_${name.replace(/\./g, "_dot_")}`; - } - if(request.length > 1) { - expression += request.slice(1).map(r => `[${JSON.stringify(r)}]`).join(""); - } - if(!ParserHelpers.addParsedVariableToModule(this, nameIdentifier, expression)) { - return false; - } - if(scopedName) { - ParserHelpers.toConstantDependency(nameIdentifier).bind(this)(expr); - } - return true; - }); - }); - }); - }); - } -} -module.exports = ProvidePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const ParserHelpers = require("./ParserHelpers"); +const ConstDependency = require("./dependencies/ConstDependency"); + +const NullFactory = require("./NullFactory"); + +class ProvidePlugin { + constructor(definitions) { + this.definitions = definitions; + } + + apply(compiler) { + const definitions = this.definitions; + compiler.hooks.compilation.tap( + "ProvidePlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set(ConstDependency, new NullFactory()); + compilation.dependencyTemplates.set( + ConstDependency, + new ConstDependency.Template() + ); + const handler = (parser, parserOptions) => { + Object.keys(definitions).forEach(name => { + var request = [].concat(definitions[name]); + var splittedName = name.split("."); + if (splittedName.length > 0) { + splittedName.slice(1).forEach((_, i) => { + const name = splittedName.slice(0, i + 1).join("."); + parser.hooks.canRename + .for(name) + .tap("ProvidePlugin", ParserHelpers.approve); + }); + } + parser.hooks.expression.for(name).tap("ProvidePlugin", expr => { + let nameIdentifier = name; + const scopedName = name.includes("."); + let expression = `require(${JSON.stringify(request[0])})`; + if (scopedName) { + nameIdentifier = `__webpack_provided_${name.replace( + /\./g, + "_dot_" + )}`; + } + if (request.length > 1) { + expression += request + .slice(1) + .map(r => `[${JSON.stringify(r)}]`) + .join(""); + } + if ( + !ParserHelpers.addParsedVariableToModule( + parser, + nameIdentifier, + expression + ) + ) { + return false; + } + if (scopedName) { + ParserHelpers.toConstantDependency(parser, nameIdentifier)( + expr + ); + } + return true; + }); + }); + }; + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("ProvidePlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("ProvidePlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/esm") + .tap("ProvidePlugin", handler); + } + ); + } +} +module.exports = ProvidePlugin; diff --git a/node_modules/webpack/lib/RawModule.js b/node_modules/webpack/lib/RawModule.js index d937cafc0..ab3fd3ab5 100644 --- a/node_modules/webpack/lib/RawModule.js +++ b/node_modules/webpack/lib/RawModule.js @@ -1,54 +1,56 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const Module = require("./Module"); -const OriginalSource = require("webpack-sources").OriginalSource; -const RawSource = require("webpack-sources").RawSource; - -module.exports = class RawModule extends Module { - - constructor(source, identifier, readableIdentifier) { - super(); - this.sourceStr = source; - this.identifierStr = identifier || this.sourceStr; - this.readableIdentifierStr = readableIdentifier || this.identifierStr; - this.cacheable = true; - this.built = false; - } - - identifier() { - return this.identifierStr; - } - - size() { - return this.sourceStr.length; - } - - readableIdentifier(requestShortener) { - return requestShortener.shorten(this.readableIdentifierStr); - } - - needRebuild() { - return false; - } - - build(options, compilations, resolver, fs, callback) { - this.builtTime = Date.now(); - callback(); - } - - source() { - if(this.useSourceMap) - return new OriginalSource(this.sourceStr, this.identifier()); - else - return new RawSource(this.sourceStr); - } - - updateHash(hash) { - hash.update(this.sourceStr); - super.updateHash(hash); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const Module = require("./Module"); +const { OriginalSource, RawSource } = require("webpack-sources"); + +module.exports = class RawModule extends Module { + constructor(source, identifier, readableIdentifier) { + super("javascript/dynamic", null); + this.sourceStr = source; + this.identifierStr = identifier || this.sourceStr; + this.readableIdentifierStr = readableIdentifier || this.identifierStr; + this.built = false; + } + + identifier() { + return this.identifierStr; + } + + size() { + return this.sourceStr.length; + } + + readableIdentifier(requestShortener) { + return requestShortener.shorten(this.readableIdentifierStr); + } + + needRebuild() { + return false; + } + + build(options, compilations, resolver, fs, callback) { + this.built = true; + this.buildMeta = {}; + this.buildInfo = { + cacheable: true + }; + callback(); + } + + source() { + if (this.useSourceMap) { + return new OriginalSource(this.sourceStr, this.identifier()); + } else { + return new RawSource(this.sourceStr); + } + } + + updateHash(hash) { + hash.update(this.sourceStr); + super.updateHash(hash); + } +}; diff --git a/node_modules/webpack/lib/RecordIdsPlugin.js b/node_modules/webpack/lib/RecordIdsPlugin.js index a4d53085b..88c6a9a3c 100644 --- a/node_modules/webpack/lib/RecordIdsPlugin.js +++ b/node_modules/webpack/lib/RecordIdsPlugin.js @@ -1,117 +1,230 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const identifierUtils = require("./util/identifier"); - -class RecordIdsPlugin { - - apply(compiler) { - compiler.plugin("compilation", compilation => { - compilation.plugin("record-modules", (modules, records) => { - if(!records.modules) records.modules = {}; - if(!records.modules.byIdentifier) records.modules.byIdentifier = {}; - if(!records.modules.usedIds) records.modules.usedIds = {}; - modules.forEach(function(module) { - if(!module.portableId) module.portableId = identifierUtils.makePathsRelative(compiler.context, module.identifier()); - const identifier = module.portableId; - records.modules.byIdentifier[identifier] = module.id; - records.modules.usedIds[module.id] = module.id; - }); - }); - compilation.plugin("revive-modules", (modules, records) => { - if(!records.modules) return; - if(records.modules.byIdentifier) { - const usedIds = {}; - modules.forEach(function(module) { - if(module.id !== null) return; - if(!module.portableId) module.portableId = identifierUtils.makePathsRelative(compiler.context, module.identifier()); - const identifier = module.portableId; - const id = records.modules.byIdentifier[identifier]; - if(id === undefined) return; - if(usedIds[id]) return; - usedIds[id] = true; - module.id = id; - }); - } - compilation.usedModuleIds = records.modules.usedIds; - }); - - function getDepBlockIdent(chunk, block) { - const ident = []; - if(block.chunks.length > 1) - ident.push(block.chunks.indexOf(chunk)); - while(block.parent) { - const p = block.parent; - const idx = p.blocks.indexOf(block); - const l = p.blocks.length - 1; - ident.push(`${idx}/${l}`); - block = block.parent; - } - if(!block.identifier) return null; - ident.push(identifierUtils.makePathsRelative(compiler.context, block.identifier())); - return ident.reverse().join(":"); - } - compilation.plugin("record-chunks", (chunks, records) => { - records.nextFreeChunkId = compilation.nextFreeChunkId; - if(!records.chunks) records.chunks = {}; - if(!records.chunks.byName) records.chunks.byName = {}; - if(!records.chunks.byBlocks) records.chunks.byBlocks = {}; - records.chunks.usedIds = {}; - chunks.forEach(chunk => { - const name = chunk.name; - const blockIdents = chunk.blocks.map(getDepBlockIdent.bind(null, chunk)).filter(Boolean); - if(name) records.chunks.byName[name] = chunk.id; - blockIdents.forEach((blockIdent) => { - records.chunks.byBlocks[blockIdent] = chunk.id; - }); - records.chunks.usedIds[chunk.id] = chunk.id; - }); - }); - compilation.plugin("revive-chunks", (chunks, records) => { - if(!records.chunks) return; - const usedIds = {}; - if(records.chunks.byName) { - chunks.forEach(function(chunk) { - if(chunk.id !== null) return; - if(!chunk.name) return; - const id = records.chunks.byName[chunk.name]; - if(id === undefined) return; - if(usedIds[id]) return; - usedIds[id] = true; - chunk.id = id; - }); - } - if(records.chunks.byBlocks) { - const argumentedChunks = chunks.filter(chunk => chunk.id === null).map(chunk => ({ - chunk, - blockIdents: chunk.blocks.map(getDepBlockIdent.bind(null, chunk)).filter(Boolean) - })).filter(arg => arg.blockIdents.length > 0); - let blockIdentsCount = {}; - argumentedChunks.forEach((arg, idx) => { - arg.blockIdents.forEach(blockIdent => { - const id = records.chunks.byBlocks[blockIdent]; - if(typeof id !== "number") return; - const accessor = `${id}:${idx}`; - blockIdentsCount[accessor] = (blockIdentsCount[accessor] || 0) + 1; - }); - }); - blockIdentsCount = Object.keys(blockIdentsCount).map(accessor => [blockIdentsCount[accessor]].concat(accessor.split(":").map(Number))).sort((a, b) => b[0] - a[0]); - blockIdentsCount.forEach(function(arg) { - const id = arg[1]; - if(usedIds[id]) return; - const idx = arg[2]; - const chunk = argumentedChunks[idx].chunk; - if(chunk.id !== null) return; - usedIds[id] = true; - chunk.id = id; - }); - } - compilation.usedChunkIds = records.chunks.usedIds; - }); - }); - } -} -module.exports = RecordIdsPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const identifierUtils = require("./util/identifier"); + +/** @typedef {import("./Compiler")} Compiler */ +/** @typedef {import("./Chunk")} Chunk */ +/** @typedef {import("./Module")} Module */ + +/** + * @typedef {Object} RecordsChunks + * @property {Record=} byName + * @property {Record=} bySource + * @property {number[]=} usedIds + */ + +/** + * @typedef {Object} RecordsModules + * @property {Record=} byIdentifier + * @property {Record=} bySource + * @property {Record=} usedIds + */ + +/** + * @typedef {Object} Records + * @property {RecordsChunks=} chunks + * @property {RecordsModules=} modules + */ + +class RecordIdsPlugin { + /** + * @param {Object} options Options object + * @param {boolean=} options.portableIds true, when ids need to be portable + */ + constructor(options) { + this.options = options || {}; + } + + /** + * @param {Compiler} compiler the Compiler + * @returns {void} + */ + apply(compiler) { + const portableIds = this.options.portableIds; + compiler.hooks.compilation.tap("RecordIdsPlugin", compilation => { + compilation.hooks.recordModules.tap( + "RecordIdsPlugin", + /** + * @param {Module[]} modules the modules array + * @param {Records} records the records object + * @returns {void} + */ + (modules, records) => { + if (!records.modules) records.modules = {}; + if (!records.modules.byIdentifier) records.modules.byIdentifier = {}; + if (!records.modules.usedIds) records.modules.usedIds = {}; + for (const module of modules) { + if (typeof module.id !== "number") continue; + const identifier = portableIds + ? identifierUtils.makePathsRelative( + compiler.context, + module.identifier(), + compilation.cache + ) + : module.identifier(); + records.modules.byIdentifier[identifier] = module.id; + records.modules.usedIds[module.id] = module.id; + } + } + ); + compilation.hooks.reviveModules.tap( + "RecordIdsPlugin", + /** + * @param {Module[]} modules the modules array + * @param {Records} records the records object + * @returns {void} + */ + (modules, records) => { + if (!records.modules) return; + if (records.modules.byIdentifier) { + /** @type {Set} */ + const usedIds = new Set(); + for (const module of modules) { + if (module.id !== null) continue; + const identifier = portableIds + ? identifierUtils.makePathsRelative( + compiler.context, + module.identifier(), + compilation.cache + ) + : module.identifier(); + const id = records.modules.byIdentifier[identifier]; + if (id === undefined) continue; + if (usedIds.has(id)) continue; + usedIds.add(id); + module.id = id; + } + } + if (Array.isArray(records.modules.usedIds)) { + compilation.usedModuleIds = new Set(records.modules.usedIds); + } + } + ); + + /** + * @param {Module} module the module + * @returns {string} the (portable) identifier + */ + const getModuleIdentifier = module => { + if (portableIds) { + return identifierUtils.makePathsRelative( + compiler.context, + module.identifier(), + compilation.cache + ); + } + return module.identifier(); + }; + + /** + * @param {Chunk} chunk the chunk + * @returns {string[]} sources of the chunk + */ + const getChunkSources = chunk => { + /** @type {string[]} */ + const sources = []; + for (const chunkGroup of chunk.groupsIterable) { + const index = chunkGroup.chunks.indexOf(chunk); + for (const origin of chunkGroup.origins) { + if (origin.module) { + if (origin.request) { + sources.push( + `${index} ${getModuleIdentifier(origin.module)} ${ + origin.request + }` + ); + } else if (typeof origin.loc === "string") { + sources.push( + `${index} ${getModuleIdentifier(origin.module)} ${origin.loc}` + ); + } else if ( + origin.loc && + typeof origin.loc === "object" && + origin.loc.start + ) { + sources.push( + `${index} ${getModuleIdentifier( + origin.module + )} ${JSON.stringify(origin.loc.start)}` + ); + } + } + } + } + return sources; + }; + + compilation.hooks.recordChunks.tap( + "RecordIdsPlugin", + /** + * @param {Chunk[]} chunks the chunks array + * @param {Records} records the records object + * @returns {void} + */ + (chunks, records) => { + if (!records.chunks) records.chunks = {}; + if (!records.chunks.byName) records.chunks.byName = {}; + if (!records.chunks.bySource) records.chunks.bySource = {}; + /** @type {Set} */ + const usedIds = new Set(); + for (const chunk of chunks) { + if (typeof chunk.id !== "number") continue; + const name = chunk.name; + if (name) records.chunks.byName[name] = chunk.id; + const sources = getChunkSources(chunk); + for (const source of sources) { + records.chunks.bySource[source] = chunk.id; + } + usedIds.add(chunk.id); + } + records.chunks.usedIds = Array.from(usedIds).sort(); + } + ); + compilation.hooks.reviveChunks.tap( + "RecordIdsPlugin", + /** + * @param {Chunk[]} chunks the chunks array + * @param {Records} records the records object + * @returns {void} + */ + (chunks, records) => { + if (!records.chunks) return; + /** @type {Set} */ + const usedIds = new Set(); + if (records.chunks.byName) { + for (const chunk of chunks) { + if (chunk.id !== null) continue; + if (!chunk.name) continue; + const id = records.chunks.byName[chunk.name]; + if (id === undefined) continue; + if (usedIds.has(id)) continue; + usedIds.add(id); + chunk.id = id; + } + } + if (records.chunks.bySource) { + for (const chunk of chunks) { + const sources = getChunkSources(chunk); + for (const source of sources) { + const id = records.chunks.bySource[source]; + if (id === undefined) continue; + if (usedIds.has(id)) continue; + usedIds.add(id); + chunk.id = id; + break; + } + } + } + if (Array.isArray(records.chunks.usedIds)) { + compilation.usedChunkIds = new Set(records.chunks.usedIds); + } + } + ); + }); + } +} +module.exports = RecordIdsPlugin; diff --git a/node_modules/webpack/lib/RequestShortener.js b/node_modules/webpack/lib/RequestShortener.js index 0dd27a7d2..7b007816a 100644 --- a/node_modules/webpack/lib/RequestShortener.js +++ b/node_modules/webpack/lib/RequestShortener.js @@ -1,63 +1,83 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const path = require("path"); -const NORMALIZE_SLASH_DIRECTION_REGEXP = /\\/g; -const PATH_CHARS_REGEXP = /[-[\]{}()*+?.,\\^$|#\s]/g; -const SEPARATOR_REGEXP = /[/\\]$/; -const FRONT_OR_BACK_BANG_REGEXP = /^!|!$/g; -const INDEX_JS_REGEXP = /\/index.js(!|\?|\(query\))/g; - -const normalizeBackSlashDirection = (request) => { - return request.replace(NORMALIZE_SLASH_DIRECTION_REGEXP, "/"); -}; - -const createRegExpForPath = (path) => { - const regexpTypePartial = path.replace(PATH_CHARS_REGEXP, "\\$&"); - return new RegExp(`(^|!)${regexpTypePartial}`, "g"); -}; - -class RequestShortener { - constructor(directory) { - directory = normalizeBackSlashDirection(directory); - if(SEPARATOR_REGEXP.test(directory)) directory = directory.substr(0, directory.length - 1); - - if(directory) { - this.currentDirectoryRegExp = createRegExpForPath(directory); - } - - const dirname = path.dirname(directory); - const endsWithSeperator = SEPARATOR_REGEXP.test(dirname); - const parentDirectory = endsWithSeperator ? dirname.substr(0, dirname.length - 1) : dirname; - if(parentDirectory && parentDirectory !== directory) { - this.parentDirectoryRegExp = createRegExpForPath(parentDirectory); - } - - if(__dirname.length >= 2) { - const buildins = normalizeBackSlashDirection(path.join(__dirname, "..")); - const buildinsAsModule = this.currentDirectoryRegExp && this.currentDirectoryRegExp.test(buildins); - this.buildinsAsModule = buildinsAsModule; - this.buildinsRegExp = createRegExpForPath(buildins); - } - } - - shorten(request) { - if(!request) return request; - request = normalizeBackSlashDirection(request); - if(this.buildinsAsModule && this.buildinsRegExp) - request = request.replace(this.buildinsRegExp, "!(webpack)"); - if(this.currentDirectoryRegExp) - request = request.replace(this.currentDirectoryRegExp, "!."); - if(this.parentDirectoryRegExp) - request = request.replace(this.parentDirectoryRegExp, "!.."); - if(!this.buildinsAsModule && this.buildinsRegExp) - request = request.replace(this.buildinsRegExp, "!(webpack)"); - request = request.replace(INDEX_JS_REGEXP, "$1"); - return request.replace(FRONT_OR_BACK_BANG_REGEXP, ""); - } -} - -module.exports = RequestShortener; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const path = require("path"); +const NORMALIZE_SLASH_DIRECTION_REGEXP = /\\/g; +const PATH_CHARS_REGEXP = /[-[\]{}()*+?.,\\^$|#\s]/g; +const SEPARATOR_REGEXP = /[/\\]$/; +const FRONT_OR_BACK_BANG_REGEXP = /^!|!$/g; +const INDEX_JS_REGEXP = /\/index.js(!|\?|\(query\))/g; +const MATCH_RESOURCE_REGEXP = /!=!/; + +const normalizeBackSlashDirection = request => { + return request.replace(NORMALIZE_SLASH_DIRECTION_REGEXP, "/"); +}; + +const createRegExpForPath = path => { + const regexpTypePartial = path.replace(PATH_CHARS_REGEXP, "\\$&"); + return new RegExp(`(^|!)${regexpTypePartial}`, "g"); +}; + +class RequestShortener { + constructor(directory) { + directory = normalizeBackSlashDirection(directory); + if (SEPARATOR_REGEXP.test(directory)) { + directory = directory.substr(0, directory.length - 1); + } + + if (directory) { + this.currentDirectoryRegExp = createRegExpForPath(directory); + } + + const dirname = path.dirname(directory); + const endsWithSeparator = SEPARATOR_REGEXP.test(dirname); + const parentDirectory = endsWithSeparator + ? dirname.substr(0, dirname.length - 1) + : dirname; + if (parentDirectory && parentDirectory !== directory) { + this.parentDirectoryRegExp = createRegExpForPath(parentDirectory); + } + + if (__dirname.length >= 2) { + const buildins = normalizeBackSlashDirection(path.join(__dirname, "..")); + const buildinsAsModule = + this.currentDirectoryRegExp && + this.currentDirectoryRegExp.test(buildins); + this.buildinsAsModule = buildinsAsModule; + this.buildinsRegExp = createRegExpForPath(buildins); + } + + this.cache = new Map(); + } + + shorten(request) { + if (!request) return request; + const cacheEntry = this.cache.get(request); + if (cacheEntry !== undefined) { + return cacheEntry; + } + let result = normalizeBackSlashDirection(request); + if (this.buildinsAsModule && this.buildinsRegExp) { + result = result.replace(this.buildinsRegExp, "!(webpack)"); + } + if (this.currentDirectoryRegExp) { + result = result.replace(this.currentDirectoryRegExp, "!."); + } + if (this.parentDirectoryRegExp) { + result = result.replace(this.parentDirectoryRegExp, "!.."); + } + if (!this.buildinsAsModule && this.buildinsRegExp) { + result = result.replace(this.buildinsRegExp, "!(webpack)"); + } + result = result.replace(INDEX_JS_REGEXP, "$1"); + result = result.replace(FRONT_OR_BACK_BANG_REGEXP, ""); + result = result.replace(MATCH_RESOURCE_REGEXP, " = "); + this.cache.set(request, result); + return result; + } +} + +module.exports = RequestShortener; diff --git a/node_modules/webpack/lib/RequireJsStuffPlugin.js b/node_modules/webpack/lib/RequireJsStuffPlugin.js index 92bc3fc91..632deefc2 100644 --- a/node_modules/webpack/lib/RequireJsStuffPlugin.js +++ b/node_modules/webpack/lib/RequireJsStuffPlugin.js @@ -1,31 +1,66 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ParserHelpers = require("./ParserHelpers"); -const ConstDependency = require("./dependencies/ConstDependency"); -const NullFactory = require("./NullFactory"); - -module.exports = class RequireJsStuffPlugin { - - apply(compiler) { - compiler.plugin("compilation", function(compilation, params) { - compilation.dependencyFactories.set(ConstDependency, new NullFactory()); - compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template()); - params.normalModuleFactory.plugin("parser", function(parser, parserOptions) { - - if(typeof parserOptions.requireJs !== "undefined" && !parserOptions.requireJs) - return; - - parser.plugin("call require.config", ParserHelpers.toConstantDependency("undefined")); - parser.plugin("call requirejs.config", ParserHelpers.toConstantDependency("undefined")); - - parser.plugin("expression require.version", ParserHelpers.toConstantDependency(JSON.stringify("0.0.0"))); - parser.plugin("expression requirejs.onError", ParserHelpers.toConstantDependency("__webpack_require__.oe")); - }); - }); - } - -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const ParserHelpers = require("./ParserHelpers"); +const ConstDependency = require("./dependencies/ConstDependency"); +const NullFactory = require("./NullFactory"); + +module.exports = class RequireJsStuffPlugin { + apply(compiler) { + compiler.hooks.compilation.tap( + "RequireJsStuffPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set(ConstDependency, new NullFactory()); + compilation.dependencyTemplates.set( + ConstDependency, + new ConstDependency.Template() + ); + const handler = (parser, parserOptions) => { + if (parserOptions.requireJs !== undefined && !parserOptions.requireJs) + return; + + parser.hooks.call + .for("require.config") + .tap( + "RequireJsStuffPlugin", + ParserHelpers.toConstantDependency(parser, "undefined") + ); + parser.hooks.call + .for("requirejs.config") + .tap( + "RequireJsStuffPlugin", + ParserHelpers.toConstantDependency(parser, "undefined") + ); + + parser.hooks.expression + .for("require.version") + .tap( + "RequireJsStuffPlugin", + ParserHelpers.toConstantDependency( + parser, + JSON.stringify("0.0.0") + ) + ); + parser.hooks.expression + .for("requirejs.onError") + .tap( + "RequireJsStuffPlugin", + ParserHelpers.toConstantDependencyWithWebpackRequire( + parser, + "__webpack_require__.oe" + ) + ); + }; + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("RequireJsStuffPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("RequireJsStuffPlugin", handler); + } + ); + } +}; diff --git a/node_modules/webpack/lib/RuleSet.js b/node_modules/webpack/lib/RuleSet.js index cb679b5f6..7ed8eba6f 100644 --- a/node_modules/webpack/lib/RuleSet.js +++ b/node_modules/webpack/lib/RuleSet.js @@ -1,444 +1,567 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -/* -: -: [] -: { - resource: { - test: , - include: , - exclude: , - }, - resource: , -> resource.test - test: , -> resource.test - include: , -> resource.include - exclude: , -> resource.exclude - resourceQuery: , - compiler: , - issuer: , - use: "loader", -> use[0].loader - loader: <>, -> use[0].loader - loaders: <>, -> use - options: {}, -> use[0].options, - query: {}, -> options - parser: {}, - use: [ - "loader" -> use[x].loader - ], - use: [ - { - loader: "loader", - options: {} - } - ], - rules: [ - - ], - oneOf: [ - - ] -} - -: /regExp/ -: function(arg) {} -: "starting" -: [] // or -: { and: [] } -: { or: [] } -: { not: [] } -: { test: , include: , exclude: } - - -normalized: - -{ - resource: function(), - resourceQuery: function(), - compiler: function(), - issuer: function(), - use: [ - { - loader: string, - options: string, - : - } - ], - rules: [], - oneOf: [], - : , -} - -*/ - -"use strict"; - -module.exports = class RuleSet { - constructor(rules) { - this.references = Object.create(null); - this.rules = RuleSet.normalizeRules(rules, this.references, "ref-"); - } - - static normalizeRules(rules, refs, ident) { - if(Array.isArray(rules)) { - return rules.map((rule, idx) => { - return RuleSet.normalizeRule(rule, refs, `${ident}-${idx}`); - }); - } else if(rules) { - return [RuleSet.normalizeRule(rules, refs, ident)]; - } else { - return []; - } - } - - static normalizeRule(rule, refs, ident) { - if(typeof rule === "string") - return { - use: [{ - loader: rule - }] - }; - if(!rule) - throw new Error("Unexcepted null when object was expected as rule"); - if(typeof rule !== "object") - throw new Error("Unexcepted " + typeof rule + " when object was expected as rule (" + rule + ")"); - - const newRule = {}; - let useSource; - let resourceSource; - let condition; - - if(rule.test || rule.include || rule.exclude) { - checkResourceSource("test + include + exclude"); - condition = { - test: rule.test, - include: rule.include, - exclude: rule.exclude - }; - try { - newRule.resource = RuleSet.normalizeCondition(condition); - } catch(error) { - throw new Error(RuleSet.buildErrorMessage(condition, error)); - } - } - - if(rule.resource) { - checkResourceSource("resource"); - try { - newRule.resource = RuleSet.normalizeCondition(rule.resource); - } catch(error) { - throw new Error(RuleSet.buildErrorMessage(rule.resource, error)); - } - } - - if(rule.resourceQuery) { - try { - newRule.resourceQuery = RuleSet.normalizeCondition(rule.resourceQuery); - } catch(error) { - throw new Error(RuleSet.buildErrorMessage(rule.resourceQuery, error)); - } - } - - if(rule.compiler) { - try { - newRule.compiler = RuleSet.normalizeCondition(rule.compiler); - } catch(error) { - throw new Error(RuleSet.buildErrorMessage(rule.compiler, error)); - } - } - - if(rule.issuer) { - try { - newRule.issuer = RuleSet.normalizeCondition(rule.issuer); - } catch(error) { - throw new Error(RuleSet.buildErrorMessage(rule.issuer, error)); - } - } - - if(rule.loader && rule.loaders) - throw new Error(RuleSet.buildErrorMessage(rule, new Error("Provided loader and loaders for rule (use only one of them)"))); - - const loader = rule.loaders || rule.loader; - if(typeof loader === "string" && !rule.options && !rule.query) { - checkUseSource("loader"); - newRule.use = RuleSet.normalizeUse(loader.split("!"), ident); - } else if(typeof loader === "string" && (rule.options || rule.query)) { - checkUseSource("loader + options/query"); - newRule.use = RuleSet.normalizeUse({ - loader: loader, - options: rule.options, - query: rule.query - }, ident); - } else if(loader && (rule.options || rule.query)) { - throw new Error(RuleSet.buildErrorMessage(rule, new Error("options/query cannot be used with loaders (use options for each array item)"))); - } else if(loader) { - checkUseSource("loaders"); - newRule.use = RuleSet.normalizeUse(loader, ident); - } else if(rule.options || rule.query) { - throw new Error(RuleSet.buildErrorMessage(rule, new Error("options/query provided without loader (use loader + options)"))); - } - - if(rule.use) { - checkUseSource("use"); - newRule.use = RuleSet.normalizeUse(rule.use, ident); - } - - if(rule.rules) - newRule.rules = RuleSet.normalizeRules(rule.rules, refs, `${ident}-rules`); - - if(rule.oneOf) - newRule.oneOf = RuleSet.normalizeRules(rule.oneOf, refs, `${ident}-oneOf`); - - const keys = Object.keys(rule).filter((key) => { - return ["resource", "resourceQuery", "compiler", "test", "include", "exclude", "issuer", "loader", "options", "query", "loaders", "use", "rules", "oneOf"].indexOf(key) < 0; - }); - keys.forEach((key) => { - newRule[key] = rule[key]; - }); - - function checkUseSource(newSource) { - if(useSource && useSource !== newSource) - throw new Error(RuleSet.buildErrorMessage(rule, new Error("Rule can only have one result source (provided " + newSource + " and " + useSource + ")"))); - useSource = newSource; - } - - function checkResourceSource(newSource) { - if(resourceSource && resourceSource !== newSource) - throw new Error(RuleSet.buildErrorMessage(rule, new Error("Rule can only have one resource source (provided " + newSource + " and " + resourceSource + ")"))); - resourceSource = newSource; - } - - if(Array.isArray(newRule.use)) { - newRule.use.forEach((item) => { - if(item.ident) { - refs[item.ident] = item.options; - } - }); - } - - return newRule; - } - - static buildErrorMessage(condition, error) { - const conditionAsText = JSON.stringify(condition, (key, value) => { - return value === undefined ? "undefined" : value; - }, 2); - return error.message + " in " + conditionAsText; - } - - static normalizeUse(use, ident) { - if(Array.isArray(use)) { - return use - .map((item, idx) => RuleSet.normalizeUse(item, `${ident}-${idx}`)) - .reduce((arr, items) => arr.concat(items), []); - } - return [RuleSet.normalizeUseItem(use, ident)]; - } - - static normalizeUseItemFunction(use, data) { - const result = use(data); - if(typeof result === "string") { - return RuleSet.normalizeUseItem(result); - } - return result; - } - - static normalizeUseItemString(useItemString) { - const idx = useItemString.indexOf("?"); - if(idx >= 0) { - return { - loader: useItemString.substr(0, idx), - options: useItemString.substr(idx + 1) - }; - } - return { - loader: useItemString - }; - } - - static normalizeUseItem(item, ident) { - if(typeof item === "function") - return item; - - if(typeof item === "string") { - return RuleSet.normalizeUseItemString(item); - } - - const newItem = {}; - - if(item.options && item.query) - throw new Error("Provided options and query in use"); - - if(!item.loader) - throw new Error("No loader specified"); - - newItem.options = item.options || item.query; - - if(typeof newItem.options === "object" && newItem.options) { - if(newItem.options.ident) - newItem.ident = newItem.options.ident; - else - newItem.ident = ident; - } - - const keys = Object.keys(item).filter(function(key) { - return ["options", "query"].indexOf(key) < 0; - }); - - keys.forEach(function(key) { - newItem[key] = item[key]; - }); - - return newItem; - } - - static normalizeCondition(condition) { - if(!condition) - throw new Error("Expected condition but got falsy value"); - if(typeof condition === "string") { - return str => str.indexOf(condition) === 0; - } - if(typeof condition === "function") { - return condition; - } - if(condition instanceof RegExp) { - return condition.test.bind(condition); - } - if(Array.isArray(condition)) { - const items = condition.map(c => RuleSet.normalizeCondition(c)); - return orMatcher(items); - } - if(typeof condition !== "object") - throw Error("Unexcepted " + typeof condition + " when condition was expected (" + condition + ")"); - - const matchers = []; - Object.keys(condition).forEach(key => { - const value = condition[key]; - switch(key) { - case "or": - case "include": - case "test": - if(value) - matchers.push(RuleSet.normalizeCondition(value)); - break; - case "and": - if(value) { - const items = value.map(c => RuleSet.normalizeCondition(c)); - matchers.push(andMatcher(items)); - } - break; - case "not": - case "exclude": - if(value) { - const matcher = RuleSet.normalizeCondition(value); - matchers.push(notMatcher(matcher)); - } - break; - default: - throw new Error("Unexcepted property " + key + " in condition"); - } - }); - if(matchers.length === 0) - throw new Error("Excepted condition but got " + condition); - if(matchers.length === 1) - return matchers[0]; - return andMatcher(matchers); - } - - exec(data) { - const result = []; - this._run(data, { - rules: this.rules - }, result); - return result; - } - - _run(data, rule, result) { - // test conditions - if(rule.resource && !data.resource) - return false; - if(rule.resourceQuery && !data.resourceQuery) - return false; - if(rule.compiler && !data.compiler) - return false; - if(rule.issuer && !data.issuer) - return false; - if(rule.resource && !rule.resource(data.resource)) - return false; - if(data.issuer && rule.issuer && !rule.issuer(data.issuer)) - return false; - if(data.resourceQuery && rule.resourceQuery && !rule.resourceQuery(data.resourceQuery)) - return false; - if(data.compiler && rule.compiler && !rule.compiler(data.compiler)) - return false; - - // apply - const keys = Object.keys(rule).filter((key) => { - return ["resource", "resourceQuery", "compiler", "issuer", "rules", "oneOf", "use", "enforce"].indexOf(key) < 0; - }); - keys.forEach((key) => { - result.push({ - type: key, - value: rule[key] - }); - }); - - if(rule.use) { - rule.use.forEach((use) => { - result.push({ - type: "use", - value: typeof use === "function" ? RuleSet.normalizeUseItemFunction(use, data) : use, - enforce: rule.enforce - }); - }); - } - - if(rule.rules) { - for(let i = 0; i < rule.rules.length; i++) { - this._run(data, rule.rules[i], result); - } - } - - if(rule.oneOf) { - for(let i = 0; i < rule.oneOf.length; i++) { - if(this._run(data, rule.oneOf[i], result)) - break; - } - } - - return true; - } - - findOptionsByIdent(ident) { - const options = this.references[ident]; - if(!options) throw new Error("Can't find options with ident '" + ident + "'"); - return options; - } -}; - -function notMatcher(matcher) { - return function(str) { - return !matcher(str); - }; -} - -function orMatcher(items) { - return function(str) { - for(let i = 0; i < items.length; i++) { - if(items[i](str)) - return true; - } - return false; - }; -} - -function andMatcher(items) { - return function(str) { - for(let i = 0; i < items.length; i++) { - if(!items[i](str)) - return false; - } - return true; - }; -} +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +/* +: +: [] +: { + resource: { + test: , + include: , + exclude: , + }, + resource: , -> resource.test + test: , -> resource.test + include: , -> resource.include + exclude: , -> resource.exclude + resourceQuery: , + compiler: , + issuer: , + use: "loader", -> use[0].loader + loader: <>, -> use[0].loader + loaders: <>, -> use + options: {}, -> use[0].options, + query: {}, -> options + parser: {}, + use: [ + "loader" -> use[x].loader + ], + use: [ + { + loader: "loader", + options: {} + } + ], + rules: [ + + ], + oneOf: [ + + ] +} + +: /regExp/ +: function(arg) {} +: "starting" +: [] // or +: { and: [] } +: { or: [] } +: { not: [] } +: { test: , include: , exclude: } + + +normalized: + +{ + resource: function(), + resourceQuery: function(), + compiler: function(), + issuer: function(), + use: [ + { + loader: string, + options: string, + : + } + ], + rules: [], + oneOf: [], + : , +} + +*/ + +"use strict"; + +const notMatcher = matcher => { + return str => { + return !matcher(str); + }; +}; + +const orMatcher = items => { + return str => { + for (let i = 0; i < items.length; i++) { + if (items[i](str)) return true; + } + return false; + }; +}; + +const andMatcher = items => { + return str => { + for (let i = 0; i < items.length; i++) { + if (!items[i](str)) return false; + } + return true; + }; +}; + +module.exports = class RuleSet { + constructor(rules) { + this.references = Object.create(null); + this.rules = RuleSet.normalizeRules(rules, this.references, "ref-"); + } + + static normalizeRules(rules, refs, ident) { + if (Array.isArray(rules)) { + return rules.map((rule, idx) => { + return RuleSet.normalizeRule(rule, refs, `${ident}-${idx}`); + }); + } else if (rules) { + return [RuleSet.normalizeRule(rules, refs, ident)]; + } else { + return []; + } + } + + static normalizeRule(rule, refs, ident) { + if (typeof rule === "string") { + return { + use: [ + { + loader: rule + } + ] + }; + } + if (!rule) { + throw new Error("Unexcepted null when object was expected as rule"); + } + if (typeof rule !== "object") { + throw new Error( + "Unexcepted " + + typeof rule + + " when object was expected as rule (" + + rule + + ")" + ); + } + + const newRule = {}; + let useSource; + let resourceSource; + let condition; + + const checkUseSource = newSource => { + if (useSource && useSource !== newSource) { + throw new Error( + RuleSet.buildErrorMessage( + rule, + new Error( + "Rule can only have one result source (provided " + + newSource + + " and " + + useSource + + ")" + ) + ) + ); + } + useSource = newSource; + }; + + const checkResourceSource = newSource => { + if (resourceSource && resourceSource !== newSource) { + throw new Error( + RuleSet.buildErrorMessage( + rule, + new Error( + "Rule can only have one resource source (provided " + + newSource + + " and " + + resourceSource + + ")" + ) + ) + ); + } + resourceSource = newSource; + }; + + if (rule.test || rule.include || rule.exclude) { + checkResourceSource("test + include + exclude"); + condition = { + test: rule.test, + include: rule.include, + exclude: rule.exclude + }; + try { + newRule.resource = RuleSet.normalizeCondition(condition); + } catch (error) { + throw new Error(RuleSet.buildErrorMessage(condition, error)); + } + } + + if (rule.resource) { + checkResourceSource("resource"); + try { + newRule.resource = RuleSet.normalizeCondition(rule.resource); + } catch (error) { + throw new Error(RuleSet.buildErrorMessage(rule.resource, error)); + } + } + + if (rule.realResource) { + try { + newRule.realResource = RuleSet.normalizeCondition(rule.realResource); + } catch (error) { + throw new Error(RuleSet.buildErrorMessage(rule.realResource, error)); + } + } + + if (rule.resourceQuery) { + try { + newRule.resourceQuery = RuleSet.normalizeCondition(rule.resourceQuery); + } catch (error) { + throw new Error(RuleSet.buildErrorMessage(rule.resourceQuery, error)); + } + } + + if (rule.compiler) { + try { + newRule.compiler = RuleSet.normalizeCondition(rule.compiler); + } catch (error) { + throw new Error(RuleSet.buildErrorMessage(rule.compiler, error)); + } + } + + if (rule.issuer) { + try { + newRule.issuer = RuleSet.normalizeCondition(rule.issuer); + } catch (error) { + throw new Error(RuleSet.buildErrorMessage(rule.issuer, error)); + } + } + + if (rule.loader && rule.loaders) { + throw new Error( + RuleSet.buildErrorMessage( + rule, + new Error( + "Provided loader and loaders for rule (use only one of them)" + ) + ) + ); + } + + const loader = rule.loaders || rule.loader; + if (typeof loader === "string" && !rule.options && !rule.query) { + checkUseSource("loader"); + newRule.use = RuleSet.normalizeUse(loader.split("!"), ident); + } else if (typeof loader === "string" && (rule.options || rule.query)) { + checkUseSource("loader + options/query"); + newRule.use = RuleSet.normalizeUse( + { + loader: loader, + options: rule.options, + query: rule.query + }, + ident + ); + } else if (loader && (rule.options || rule.query)) { + throw new Error( + RuleSet.buildErrorMessage( + rule, + new Error( + "options/query cannot be used with loaders (use options for each array item)" + ) + ) + ); + } else if (loader) { + checkUseSource("loaders"); + newRule.use = RuleSet.normalizeUse(loader, ident); + } else if (rule.options || rule.query) { + throw new Error( + RuleSet.buildErrorMessage( + rule, + new Error( + "options/query provided without loader (use loader + options)" + ) + ) + ); + } + + if (rule.use) { + checkUseSource("use"); + newRule.use = RuleSet.normalizeUse(rule.use, ident); + } + + if (rule.rules) { + newRule.rules = RuleSet.normalizeRules( + rule.rules, + refs, + `${ident}-rules` + ); + } + + if (rule.oneOf) { + newRule.oneOf = RuleSet.normalizeRules( + rule.oneOf, + refs, + `${ident}-oneOf` + ); + } + + const keys = Object.keys(rule).filter(key => { + return ![ + "resource", + "resourceQuery", + "compiler", + "test", + "include", + "exclude", + "issuer", + "loader", + "options", + "query", + "loaders", + "use", + "rules", + "oneOf" + ].includes(key); + }); + for (const key of keys) { + newRule[key] = rule[key]; + } + + if (Array.isArray(newRule.use)) { + for (const item of newRule.use) { + if (item.ident) { + refs[item.ident] = item.options; + } + } + } + + return newRule; + } + + static buildErrorMessage(condition, error) { + const conditionAsText = JSON.stringify( + condition, + (key, value) => { + return value === undefined ? "undefined" : value; + }, + 2 + ); + return error.message + " in " + conditionAsText; + } + + static normalizeUse(use, ident) { + if (typeof use === "function") { + return data => RuleSet.normalizeUse(use(data), ident); + } + if (Array.isArray(use)) { + return use + .map((item, idx) => RuleSet.normalizeUse(item, `${ident}-${idx}`)) + .reduce((arr, items) => arr.concat(items), []); + } + return [RuleSet.normalizeUseItem(use, ident)]; + } + + static normalizeUseItemString(useItemString) { + const idx = useItemString.indexOf("?"); + if (idx >= 0) { + return { + loader: useItemString.substr(0, idx), + options: useItemString.substr(idx + 1) + }; + } + return { + loader: useItemString, + options: undefined + }; + } + + static normalizeUseItem(item, ident) { + if (typeof item === "string") { + return RuleSet.normalizeUseItemString(item); + } + + const newItem = {}; + + if (item.options && item.query) { + throw new Error("Provided options and query in use"); + } + + if (!item.loader) { + throw new Error("No loader specified"); + } + + newItem.options = item.options || item.query; + + if (typeof newItem.options === "object" && newItem.options) { + if (newItem.options.ident) { + newItem.ident = newItem.options.ident; + } else { + newItem.ident = ident; + } + } + + const keys = Object.keys(item).filter(function(key) { + return !["options", "query"].includes(key); + }); + + for (const key of keys) { + newItem[key] = item[key]; + } + + return newItem; + } + + static normalizeCondition(condition) { + if (!condition) throw new Error("Expected condition but got falsy value"); + if (typeof condition === "string") { + return str => str.indexOf(condition) === 0; + } + if (typeof condition === "function") { + return condition; + } + if (condition instanceof RegExp) { + return condition.test.bind(condition); + } + if (Array.isArray(condition)) { + const items = condition.map(c => RuleSet.normalizeCondition(c)); + return orMatcher(items); + } + if (typeof condition !== "object") { + throw Error( + "Unexcepted " + + typeof condition + + " when condition was expected (" + + condition + + ")" + ); + } + + const matchers = []; + Object.keys(condition).forEach(key => { + const value = condition[key]; + switch (key) { + case "or": + case "include": + case "test": + if (value) matchers.push(RuleSet.normalizeCondition(value)); + break; + case "and": + if (value) { + const items = value.map(c => RuleSet.normalizeCondition(c)); + matchers.push(andMatcher(items)); + } + break; + case "not": + case "exclude": + if (value) { + const matcher = RuleSet.normalizeCondition(value); + matchers.push(notMatcher(matcher)); + } + break; + default: + throw new Error("Unexcepted property " + key + " in condition"); + } + }); + if (matchers.length === 0) { + throw new Error("Excepted condition but got " + condition); + } + if (matchers.length === 1) { + return matchers[0]; + } + return andMatcher(matchers); + } + + exec(data) { + const result = []; + this._run( + data, + { + rules: this.rules + }, + result + ); + return result; + } + + _run(data, rule, result) { + // test conditions + if (rule.resource && !data.resource) return false; + if (rule.realResource && !data.realResource) return false; + if (rule.resourceQuery && !data.resourceQuery) return false; + if (rule.compiler && !data.compiler) return false; + if (rule.issuer && !data.issuer) return false; + if (rule.resource && !rule.resource(data.resource)) return false; + if (rule.realResource && !rule.realResource(data.realResource)) + return false; + if (data.issuer && rule.issuer && !rule.issuer(data.issuer)) return false; + if ( + data.resourceQuery && + rule.resourceQuery && + !rule.resourceQuery(data.resourceQuery) + ) { + return false; + } + if (data.compiler && rule.compiler && !rule.compiler(data.compiler)) { + return false; + } + + // apply + const keys = Object.keys(rule).filter(key => { + return ![ + "resource", + "realResource", + "resourceQuery", + "compiler", + "issuer", + "rules", + "oneOf", + "use", + "enforce" + ].includes(key); + }); + for (const key of keys) { + result.push({ + type: key, + value: rule[key] + }); + } + + if (rule.use) { + const process = use => { + if (typeof use === "function") { + process(use(data)); + } else if (Array.isArray(use)) { + use.forEach(process); + } else { + result.push({ + type: "use", + value: use, + enforce: rule.enforce + }); + } + }; + process(rule.use); + } + + if (rule.rules) { + for (let i = 0; i < rule.rules.length; i++) { + this._run(data, rule.rules[i], result); + } + } + + if (rule.oneOf) { + for (let i = 0; i < rule.oneOf.length; i++) { + if (this._run(data, rule.oneOf[i], result)) break; + } + } + + return true; + } + + findOptionsByIdent(ident) { + const options = this.references[ident]; + if (!options) { + throw new Error("Can't find options with ident '" + ident + "'"); + } + return options; + } +}; diff --git a/node_modules/webpack/lib/SetVarMainTemplatePlugin.js b/node_modules/webpack/lib/SetVarMainTemplatePlugin.js index 67b3e744e..63db2821a 100644 --- a/node_modules/webpack/lib/SetVarMainTemplatePlugin.js +++ b/node_modules/webpack/lib/SetVarMainTemplatePlugin.js @@ -1,41 +1,69 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ConcatSource = require("webpack-sources").ConcatSource; - -class SetVarMainTemplatePlugin { - constructor(varExpression, copyObject) { - this.varExpression = varExpression; - this.copyObject = copyObject; - } - - apply(compilation) { - const mainTemplate = compilation.mainTemplate; - compilation.templatesPlugin("render-with-entry", (source, chunk, hash) => { - const varExpression = mainTemplate.applyPluginsWaterfall("asset-path", this.varExpression, { - hash, - chunk - }); - if(this.copyObject) { - return new ConcatSource(`(function(e, a) { for(var i in a) e[i] = a[i]; }(${varExpression}, `, source, "))"); - } else { - const prefix = `${varExpression} =\n`; - return new ConcatSource(prefix, source); - } - }); - mainTemplate.plugin("global-hash-paths", (paths) => { - if(this.varExpression) paths.push(this.varExpression); - return paths; - }); - mainTemplate.plugin("hash", hash => { - hash.update("set var"); - hash.update(`${this.varExpression}`); - hash.update(`${this.copyObject}`); - }); - } -} - -module.exports = SetVarMainTemplatePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const { ConcatSource } = require("webpack-sources"); + +/** @typedef {import("./Compilation")} Compilation */ + +class SetVarMainTemplatePlugin { + /** + * @param {string} varExpression the accessor where the library is exported + * @param {boolean} copyObject specify copying the exports + */ + constructor(varExpression, copyObject) { + /** @type {string} */ + this.varExpression = varExpression; + /** @type {boolean} */ + this.copyObject = copyObject; + } + + /** + * @param {Compilation} compilation the compilation instance + * @returns {void} + */ + apply(compilation) { + const { mainTemplate, chunkTemplate } = compilation; + + const onRenderWithEntry = (source, chunk, hash) => { + const varExpression = mainTemplate.getAssetPath(this.varExpression, { + hash, + chunk + }); + if (this.copyObject) { + return new ConcatSource( + `(function(e, a) { for(var i in a) e[i] = a[i]; }(${varExpression}, `, + source, + "))" + ); + } else { + const prefix = `${varExpression} =\n`; + return new ConcatSource(prefix, source); + } + }; + + for (const template of [mainTemplate, chunkTemplate]) { + template.hooks.renderWithEntry.tap( + "SetVarMainTemplatePlugin", + onRenderWithEntry + ); + } + + mainTemplate.hooks.globalHashPaths.tap( + "SetVarMainTemplatePlugin", + paths => { + if (this.varExpression) paths.push(this.varExpression); + return paths; + } + ); + mainTemplate.hooks.hash.tap("SetVarMainTemplatePlugin", hash => { + hash.update("set var"); + hash.update(`${this.varExpression}`); + hash.update(`${this.copyObject}`); + }); + } +} + +module.exports = SetVarMainTemplatePlugin; diff --git a/node_modules/webpack/lib/SingleEntryPlugin.js b/node_modules/webpack/lib/SingleEntryPlugin.js index aa5da3a0a..4a1703b1f 100644 --- a/node_modules/webpack/lib/SingleEntryPlugin.js +++ b/node_modules/webpack/lib/SingleEntryPlugin.js @@ -1,35 +1,63 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const SingleEntryDependency = require("./dependencies/SingleEntryDependency"); - -class SingleEntryPlugin { - constructor(context, entry, name) { - this.context = context; - this.entry = entry; - this.name = name; - } - - apply(compiler) { - compiler.plugin("compilation", (compilation, params) => { - const normalModuleFactory = params.normalModuleFactory; - - compilation.dependencyFactories.set(SingleEntryDependency, normalModuleFactory); - }); - - compiler.plugin("make", (compilation, callback) => { - const dep = SingleEntryPlugin.createDependency(this.entry, this.name); - compilation.addEntry(this.context, dep, this.name, callback); - }); - } - - static createDependency(entry, name) { - const dep = new SingleEntryDependency(entry); - dep.loc = name; - return dep; - } -} - -module.exports = SingleEntryPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const SingleEntryDependency = require("./dependencies/SingleEntryDependency"); + +/** @typedef {import("./Compiler")} Compiler */ + +class SingleEntryPlugin { + /** + * An entry plugin which will handle + * creation of the SingleEntryDependency + * + * @param {string} context context path + * @param {string} entry entry path + * @param {string} name entry key name + */ + constructor(context, entry, name) { + this.context = context; + this.entry = entry; + this.name = name; + } + + /** + * @param {Compiler} compiler the compiler instance + * @returns {void} + */ + apply(compiler) { + compiler.hooks.compilation.tap( + "SingleEntryPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set( + SingleEntryDependency, + normalModuleFactory + ); + } + ); + + compiler.hooks.make.tapAsync( + "SingleEntryPlugin", + (compilation, callback) => { + const { entry, name, context } = this; + + const dep = SingleEntryPlugin.createDependency(entry, name); + compilation.addEntry(context, dep, name, callback); + } + ); + } + + /** + * @param {string} entry entry request + * @param {string} name entry name + * @returns {SingleEntryDependency} the dependency + */ + static createDependency(entry, name) { + const dep = new SingleEntryDependency(entry); + dep.loc = { name }; + return dep; + } +} + +module.exports = SingleEntryPlugin; diff --git a/node_modules/webpack/lib/SizeFormatHelpers.js b/node_modules/webpack/lib/SizeFormatHelpers.js index 3b7732199..c4677f60b 100644 --- a/node_modules/webpack/lib/SizeFormatHelpers.js +++ b/node_modules/webpack/lib/SizeFormatHelpers.js @@ -1,18 +1,24 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Sean Larkin @thelarkinn -*/ -"use strict"; - -const SizeFormatHelpers = exports; - -SizeFormatHelpers.formatSize = size => { - if(size <= 0) { - return "0 bytes"; - } - - const abbreviations = ["bytes", "kB", "MB", "GB"]; - const index = Math.floor(Math.log(size) / Math.log(1000)); - - return `${+(size / Math.pow(1000, index)).toPrecision(3)} ${abbreviations[index]}`; -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Sean Larkin @thelarkinn +*/ +"use strict"; + +const SizeFormatHelpers = exports; + +SizeFormatHelpers.formatSize = size => { + if (typeof size !== "number" || Number.isNaN(size) === true) { + return "unknown size"; + } + + if (size <= 0) { + return "0 bytes"; + } + + const abbreviations = ["bytes", "KiB", "MiB", "GiB"]; + const index = Math.floor(Math.log(size) / Math.log(1024)); + + return `${+(size / Math.pow(1024, index)).toPrecision(3)} ${ + abbreviations[index] + }`; +}; diff --git a/node_modules/webpack/lib/SourceMapDevToolModuleOptionsPlugin.js b/node_modules/webpack/lib/SourceMapDevToolModuleOptionsPlugin.js index 312ad43fe..e593ced7b 100644 --- a/node_modules/webpack/lib/SourceMapDevToolModuleOptionsPlugin.js +++ b/node_modules/webpack/lib/SourceMapDevToolModuleOptionsPlugin.js @@ -1,37 +1,49 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ModuleFilenameHelpers = require("./ModuleFilenameHelpers"); - -class SourceMapDevToolModuleOptionsPlugin { - constructor(options) { - this.options = options; - } - - apply(compilation) { - const options = this.options; - if(options.module !== false) { - compilation.plugin("build-module", module => { - module.useSourceMap = true; - }); - } - if(options.lineToLine === true) { - compilation.plugin("build-module", module => { - module.lineToLine = true; - }); - } else if(options.lineToLine) { - compilation.plugin("build-module", module => { - if(!module.resource) return; - let resourcePath = module.resource; - const idx = resourcePath.indexOf("?"); - if(idx >= 0) resourcePath = resourcePath.substr(0, idx); - module.lineToLine = ModuleFilenameHelpers.matchObject(options.lineToLine, resourcePath); - }); - } - } -} - -module.exports = SourceMapDevToolModuleOptionsPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const ModuleFilenameHelpers = require("./ModuleFilenameHelpers"); + +class SourceMapDevToolModuleOptionsPlugin { + constructor(options) { + this.options = options; + } + + apply(compilation) { + const options = this.options; + if (options.module !== false) { + compilation.hooks.buildModule.tap( + "SourceMapDevToolModuleOptionsPlugin", + module => { + module.useSourceMap = true; + } + ); + } + if (options.lineToLine === true) { + compilation.hooks.buildModule.tap( + "SourceMapDevToolModuleOptionsPlugin", + module => { + module.lineToLine = true; + } + ); + } else if (options.lineToLine) { + compilation.hooks.buildModule.tap( + "SourceMapDevToolModuleOptionsPlugin", + module => { + if (!module.resource) return; + let resourcePath = module.resource; + const idx = resourcePath.indexOf("?"); + if (idx >= 0) resourcePath = resourcePath.substr(0, idx); + module.lineToLine = ModuleFilenameHelpers.matchObject( + options.lineToLine, + resourcePath + ); + } + ); + } + } +} + +module.exports = SourceMapDevToolModuleOptionsPlugin; diff --git a/node_modules/webpack/lib/SourceMapDevToolPlugin.js b/node_modules/webpack/lib/SourceMapDevToolPlugin.js index e63f34afb..315a9c22c 100644 --- a/node_modules/webpack/lib/SourceMapDevToolPlugin.js +++ b/node_modules/webpack/lib/SourceMapDevToolPlugin.js @@ -1,209 +1,301 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const path = require("path"); -const crypto = require("crypto"); -const RequestShortener = require("./RequestShortener"); -const ConcatSource = require("webpack-sources").ConcatSource; -const RawSource = require("webpack-sources").RawSource; -const ModuleFilenameHelpers = require("./ModuleFilenameHelpers"); -const SourceMapDevToolModuleOptionsPlugin = require("./SourceMapDevToolModuleOptionsPlugin"); - -const basename = (name) => { - if(name.indexOf("/") < 0) return name; - return name.substr(name.lastIndexOf("/") + 1); -}; - -function getTaskForFile(file, chunk, options, compilation) { - const asset = compilation.assets[file]; - if(asset.__SourceMapDevToolFile === file && asset.__SourceMapDevToolData) { - const data = asset.__SourceMapDevToolData; - for(const cachedFile in data) { - compilation.assets[cachedFile] = data[cachedFile]; - if(cachedFile !== file) - chunk.files.push(cachedFile); - } - return; - } - let source, sourceMap; - if(asset.sourceAndMap) { - const sourceAndMap = asset.sourceAndMap(options); - sourceMap = sourceAndMap.map; - source = sourceAndMap.source; - } else { - sourceMap = asset.map(options); - source = asset.source(); - } - if(sourceMap) { - return { - chunk, - file, - asset, - source, - sourceMap, - modules: undefined - }; - } -} - -class SourceMapDevToolPlugin { - constructor(options) { - if(arguments.length > 1) - throw new Error("SourceMapDevToolPlugin only takes one argument (pass an options object)"); - // TODO: remove in webpack 3 - if(typeof options === "string") { - options = { - sourceMapFilename: options - }; - } - if(!options) options = {}; - this.sourceMapFilename = options.filename; - this.sourceMappingURLComment = options.append === false ? false : options.append || "\n//# sourceMappingURL=[url]"; - this.moduleFilenameTemplate = options.moduleFilenameTemplate || "webpack:///[resourcePath]"; - this.fallbackModuleFilenameTemplate = options.fallbackModuleFilenameTemplate || "webpack:///[resourcePath]?[hash]"; - this.options = options; - } - - apply(compiler) { - const sourceMapFilename = this.sourceMapFilename; - const sourceMappingURLComment = this.sourceMappingURLComment; - const moduleFilenameTemplate = this.moduleFilenameTemplate; - const fallbackModuleFilenameTemplate = this.fallbackModuleFilenameTemplate; - const requestShortener = new RequestShortener(compiler.context); - const options = this.options; - options.test = options.test || /\.(js|css)($|\?)/i; - - const matchObject = ModuleFilenameHelpers.matchObject.bind(undefined, options); - - compiler.plugin("compilation", compilation => { - new SourceMapDevToolModuleOptionsPlugin(options).apply(compilation); - - compilation.plugin("after-optimize-chunk-assets", function(chunks) { - const moduleToSourceNameMapping = new Map(); - const tasks = []; - - chunks.forEach(function(chunk) { - chunk.files.forEach(file => { - if(matchObject(file)) { - const task = getTaskForFile(file, chunk, options, compilation); - - if(task) { - const modules = task.sourceMap.sources.map(source => { - const module = compilation.findModule(source); - return module || source; - }); - - for(let idx = 0; idx < modules.length; idx++) { - const module = modules[idx]; - if(!moduleToSourceNameMapping.get(module)) { - moduleToSourceNameMapping.set(module, ModuleFilenameHelpers.createFilename(module, moduleFilenameTemplate, requestShortener)); - } - } - - task.modules = modules; - - tasks.push(task); - } - } - }); - }); - - const usedNamesSet = new Set(moduleToSourceNameMapping.values()); - const conflictDetectionSet = new Set(); - - // all modules in defined order (longest identifier first) - const allModules = Array.from(moduleToSourceNameMapping.keys()).sort((a, b) => { - const ai = typeof a === "string" ? a : a.identifier(); - const bi = typeof b === "string" ? b : b.identifier(); - return ai.length - bi.length; - }); - - // find modules with conflicting source names - for(let idx = 0; idx < allModules.length; idx++) { - const module = allModules[idx]; - let sourceName = moduleToSourceNameMapping.get(module); - let hasName = conflictDetectionSet.has(sourceName); - if(!hasName) { - conflictDetectionSet.add(sourceName); - continue; - } - - // try the fallback name first - sourceName = ModuleFilenameHelpers.createFilename(module, fallbackModuleFilenameTemplate, requestShortener); - hasName = usedNamesSet.has(sourceName); - if(!hasName) { - moduleToSourceNameMapping.set(module, sourceName); - usedNamesSet.add(sourceName); - continue; - } - - // elsewise just append stars until we have a valid name - while(hasName) { - sourceName += "*"; - hasName = usedNamesSet.has(sourceName); - } - moduleToSourceNameMapping.set(module, sourceName); - usedNamesSet.add(sourceName); - } - tasks.forEach(function(task) { - const chunk = task.chunk; - const file = task.file; - const asset = task.asset; - const sourceMap = task.sourceMap; - const source = task.source; - const modules = task.modules; - const moduleFilenames = modules.map(m => moduleToSourceNameMapping.get(m)); - sourceMap.sources = moduleFilenames; - if(sourceMap.sourcesContent && !options.noSources) { - sourceMap.sourcesContent = sourceMap.sourcesContent.map((content, i) => typeof content === "string" ? `${content}\n\n\n${ModuleFilenameHelpers.createFooter(modules[i], requestShortener)}` : null); - } else { - sourceMap.sourcesContent = undefined; - } - sourceMap.sourceRoot = options.sourceRoot || ""; - sourceMap.file = file; - asset.__SourceMapDevToolFile = file; - asset.__SourceMapDevToolData = {}; - let currentSourceMappingURLComment = sourceMappingURLComment; - if(currentSourceMappingURLComment !== false && /\.css($|\?)/i.test(file)) { - currentSourceMappingURLComment = currentSourceMappingURLComment.replace(/^\n\/\/(.*)$/, "\n/*$1*/"); - } - const sourceMapString = JSON.stringify(sourceMap); - if(sourceMapFilename) { - let filename = file; - let query = ""; - const idx = filename.indexOf("?"); - if(idx >= 0) { - query = filename.substr(idx); - filename = filename.substr(0, idx); - } - let sourceMapFile = compilation.getPath(sourceMapFilename, { - chunk, - filename: options.fileContext ? path.relative(options.fileContext, filename) : filename, - query, - basename: basename(filename) - }); - if(sourceMapFile.indexOf("[contenthash]") !== -1) { - sourceMapFile = sourceMapFile.replace(/\[contenthash\]/g, crypto.createHash("md5").update(sourceMapString).digest("hex")); - } - const sourceMapUrl = options.publicPath ? options.publicPath + sourceMapFile.replace(/\\/g, "/") : path.relative(path.dirname(file), sourceMapFile).replace(/\\/g, "/"); - if(currentSourceMappingURLComment !== false) { - asset.__SourceMapDevToolData[file] = compilation.assets[file] = new ConcatSource(new RawSource(source), currentSourceMappingURLComment.replace(/\[url\]/g, sourceMapUrl)); - } - asset.__SourceMapDevToolData[sourceMapFile] = compilation.assets[sourceMapFile] = new RawSource(sourceMapString); - chunk.files.push(sourceMapFile); - } else { - asset.__SourceMapDevToolData[file] = compilation.assets[file] = new ConcatSource(new RawSource(source), currentSourceMappingURLComment - .replace(/\[map\]/g, () => sourceMapString) - .replace(/\[url\]/g, () => `data:application/json;charset=utf-8;base64,${new Buffer(sourceMapString, "utf-8").toString("base64")}`) // eslint-disable-line - ); - } - }); - }); - }); - } -} - -module.exports = SourceMapDevToolPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const path = require("path"); +const { ConcatSource, RawSource } = require("webpack-sources"); +const ModuleFilenameHelpers = require("./ModuleFilenameHelpers"); +const SourceMapDevToolModuleOptionsPlugin = require("./SourceMapDevToolModuleOptionsPlugin"); +const createHash = require("./util/createHash"); + +const validateOptions = require("schema-utils"); +const schema = require("../schemas/plugins/SourceMapDevToolPlugin.json"); + +const basename = name => { + if (!name.includes("/")) return name; + return name.substr(name.lastIndexOf("/") + 1); +}; + +const assetsCache = new WeakMap(); + +const getTaskForFile = (file, chunk, options, compilation) => { + const asset = compilation.assets[file]; + const cache = assetsCache.get(asset); + if (cache && cache.file === file) { + for (const cachedFile in cache.assets) { + compilation.assets[cachedFile] = cache.assets[cachedFile]; + if (cachedFile !== file) chunk.files.push(cachedFile); + } + return; + } + let source, sourceMap; + if (asset.sourceAndMap) { + const sourceAndMap = asset.sourceAndMap(options); + sourceMap = sourceAndMap.map; + source = sourceAndMap.source; + } else { + sourceMap = asset.map(options); + source = asset.source(); + } + if (sourceMap) { + return { + chunk, + file, + asset, + source, + sourceMap, + modules: undefined + }; + } +}; + +class SourceMapDevToolPlugin { + constructor(options) { + if (arguments.length > 1) { + throw new Error( + "SourceMapDevToolPlugin only takes one argument (pass an options object)" + ); + } + + validateOptions(schema, options || {}, "SourceMap DevTool Plugin"); + + if (!options) options = {}; + this.sourceMapFilename = options.filename; + this.sourceMappingURLComment = + options.append === false + ? false + : options.append || "\n//# sourceMappingURL=[url]"; + this.moduleFilenameTemplate = + options.moduleFilenameTemplate || "webpack://[namespace]/[resourcePath]"; + this.fallbackModuleFilenameTemplate = + options.fallbackModuleFilenameTemplate || + "webpack://[namespace]/[resourcePath]?[hash]"; + this.namespace = options.namespace || ""; + this.options = options; + } + + apply(compiler) { + const sourceMapFilename = this.sourceMapFilename; + const sourceMappingURLComment = this.sourceMappingURLComment; + const moduleFilenameTemplate = this.moduleFilenameTemplate; + const namespace = this.namespace; + const fallbackModuleFilenameTemplate = this.fallbackModuleFilenameTemplate; + const requestShortener = compiler.requestShortener; + const options = this.options; + options.test = options.test || /\.(m?js|css)($|\?)/i; + + const matchObject = ModuleFilenameHelpers.matchObject.bind( + undefined, + options + ); + + compiler.hooks.compilation.tap("SourceMapDevToolPlugin", compilation => { + new SourceMapDevToolModuleOptionsPlugin(options).apply(compilation); + + compilation.hooks.afterOptimizeChunkAssets.tap( + { + name: "SourceMapDevToolPlugin", + context: true + }, + (context, chunks) => { + const moduleToSourceNameMapping = new Map(); + const reportProgress = + context && context.reportProgress + ? context.reportProgress + : () => {}; + + const files = []; + for (const chunk of chunks) { + for (const file of chunk.files) { + if (matchObject(file)) { + files.push({ + file, + chunk + }); + } + } + } + + reportProgress(0.0); + const tasks = []; + files.forEach(({ file, chunk }, idx) => { + reportProgress( + (0.5 * idx) / files.length, + file, + "generate SourceMap" + ); + const task = getTaskForFile(file, chunk, options, compilation); + + if (task) { + const modules = task.sourceMap.sources.map(source => { + const module = compilation.findModule(source); + return module || source; + }); + + for (let idx = 0; idx < modules.length; idx++) { + const module = modules[idx]; + if (!moduleToSourceNameMapping.get(module)) { + moduleToSourceNameMapping.set( + module, + ModuleFilenameHelpers.createFilename( + module, + { + moduleFilenameTemplate: moduleFilenameTemplate, + namespace: namespace + }, + requestShortener + ) + ); + } + } + + task.modules = modules; + + tasks.push(task); + } + }); + + reportProgress(0.5, "resolve sources"); + const usedNamesSet = new Set(moduleToSourceNameMapping.values()); + const conflictDetectionSet = new Set(); + + // all modules in defined order (longest identifier first) + const allModules = Array.from(moduleToSourceNameMapping.keys()).sort( + (a, b) => { + const ai = typeof a === "string" ? a : a.identifier(); + const bi = typeof b === "string" ? b : b.identifier(); + return ai.length - bi.length; + } + ); + + // find modules with conflicting source names + for (let idx = 0; idx < allModules.length; idx++) { + const module = allModules[idx]; + let sourceName = moduleToSourceNameMapping.get(module); + let hasName = conflictDetectionSet.has(sourceName); + if (!hasName) { + conflictDetectionSet.add(sourceName); + continue; + } + + // try the fallback name first + sourceName = ModuleFilenameHelpers.createFilename( + module, + { + moduleFilenameTemplate: fallbackModuleFilenameTemplate, + namespace: namespace + }, + requestShortener + ); + hasName = usedNamesSet.has(sourceName); + if (!hasName) { + moduleToSourceNameMapping.set(module, sourceName); + usedNamesSet.add(sourceName); + continue; + } + + // elsewise just append stars until we have a valid name + while (hasName) { + sourceName += "*"; + hasName = usedNamesSet.has(sourceName); + } + moduleToSourceNameMapping.set(module, sourceName); + usedNamesSet.add(sourceName); + } + tasks.forEach((task, index) => { + reportProgress( + 0.5 + (0.5 * index) / tasks.length, + task.file, + "attach SourceMap" + ); + const assets = Object.create(null); + const chunk = task.chunk; + const file = task.file; + const asset = task.asset; + const sourceMap = task.sourceMap; + const source = task.source; + const modules = task.modules; + const moduleFilenames = modules.map(m => + moduleToSourceNameMapping.get(m) + ); + sourceMap.sources = moduleFilenames; + if (options.noSources) { + sourceMap.sourcesContent = undefined; + } + sourceMap.sourceRoot = options.sourceRoot || ""; + sourceMap.file = file; + assetsCache.set(asset, { file, assets }); + let currentSourceMappingURLComment = sourceMappingURLComment; + if ( + currentSourceMappingURLComment !== false && + /\.css($|\?)/i.test(file) + ) { + currentSourceMappingURLComment = currentSourceMappingURLComment.replace( + /^\n\/\/(.*)$/, + "\n/*$1*/" + ); + } + const sourceMapString = JSON.stringify(sourceMap); + if (sourceMapFilename) { + let filename = file; + let query = ""; + const idx = filename.indexOf("?"); + if (idx >= 0) { + query = filename.substr(idx); + filename = filename.substr(0, idx); + } + let sourceMapFile = compilation.getPath(sourceMapFilename, { + chunk, + filename: options.fileContext + ? path.relative(options.fileContext, filename) + : filename, + query, + basename: basename(filename), + contentHash: createHash("md4") + .update(sourceMapString) + .digest("hex") + }); + const sourceMapUrl = options.publicPath + ? options.publicPath + sourceMapFile.replace(/\\/g, "/") + : path + .relative(path.dirname(file), sourceMapFile) + .replace(/\\/g, "/"); + if (currentSourceMappingURLComment !== false) { + assets[file] = compilation.assets[file] = new ConcatSource( + new RawSource(source), + currentSourceMappingURLComment.replace( + /\[url\]/g, + sourceMapUrl + ) + ); + } + assets[sourceMapFile] = compilation.assets[ + sourceMapFile + ] = new RawSource(sourceMapString); + chunk.files.push(sourceMapFile); + } else { + assets[file] = compilation.assets[file] = new ConcatSource( + new RawSource(source), + currentSourceMappingURLComment + .replace(/\[map\]/g, () => sourceMapString) + .replace( + /\[url\]/g, + () => + `data:application/json;charset=utf-8;base64,${Buffer.from( + sourceMapString, + "utf-8" + ).toString("base64")}` + ) + ); + } + }); + reportProgress(1.0); + } + ); + }); + } +} + +module.exports = SourceMapDevToolPlugin; diff --git a/node_modules/webpack/lib/Stats.js b/node_modules/webpack/lib/Stats.js index 6aa3d1ac9..fd7902bee 100644 --- a/node_modules/webpack/lib/Stats.js +++ b/node_modules/webpack/lib/Stats.js @@ -1,983 +1,1435 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const RequestShortener = require("./RequestShortener"); -const SizeFormatHelpers = require("./SizeFormatHelpers"); -const formatLocation = require("./formatLocation"); -const identifierUtils = require("./util/identifier"); - -const optionsOrFallback = function() { - let optionValues = []; - optionValues.push.apply(optionValues, arguments); - return optionValues.find(optionValue => typeof optionValue !== "undefined"); -}; - -class Stats { - constructor(compilation) { - this.compilation = compilation; - this.hash = compilation.hash; - } - - static filterWarnings(warnings, warningsFilter) { - // we dont have anything to filter so all warnings can be shown - if(!warningsFilter) { - return warnings; - } - - // create a chain of filters - // if they return "true" a warning should be surpressed - const normalizedWarningsFilters = [].concat(warningsFilter).map(filter => { - if(typeof filter === "string") { - return warning => warning.indexOf(filter) > -1; - } - - if(filter instanceof RegExp) { - return warning => filter.test(warning); - } - - if(typeof filter === "function") { - return filter; - } - - throw new Error(`Can only filter warnings with Strings or RegExps. (Given: ${filter})`); - }); - return warnings.filter(warning => { - return !normalizedWarningsFilters.some(check => check(warning)); - }); - } - - hasWarnings() { - return this.compilation.warnings.length > 0; - } - - hasErrors() { - return this.compilation.errors.length > 0; - } - - // remove a prefixed "!" that can be specified to reverse sort order - normalizeFieldKey(field) { - if(field[0] === "!") { - return field.substr(1); - } - return field; - } - - // if a field is prefixed by a "!" reverse sort order - sortOrderRegular(field) { - if(field[0] === "!") { - return false; - } - return true; - } - - toJson(options, forToString) { - if(typeof options === "boolean" || typeof options === "string") { - options = Stats.presetToOptions(options); - } else if(!options) { - options = {}; - } - - const optionOrLocalFallback = (v, def) => - typeof v !== "undefined" ? v : - typeof options.all !== "undefined" ? options.all : def; - - const testAgainstGivenOption = (item) => { - if(typeof item === "string") { - const regExp = new RegExp(`[\\\\/]${item.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")}([\\\\/]|$|!|\\?)`); // eslint-disable-line no-useless-escape - return ident => regExp.test(ident); - } - if(item && typeof item === "object" && typeof item.test === "function") - return ident => item.test(ident); - if(typeof item === "function") - return item; - }; - - const compilation = this.compilation; - const context = optionsOrFallback(options.context, process.cwd()); - const requestShortener = new RequestShortener(context); - const showPerformance = optionOrLocalFallback(options.performance, true); - const showHash = optionOrLocalFallback(options.hash, true); - const showEnv = optionOrLocalFallback(options.env, false); - const showVersion = optionOrLocalFallback(options.version, true); - const showTimings = optionOrLocalFallback(options.timings, true); - const showAssets = optionOrLocalFallback(options.assets, true); - const showEntrypoints = optionOrLocalFallback(options.entrypoints, !forToString); - const showChunks = optionOrLocalFallback(options.chunks, !forToString); - const showChunkModules = optionOrLocalFallback(options.chunkModules, true); - const showChunkOrigins = optionOrLocalFallback(options.chunkOrigins, !forToString); - const showModules = optionOrLocalFallback(options.modules, true); - const showDepth = optionOrLocalFallback(options.depth, !forToString); - const showCachedModules = optionOrLocalFallback(options.cached, true); - const showCachedAssets = optionOrLocalFallback(options.cachedAssets, true); - const showReasons = optionOrLocalFallback(options.reasons, !forToString); - const showUsedExports = optionOrLocalFallback(options.usedExports, !forToString); - const showProvidedExports = optionOrLocalFallback(options.providedExports, !forToString); - const showOptimizationBailout = optionOrLocalFallback(options.optimizationBailout, !forToString); - const showChildren = optionOrLocalFallback(options.children, true); - const showSource = optionOrLocalFallback(options.source, !forToString); - const showModuleTrace = optionOrLocalFallback(options.moduleTrace, true); - const showErrors = optionOrLocalFallback(options.errors, true); - const showErrorDetails = optionOrLocalFallback(options.errorDetails, !forToString); - const showWarnings = optionOrLocalFallback(options.warnings, true); - const warningsFilter = optionsOrFallback(options.warningsFilter, null); - const showPublicPath = optionOrLocalFallback(options.publicPath, !forToString); - const excludeModules = [].concat(optionsOrFallback(options.excludeModules, options.exclude, [])).map(testAgainstGivenOption); - const excludeAssets = [].concat(optionsOrFallback(options.excludeAssets, [])).map(testAgainstGivenOption); - const maxModules = optionsOrFallback(options.maxModules, forToString ? 15 : Infinity); - const sortModules = optionsOrFallback(options.modulesSort, "id"); - const sortChunks = optionsOrFallback(options.chunksSort, "id"); - const sortAssets = optionsOrFallback(options.assetsSort, ""); - - if(!showCachedModules) { - excludeModules.push((ident, module) => !module.built); - } - - const createModuleFilter = () => { - let i = 0; - return module => { - if(excludeModules.length > 0) { - const ident = requestShortener.shorten(module.resource); - const excluded = excludeModules.some(fn => fn(ident, module)); - if(excluded) - return false; - } - return i++ < maxModules; - }; - }; - - const createAssetFilter = () => { - return asset => { - if(excludeAssets.length > 0) { - const ident = asset.name; - const excluded = excludeAssets.some(fn => fn(ident, asset)); - if(excluded) - return false; - } - return showCachedAssets || asset.emitted; - }; - }; - - const sortByFieldAndOrder = (fieldKey, a, b) => { - if(a[fieldKey] === null && b[fieldKey] === null) return 0; - if(a[fieldKey] === null) return 1; - if(b[fieldKey] === null) return -1; - if(a[fieldKey] === b[fieldKey]) return 0; - return a[fieldKey] < b[fieldKey] ? -1 : 1; - }; - - const sortByField = (field) => (a, b) => { - if(!field) { - return 0; - } - - const fieldKey = this.normalizeFieldKey(field); - - // if a field is prefixed with a "!" the sort is reversed! - const sortIsRegular = this.sortOrderRegular(field); - - return sortByFieldAndOrder(fieldKey, sortIsRegular ? a : b, sortIsRegular ? b : a); - }; - - const formatError = (e) => { - let text = ""; - if(typeof e === "string") - e = { - message: e - }; - if(e.chunk) { - text += `chunk ${e.chunk.name || e.chunk.id}${e.chunk.hasRuntime() ? " [entry]" : e.chunk.isInitial() ? " [initial]" : ""}\n`; - } - if(e.file) { - text += `${e.file}\n`; - } - if(e.module && e.module.readableIdentifier && typeof e.module.readableIdentifier === "function") { - text += `${e.module.readableIdentifier(requestShortener)}\n`; - } - text += e.message; - if(showErrorDetails && e.details) text += `\n${e.details}`; - if(showErrorDetails && e.missing) text += e.missing.map(item => `\n[${item}]`).join(""); - if(showModuleTrace && e.origin) { - text += `\n @ ${e.origin.readableIdentifier(requestShortener)}`; - if(typeof e.originLoc === "object") { - const locInfo = formatLocation(e.originLoc); - if(locInfo) - text += ` ${locInfo}`; - } - if(e.dependencies) { - e.dependencies.forEach(dep => { - if(!dep.loc) return; - if(typeof dep.loc === "string") return; - const locInfo = formatLocation(dep.loc); - if(!locInfo) return; - text += ` ${locInfo}`; - }); - } - let current = e.origin; - while(current.issuer) { - current = current.issuer; - text += `\n @ ${current.readableIdentifier(requestShortener)}`; - } - } - return text; - }; - - const obj = { - errors: compilation.errors.map(formatError), - warnings: Stats.filterWarnings(compilation.warnings.map(formatError), warningsFilter) - }; - - //We just hint other renderers since actually omitting - //errors/warnings from the JSON would be kind of weird. - Object.defineProperty(obj, "_showWarnings", { - value: showWarnings, - enumerable: false - }); - Object.defineProperty(obj, "_showErrors", { - value: showErrors, - enumerable: false - }); - - if(showVersion) { - obj.version = require("../package.json").version; - } - - if(showHash) obj.hash = this.hash; - if(showTimings && this.startTime && this.endTime) { - obj.time = this.endTime - this.startTime; - } - - if(showEnv && options._env) { - obj.env = options._env; - } - - if(compilation.needAdditionalPass) { - obj.needAdditionalPass = true; - } - if(showPublicPath) { - obj.publicPath = this.compilation.mainTemplate.getPublicPath({ - hash: this.compilation.hash - }); - } - if(showAssets) { - const assetsByFile = {}; - const compilationAssets = Object.keys(compilation.assets); - obj.assetsByChunkName = {}; - obj.assets = compilationAssets.map(asset => { - const obj = { - name: asset, - size: compilation.assets[asset].size(), - chunks: [], - chunkNames: [], - emitted: compilation.assets[asset].emitted - }; - - if(showPerformance) { - obj.isOverSizeLimit = compilation.assets[asset].isOverSizeLimit; - } - - assetsByFile[asset] = obj; - return obj; - }).filter(createAssetFilter()); - obj.filteredAssets = compilationAssets.length - obj.assets.length; - - compilation.chunks.forEach(chunk => { - chunk.files.forEach(asset => { - if(assetsByFile[asset]) { - chunk.ids.forEach(id => { - assetsByFile[asset].chunks.push(id); - }); - if(chunk.name) { - assetsByFile[asset].chunkNames.push(chunk.name); - if(obj.assetsByChunkName[chunk.name]) - obj.assetsByChunkName[chunk.name] = [].concat(obj.assetsByChunkName[chunk.name]).concat([asset]); - else - obj.assetsByChunkName[chunk.name] = asset; - } - } - }); - }); - obj.assets.sort(sortByField(sortAssets)); - } - - if(showEntrypoints) { - obj.entrypoints = {}; - Object.keys(compilation.entrypoints).forEach(name => { - const ep = compilation.entrypoints[name]; - obj.entrypoints[name] = { - chunks: ep.chunks.map(c => c.id), - assets: ep.chunks.reduce((array, c) => array.concat(c.files || []), []) - }; - if(showPerformance) { - obj.entrypoints[name].isOverSizeLimit = ep.isOverSizeLimit; - } - }); - } - - function fnModule(module) { - const obj = { - id: module.id, - identifier: module.identifier(), - name: module.readableIdentifier(requestShortener), - index: module.index, - index2: module.index2, - size: module.size(), - cacheable: !!module.cacheable, - built: !!module.built, - optional: !!module.optional, - prefetched: !!module.prefetched, - chunks: module.mapChunks(chunk => chunk.id), - assets: Object.keys(module.assets || {}), - issuer: module.issuer && module.issuer.identifier(), - issuerId: module.issuer && module.issuer.id, - issuerName: module.issuer && module.issuer.readableIdentifier(requestShortener), - profile: module.profile, - failed: !!module.error, - errors: module.errors && module.dependenciesErrors && (module.errors.length + module.dependenciesErrors.length), - warnings: module.errors && module.dependenciesErrors && (module.warnings.length + module.dependenciesWarnings.length) - }; - if(showReasons) { - obj.reasons = module.reasons.filter(reason => reason.dependency && reason.module).map(reason => { - const obj = { - moduleId: reason.module.id, - moduleIdentifier: reason.module.identifier(), - module: reason.module.readableIdentifier(requestShortener), - moduleName: reason.module.readableIdentifier(requestShortener), - type: reason.dependency.type, - userRequest: reason.dependency.userRequest - }; - const locInfo = formatLocation(reason.dependency.loc); - if(locInfo) obj.loc = locInfo; - return obj; - }).sort((a, b) => a.moduleId - b.moduleId); - } - if(showUsedExports) { - obj.usedExports = module.used ? module.usedExports : false; - } - if(showProvidedExports) { - obj.providedExports = Array.isArray(module.providedExports) ? module.providedExports : null; - } - if(showOptimizationBailout) { - obj.optimizationBailout = module.optimizationBailout.map(item => { - if(typeof item === "function") return item(requestShortener); - return item; - }); - } - if(showDepth) { - obj.depth = module.depth; - } - if(showSource && module._source) { - obj.source = module._source.source(); - } - return obj; - } - if(showChunks) { - obj.chunks = compilation.chunks.map(chunk => { - const obj = { - id: chunk.id, - rendered: chunk.rendered, - initial: chunk.isInitial(), - entry: chunk.hasRuntime(), - recorded: chunk.recorded, - extraAsync: !!chunk.extraAsync, - size: chunk.mapModules(m => m.size()).reduce((size, moduleSize) => size + moduleSize, 0), - names: chunk.name ? [chunk.name] : [], - files: chunk.files.slice(), - hash: chunk.renderedHash, - parents: chunk.parents.map(c => c.id) - }; - if(showChunkModules) { - obj.modules = chunk - .getModules() - .sort(sortByField("depth")) - .filter(createModuleFilter()) - .map(fnModule); - obj.filteredModules = chunk.getNumberOfModules() - obj.modules.length; - obj.modules.sort(sortByField(sortModules)); - } - if(showChunkOrigins) { - obj.origins = chunk.origins.map(origin => ({ - moduleId: origin.module ? origin.module.id : undefined, - module: origin.module ? origin.module.identifier() : "", - moduleIdentifier: origin.module ? origin.module.identifier() : "", - moduleName: origin.module ? origin.module.readableIdentifier(requestShortener) : "", - loc: formatLocation(origin.loc), - name: origin.name, - reasons: origin.reasons || [] - })); - } - return obj; - }); - obj.chunks.sort(sortByField(sortChunks)); - } - if(showModules) { - obj.modules = compilation.modules - .slice() - .sort(sortByField("depth")) - .filter(createModuleFilter()) - .map(fnModule); - obj.filteredModules = compilation.modules.length - obj.modules.length; - obj.modules.sort(sortByField(sortModules)); - } - if(showChildren) { - obj.children = compilation.children.map((child, idx) => { - const childOptions = Stats.getChildOptions(options, idx); - const obj = new Stats(child).toJson(childOptions, forToString); - delete obj.hash; - delete obj.version; - if(child.name) - obj.name = identifierUtils.makePathsRelative(context, child.name, compilation.cache); - return obj; - }); - } - - return obj; - } - - toString(options) { - if(typeof options === "boolean" || typeof options === "string") { - options = Stats.presetToOptions(options); - } else if(!options) { - options = {}; - } - - const useColors = optionsOrFallback(options.colors, false); - - const obj = this.toJson(options, true); - - return Stats.jsonToString(obj, useColors); - } - - static jsonToString(obj, useColors) { - const buf = []; - - const defaultColors = { - bold: "\u001b[1m", - yellow: "\u001b[1m\u001b[33m", - red: "\u001b[1m\u001b[31m", - green: "\u001b[1m\u001b[32m", - cyan: "\u001b[1m\u001b[36m", - magenta: "\u001b[1m\u001b[35m" - }; - - const colors = Object.keys(defaultColors).reduce((obj, color) => { - obj[color] = str => { - if(useColors) { - buf.push( - (useColors === true || useColors[color] === undefined) ? - defaultColors[color] : useColors[color] - ); - } - buf.push(str); - if(useColors) { - buf.push("\u001b[39m\u001b[22m"); - } - }; - return obj; - }, { - normal: (str) => buf.push(str) - }); - - const coloredTime = (time) => { - let times = [800, 400, 200, 100]; - if(obj.time) { - times = [obj.time / 2, obj.time / 4, obj.time / 8, obj.time / 16]; - } - if(time < times[3]) - colors.normal(`${time}ms`); - else if(time < times[2]) - colors.bold(`${time}ms`); - else if(time < times[1]) - colors.green(`${time}ms`); - else if(time < times[0]) - colors.yellow(`${time}ms`); - else - colors.red(`${time}ms`); - }; - - const newline = () => buf.push("\n"); - - const getText = (arr, row, col) => { - return arr[row][col].value; - }; - - const table = (array, align, splitter) => { - const rows = array.length; - const cols = array[0].length; - const colSizes = new Array(cols); - for(let col = 0; col < cols; col++) - colSizes[col] = 0; - for(let row = 0; row < rows; row++) { - for(let col = 0; col < cols; col++) { - const value = `${getText(array, row, col)}`; - if(value.length > colSizes[col]) { - colSizes[col] = value.length; - } - } - } - for(let row = 0; row < rows; row++) { - for(let col = 0; col < cols; col++) { - const format = array[row][col].color; - const value = `${getText(array, row, col)}`; - let l = value.length; - if(align[col] === "l") - format(value); - for(; l < colSizes[col] && col !== cols - 1; l++) - colors.normal(" "); - if(align[col] === "r") - format(value); - if(col + 1 < cols && colSizes[col] !== 0) - colors.normal(splitter || " "); - } - newline(); - } - }; - - const getAssetColor = (asset, defaultColor) => { - if(asset.isOverSizeLimit) { - return colors.yellow; - } - - return defaultColor; - }; - - if(obj.hash) { - colors.normal("Hash: "); - colors.bold(obj.hash); - newline(); - } - if(obj.version) { - colors.normal("Version: webpack "); - colors.bold(obj.version); - newline(); - } - if(typeof obj.time === "number") { - colors.normal("Time: "); - colors.bold(obj.time); - colors.normal("ms"); - newline(); - } - if(obj.env) { - colors.normal("Environment (--env): "); - colors.bold(JSON.stringify(obj.env, null, 2)); - newline(); - } - if(obj.publicPath) { - colors.normal("PublicPath: "); - colors.bold(obj.publicPath); - newline(); - } - - if(obj.assets && obj.assets.length > 0) { - const t = [ - [{ - value: "Asset", - color: colors.bold - }, { - value: "Size", - color: colors.bold - }, { - value: "Chunks", - color: colors.bold - }, { - value: "", - color: colors.bold - }, { - value: "", - color: colors.bold - }, { - value: "Chunk Names", - color: colors.bold - }] - ]; - obj.assets.forEach(asset => { - t.push([{ - value: asset.name, - color: getAssetColor(asset, colors.green) - }, { - value: SizeFormatHelpers.formatSize(asset.size), - color: getAssetColor(asset, colors.normal) - }, { - value: asset.chunks.join(", "), - color: colors.bold - }, { - value: asset.emitted ? "[emitted]" : "", - color: colors.green - }, { - value: asset.isOverSizeLimit ? "[big]" : "", - color: getAssetColor(asset, colors.normal) - }, { - value: asset.chunkNames.join(", "), - color: colors.normal - }]); - }); - table(t, "rrrlll"); - } - if(obj.filteredAssets > 0) { - colors.normal(" "); - if(obj.assets.length > 0) - colors.normal("+ "); - colors.normal(obj.filteredAssets); - if(obj.assets.length > 0) - colors.normal(" hidden"); - colors.normal(obj.filteredAssets !== 1 ? " assets" : " asset"); - newline(); - } - if(obj.entrypoints) { - Object.keys(obj.entrypoints).forEach(name => { - const ep = obj.entrypoints[name]; - colors.normal("Entrypoint "); - colors.bold(name); - if(ep.isOverSizeLimit) { - colors.normal(" "); - colors.yellow("[big]"); - } - colors.normal(" ="); - ep.assets.forEach(asset => { - colors.normal(" "); - colors.green(asset); - }); - newline(); - }); - } - const modulesByIdentifier = {}; - if(obj.modules) { - obj.modules.forEach(module => { - modulesByIdentifier[`$${module.identifier}`] = module; - }); - } else if(obj.chunks) { - obj.chunks.forEach(chunk => { - if(chunk.modules) { - chunk.modules.forEach(module => { - modulesByIdentifier[`$${module.identifier}`] = module; - }); - } - }); - } - - const processModuleAttributes = (module) => { - colors.normal(" "); - colors.normal(SizeFormatHelpers.formatSize(module.size)); - if(module.chunks) { - module.chunks.forEach(chunk => { - colors.normal(" {"); - colors.yellow(chunk); - colors.normal("}"); - }); - } - if(typeof module.depth === "number") { - colors.normal(` [depth ${module.depth}]`); - } - if(!module.cacheable) { - colors.red(" [not cacheable]"); - } - if(module.optional) { - colors.yellow(" [optional]"); - } - if(module.built) { - colors.green(" [built]"); - } - if(module.prefetched) { - colors.magenta(" [prefetched]"); - } - if(module.failed) - colors.red(" [failed]"); - if(module.warnings) - colors.yellow(` [${module.warnings} warning${module.warnings === 1 ? "" : "s"}]`); - if(module.errors) - colors.red(` [${module.errors} error${module.errors === 1 ? "" : "s"}]`); - }; - - const processModuleContent = (module, prefix) => { - if(Array.isArray(module.providedExports)) { - colors.normal(prefix); - if(module.providedExports.length === 0) - colors.cyan("[no exports]"); - else - colors.cyan(`[exports: ${module.providedExports.join(", ")}]`); - newline(); - } - if(module.usedExports !== undefined) { - if(module.usedExports !== true) { - colors.normal(prefix); - if(module.usedExports === false || module.usedExports.length === 0) - colors.cyan("[no exports used]"); - else - colors.cyan(`[only some exports used: ${module.usedExports.join(", ")}]`); - newline(); - } - } - if(Array.isArray(module.optimizationBailout)) { - module.optimizationBailout.forEach(item => { - colors.normal(prefix); - colors.yellow(item); - newline(); - }); - } - if(module.reasons) { - module.reasons.forEach(reason => { - colors.normal(prefix); - colors.normal(reason.type); - colors.normal(" "); - colors.cyan(reason.userRequest); - colors.normal(" ["); - colors.normal(reason.moduleId); - colors.normal("] "); - colors.magenta(reason.module); - if(reason.loc) { - colors.normal(" "); - colors.normal(reason.loc); - } - newline(); - }); - } - if(module.profile) { - colors.normal(prefix); - let sum = 0; - const path = []; - let current = module; - while(current.issuer) { - path.push(current = current.issuer); - } - path.reverse().forEach(module => { - colors.normal("["); - colors.normal(module.id); - colors.normal("] "); - if(module.profile) { - const time = (module.profile.factory || 0) + (module.profile.building || 0); - coloredTime(time); - sum += time; - colors.normal(" "); - } - colors.normal("->"); - }); - Object.keys(module.profile).forEach(key => { - colors.normal(` ${key}:`); - const time = module.profile[key]; - coloredTime(time); - sum += time; - }); - colors.normal(" = "); - coloredTime(sum); - newline(); - } - }; - - const processModulesList = (obj, prefix) => { - if(obj.modules) { - obj.modules.forEach(module => { - colors.normal(prefix); - if(module.id < 1000) colors.normal(" "); - if(module.id < 100) colors.normal(" "); - if(module.id < 10) colors.normal(" "); - colors.normal("["); - colors.normal(module.id); - colors.normal("] "); - colors.bold(module.name || module.identifier); - processModuleAttributes(module); - newline(); - processModuleContent(module, prefix + " "); - }); - if(obj.filteredModules > 0) { - colors.normal(prefix); - colors.normal(" "); - if(obj.modules.length > 0) - colors.normal(" + "); - colors.normal(obj.filteredModules); - if(obj.modules.length > 0) - colors.normal(" hidden"); - colors.normal(obj.filteredModules !== 1 ? " modules" : " module"); - newline(); - } - } - }; - - if(obj.chunks) { - obj.chunks.forEach(chunk => { - colors.normal("chunk "); - if(chunk.id < 1000) colors.normal(" "); - if(chunk.id < 100) colors.normal(" "); - if(chunk.id < 10) colors.normal(" "); - colors.normal("{"); - colors.yellow(chunk.id); - colors.normal("} "); - colors.green(chunk.files.join(", ")); - if(chunk.names && chunk.names.length > 0) { - colors.normal(" ("); - colors.normal(chunk.names.join(", ")); - colors.normal(")"); - } - colors.normal(" "); - colors.normal(SizeFormatHelpers.formatSize(chunk.size)); - chunk.parents.forEach(id => { - colors.normal(" {"); - colors.yellow(id); - colors.normal("}"); - }); - if(chunk.entry) { - colors.yellow(" [entry]"); - } else if(chunk.initial) { - colors.yellow(" [initial]"); - } - if(chunk.rendered) { - colors.green(" [rendered]"); - } - if(chunk.recorded) { - colors.green(" [recorded]"); - } - newline(); - if(chunk.origins) { - chunk.origins.forEach(origin => { - colors.normal(" > "); - if(origin.reasons && origin.reasons.length) { - colors.yellow(origin.reasons.join(" ")); - colors.normal(" "); - } - if(origin.name) { - colors.normal(origin.name); - colors.normal(" "); - } - if(origin.module) { - colors.normal("["); - colors.normal(origin.moduleId); - colors.normal("] "); - const module = modulesByIdentifier[`$${origin.module}`]; - if(module) { - colors.bold(module.name); - colors.normal(" "); - } - if(origin.loc) { - colors.normal(origin.loc); - } - } - newline(); - }); - } - processModulesList(chunk, " "); - }); - } - - processModulesList(obj, ""); - - if(obj._showWarnings && obj.warnings) { - obj.warnings.forEach(warning => { - newline(); - colors.yellow(`WARNING in ${warning}`); - newline(); - }); - } - if(obj._showErrors && obj.errors) { - obj.errors.forEach(error => { - newline(); - colors.red(`ERROR in ${error}`); - newline(); - }); - } - if(obj.children) { - obj.children.forEach(child => { - const childString = Stats.jsonToString(child, useColors); - if(childString) { - if(child.name) { - colors.normal("Child "); - colors.bold(child.name); - colors.normal(":"); - } else { - colors.normal("Child"); - } - newline(); - buf.push(" "); - buf.push(childString.replace(/\n/g, "\n ")); - newline(); - } - }); - } - if(obj.needAdditionalPass) { - colors.yellow("Compilation needs an additional pass and will compile again."); - } - - while(buf[buf.length - 1] === "\n") buf.pop(); - return buf.join(""); - } - - static presetToOptions(name) { - // Accepted values: none, errors-only, minimal, normal, detailed, verbose - // Any other falsy value will behave as 'none', truthy values as 'normal' - const pn = (typeof name === "string") && name.toLowerCase() || name || "none"; - switch(pn) { - case "none": - return { - all: false - }; - case "verbose": - return { - entrypoints: true, - modules: false, - chunks: true, - chunkModules: true, - chunkOrigins: true, - depth: true, - env: true, - reasons: true, - usedExports: true, - providedExports: true, - optimizationBailout: true, - errorDetails: true, - publicPath: true, - exclude: () => false, - maxModules: Infinity, - }; - case "detailed": - return { - entrypoints: true, - chunks: true, - chunkModules: false, - chunkOrigins: true, - depth: true, - usedExports: true, - providedExports: true, - optimizationBailout: true, - errorDetails: true, - publicPath: true, - exclude: () => false, - maxModules: Infinity, - }; - case "minimal": - return { - all: false, - modules: true, - maxModules: 0, - errors: true, - warnings: true, - }; - case "errors-only": - return { - all: false, - errors: true, - moduleTrace: true, - }; - default: - return {}; - } - } - - static getChildOptions(options, idx) { - let innerOptions; - if(Array.isArray(options.children)) { - if(idx < options.children.length) - innerOptions = options.children[idx]; - } else if(typeof options.children === "object" && options.children) { - innerOptions = options.children; - } - if(typeof innerOptions === "boolean" || typeof innerOptions === "string") - innerOptions = Stats.presetToOptions(innerOptions); - if(!innerOptions) - return options; - const childOptions = Object.assign({}, options); - delete childOptions.children; // do not inherit children - return Object.assign(childOptions, innerOptions); - } -} - -module.exports = Stats; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const RequestShortener = require("./RequestShortener"); +const SizeFormatHelpers = require("./SizeFormatHelpers"); +const formatLocation = require("./formatLocation"); +const identifierUtils = require("./util/identifier"); +const compareLocations = require("./compareLocations"); + +const optionsOrFallback = (...args) => { + let optionValues = []; + optionValues.push(...args); + return optionValues.find(optionValue => optionValue !== undefined); +}; + +const compareId = (a, b) => { + if (a < b) return -1; + if (a > b) return 1; + return 0; +}; + +class Stats { + constructor(compilation) { + this.compilation = compilation; + this.hash = compilation.hash; + this.startTime = undefined; + this.endTime = undefined; + } + + static filterWarnings(warnings, warningsFilter) { + // we dont have anything to filter so all warnings can be shown + if (!warningsFilter) { + return warnings; + } + + // create a chain of filters + // if they return "true" a warning should be suppressed + const normalizedWarningsFilters = [].concat(warningsFilter).map(filter => { + if (typeof filter === "string") { + return warning => warning.includes(filter); + } + + if (filter instanceof RegExp) { + return warning => filter.test(warning); + } + + if (typeof filter === "function") { + return filter; + } + + throw new Error( + `Can only filter warnings with Strings or RegExps. (Given: ${filter})` + ); + }); + return warnings.filter(warning => { + return !normalizedWarningsFilters.some(check => check(warning)); + }); + } + + formatFilePath(filePath) { + const OPTIONS_REGEXP = /^(\s|\S)*!/; + return filePath.includes("!") + ? `${filePath.replace(OPTIONS_REGEXP, "")} (${filePath})` + : `${filePath}`; + } + + hasWarnings() { + return ( + this.compilation.warnings.length > 0 || + this.compilation.children.some(child => child.getStats().hasWarnings()) + ); + } + + hasErrors() { + return ( + this.compilation.errors.length > 0 || + this.compilation.children.some(child => child.getStats().hasErrors()) + ); + } + + // remove a prefixed "!" that can be specified to reverse sort order + normalizeFieldKey(field) { + if (field[0] === "!") { + return field.substr(1); + } + return field; + } + + // if a field is prefixed by a "!" reverse sort order + sortOrderRegular(field) { + if (field[0] === "!") { + return false; + } + return true; + } + + toJson(options, forToString) { + if (typeof options === "boolean" || typeof options === "string") { + options = Stats.presetToOptions(options); + } else if (!options) { + options = {}; + } + + const optionOrLocalFallback = (v, def) => + v !== undefined ? v : options.all !== undefined ? options.all : def; + + const testAgainstGivenOption = item => { + if (typeof item === "string") { + const regExp = new RegExp( + `[\\\\/]${item.replace( + // eslint-disable-next-line no-useless-escape + /[-[\]{}()*+?.\\^$|]/g, + "\\$&" + )}([\\\\/]|$|!|\\?)` + ); + return ident => regExp.test(ident); + } + if (item && typeof item === "object" && typeof item.test === "function") { + return ident => item.test(ident); + } + if (typeof item === "function") { + return item; + } + if (typeof item === "boolean") { + return () => item; + } + }; + + const compilation = this.compilation; + const context = optionsOrFallback( + options.context, + compilation.compiler.context + ); + const requestShortener = + compilation.compiler.context === context + ? compilation.requestShortener + : new RequestShortener(context); + const showPerformance = optionOrLocalFallback(options.performance, true); + const showHash = optionOrLocalFallback(options.hash, true); + const showEnv = optionOrLocalFallback(options.env, false); + const showVersion = optionOrLocalFallback(options.version, true); + const showTimings = optionOrLocalFallback(options.timings, true); + const showBuiltAt = optionOrLocalFallback(options.builtAt, true); + const showAssets = optionOrLocalFallback(options.assets, true); + const showEntrypoints = optionOrLocalFallback(options.entrypoints, true); + const showChunkGroups = optionOrLocalFallback( + options.chunkGroups, + !forToString + ); + const showChunks = optionOrLocalFallback(options.chunks, !forToString); + const showChunkModules = optionOrLocalFallback(options.chunkModules, true); + const showChunkOrigins = optionOrLocalFallback( + options.chunkOrigins, + !forToString + ); + const showModules = optionOrLocalFallback(options.modules, true); + const showNestedModules = optionOrLocalFallback( + options.nestedModules, + true + ); + const showModuleAssets = optionOrLocalFallback( + options.moduleAssets, + !forToString + ); + const showDepth = optionOrLocalFallback(options.depth, !forToString); + const showCachedModules = optionOrLocalFallback(options.cached, true); + const showCachedAssets = optionOrLocalFallback(options.cachedAssets, true); + const showReasons = optionOrLocalFallback(options.reasons, !forToString); + const showUsedExports = optionOrLocalFallback( + options.usedExports, + !forToString + ); + const showProvidedExports = optionOrLocalFallback( + options.providedExports, + !forToString + ); + const showOptimizationBailout = optionOrLocalFallback( + options.optimizationBailout, + !forToString + ); + const showChildren = optionOrLocalFallback(options.children, true); + const showSource = optionOrLocalFallback(options.source, !forToString); + const showModuleTrace = optionOrLocalFallback(options.moduleTrace, true); + const showErrors = optionOrLocalFallback(options.errors, true); + const showErrorDetails = optionOrLocalFallback( + options.errorDetails, + !forToString + ); + const showWarnings = optionOrLocalFallback(options.warnings, true); + const warningsFilter = optionsOrFallback(options.warningsFilter, null); + const showPublicPath = optionOrLocalFallback( + options.publicPath, + !forToString + ); + const excludeModules = [] + .concat(optionsOrFallback(options.excludeModules, options.exclude, [])) + .map(testAgainstGivenOption); + const excludeAssets = [] + .concat(optionsOrFallback(options.excludeAssets, [])) + .map(testAgainstGivenOption); + const maxModules = optionsOrFallback( + options.maxModules, + forToString ? 15 : Infinity + ); + const sortModules = optionsOrFallback(options.modulesSort, "id"); + const sortChunks = optionsOrFallback(options.chunksSort, "id"); + const sortAssets = optionsOrFallback(options.assetsSort, ""); + const showOutputPath = optionOrLocalFallback( + options.outputPath, + !forToString + ); + + if (!showCachedModules) { + excludeModules.push((ident, module) => !module.built); + } + + const createModuleFilter = () => { + let i = 0; + return module => { + if (excludeModules.length > 0) { + const ident = requestShortener.shorten(module.resource); + const excluded = excludeModules.some(fn => fn(ident, module)); + if (excluded) return false; + } + const result = i < maxModules; + i++; + return result; + }; + }; + + const createAssetFilter = () => { + return asset => { + if (excludeAssets.length > 0) { + const ident = asset.name; + const excluded = excludeAssets.some(fn => fn(ident, asset)); + if (excluded) return false; + } + return showCachedAssets || asset.emitted; + }; + }; + + const sortByFieldAndOrder = (fieldKey, a, b) => { + if (a[fieldKey] === null && b[fieldKey] === null) return 0; + if (a[fieldKey] === null) return 1; + if (b[fieldKey] === null) return -1; + if (a[fieldKey] === b[fieldKey]) return 0; + return a[fieldKey] < b[fieldKey] ? -1 : 1; + }; + + const sortByField = field => (a, b) => { + if (!field) { + return 0; + } + + const fieldKey = this.normalizeFieldKey(field); + + // if a field is prefixed with a "!" the sort is reversed! + const sortIsRegular = this.sortOrderRegular(field); + + return sortByFieldAndOrder( + fieldKey, + sortIsRegular ? a : b, + sortIsRegular ? b : a + ); + }; + + const formatError = e => { + let text = ""; + if (typeof e === "string") { + e = { message: e }; + } + if (e.chunk) { + text += `chunk ${e.chunk.name || e.chunk.id}${ + e.chunk.hasRuntime() + ? " [entry]" + : e.chunk.canBeInitial() + ? " [initial]" + : "" + }\n`; + } + if (e.file) { + text += `${e.file}\n`; + } + if ( + e.module && + e.module.readableIdentifier && + typeof e.module.readableIdentifier === "function" + ) { + text += this.formatFilePath( + e.module.readableIdentifier(requestShortener) + ); + if (typeof e.loc === "object") { + const locInfo = formatLocation(e.loc); + if (locInfo) text += ` ${locInfo}`; + } + text += "\n"; + } + text += e.message; + if (showErrorDetails && e.details) { + text += `\n${e.details}`; + } + if (showErrorDetails && e.missing) { + text += e.missing.map(item => `\n[${item}]`).join(""); + } + if (showModuleTrace && e.origin) { + text += `\n @ ${this.formatFilePath( + e.origin.readableIdentifier(requestShortener) + )}`; + if (typeof e.originLoc === "object") { + const locInfo = formatLocation(e.originLoc); + if (locInfo) text += ` ${locInfo}`; + } + if (e.dependencies) { + for (const dep of e.dependencies) { + if (!dep.loc) continue; + if (typeof dep.loc === "string") continue; + const locInfo = formatLocation(dep.loc); + if (!locInfo) continue; + text += ` ${locInfo}`; + } + } + let current = e.origin; + while (current.issuer) { + current = current.issuer; + text += `\n @ ${current.readableIdentifier(requestShortener)}`; + } + } + return text; + }; + + const obj = { + errors: compilation.errors.map(formatError), + warnings: Stats.filterWarnings( + compilation.warnings.map(formatError), + warningsFilter + ) + }; + + //We just hint other renderers since actually omitting + //errors/warnings from the JSON would be kind of weird. + Object.defineProperty(obj, "_showWarnings", { + value: showWarnings, + enumerable: false + }); + Object.defineProperty(obj, "_showErrors", { + value: showErrors, + enumerable: false + }); + + if (showVersion) { + obj.version = require("../package.json").version; + } + + if (showHash) obj.hash = this.hash; + if (showTimings && this.startTime && this.endTime) { + obj.time = this.endTime - this.startTime; + } + + if (showBuiltAt && this.endTime) { + obj.builtAt = this.endTime; + } + + if (showEnv && options._env) { + obj.env = options._env; + } + + if (compilation.needAdditionalPass) { + obj.needAdditionalPass = true; + } + if (showPublicPath) { + obj.publicPath = this.compilation.mainTemplate.getPublicPath({ + hash: this.compilation.hash + }); + } + if (showOutputPath) { + obj.outputPath = this.compilation.mainTemplate.outputOptions.path; + } + if (showAssets) { + const assetsByFile = {}; + const compilationAssets = Object.keys(compilation.assets); + obj.assetsByChunkName = {}; + obj.assets = compilationAssets + .map(asset => { + const obj = { + name: asset, + size: compilation.assets[asset].size(), + chunks: [], + chunkNames: [], + emitted: compilation.assets[asset].emitted + }; + + if (showPerformance) { + obj.isOverSizeLimit = compilation.assets[asset].isOverSizeLimit; + } + + assetsByFile[asset] = obj; + return obj; + }) + .filter(createAssetFilter()); + obj.filteredAssets = compilationAssets.length - obj.assets.length; + + for (const chunk of compilation.chunks) { + for (const asset of chunk.files) { + if (assetsByFile[asset]) { + for (const id of chunk.ids) { + assetsByFile[asset].chunks.push(id); + } + if (chunk.name) { + assetsByFile[asset].chunkNames.push(chunk.name); + if (obj.assetsByChunkName[chunk.name]) { + obj.assetsByChunkName[chunk.name] = [] + .concat(obj.assetsByChunkName[chunk.name]) + .concat([asset]); + } else { + obj.assetsByChunkName[chunk.name] = asset; + } + } + } + } + } + obj.assets.sort(sortByField(sortAssets)); + } + + const fnChunkGroup = groupMap => { + const obj = {}; + for (const keyValuePair of groupMap) { + const name = keyValuePair[0]; + const cg = keyValuePair[1]; + const children = cg.getChildrenByOrders(); + obj[name] = { + chunks: cg.chunks.map(c => c.id), + assets: cg.chunks.reduce( + (array, c) => array.concat(c.files || []), + [] + ), + children: Object.keys(children).reduce((obj, key) => { + const groups = children[key]; + obj[key] = groups.map(group => ({ + name: group.name, + chunks: group.chunks.map(c => c.id), + assets: group.chunks.reduce( + (array, c) => array.concat(c.files || []), + [] + ) + })); + return obj; + }, Object.create(null)), + childAssets: Object.keys(children).reduce((obj, key) => { + const groups = children[key]; + obj[key] = Array.from( + groups.reduce((set, group) => { + for (const chunk of group.chunks) { + for (const asset of chunk.files) { + set.add(asset); + } + } + return set; + }, new Set()) + ); + return obj; + }, Object.create(null)) + }; + if (showPerformance) { + obj[name].isOverSizeLimit = cg.isOverSizeLimit; + } + } + + return obj; + }; + + if (showEntrypoints) { + obj.entrypoints = fnChunkGroup(compilation.entrypoints); + } + + if (showChunkGroups) { + obj.namedChunkGroups = fnChunkGroup(compilation.namedChunkGroups); + } + + const fnModule = module => { + const path = []; + let current = module; + while (current.issuer) { + path.push((current = current.issuer)); + } + path.reverse(); + const obj = { + id: module.id, + identifier: module.identifier(), + name: module.readableIdentifier(requestShortener), + index: module.index, + index2: module.index2, + size: module.size(), + cacheable: module.buildInfo.cacheable, + built: !!module.built, + optional: module.optional, + prefetched: module.prefetched, + chunks: Array.from(module.chunksIterable, chunk => chunk.id), + issuer: module.issuer && module.issuer.identifier(), + issuerId: module.issuer && module.issuer.id, + issuerName: + module.issuer && module.issuer.readableIdentifier(requestShortener), + issuerPath: + module.issuer && + path.map(module => ({ + id: module.id, + identifier: module.identifier(), + name: module.readableIdentifier(requestShortener), + profile: module.profile + })), + profile: module.profile, + failed: !!module.error, + errors: module.errors ? module.errors.length : 0, + warnings: module.warnings ? module.warnings.length : 0 + }; + if (showModuleAssets) { + obj.assets = Object.keys(module.buildInfo.assets || {}); + } + if (showReasons) { + obj.reasons = module.reasons + .sort((a, b) => { + if (a.module && !b.module) return -1; + if (!a.module && b.module) return 1; + if (a.module && b.module) { + const cmp = compareId(a.module.id, b.module.id); + if (cmp) return cmp; + } + if (a.dependency && !b.dependency) return -1; + if (!a.dependency && b.dependency) return 1; + if (a.dependency && b.dependency) { + const cmp = compareLocations(a.dependency.loc, b.dependency.loc); + if (cmp) return cmp; + if (a.dependency.type < b.dependency.type) return -1; + if (a.dependency.type > b.dependency.type) return 1; + } + return 0; + }) + .map(reason => { + const obj = { + moduleId: reason.module ? reason.module.id : null, + moduleIdentifier: reason.module + ? reason.module.identifier() + : null, + module: reason.module + ? reason.module.readableIdentifier(requestShortener) + : null, + moduleName: reason.module + ? reason.module.readableIdentifier(requestShortener) + : null, + type: reason.dependency ? reason.dependency.type : null, + explanation: reason.explanation, + userRequest: reason.dependency + ? reason.dependency.userRequest + : null + }; + if (reason.dependency) { + const locInfo = formatLocation(reason.dependency.loc); + if (locInfo) { + obj.loc = locInfo; + } + } + return obj; + }); + } + if (showUsedExports) { + if (module.used === true) { + obj.usedExports = module.usedExports; + } else if (module.used === false) { + obj.usedExports = false; + } + } + if (showProvidedExports) { + obj.providedExports = Array.isArray(module.buildMeta.providedExports) + ? module.buildMeta.providedExports + : null; + } + if (showOptimizationBailout) { + obj.optimizationBailout = module.optimizationBailout.map(item => { + if (typeof item === "function") return item(requestShortener); + return item; + }); + } + if (showDepth) { + obj.depth = module.depth; + } + if (showNestedModules) { + if (module.modules) { + const modules = module.modules; + obj.modules = modules + .sort(sortByField("depth")) + .filter(createModuleFilter()) + .map(fnModule); + obj.filteredModules = modules.length - obj.modules.length; + obj.modules.sort(sortByField(sortModules)); + } + } + if (showSource && module._source) { + obj.source = module._source.source(); + } + return obj; + }; + if (showChunks) { + obj.chunks = compilation.chunks.map(chunk => { + const parents = new Set(); + const children = new Set(); + const siblings = new Set(); + const childIdByOrder = chunk.getChildIdsByOrders(); + for (const chunkGroup of chunk.groupsIterable) { + for (const parentGroup of chunkGroup.parentsIterable) { + for (const chunk of parentGroup.chunks) { + parents.add(chunk.id); + } + } + for (const childGroup of chunkGroup.childrenIterable) { + for (const chunk of childGroup.chunks) { + children.add(chunk.id); + } + } + for (const sibling of chunkGroup.chunks) { + if (sibling !== chunk) siblings.add(sibling.id); + } + } + const obj = { + id: chunk.id, + rendered: chunk.rendered, + initial: chunk.canBeInitial(), + entry: chunk.hasRuntime(), + recorded: chunk.recorded, + reason: chunk.chunkReason, + size: chunk.modulesSize(), + names: chunk.name ? [chunk.name] : [], + files: chunk.files.slice(), + hash: chunk.renderedHash, + siblings: Array.from(siblings).sort(compareId), + parents: Array.from(parents).sort(compareId), + children: Array.from(children).sort(compareId), + childrenByOrder: childIdByOrder + }; + if (showChunkModules) { + obj.modules = chunk + .getModules() + .sort(sortByField("depth")) + .filter(createModuleFilter()) + .map(fnModule); + obj.filteredModules = chunk.getNumberOfModules() - obj.modules.length; + obj.modules.sort(sortByField(sortModules)); + } + if (showChunkOrigins) { + obj.origins = Array.from(chunk.groupsIterable, g => g.origins) + .reduce((a, b) => a.concat(b), []) + .map(origin => ({ + moduleId: origin.module ? origin.module.id : undefined, + module: origin.module ? origin.module.identifier() : "", + moduleIdentifier: origin.module ? origin.module.identifier() : "", + moduleName: origin.module + ? origin.module.readableIdentifier(requestShortener) + : "", + loc: formatLocation(origin.loc), + request: origin.request, + reasons: origin.reasons || [] + })) + .sort((a, b) => { + if ( + typeof a.moduleId === "number" && + typeof b.moduleId !== "number" + ) + return 1; + if ( + typeof a.moduleId !== "number" && + typeof b.moduleId === "number" + ) + return -1; + if ( + typeof a.moduleId === "number" && + typeof b.moduleId === "number" + ) { + const diffId = a.moduleId - b.moduleId; + if (diffId !== 0) return diffId; + } + if (a.loc < b.loc) return -1; + if (a.loc > b.loc) return 1; + return 0; + }); + } + return obj; + }); + obj.chunks.sort(sortByField(sortChunks)); + } + if (showModules) { + obj.modules = compilation.modules + .slice() + .sort(sortByField("depth")) + .filter(createModuleFilter()) + .map(fnModule); + obj.filteredModules = compilation.modules.length - obj.modules.length; + obj.modules.sort(sortByField(sortModules)); + } + if (showChildren) { + obj.children = compilation.children.map((child, idx) => { + const childOptions = Stats.getChildOptions(options, idx); + const obj = new Stats(child).toJson(childOptions, forToString); + delete obj.hash; + delete obj.version; + if (child.name) { + obj.name = identifierUtils.makePathsRelative( + context, + child.name, + compilation.cache + ); + } + return obj; + }); + } + + return obj; + } + + toString(options) { + if (typeof options === "boolean" || typeof options === "string") { + options = Stats.presetToOptions(options); + } else if (!options) { + options = {}; + } + + const useColors = optionsOrFallback(options.colors, false); + + const obj = this.toJson(options, true); + + return Stats.jsonToString(obj, useColors); + } + + static jsonToString(obj, useColors) { + const buf = []; + + const defaultColors = { + bold: "\u001b[1m", + yellow: "\u001b[1m\u001b[33m", + red: "\u001b[1m\u001b[31m", + green: "\u001b[1m\u001b[32m", + cyan: "\u001b[1m\u001b[36m", + magenta: "\u001b[1m\u001b[35m" + }; + + const colors = Object.keys(defaultColors).reduce( + (obj, color) => { + obj[color] = str => { + if (useColors) { + buf.push( + useColors === true || useColors[color] === undefined + ? defaultColors[color] + : useColors[color] + ); + } + buf.push(str); + if (useColors) { + buf.push("\u001b[39m\u001b[22m"); + } + }; + return obj; + }, + { + normal: str => buf.push(str) + } + ); + + const coloredTime = time => { + let times = [800, 400, 200, 100]; + if (obj.time) { + times = [obj.time / 2, obj.time / 4, obj.time / 8, obj.time / 16]; + } + if (time < times[3]) colors.normal(`${time}ms`); + else if (time < times[2]) colors.bold(`${time}ms`); + else if (time < times[1]) colors.green(`${time}ms`); + else if (time < times[0]) colors.yellow(`${time}ms`); + else colors.red(`${time}ms`); + }; + + const newline = () => buf.push("\n"); + + const getText = (arr, row, col) => { + return arr[row][col].value; + }; + + const table = (array, align, splitter) => { + const rows = array.length; + const cols = array[0].length; + const colSizes = new Array(cols); + for (let col = 0; col < cols; col++) { + colSizes[col] = 0; + } + for (let row = 0; row < rows; row++) { + for (let col = 0; col < cols; col++) { + const value = `${getText(array, row, col)}`; + if (value.length > colSizes[col]) { + colSizes[col] = value.length; + } + } + } + for (let row = 0; row < rows; row++) { + for (let col = 0; col < cols; col++) { + const format = array[row][col].color; + const value = `${getText(array, row, col)}`; + let l = value.length; + if (align[col] === "l") { + format(value); + } + for (; l < colSizes[col] && col !== cols - 1; l++) { + colors.normal(" "); + } + if (align[col] === "r") { + format(value); + } + if (col + 1 < cols && colSizes[col] !== 0) { + colors.normal(splitter || " "); + } + } + newline(); + } + }; + + const getAssetColor = (asset, defaultColor) => { + if (asset.isOverSizeLimit) { + return colors.yellow; + } + + return defaultColor; + }; + + if (obj.hash) { + colors.normal("Hash: "); + colors.bold(obj.hash); + newline(); + } + if (obj.version) { + colors.normal("Version: webpack "); + colors.bold(obj.version); + newline(); + } + if (typeof obj.time === "number") { + colors.normal("Time: "); + colors.bold(obj.time); + colors.normal("ms"); + newline(); + } + if (typeof obj.builtAt === "number") { + const builtAtDate = new Date(obj.builtAt); + colors.normal("Built at: "); + colors.normal( + builtAtDate.toLocaleDateString(undefined, { + day: "2-digit", + month: "2-digit", + year: "numeric" + }) + ); + colors.normal(" "); + colors.bold(builtAtDate.toLocaleTimeString()); + newline(); + } + if (obj.env) { + colors.normal("Environment (--env): "); + colors.bold(JSON.stringify(obj.env, null, 2)); + newline(); + } + if (obj.publicPath) { + colors.normal("PublicPath: "); + colors.bold(obj.publicPath); + newline(); + } + + if (obj.assets && obj.assets.length > 0) { + const t = [ + [ + { + value: "Asset", + color: colors.bold + }, + { + value: "Size", + color: colors.bold + }, + { + value: "Chunks", + color: colors.bold + }, + { + value: "", + color: colors.bold + }, + { + value: "", + color: colors.bold + }, + { + value: "Chunk Names", + color: colors.bold + } + ] + ]; + for (const asset of obj.assets) { + t.push([ + { + value: asset.name, + color: getAssetColor(asset, colors.green) + }, + { + value: SizeFormatHelpers.formatSize(asset.size), + color: getAssetColor(asset, colors.normal) + }, + { + value: asset.chunks.join(", "), + color: colors.bold + }, + { + value: asset.emitted ? "[emitted]" : "", + color: colors.green + }, + { + value: asset.isOverSizeLimit ? "[big]" : "", + color: getAssetColor(asset, colors.normal) + }, + { + value: asset.chunkNames.join(", "), + color: colors.normal + } + ]); + } + table(t, "rrrlll"); + } + if (obj.filteredAssets > 0) { + colors.normal(" "); + if (obj.assets.length > 0) colors.normal("+ "); + colors.normal(obj.filteredAssets); + if (obj.assets.length > 0) colors.normal(" hidden"); + colors.normal(obj.filteredAssets !== 1 ? " assets" : " asset"); + newline(); + } + + const processChunkGroups = (namedGroups, prefix) => { + for (const name of Object.keys(namedGroups)) { + const cg = namedGroups[name]; + colors.normal(`${prefix} `); + colors.bold(name); + if (cg.isOverSizeLimit) { + colors.normal(" "); + colors.yellow("[big]"); + } + colors.normal(" ="); + for (const asset of cg.assets) { + colors.normal(" "); + colors.green(asset); + } + for (const name of Object.keys(cg.childAssets)) { + const assets = cg.childAssets[name]; + if (assets && assets.length > 0) { + colors.normal(" "); + colors.magenta(`(${name}:`); + for (const asset of assets) { + colors.normal(" "); + colors.green(asset); + } + colors.magenta(")"); + } + } + newline(); + } + }; + + if (obj.entrypoints) { + processChunkGroups(obj.entrypoints, "Entrypoint"); + } + + if (obj.namedChunkGroups) { + let outputChunkGroups = obj.namedChunkGroups; + if (obj.entrypoints) { + outputChunkGroups = Object.keys(outputChunkGroups) + .filter(name => !obj.entrypoints[name]) + .reduce((result, name) => { + result[name] = obj.namedChunkGroups[name]; + return result; + }, {}); + } + processChunkGroups(outputChunkGroups, "Chunk Group"); + } + + const modulesByIdentifier = {}; + if (obj.modules) { + for (const module of obj.modules) { + modulesByIdentifier[`$${module.identifier}`] = module; + } + } else if (obj.chunks) { + for (const chunk of obj.chunks) { + if (chunk.modules) { + for (const module of chunk.modules) { + modulesByIdentifier[`$${module.identifier}`] = module; + } + } + } + } + + const processModuleAttributes = module => { + colors.normal(" "); + colors.normal(SizeFormatHelpers.formatSize(module.size)); + if (module.chunks) { + for (const chunk of module.chunks) { + colors.normal(" {"); + colors.yellow(chunk); + colors.normal("}"); + } + } + if (typeof module.depth === "number") { + colors.normal(` [depth ${module.depth}]`); + } + if (module.cacheable === false) { + colors.red(" [not cacheable]"); + } + if (module.optional) { + colors.yellow(" [optional]"); + } + if (module.built) { + colors.green(" [built]"); + } + if (module.assets && module.assets.length) { + colors.magenta( + ` [${module.assets.length} asset${ + module.assets.length === 1 ? "" : "s" + }]` + ); + } + if (module.prefetched) { + colors.magenta(" [prefetched]"); + } + if (module.failed) colors.red(" [failed]"); + if (module.warnings) { + colors.yellow( + ` [${module.warnings} warning${module.warnings === 1 ? "" : "s"}]` + ); + } + if (module.errors) { + colors.red( + ` [${module.errors} error${module.errors === 1 ? "" : "s"}]` + ); + } + }; + + const processModuleContent = (module, prefix) => { + if (Array.isArray(module.providedExports)) { + colors.normal(prefix); + if (module.providedExports.length === 0) { + colors.cyan("[no exports]"); + } else { + colors.cyan(`[exports: ${module.providedExports.join(", ")}]`); + } + newline(); + } + if (module.usedExports !== undefined) { + if (module.usedExports !== true) { + colors.normal(prefix); + if (module.usedExports === null) { + colors.cyan("[used exports unknown]"); + } else if (module.usedExports === false) { + colors.cyan("[no exports used]"); + } else if ( + Array.isArray(module.usedExports) && + module.usedExports.length === 0 + ) { + colors.cyan("[no exports used]"); + } else if (Array.isArray(module.usedExports)) { + const providedExportsCount = Array.isArray(module.providedExports) + ? module.providedExports.length + : null; + if ( + providedExportsCount !== null && + providedExportsCount === module.usedExports.length + ) { + colors.cyan("[all exports used]"); + } else { + colors.cyan( + `[only some exports used: ${module.usedExports.join(", ")}]` + ); + } + } + newline(); + } + } + if (Array.isArray(module.optimizationBailout)) { + for (const item of module.optimizationBailout) { + colors.normal(prefix); + colors.yellow(item); + newline(); + } + } + if (module.reasons) { + for (const reason of module.reasons) { + colors.normal(prefix); + if (reason.type) { + colors.normal(reason.type); + colors.normal(" "); + } + if (reason.userRequest) { + colors.cyan(reason.userRequest); + colors.normal(" "); + } + if (reason.moduleId !== null) { + colors.normal("["); + colors.normal(reason.moduleId); + colors.normal("]"); + } + if (reason.module && reason.module !== reason.moduleId) { + colors.normal(" "); + colors.magenta(reason.module); + } + if (reason.loc) { + colors.normal(" "); + colors.normal(reason.loc); + } + if (reason.explanation) { + colors.normal(" "); + colors.cyan(reason.explanation); + } + newline(); + } + } + if (module.profile) { + colors.normal(prefix); + let sum = 0; + if (module.issuerPath) { + for (const m of module.issuerPath) { + colors.normal("["); + colors.normal(m.id); + colors.normal("] "); + if (m.profile) { + const time = (m.profile.factory || 0) + (m.profile.building || 0); + coloredTime(time); + sum += time; + colors.normal(" "); + } + colors.normal("-> "); + } + } + for (const key of Object.keys(module.profile)) { + colors.normal(`${key}:`); + const time = module.profile[key]; + coloredTime(time); + colors.normal(" "); + sum += time; + } + colors.normal("= "); + coloredTime(sum); + newline(); + } + if (module.modules) { + processModulesList(module, prefix + "| "); + } + }; + + const processModulesList = (obj, prefix) => { + if (obj.modules) { + let maxModuleId = 0; + for (const module of obj.modules) { + if (typeof module.id === "number") { + if (maxModuleId < module.id) maxModuleId = module.id; + } + } + let contentPrefix = prefix + " "; + if (maxModuleId >= 10) contentPrefix += " "; + if (maxModuleId >= 100) contentPrefix += " "; + if (maxModuleId >= 1000) contentPrefix += " "; + for (const module of obj.modules) { + colors.normal(prefix); + const name = module.name || module.identifier; + if (typeof module.id === "string" || typeof module.id === "number") { + if (typeof module.id === "number") { + if (module.id < 1000 && maxModuleId >= 1000) colors.normal(" "); + if (module.id < 100 && maxModuleId >= 100) colors.normal(" "); + if (module.id < 10 && maxModuleId >= 10) colors.normal(" "); + } else { + if (maxModuleId >= 1000) colors.normal(" "); + if (maxModuleId >= 100) colors.normal(" "); + if (maxModuleId >= 10) colors.normal(" "); + } + if (name !== module.id) { + colors.normal("["); + colors.normal(module.id); + colors.normal("]"); + colors.normal(" "); + } else { + colors.normal("["); + colors.bold(module.id); + colors.normal("]"); + } + } + if (name !== module.id) { + colors.bold(name); + } + processModuleAttributes(module); + newline(); + processModuleContent(module, contentPrefix); + } + if (obj.filteredModules > 0) { + colors.normal(prefix); + colors.normal(" "); + if (obj.modules.length > 0) colors.normal(" + "); + colors.normal(obj.filteredModules); + if (obj.modules.length > 0) colors.normal(" hidden"); + colors.normal(obj.filteredModules !== 1 ? " modules" : " module"); + newline(); + } + } + }; + + if (obj.chunks) { + for (const chunk of obj.chunks) { + colors.normal("chunk "); + if (chunk.id < 1000) colors.normal(" "); + if (chunk.id < 100) colors.normal(" "); + if (chunk.id < 10) colors.normal(" "); + colors.normal("{"); + colors.yellow(chunk.id); + colors.normal("} "); + colors.green(chunk.files.join(", ")); + if (chunk.names && chunk.names.length > 0) { + colors.normal(" ("); + colors.normal(chunk.names.join(", ")); + colors.normal(")"); + } + colors.normal(" "); + colors.normal(SizeFormatHelpers.formatSize(chunk.size)); + for (const id of chunk.parents) { + colors.normal(" <{"); + colors.yellow(id); + colors.normal("}>"); + } + for (const id of chunk.siblings) { + colors.normal(" ={"); + colors.yellow(id); + colors.normal("}="); + } + for (const id of chunk.children) { + colors.normal(" >{"); + colors.yellow(id); + colors.normal("}<"); + } + if (chunk.childrenByOrder) { + for (const name of Object.keys(chunk.childrenByOrder)) { + const children = chunk.childrenByOrder[name]; + colors.normal(" "); + colors.magenta(`(${name}:`); + for (const id of children) { + colors.normal(" {"); + colors.yellow(id); + colors.normal("}"); + } + colors.magenta(")"); + } + } + if (chunk.entry) { + colors.yellow(" [entry]"); + } else if (chunk.initial) { + colors.yellow(" [initial]"); + } + if (chunk.rendered) { + colors.green(" [rendered]"); + } + if (chunk.recorded) { + colors.green(" [recorded]"); + } + if (chunk.reason) { + colors.yellow(` ${chunk.reason}`); + } + newline(); + if (chunk.origins) { + for (const origin of chunk.origins) { + colors.normal(" > "); + if (origin.reasons && origin.reasons.length) { + colors.yellow(origin.reasons.join(" ")); + colors.normal(" "); + } + if (origin.request) { + colors.normal(origin.request); + colors.normal(" "); + } + if (origin.module) { + colors.normal("["); + colors.normal(origin.moduleId); + colors.normal("] "); + const module = modulesByIdentifier[`$${origin.module}`]; + if (module) { + colors.bold(module.name); + colors.normal(" "); + } + } + if (origin.loc) { + colors.normal(origin.loc); + } + newline(); + } + } + processModulesList(chunk, " "); + } + } + + processModulesList(obj, ""); + + if (obj._showWarnings && obj.warnings) { + for (const warning of obj.warnings) { + newline(); + colors.yellow(`WARNING in ${warning}`); + newline(); + } + } + if (obj._showErrors && obj.errors) { + for (const error of obj.errors) { + newline(); + colors.red(`ERROR in ${error}`); + newline(); + } + } + if (obj.children) { + for (const child of obj.children) { + const childString = Stats.jsonToString(child, useColors); + if (childString) { + if (child.name) { + colors.normal("Child "); + colors.bold(child.name); + colors.normal(":"); + } else { + colors.normal("Child"); + } + newline(); + buf.push(" "); + buf.push(childString.replace(/\n/g, "\n ")); + newline(); + } + } + } + if (obj.needAdditionalPass) { + colors.yellow( + "Compilation needs an additional pass and will compile again." + ); + } + + while (buf[buf.length - 1] === "\n") { + buf.pop(); + } + return buf.join(""); + } + + static presetToOptions(name) { + // Accepted values: none, errors-only, minimal, normal, detailed, verbose + // Any other falsy value will behave as 'none', truthy values as 'normal' + const pn = + (typeof name === "string" && name.toLowerCase()) || name || "none"; + switch (pn) { + case "none": + return { + all: false + }; + case "verbose": + return { + entrypoints: true, + chunkGroups: true, + modules: false, + chunks: true, + chunkModules: true, + chunkOrigins: true, + depth: true, + env: true, + reasons: true, + usedExports: true, + providedExports: true, + optimizationBailout: true, + errorDetails: true, + publicPath: true, + exclude: false, + maxModules: Infinity + }; + case "detailed": + return { + entrypoints: true, + chunkGroups: true, + chunks: true, + chunkModules: false, + chunkOrigins: true, + depth: true, + usedExports: true, + providedExports: true, + optimizationBailout: true, + errorDetails: true, + publicPath: true, + exclude: false, + maxModules: Infinity + }; + case "minimal": + return { + all: false, + modules: true, + maxModules: 0, + errors: true, + warnings: true + }; + case "errors-only": + return { + all: false, + errors: true, + moduleTrace: true + }; + default: + return {}; + } + } + + static getChildOptions(options, idx) { + let innerOptions; + if (Array.isArray(options.children)) { + if (idx < options.children.length) { + innerOptions = options.children[idx]; + } + } else if (typeof options.children === "object" && options.children) { + innerOptions = options.children; + } + if (typeof innerOptions === "boolean" || typeof innerOptions === "string") { + innerOptions = Stats.presetToOptions(innerOptions); + } + if (!innerOptions) { + return options; + } + const childOptions = Object.assign({}, options); + delete childOptions.children; // do not inherit children + return Object.assign(childOptions, innerOptions); + } +} + +module.exports = Stats; diff --git a/node_modules/webpack/lib/Template.js b/node_modules/webpack/lib/Template.js index 57a8b9730..572d4b5ed 100644 --- a/node_modules/webpack/lib/Template.js +++ b/node_modules/webpack/lib/Template.js @@ -1,176 +1,290 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const Tapable = require("tapable"); -const ConcatSource = require("webpack-sources").ConcatSource; - -const START_LOWERCASE_ALPHABET_CODE = "a".charCodeAt(0); -const START_UPPERCASE_ALPHABET_CODE = "A".charCodeAt(0); -const DELTA_A_TO_Z = "z".charCodeAt(0) - START_LOWERCASE_ALPHABET_CODE + 1; -const FUNCTION_CONTENT_REGEX = /^function\s?\(\)\s?\{\n?|\n?\}$/g; -const INDENT_MULTILINE_REGEX = /^\t/mg; -const IDENTIFIER_NAME_REPLACE_REGEX = /^[^a-zA-Z$_]/; -const IDENTIFIER_ALPHA_NUMERIC_NAME_REPLACE_REGEX = /[^a-zA-Z0-9$_]/g; -const PATH_NAME_NORMALIZE_REPLACE_REGEX = /[^a-zA-Z0-9_!§$()=\-^°]+/g; -const MATCH_PADDED_HYPHENS_REPLACE_REGEX = /^-|-$/g; - -module.exports = class Template extends Tapable { - constructor(outputOptions) { - super(); - this.outputOptions = outputOptions || {}; - } - - static getFunctionContent(fn) { - return fn.toString().replace(FUNCTION_CONTENT_REGEX, "").replace(INDENT_MULTILINE_REGEX, ""); - } - - static toIdentifier(str) { - if(typeof str !== "string") return ""; - return str.replace(IDENTIFIER_NAME_REPLACE_REGEX, "_").replace(IDENTIFIER_ALPHA_NUMERIC_NAME_REPLACE_REGEX, "_"); - } - - static toPath(str) { - if(typeof str !== "string") return ""; - return str.replace(PATH_NAME_NORMALIZE_REPLACE_REGEX, "-").replace(MATCH_PADDED_HYPHENS_REPLACE_REGEX, ""); - } - - // map number to a single character a-z, A-Z or <_ + number> if number is too big - static numberToIdentifer(n) { - // lower case - if(n < DELTA_A_TO_Z) return String.fromCharCode(START_LOWERCASE_ALPHABET_CODE + n); - - // upper case - n -= DELTA_A_TO_Z; - if(n < DELTA_A_TO_Z) return String.fromCharCode(START_UPPERCASE_ALPHABET_CODE + n); - - // fall back to _ + number - n -= DELTA_A_TO_Z; - return "_" + n; - } - - indent(str) { - if(Array.isArray(str)) { - return str.map(this.indent.bind(this)).join("\n"); - } else { - str = str.trimRight(); - if(!str) return ""; - var ind = (str[0] === "\n" ? "" : "\t"); - return ind + str.replace(/\n([^\n])/g, "\n\t$1"); - } - } - - prefix(str, prefix) { - if(Array.isArray(str)) { - str = str.join("\n"); - } - str = str.trim(); - if(!str) return ""; - const ind = (str[0] === "\n" ? "" : prefix); - return ind + str.replace(/\n([^\n])/g, "\n" + prefix + "$1"); - } - - asString(str) { - if(Array.isArray(str)) { - return str.join("\n"); - } - return str; - } - - getModulesArrayBounds(modules) { - if(!modules.every(moduleIdIsNumber)) - return false; - var maxId = -Infinity; - var minId = Infinity; - modules.forEach(function(module) { - if(maxId < module.id) maxId = module.id; - if(minId > module.id) minId = module.id; - }); - if(minId < 16 + ("" + minId).length) { - // add minId x ',' instead of 'Array(minId).concat(...)' - minId = 0; - } - var objectOverhead = modules.map(function(module) { - var idLength = (module.id + "").length; - return idLength + 2; - }).reduce(function(a, b) { - return a + b; - }, -1); - var arrayOverhead = minId === 0 ? maxId : 16 + ("" + minId).length + maxId; - return arrayOverhead < objectOverhead ? [minId, maxId] : false; - } - - renderChunkModules(chunk, moduleTemplate, dependencyTemplates, prefix) { - if(!prefix) prefix = ""; - var source = new ConcatSource(); - if(chunk.getNumberOfModules() === 0) { - source.add("[]"); - return source; - } - var removedModules = chunk.removedModules; - var allModules = chunk.mapModules(function(module) { - return { - id: module.id, - source: moduleTemplate.render(module, dependencyTemplates, chunk) - }; - }); - if(removedModules && removedModules.length > 0) { - removedModules.forEach(function(id) { - allModules.push({ - id: id, - source: "false" - }); - }); - } - var bounds = this.getModulesArrayBounds(allModules); - - if(bounds) { - // Render a spare array - var minId = bounds[0]; - var maxId = bounds[1]; - if(minId !== 0) source.add("Array(" + minId + ").concat("); - source.add("[\n"); - var modules = {}; - allModules.forEach(function(module) { - modules[module.id] = module; - }); - for(var idx = minId; idx <= maxId; idx++) { - var module = modules[idx]; - if(idx !== minId) source.add(",\n"); - source.add("/* " + idx + " */"); - if(module) { - source.add("\n"); - source.add(module.source); - } - } - source.add("\n" + prefix + "]"); - if(minId !== 0) source.add(")"); - } else { - // Render an object - source.add("{\n"); - allModules - .sort(stringifyIdSortPredicate) - .forEach(function(module, idx) { - if(idx !== 0) source.add(",\n"); - source.add(`\n/***/ ${JSON.stringify(module.id)}:\n`); - source.add(module.source); - }); - source.add("\n\n" + prefix + "}"); - } - return source; - } -}; - -function stringifyIdSortPredicate(a, b) { - var aId = a.id + ""; - var bId = b.id + ""; - if(aId < bId) return -1; - if(aId > bId) return 1; - return 0; -} - -function moduleIdIsNumber(module) { - return typeof module.id === "number"; -} +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +/** @typedef {import("./Module")} Module */ +/** @typedef {import("./Chunk")} Chunk */ +/** @typedef {import("./ModuleTemplate")} ModuleTemplate */ +/** @typedef {import("webpack-sources").ConcatSource} ConcatSource */ + +const { ConcatSource } = require("webpack-sources"); +const HotUpdateChunk = require("./HotUpdateChunk"); + +const START_LOWERCASE_ALPHABET_CODE = "a".charCodeAt(0); +const START_UPPERCASE_ALPHABET_CODE = "A".charCodeAt(0); +const DELTA_A_TO_Z = "z".charCodeAt(0) - START_LOWERCASE_ALPHABET_CODE + 1; +const FUNCTION_CONTENT_REGEX = /^function\s?\(\)\s?\{\r?\n?|\r?\n?\}$/g; +const INDENT_MULTILINE_REGEX = /^\t/gm; +const LINE_SEPARATOR_REGEX = /\r?\n/g; +const IDENTIFIER_NAME_REPLACE_REGEX = /^([^a-zA-Z$_])/; +const IDENTIFIER_ALPHA_NUMERIC_NAME_REPLACE_REGEX = /[^a-zA-Z0-9$]+/g; +const COMMENT_END_REGEX = /\*\//g; +const PATH_NAME_NORMALIZE_REPLACE_REGEX = /[^a-zA-Z0-9_!§$()=\-^°]+/g; +const MATCH_PADDED_HYPHENS_REPLACE_REGEX = /^-|-$/g; + +/** @typedef {import("webpack-sources").Source} Source */ + +/** + * @typedef {Object} HasId + * @property {number | string} id + */ + +/** + * @typedef {function(Module, number): boolean} ModuleFilterPredicate + */ + +/** + * @param {HasId} a first id object to be sorted + * @param {HasId} b second id object to be sorted against + * @returns {-1|0|1} the sort value + */ +const stringifyIdSortPredicate = (a, b) => { + const aId = a.id + ""; + const bId = b.id + ""; + if (aId < bId) return -1; + if (aId > bId) return 1; + return 0; +}; + +class Template { + /** + * + * @param {Function} fn - a runtime function (.runtime.js) "template" + * @returns {string} the updated and normalized function string + */ + static getFunctionContent(fn) { + return fn + .toString() + .replace(FUNCTION_CONTENT_REGEX, "") + .replace(INDENT_MULTILINE_REGEX, "") + .replace(LINE_SEPARATOR_REGEX, "\n"); + } + + /** + * @param {string} str the string converted to identifier + * @returns {string} created identifier + */ + static toIdentifier(str) { + if (typeof str !== "string") return ""; + return str + .replace(IDENTIFIER_NAME_REPLACE_REGEX, "_$1") + .replace(IDENTIFIER_ALPHA_NUMERIC_NAME_REPLACE_REGEX, "_"); + } + /** + * + * @param {string} str string to be converted to commented in bundle code + * @returns {string} returns a commented version of string + */ + static toComment(str) { + if (!str) return ""; + return `/*! ${str.replace(COMMENT_END_REGEX, "* /")} */`; + } + + /** + * + * @param {string} str string to be converted to "normal comment" + * @returns {string} returns a commented version of string + */ + static toNormalComment(str) { + if (!str) return ""; + return `/* ${str.replace(COMMENT_END_REGEX, "* /")} */`; + } + + /** + * @param {string} str string path to be normalized + * @returns {string} normalized bundle-safe path + */ + static toPath(str) { + if (typeof str !== "string") return ""; + return str + .replace(PATH_NAME_NORMALIZE_REPLACE_REGEX, "-") + .replace(MATCH_PADDED_HYPHENS_REPLACE_REGEX, ""); + } + + // map number to a single character a-z, A-Z or <_ + number> if number is too big + /** + * + * @param {number} n number to convert to ident + * @returns {string} returns single character ident + */ + static numberToIdentifer(n) { + // lower case + if (n < DELTA_A_TO_Z) { + return String.fromCharCode(START_LOWERCASE_ALPHABET_CODE + n); + } + + // upper case + if (n < DELTA_A_TO_Z * 2) { + return String.fromCharCode( + START_UPPERCASE_ALPHABET_CODE + n - DELTA_A_TO_Z + ); + } + + // use multiple letters + return ( + Template.numberToIdentifer(n % (2 * DELTA_A_TO_Z)) + + Template.numberToIdentifer(Math.floor(n / (2 * DELTA_A_TO_Z))) + ); + } + + /** + * + * @param {string | string[]} s string to convert to identity + * @returns {string} converted identity + */ + static indent(s) { + if (Array.isArray(s)) { + return s.map(Template.indent).join("\n"); + } else { + const str = s.trimRight(); + if (!str) return ""; + const ind = str[0] === "\n" ? "" : "\t"; + return ind + str.replace(/\n([^\n])/g, "\n\t$1"); + } + } + + /** + * + * @param {string|string[]} s string to create prefix for + * @param {string} prefix prefix to compose + * @returns {string} returns new prefix string + */ + static prefix(s, prefix) { + const str = Template.asString(s).trim(); + if (!str) return ""; + const ind = str[0] === "\n" ? "" : prefix; + return ind + str.replace(/\n([^\n])/g, "\n" + prefix + "$1"); + } + + /** + * + * @param {string|string[]} str string or string collection + * @returns {string} returns a single string from array + */ + static asString(str) { + if (Array.isArray(str)) { + return str.join("\n"); + } + return str; + } + + /** + * @typedef {Object} WithId + * @property {string|number} id + */ + + /** + * @param {WithId[]} modules a collection of modules to get array bounds for + * @returns {[number, number] | false} returns the upper and lower array bounds + * or false if not every module has a number based id + */ + static getModulesArrayBounds(modules) { + let maxId = -Infinity; + let minId = Infinity; + for (const module of modules) { + if (typeof module.id !== "number") return false; + if (maxId < module.id) maxId = /** @type {number} */ (module.id); + if (minId > module.id) minId = /** @type {number} */ (module.id); + } + if (minId < 16 + ("" + minId).length) { + // add minId x ',' instead of 'Array(minId).concat(…)' + minId = 0; + } + const objectOverhead = modules + .map(module => (module.id + "").length + 2) + .reduce((a, b) => a + b, -1); + const arrayOverhead = + minId === 0 ? maxId : 16 + ("" + minId).length + maxId; + return arrayOverhead < objectOverhead ? [minId, maxId] : false; + } + + /** + * @param {Chunk} chunk chunk whose modules will be rendered + * @param {ModuleFilterPredicate} filterFn function used to filter modules from chunk to render + * @param {ModuleTemplate} moduleTemplate ModuleTemplate instance used to render modules + * @param {TODO | TODO[]} dependencyTemplates templates needed for each module to render dependencies + * @param {string=} prefix applying prefix strings + * @returns {ConcatSource} rendered chunk modules in a Source object + */ + static renderChunkModules( + chunk, + filterFn, + moduleTemplate, + dependencyTemplates, + prefix = "" + ) { + const source = new ConcatSource(); + const modules = chunk.getModules().filter(filterFn); + let removedModules; + if (chunk instanceof HotUpdateChunk) { + removedModules = chunk.removedModules; + } + if ( + modules.length === 0 && + (!removedModules || removedModules.length === 0) + ) { + source.add("[]"); + return source; + } + /** @type {{id: string|number, source: Source|string}[]} */ + const allModules = modules.map(module => { + return { + id: module.id, + source: moduleTemplate.render(module, dependencyTemplates, { + chunk + }) + }; + }); + if (removedModules && removedModules.length > 0) { + for (const id of removedModules) { + allModules.push({ + id, + source: "false" + }); + } + } + const bounds = Template.getModulesArrayBounds(allModules); + if (bounds) { + // Render a spare array + const minId = bounds[0]; + const maxId = bounds[1]; + if (minId !== 0) { + source.add(`Array(${minId}).concat(`); + } + source.add("[\n"); + const modules = new Map(); + for (const module of allModules) { + modules.set(module.id, module); + } + for (let idx = minId; idx <= maxId; idx++) { + const module = modules.get(idx); + if (idx !== minId) { + source.add(",\n"); + } + source.add(`/* ${idx} */`); + if (module) { + source.add("\n"); + source.add(module.source); + } + } + source.add("\n" + prefix + "]"); + if (minId !== 0) { + source.add(")"); + } + } else { + // Render an object + source.add("{\n"); + allModules.sort(stringifyIdSortPredicate).forEach((module, idx) => { + if (idx !== 0) { + source.add(",\n"); + } + source.add(`\n/***/ ${JSON.stringify(module.id)}:\n`); + source.add(module.source); + }); + source.add(`\n\n${prefix}}`); + } + return source; + } +} + +module.exports = Template; diff --git a/node_modules/webpack/lib/TemplatedPathPlugin.js b/node_modules/webpack/lib/TemplatedPathPlugin.js index 6c8a2addd..8cd1ef40a 100644 --- a/node_modules/webpack/lib/TemplatedPathPlugin.js +++ b/node_modules/webpack/lib/TemplatedPathPlugin.js @@ -1,112 +1,173 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Jason Anderson @diurnalist -*/ -"use strict"; - -const REGEXP_HASH = /\[hash(?::(\d+))?\]/gi, - REGEXP_CHUNKHASH = /\[chunkhash(?::(\d+))?\]/gi, - REGEXP_NAME = /\[name\]/gi, - REGEXP_ID = /\[id\]/gi, - REGEXP_FILE = /\[file\]/gi, - REGEXP_QUERY = /\[query\]/gi, - REGEXP_FILEBASE = /\[filebase\]/gi; - -// Using global RegExp for .test is dangerous -// We use a normal RegExp instead of .test -const REGEXP_HASH_FOR_TEST = new RegExp(REGEXP_HASH.source, "i"), - REGEXP_CHUNKHASH_FOR_TEST = new RegExp(REGEXP_CHUNKHASH.source, "i"), - REGEXP_NAME_FOR_TEST = new RegExp(REGEXP_NAME.source, "i"); - -// TODO: remove in webpack 3 -// Backwards compatibility; expose regexes on Template object -const Template = require("./Template"); -Template.REGEXP_HASH = REGEXP_HASH; -Template.REGEXP_CHUNKHASH = REGEXP_CHUNKHASH; -Template.REGEXP_NAME = REGEXP_NAME; -Template.REGEXP_ID = REGEXP_ID; -Template.REGEXP_FILE = REGEXP_FILE; -Template.REGEXP_QUERY = REGEXP_QUERY; -Template.REGEXP_FILEBASE = REGEXP_FILEBASE; - -const withHashLength = (replacer, handlerFn) => { - return function(_, hashLength) { - const length = hashLength && parseInt(hashLength, 10); - if(length && handlerFn) { - return handlerFn(length); - } - const hash = replacer.apply(this, arguments); - return length ? hash.slice(0, length) : hash; - }; -}; - -const getReplacer = (value, allowEmpty) => { - return function(match) { - // last argument in replacer is the entire input string - const input = arguments[arguments.length - 1]; - if(value === null || value === undefined) { - if(!allowEmpty) throw new Error(`Path variable ${match} not implemented in this context: ${input}`); - return ""; - } else { - return `${value}`; - } - }; -}; - -const replacePathVariables = (path, data) => { - const chunk = data.chunk; - const chunkId = chunk && chunk.id; - const chunkName = chunk && (chunk.name || chunk.id); - const chunkHash = chunk && (chunk.renderedHash || chunk.hash); - const chunkHashWithLength = chunk && chunk.hashWithLength; - - if(data.noChunkHash && REGEXP_CHUNKHASH_FOR_TEST.test(path)) { - throw new Error(`Cannot use [chunkhash] for chunk in '${path}' (use [hash] instead)`); - } - - return path - .replace(REGEXP_HASH, withHashLength(getReplacer(data.hash), data.hashWithLength)) - .replace(REGEXP_CHUNKHASH, withHashLength(getReplacer(chunkHash), chunkHashWithLength)) - .replace(REGEXP_ID, getReplacer(chunkId)) - .replace(REGEXP_NAME, getReplacer(chunkName)) - .replace(REGEXP_FILE, getReplacer(data.filename)) - .replace(REGEXP_FILEBASE, getReplacer(data.basename)) - // query is optional, it's OK if it's in a path but there's nothing to replace it with - .replace(REGEXP_QUERY, getReplacer(data.query, true)); -}; - -class TemplatedPathPlugin { - apply(compiler) { - compiler.plugin("compilation", compilation => { - const mainTemplate = compilation.mainTemplate; - - mainTemplate.plugin("asset-path", replacePathVariables); - - mainTemplate.plugin("global-hash", function(chunk, paths) { - const outputOptions = this.outputOptions; - const publicPath = outputOptions.publicPath || ""; - const filename = outputOptions.filename || ""; - const chunkFilename = outputOptions.chunkFilename || outputOptions.filename; - if(REGEXP_HASH_FOR_TEST.test(publicPath) || REGEXP_CHUNKHASH_FOR_TEST.test(publicPath) || REGEXP_NAME_FOR_TEST.test(publicPath)) - return true; - if(REGEXP_HASH_FOR_TEST.test(filename)) - return true; - if(REGEXP_HASH_FOR_TEST.test(chunkFilename)) - return true; - if(REGEXP_HASH_FOR_TEST.test(paths.join("|"))) - return true; - }); - - mainTemplate.plugin("hash-for-chunk", function(hash, chunk) { - const outputOptions = this.outputOptions; - const chunkFilename = outputOptions.chunkFilename || outputOptions.filename; - if(REGEXP_CHUNKHASH_FOR_TEST.test(chunkFilename)) - hash.update(JSON.stringify(chunk.getChunkMaps(true, true).hash)); - if(REGEXP_NAME_FOR_TEST.test(chunkFilename)) - hash.update(JSON.stringify(chunk.getChunkMaps(true, true).name)); - }); - }); - } -} - -module.exports = TemplatedPathPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Jason Anderson @diurnalist +*/ +"use strict"; + +const REGEXP_HASH = /\[hash(?::(\d+))?\]/gi, + REGEXP_CHUNKHASH = /\[chunkhash(?::(\d+))?\]/gi, + REGEXP_MODULEHASH = /\[modulehash(?::(\d+))?\]/gi, + REGEXP_CONTENTHASH = /\[contenthash(?::(\d+))?\]/gi, + REGEXP_NAME = /\[name\]/gi, + REGEXP_ID = /\[id\]/gi, + REGEXP_MODULEID = /\[moduleid\]/gi, + REGEXP_FILE = /\[file\]/gi, + REGEXP_QUERY = /\[query\]/gi, + REGEXP_FILEBASE = /\[filebase\]/gi; + +// Using global RegExp for .test is dangerous +// We use a normal RegExp instead of .test +const REGEXP_HASH_FOR_TEST = new RegExp(REGEXP_HASH.source, "i"), + REGEXP_CHUNKHASH_FOR_TEST = new RegExp(REGEXP_CHUNKHASH.source, "i"), + REGEXP_CONTENTHASH_FOR_TEST = new RegExp(REGEXP_CONTENTHASH.source, "i"), + REGEXP_NAME_FOR_TEST = new RegExp(REGEXP_NAME.source, "i"); + +const withHashLength = (replacer, handlerFn) => { + const fn = (match, hashLength, ...args) => { + const length = hashLength && parseInt(hashLength, 10); + if (length && handlerFn) { + return handlerFn(length); + } + const hash = replacer(match, hashLength, ...args); + return length ? hash.slice(0, length) : hash; + }; + return fn; +}; + +const getReplacer = (value, allowEmpty) => { + const fn = (match, ...args) => { + // last argument in replacer is the entire input string + const input = args[args.length - 1]; + if (value === null || value === undefined) { + if (!allowEmpty) { + throw new Error( + `Path variable ${match} not implemented in this context: ${input}` + ); + } + return ""; + } else { + return `${value}`; + } + }; + return fn; +}; + +const replacePathVariables = (path, data) => { + const chunk = data.chunk; + const chunkId = chunk && chunk.id; + const chunkName = chunk && (chunk.name || chunk.id); + const chunkHash = chunk && (chunk.renderedHash || chunk.hash); + const chunkHashWithLength = chunk && chunk.hashWithLength; + const contentHashType = data.contentHashType; + const contentHash = + (chunk && chunk.contentHash && chunk.contentHash[contentHashType]) || + data.contentHash; + const contentHashWithLength = + (chunk && + chunk.contentHashWithLength && + chunk.contentHashWithLength[contentHashType]) || + data.contentHashWithLength; + const module = data.module; + const moduleId = module && module.id; + const moduleHash = module && (module.renderedHash || module.hash); + const moduleHashWithLength = module && module.hashWithLength; + + if (typeof path === "function") { + path = path(data); + } + + if ( + data.noChunkHash && + (REGEXP_CHUNKHASH_FOR_TEST.test(path) || + REGEXP_CONTENTHASH_FOR_TEST.test(path)) + ) { + throw new Error( + `Cannot use [chunkhash] or [contenthash] for chunk in '${path}' (use [hash] instead)` + ); + } + + return ( + path + .replace( + REGEXP_HASH, + withHashLength(getReplacer(data.hash), data.hashWithLength) + ) + .replace( + REGEXP_CHUNKHASH, + withHashLength(getReplacer(chunkHash), chunkHashWithLength) + ) + .replace( + REGEXP_CONTENTHASH, + withHashLength(getReplacer(contentHash), contentHashWithLength) + ) + .replace( + REGEXP_MODULEHASH, + withHashLength(getReplacer(moduleHash), moduleHashWithLength) + ) + .replace(REGEXP_ID, getReplacer(chunkId)) + .replace(REGEXP_MODULEID, getReplacer(moduleId)) + .replace(REGEXP_NAME, getReplacer(chunkName)) + .replace(REGEXP_FILE, getReplacer(data.filename)) + .replace(REGEXP_FILEBASE, getReplacer(data.basename)) + // query is optional, it's OK if it's in a path but there's nothing to replace it with + .replace(REGEXP_QUERY, getReplacer(data.query, true)) + ); +}; + +class TemplatedPathPlugin { + apply(compiler) { + compiler.hooks.compilation.tap("TemplatedPathPlugin", compilation => { + const mainTemplate = compilation.mainTemplate; + + mainTemplate.hooks.assetPath.tap( + "TemplatedPathPlugin", + replacePathVariables + ); + + mainTemplate.hooks.globalHash.tap( + "TemplatedPathPlugin", + (chunk, paths) => { + const outputOptions = mainTemplate.outputOptions; + const publicPath = outputOptions.publicPath || ""; + const filename = outputOptions.filename || ""; + const chunkFilename = + outputOptions.chunkFilename || outputOptions.filename; + if ( + REGEXP_HASH_FOR_TEST.test(publicPath) || + REGEXP_CHUNKHASH_FOR_TEST.test(publicPath) || + REGEXP_CONTENTHASH_FOR_TEST.test(publicPath) || + REGEXP_NAME_FOR_TEST.test(publicPath) + ) + return true; + if (REGEXP_HASH_FOR_TEST.test(filename)) return true; + if (REGEXP_HASH_FOR_TEST.test(chunkFilename)) return true; + if (REGEXP_HASH_FOR_TEST.test(paths.join("|"))) return true; + } + ); + + mainTemplate.hooks.hashForChunk.tap( + "TemplatedPathPlugin", + (hash, chunk) => { + const outputOptions = mainTemplate.outputOptions; + const chunkFilename = + outputOptions.chunkFilename || outputOptions.filename; + if (REGEXP_CHUNKHASH_FOR_TEST.test(chunkFilename)) { + hash.update(JSON.stringify(chunk.getChunkMaps(true).hash)); + } + if (REGEXP_CONTENTHASH_FOR_TEST.test(chunkFilename)) { + hash.update( + JSON.stringify( + chunk.getChunkMaps(true).contentHash.javascript || {} + ) + ); + } + if (REGEXP_NAME_FOR_TEST.test(chunkFilename)) { + hash.update(JSON.stringify(chunk.getChunkMaps(true).name)); + } + } + ); + }); + } +} + +module.exports = TemplatedPathPlugin; diff --git a/node_modules/webpack/lib/UmdMainTemplatePlugin.js b/node_modules/webpack/lib/UmdMainTemplatePlugin.js index cc5179692..551ac76f8 100644 --- a/node_modules/webpack/lib/UmdMainTemplatePlugin.js +++ b/node_modules/webpack/lib/UmdMainTemplatePlugin.js @@ -1,191 +1,304 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ConcatSource = require("webpack-sources").ConcatSource; -const OriginalSource = require("webpack-sources").OriginalSource; -const Template = require("./Template"); - -function accessorToObjectAccess(accessor) { - return accessor.map(a => `[${JSON.stringify(a)}]`).join(""); -} - -function accessorAccess(base, accessor) { - accessor = [].concat(accessor); - return accessor.map((a, idx) => { - a = base + accessorToObjectAccess(accessor.slice(0, idx + 1)); - if(idx === accessor.length - 1) return a; - return `${a} = ${a} || {}`; - }).join(", "); -} - -class UmdMainTemplatePlugin { - constructor(name, options) { - if(typeof name === "object" && !Array.isArray(name)) { - this.name = name.root || name.amd || name.commonjs; - this.names = name; - } else { - this.name = name; - this.names = { - commonjs: name, - root: name, - amd: name - }; - } - this.optionalAmdExternalAsGlobal = options.optionalAmdExternalAsGlobal; - this.namedDefine = options.namedDefine; - this.auxiliaryComment = options.auxiliaryComment; - } - - apply(compilation) { - const mainTemplate = compilation.mainTemplate; - compilation.templatesPlugin("render-with-entry", (source, chunk, hash) => { - let externals = chunk.getModules().filter(m => m.external && (m.type === "umd" || m.type === "umd2")); - const optionalExternals = []; - let requiredExternals = []; - if(this.optionalAmdExternalAsGlobal) { - externals.forEach(m => { - if(m.optional) { - optionalExternals.push(m); - } else { - requiredExternals.push(m); - } - }); - externals = requiredExternals.concat(optionalExternals); - } else { - requiredExternals = externals; - } - - function replaceKeys(str) { - return mainTemplate.applyPluginsWaterfall("asset-path", str, { - hash, - chunk - }); - } - - function externalsDepsArray(modules) { - return `[${replaceKeys(modules.map(m => JSON.stringify(typeof m.request === "object" ? m.request.amd : m.request)).join(", "))}]`; - } - - function externalsRootArray(modules) { - return replaceKeys(modules.map(m => { - let request = m.request; - if(typeof request === "object") request = request.root; - return `root${accessorToObjectAccess([].concat(request))}`; - }).join(", ")); - } - - function externalsRequireArray(type) { - return replaceKeys(externals.map(m => { - let expr; - let request = m.request; - if(typeof request === "object") request = request[type]; - if(typeof request === "undefined") throw new Error("Missing external configuration for type:" + type); - if(Array.isArray(request)) { - expr = `require(${JSON.stringify(request[0])})${accessorToObjectAccess(request.slice(1))}`; - } else - expr = `require(${JSON.stringify(request)})`; - if(m.optional) { - expr = `(function webpackLoadOptionalExternalModule() { try { return ${expr}; } catch(e) {} }())`; - } - return expr; - }).join(", ")); - } - - function externalsArguments(modules) { - return modules.map(m => Template.toIdentifier(`__WEBPACK_EXTERNAL_MODULE_${m.id}__`)).join(", "); - } - - function libraryName(library) { - return JSON.stringify(replaceKeys([].concat(library).pop())); - } - - let amdFactory; - if(optionalExternals.length > 0) { - const wrapperArguments = externalsArguments(requiredExternals); - const factoryArguments = requiredExternals.length > 0 ? - externalsArguments(requiredExternals) + ", " + externalsRootArray(optionalExternals) : - externalsRootArray(optionalExternals); - amdFactory = `function webpackLoadOptionalExternalModuleAmd(${wrapperArguments}) {\n` + - ` return factory(${factoryArguments});\n` + - " }"; - } else { - amdFactory = "factory"; - } - - return new ConcatSource(new OriginalSource( - "(function webpackUniversalModuleDefinition(root, factory) {\n" + - (this.auxiliaryComment && - typeof this.auxiliaryComment === "string" ? - " //" + this.auxiliaryComment + "\n" : - this.auxiliaryComment.commonjs2 ? - " //" + this.auxiliaryComment.commonjs2 + "\n" : - "" - ) + - " if(typeof exports === 'object' && typeof module === 'object')\n" + - " module.exports = factory(" + externalsRequireArray("commonjs2") + ");\n" + - (this.auxiliaryComment && - typeof this.auxiliaryComment === "string" ? - " //" + this.auxiliaryComment + "\n" : - this.auxiliaryComment.amd ? - " //" + this.auxiliaryComment.amd + "\n" : - "" - ) + - " else if(typeof define === 'function' && define.amd)\n" + - (requiredExternals.length > 0 ? - (this.names.amd && this.namedDefine === true ? - " define(" + libraryName(this.names.amd) + ", " + externalsDepsArray(requiredExternals) + ", " + amdFactory + ");\n" : - " define(" + externalsDepsArray(requiredExternals) + ", " + amdFactory + ");\n" - ) : - (this.names.amd && this.namedDefine === true ? - " define(" + libraryName(this.names.amd) + ", [], " + amdFactory + ");\n" : - " define([], " + amdFactory + ");\n" - ) - ) + - (this.names.root || this.names.commonjs ? - (this.auxiliaryComment && - typeof this.auxiliaryComment === "string" ? - " //" + this.auxiliaryComment + "\n" : - this.auxiliaryComment.commonjs ? - " //" + this.auxiliaryComment.commonjs + "\n" : - "" - ) + - " else if(typeof exports === 'object')\n" + - " exports[" + libraryName(this.names.commonjs || this.names.root) + "] = factory(" + externalsRequireArray("commonjs") + ");\n" + - (this.auxiliaryComment && - typeof this.auxiliaryComment === "string" ? - " //" + this.auxiliaryComment + "\n" : - this.auxiliaryComment.root ? - " //" + this.auxiliaryComment.root + "\n" : - "" - ) + - " else\n" + - " " + replaceKeys(accessorAccess("root", this.names.root || this.names.commonjs)) + " = factory(" + externalsRootArray(externals) + ");\n" : - " else {\n" + - (externals.length > 0 ? - " var a = typeof exports === 'object' ? factory(" + externalsRequireArray("commonjs") + ") : factory(" + externalsRootArray(externals) + ");\n" : - " var a = factory();\n" - ) + - " for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];\n" + - " }\n" - ) + - "})(typeof self !== 'undefined' ? self : this, function(" + externalsArguments(externals) + ") {\nreturn ", "webpack/universalModuleDefinition"), source, ";\n})"); - }); - mainTemplate.plugin("global-hash-paths", (paths) => { - if(this.names.root) paths = paths.concat(this.names.root); - if(this.names.amd) paths = paths.concat(this.names.amd); - if(this.names.commonjs) paths = paths.concat(this.names.commonjs); - return paths; - }); - mainTemplate.plugin("hash", (hash) => { - hash.update("umd"); - hash.update(`${this.names.root}`); - hash.update(`${this.names.amd}`); - hash.update(`${this.names.commonjs}`); - }); - } -} - -module.exports = UmdMainTemplatePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const { ConcatSource, OriginalSource } = require("webpack-sources"); +const Template = require("./Template"); + +/** @typedef {import("./Compilation")} Compilation */ + +/** + * @param {string[]} accessor the accessor to convert to path + * @returns {string} the path + */ +const accessorToObjectAccess = accessor => { + return accessor.map(a => `[${JSON.stringify(a)}]`).join(""); +}; + +/** + * @param {string=} base the path prefix + * @param {string|string[]} accessor the accessor + * @param {string=} joinWith the element separator + * @returns {string} the path + */ +const accessorAccess = (base, accessor, joinWith = ", ") => { + const accessors = Array.isArray(accessor) ? accessor : [accessor]; + return accessors + .map((_, idx) => { + const a = base + ? base + accessorToObjectAccess(accessors.slice(0, idx + 1)) + : accessors[0] + accessorToObjectAccess(accessors.slice(1, idx + 1)); + if (idx === accessors.length - 1) return a; + if (idx === 0 && base === undefined) + return `${a} = typeof ${a} === "object" ? ${a} : {}`; + return `${a} = ${a} || {}`; + }) + .join(joinWith); +}; + +/** @typedef {string | string[] | Record} UmdMainTemplatePluginName */ + +/** + * @typedef {Object} AuxiliaryCommentObject + * @property {string} root + * @property {string} commonjs + * @property {string} commonjs2 + * @property {string} amd + */ + +/** + * @typedef {Object} UmdMainTemplatePluginOption + * @property {boolean=} optionalAmdExternalAsGlobal + * @property {boolean} namedDefine + * @property {string | AuxiliaryCommentObject} auxiliaryComment + */ + +class UmdMainTemplatePlugin { + /** + * @param {UmdMainTemplatePluginName} name the name of the UMD library + * @param {UmdMainTemplatePluginOption} options the plugin option + */ + constructor(name, options) { + if (typeof name === "object" && !Array.isArray(name)) { + this.name = name.root || name.amd || name.commonjs; + this.names = name; + } else { + this.name = name; + this.names = { + commonjs: name, + root: name, + amd: name + }; + } + this.optionalAmdExternalAsGlobal = options.optionalAmdExternalAsGlobal; + this.namedDefine = options.namedDefine; + this.auxiliaryComment = options.auxiliaryComment; + } + + /** + * @param {Compilation} compilation the compilation instance + * @returns {void} + */ + apply(compilation) { + const { mainTemplate, chunkTemplate, runtimeTemplate } = compilation; + + const onRenderWithEntry = (source, chunk, hash) => { + let externals = chunk + .getModules() + .filter( + m => + m.external && + (m.externalType === "umd" || m.externalType === "umd2") + ); + const optionalExternals = []; + let requiredExternals = []; + if (this.optionalAmdExternalAsGlobal) { + for (const m of externals) { + if (m.optional) { + optionalExternals.push(m); + } else { + requiredExternals.push(m); + } + } + externals = requiredExternals.concat(optionalExternals); + } else { + requiredExternals = externals; + } + + const replaceKeys = str => { + return mainTemplate.getAssetPath(str, { + hash, + chunk + }); + }; + + const externalsDepsArray = modules => { + return `[${replaceKeys( + modules + .map(m => + JSON.stringify( + typeof m.request === "object" ? m.request.amd : m.request + ) + ) + .join(", ") + )}]`; + }; + + const externalsRootArray = modules => { + return replaceKeys( + modules + .map(m => { + let request = m.request; + if (typeof request === "object") request = request.root; + return `root${accessorToObjectAccess([].concat(request))}`; + }) + .join(", ") + ); + }; + + const externalsRequireArray = type => { + return replaceKeys( + externals + .map(m => { + let expr; + let request = m.request; + if (typeof request === "object") { + request = request[type]; + } + if (request === undefined) { + throw new Error( + "Missing external configuration for type:" + type + ); + } + if (Array.isArray(request)) { + expr = `require(${JSON.stringify( + request[0] + )})${accessorToObjectAccess(request.slice(1))}`; + } else { + expr = `require(${JSON.stringify(request)})`; + } + if (m.optional) { + expr = `(function webpackLoadOptionalExternalModule() { try { return ${expr}; } catch(e) {} }())`; + } + return expr; + }) + .join(", ") + ); + }; + + const externalsArguments = modules => { + return modules + .map( + m => + `__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(`${m.id}`)}__` + ) + .join(", "); + }; + + const libraryName = library => { + return JSON.stringify(replaceKeys([].concat(library).pop())); + }; + + let amdFactory; + if (optionalExternals.length > 0) { + const wrapperArguments = externalsArguments(requiredExternals); + const factoryArguments = + requiredExternals.length > 0 + ? externalsArguments(requiredExternals) + + ", " + + externalsRootArray(optionalExternals) + : externalsRootArray(optionalExternals); + amdFactory = + `function webpackLoadOptionalExternalModuleAmd(${wrapperArguments}) {\n` + + ` return factory(${factoryArguments});\n` + + " }"; + } else { + amdFactory = "factory"; + } + + const auxiliaryComment = this.auxiliaryComment; + + const getAuxilaryComment = type => { + if (auxiliaryComment) { + if (typeof auxiliaryComment === "string") + return "\t//" + auxiliaryComment + "\n"; + if (auxiliaryComment[type]) + return "\t//" + auxiliaryComment[type] + "\n"; + } + return ""; + }; + + return new ConcatSource( + new OriginalSource( + "(function webpackUniversalModuleDefinition(root, factory) {\n" + + getAuxilaryComment("commonjs2") + + " if(typeof exports === 'object' && typeof module === 'object')\n" + + " module.exports = factory(" + + externalsRequireArray("commonjs2") + + ");\n" + + getAuxilaryComment("amd") + + " else if(typeof define === 'function' && define.amd)\n" + + (requiredExternals.length > 0 + ? this.names.amd && this.namedDefine === true + ? " define(" + + libraryName(this.names.amd) + + ", " + + externalsDepsArray(requiredExternals) + + ", " + + amdFactory + + ");\n" + : " define(" + + externalsDepsArray(requiredExternals) + + ", " + + amdFactory + + ");\n" + : this.names.amd && this.namedDefine === true + ? " define(" + + libraryName(this.names.amd) + + ", [], " + + amdFactory + + ");\n" + : " define([], " + amdFactory + ");\n") + + (this.names.root || this.names.commonjs + ? getAuxilaryComment("commonjs") + + " else if(typeof exports === 'object')\n" + + " exports[" + + libraryName(this.names.commonjs || this.names.root) + + "] = factory(" + + externalsRequireArray("commonjs") + + ");\n" + + getAuxilaryComment("root") + + " else\n" + + " " + + replaceKeys( + accessorAccess("root", this.names.root || this.names.commonjs) + ) + + " = factory(" + + externalsRootArray(externals) + + ");\n" + : " else {\n" + + (externals.length > 0 + ? " var a = typeof exports === 'object' ? factory(" + + externalsRequireArray("commonjs") + + ") : factory(" + + externalsRootArray(externals) + + ");\n" + : " var a = factory();\n") + + " for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];\n" + + " }\n") + + `})(${ + runtimeTemplate.outputOptions.globalObject + }, function(${externalsArguments(externals)}) {\nreturn `, + "webpack/universalModuleDefinition" + ), + source, + ";\n})" + ); + }; + + for (const template of [mainTemplate, chunkTemplate]) { + template.hooks.renderWithEntry.tap( + "UmdMainTemplatePlugin", + onRenderWithEntry + ); + } + + mainTemplate.hooks.globalHashPaths.tap("UmdMainTemplatePlugin", paths => { + if (this.names.root) paths = paths.concat(this.names.root); + if (this.names.amd) paths = paths.concat(this.names.amd); + if (this.names.commonjs) paths = paths.concat(this.names.commonjs); + return paths; + }); + + mainTemplate.hooks.hash.tap("UmdMainTemplatePlugin", hash => { + hash.update("umd"); + hash.update(`${this.names.root}`); + hash.update(`${this.names.amd}`); + hash.update(`${this.names.commonjs}`); + }); + } +} + +module.exports = UmdMainTemplatePlugin; diff --git a/node_modules/webpack/lib/UnsupportedFeatureWarning.js b/node_modules/webpack/lib/UnsupportedFeatureWarning.js index d2b270336..72eef834e 100644 --- a/node_modules/webpack/lib/UnsupportedFeatureWarning.js +++ b/node_modules/webpack/lib/UnsupportedFeatureWarning.js @@ -1,21 +1,30 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const WebpackError = require("./WebpackError"); - -class UnsupportedFeatureWarning extends WebpackError { - constructor(module, message) { - super(); - - this.name = "UnsupportedFeatureWarning"; - this.message = message; - this.origin = this.module = module; - - Error.captureStackTrace(this, this.constructor); - } -} - -module.exports = UnsupportedFeatureWarning; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const WebpackError = require("./WebpackError"); + +/** @typedef {import("./Module")} Module */ +/** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */ + +class UnsupportedFeatureWarning extends WebpackError { + /** + * @param {Module} module module relevant to warning + * @param {string} message description of warning + * @param {DependencyLocation} loc location start and end positions of the module + */ + constructor(module, message, loc) { + super(message); + + this.name = "UnsupportedFeatureWarning"; + this.module = module; + this.loc = loc; + this.hideStack = true; + + Error.captureStackTrace(this, this.constructor); + } +} + +module.exports = UnsupportedFeatureWarning; diff --git a/node_modules/webpack/lib/UseStrictPlugin.js b/node_modules/webpack/lib/UseStrictPlugin.js index 2135839cf..425be2e31 100644 --- a/node_modules/webpack/lib/UseStrictPlugin.js +++ b/node_modules/webpack/lib/UseStrictPlugin.js @@ -1,34 +1,54 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ConstDependency = require("./dependencies/ConstDependency"); - -class UseStrictPlugin { - apply(compiler) { - compiler.plugin("compilation", (compilation, params) => { - params.normalModuleFactory.plugin("parser", (parser) => { - const parserInstance = parser; - parser.plugin("program", (ast) => { - const firstNode = ast.body[0]; - if(firstNode && - firstNode.type === "ExpressionStatement" && - firstNode.expression.type === "Literal" && - firstNode.expression.value === "use strict") { - // Remove "use strict" expression. It will be added later by the renderer again. - // This is necessary in order to not break the strict mode when webpack prepends code. - // @see https://github.com/webpack/webpack/issues/1970 - const dep = new ConstDependency("", firstNode.range); - dep.loc = firstNode.loc; - parserInstance.state.current.addDependency(dep); - parserInstance.state.module.strict = true; - } - }); - }); - }); - } -} - -module.exports = UseStrictPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const ConstDependency = require("./dependencies/ConstDependency"); + +/** @typedef {import("./Compiler")} Compiler */ + +class UseStrictPlugin { + /** + * @param {Compiler} compiler Webpack Compiler + * @returns {void} + */ + apply(compiler) { + compiler.hooks.compilation.tap( + "UseStrictPlugin", + (compilation, { normalModuleFactory }) => { + const handler = parser => { + parser.hooks.program.tap("UseStrictPlugin", ast => { + const firstNode = ast.body[0]; + if ( + firstNode && + firstNode.type === "ExpressionStatement" && + firstNode.expression.type === "Literal" && + firstNode.expression.value === "use strict" + ) { + // Remove "use strict" expression. It will be added later by the renderer again. + // This is necessary in order to not break the strict mode when webpack prepends code. + // @see https://github.com/webpack/webpack/issues/1970 + const dep = new ConstDependency("", firstNode.range); + dep.loc = firstNode.loc; + parser.state.current.addDependency(dep); + parser.state.module.buildInfo.strict = true; + } + }); + }; + + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("UseStrictPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("UseStrictPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/esm") + .tap("UseStrictPlugin", handler); + } + ); + } +} + +module.exports = UseStrictPlugin; diff --git a/node_modules/webpack/lib/WarnCaseSensitiveModulesPlugin.js b/node_modules/webpack/lib/WarnCaseSensitiveModulesPlugin.js index 54edb4ac7..867a33fe3 100644 --- a/node_modules/webpack/lib/WarnCaseSensitiveModulesPlugin.js +++ b/node_modules/webpack/lib/WarnCaseSensitiveModulesPlugin.js @@ -1,31 +1,37 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const CaseSensitiveModulesWarning = require("./CaseSensitiveModulesWarning"); - -class WarnCaseSensitiveModulesPlugin { - apply(compiler) { - compiler.plugin("compilation", compilation => { - compilation.plugin("seal", () => { - const moduleWithoutCase = Object.create(null); - compilation.modules.forEach(module => { - const identifier = module.identifier().toLowerCase(); - if(moduleWithoutCase[identifier]) { - moduleWithoutCase[identifier].push(module); - } else { - moduleWithoutCase[identifier] = [module]; - } - }); - Object.keys(moduleWithoutCase).forEach(key => { - if(moduleWithoutCase[key].length > 1) - compilation.warnings.push(new CaseSensitiveModulesWarning(moduleWithoutCase[key])); - }); - }); - }); - } -} - -module.exports = WarnCaseSensitiveModulesPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const CaseSensitiveModulesWarning = require("./CaseSensitiveModulesWarning"); + +class WarnCaseSensitiveModulesPlugin { + apply(compiler) { + compiler.hooks.compilation.tap( + "WarnCaseSensitiveModulesPlugin", + compilation => { + compilation.hooks.seal.tap("WarnCaseSensitiveModulesPlugin", () => { + const moduleWithoutCase = new Map(); + for (const module of compilation.modules) { + const identifier = module.identifier().toLowerCase(); + const array = moduleWithoutCase.get(identifier); + if (array) { + array.push(module); + } else { + moduleWithoutCase.set(identifier, [module]); + } + } + for (const pair of moduleWithoutCase) { + const array = pair[1]; + if (array.length > 1) { + compilation.warnings.push(new CaseSensitiveModulesWarning(array)); + } + } + }); + } + ); + } +} + +module.exports = WarnCaseSensitiveModulesPlugin; diff --git a/node_modules/webpack/lib/WatchIgnorePlugin.js b/node_modules/webpack/lib/WatchIgnorePlugin.js index 9b74b3c20..2f81ee839 100644 --- a/node_modules/webpack/lib/WatchIgnorePlugin.js +++ b/node_modules/webpack/lib/WatchIgnorePlugin.js @@ -1,49 +1,100 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class WatchIgnorePlugin { - constructor(paths) { - this.paths = paths; - } - - apply(compiler) { - compiler.plugin("after-environment", () => { - compiler.watchFileSystem = new IgnoringWatchFileSystem(compiler.watchFileSystem, this.paths); - }); - } -} - -module.exports = WatchIgnorePlugin; - -class IgnoringWatchFileSystem { - constructor(wfs, paths) { - this.wfs = wfs; - this.paths = paths; - } - - watch(files, dirs, missing, startTime, options, callback, callbackUndelayed) { - const ignored = path => this.paths.some(p => p instanceof RegExp ? p.test(path) : path.indexOf(p) === 0); - - const notIgnored = path => !ignored(path); - - const ignoredFiles = files.filter(ignored); - const ignoredDirs = dirs.filter(ignored); - - this.wfs.watch(files.filter(notIgnored), dirs.filter(notIgnored), missing, startTime, options, (err, filesModified, dirsModified, missingModified, fileTimestamps, dirTimestamps) => { - if(err) return callback(err); - - ignoredFiles.forEach(path => { - fileTimestamps[path] = 1; - }); - - ignoredDirs.forEach(path => { - dirTimestamps[path] = 1; - }); - - callback(err, filesModified, dirsModified, missingModified, fileTimestamps, dirTimestamps); - }, callbackUndelayed); - } -} +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const validateOptions = require("schema-utils"); +const schema = require("../schemas/plugins/WatchIgnorePlugin.json"); + +class IgnoringWatchFileSystem { + constructor(wfs, paths) { + this.wfs = wfs; + this.paths = paths; + } + + watch(files, dirs, missing, startTime, options, callback, callbackUndelayed) { + const ignored = path => + this.paths.some( + p => (p instanceof RegExp ? p.test(path) : path.indexOf(p) === 0) + ); + + const notIgnored = path => !ignored(path); + + const ignoredFiles = files.filter(ignored); + const ignoredDirs = dirs.filter(ignored); + + const watcher = this.wfs.watch( + files.filter(notIgnored), + dirs.filter(notIgnored), + missing, + startTime, + options, + ( + err, + filesModified, + dirsModified, + missingModified, + fileTimestamps, + dirTimestamps + ) => { + if (err) return callback(err); + + for (const path of ignoredFiles) { + fileTimestamps.set(path, 1); + } + + for (const path of ignoredDirs) { + dirTimestamps.set(path, 1); + } + + callback( + err, + filesModified, + dirsModified, + missingModified, + fileTimestamps, + dirTimestamps + ); + }, + callbackUndelayed + ); + + return { + close: () => watcher.close(), + pause: () => watcher.pause(), + getContextTimestamps: () => { + const dirTimestamps = watcher.getContextTimestamps(); + for (const path of ignoredDirs) { + dirTimestamps.set(path, 1); + } + return dirTimestamps; + }, + getFileTimestamps: () => { + const fileTimestamps = watcher.getFileTimestamps(); + for (const path of ignoredFiles) { + fileTimestamps.set(path, 1); + } + return fileTimestamps; + } + }; + } +} + +class WatchIgnorePlugin { + constructor(paths) { + validateOptions(schema, paths, "Watch Ignore Plugin"); + this.paths = paths; + } + + apply(compiler) { + compiler.hooks.afterEnvironment.tap("WatchIgnorePlugin", () => { + compiler.watchFileSystem = new IgnoringWatchFileSystem( + compiler.watchFileSystem, + this.paths + ); + }); + } +} + +module.exports = WatchIgnorePlugin; diff --git a/node_modules/webpack/lib/WebpackError.js b/node_modules/webpack/lib/WebpackError.js index abd716a63..891809a67 100644 --- a/node_modules/webpack/lib/WebpackError.js +++ b/node_modules/webpack/lib/WebpackError.js @@ -1,11 +1,29 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Jarid Margolin @jaridmargolin -*/ -"use strict"; - -module.exports = class WebpackError extends Error { - inspect() { - return this.stack + (this.details ? `\n${this.details}` : ""); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Jarid Margolin @jaridmargolin +*/ +"use strict"; + +class WebpackError extends Error { + /** + * Creates an instance of WebpackError. + * @param {string=} message error message + */ + constructor(message) { + super(message); + + this.details = undefined; + this.missing = undefined; + this.origin = undefined; + this.dependencies = undefined; + this.module = undefined; + + Error.captureStackTrace(this, this.constructor); + } + + inspect() { + return this.stack + (this.details ? `\n${this.details}` : ""); + } +} + +module.exports = WebpackError; diff --git a/node_modules/webpack/lib/WebpackOptionsApply.js b/node_modules/webpack/lib/WebpackOptionsApply.js index ebddba717..2456a7bd7 100644 --- a/node_modules/webpack/lib/WebpackOptionsApply.js +++ b/node_modules/webpack/lib/WebpackOptionsApply.js @@ -1,298 +1,519 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const OptionsApply = require("./OptionsApply"); - -const LoaderTargetPlugin = require("./LoaderTargetPlugin"); -const FunctionModulePlugin = require("./FunctionModulePlugin"); -const EvalDevToolModulePlugin = require("./EvalDevToolModulePlugin"); -const SourceMapDevToolPlugin = require("./SourceMapDevToolPlugin"); -const EvalSourceMapDevToolPlugin = require("./EvalSourceMapDevToolPlugin"); - -const EntryOptionPlugin = require("./EntryOptionPlugin"); -const RecordIdsPlugin = require("./RecordIdsPlugin"); - -const APIPlugin = require("./APIPlugin"); -const ConstPlugin = require("./ConstPlugin"); -const RequireJsStuffPlugin = require("./RequireJsStuffPlugin"); -const NodeStuffPlugin = require("./NodeStuffPlugin"); -const CompatibilityPlugin = require("./CompatibilityPlugin"); - -const TemplatedPathPlugin = require("./TemplatedPathPlugin"); -const WarnCaseSensitiveModulesPlugin = require("./WarnCaseSensitiveModulesPlugin"); -const UseStrictPlugin = require("./UseStrictPlugin"); - -const LoaderPlugin = require("./dependencies/LoaderPlugin"); -const CommonJsPlugin = require("./dependencies/CommonJsPlugin"); -const HarmonyModulesPlugin = require("./dependencies/HarmonyModulesPlugin"); -const SystemPlugin = require("./dependencies/SystemPlugin"); -const ImportPlugin = require("./dependencies/ImportPlugin"); -const AMDPlugin = require("./dependencies/AMDPlugin"); -const RequireContextPlugin = require("./dependencies/RequireContextPlugin"); -const RequireEnsurePlugin = require("./dependencies/RequireEnsurePlugin"); -const RequireIncludePlugin = require("./dependencies/RequireIncludePlugin"); - -const EnsureChunkConditionsPlugin = require("./optimize/EnsureChunkConditionsPlugin"); -const RemoveParentModulesPlugin = require("./optimize/RemoveParentModulesPlugin"); -const RemoveEmptyChunksPlugin = require("./optimize/RemoveEmptyChunksPlugin"); -const MergeDuplicateChunksPlugin = require("./optimize/MergeDuplicateChunksPlugin"); -const FlagIncludedChunksPlugin = require("./optimize/FlagIncludedChunksPlugin"); -const OccurrenceOrderPlugin = require("./optimize/OccurrenceOrderPlugin"); -const FlagDependencyUsagePlugin = require("./FlagDependencyUsagePlugin"); -const FlagDependencyExportsPlugin = require("./FlagDependencyExportsPlugin"); -const SizeLimitsPlugin = require("./performance/SizeLimitsPlugin"); - -const ResolverFactory = require("enhanced-resolve").ResolverFactory; - -class WebpackOptionsApply extends OptionsApply { - constructor() { - super(); - } - - process(options, compiler) { - let ExternalsPlugin; - compiler.outputPath = options.output.path; - compiler.recordsInputPath = options.recordsInputPath || options.recordsPath; - compiler.recordsOutputPath = options.recordsOutputPath || options.recordsPath; - compiler.name = options.name; - compiler.dependencies = options.dependencies; - if(typeof options.target === "string") { - let JsonpTemplatePlugin; - let NodeSourcePlugin; - let NodeTargetPlugin; - let NodeTemplatePlugin; - - switch(options.target) { - case "web": - JsonpTemplatePlugin = require("./JsonpTemplatePlugin"); - NodeSourcePlugin = require("./node/NodeSourcePlugin"); - compiler.apply( - new JsonpTemplatePlugin(options.output), - new FunctionModulePlugin(options.output), - new NodeSourcePlugin(options.node), - new LoaderTargetPlugin(options.target) - ); - break; - case "webworker": - { - let WebWorkerTemplatePlugin = require("./webworker/WebWorkerTemplatePlugin"); - NodeSourcePlugin = require("./node/NodeSourcePlugin"); - compiler.apply( - new WebWorkerTemplatePlugin(), - new FunctionModulePlugin(options.output), - new NodeSourcePlugin(options.node), - new LoaderTargetPlugin(options.target) - ); - break; - } - case "node": - case "async-node": - NodeTemplatePlugin = require("./node/NodeTemplatePlugin"); - NodeTargetPlugin = require("./node/NodeTargetPlugin"); - compiler.apply( - new NodeTemplatePlugin({ - asyncChunkLoading: options.target === "async-node" - }), - new FunctionModulePlugin(options.output), - new NodeTargetPlugin(), - new LoaderTargetPlugin("node") - ); - break; - case "node-webkit": - JsonpTemplatePlugin = require("./JsonpTemplatePlugin"); - NodeTargetPlugin = require("./node/NodeTargetPlugin"); - ExternalsPlugin = require("./ExternalsPlugin"); - compiler.apply( - new JsonpTemplatePlugin(options.output), - new FunctionModulePlugin(options.output), - new NodeTargetPlugin(), - new ExternalsPlugin("commonjs", "nw.gui"), - new LoaderTargetPlugin(options.target) - ); - break; - case "atom": - case "electron": - case "electron-main": - NodeTemplatePlugin = require("./node/NodeTemplatePlugin"); - NodeTargetPlugin = require("./node/NodeTargetPlugin"); - ExternalsPlugin = require("./ExternalsPlugin"); - compiler.apply( - new NodeTemplatePlugin({ - asyncChunkLoading: true - }), - new FunctionModulePlugin(options.output), - new NodeTargetPlugin(), - new ExternalsPlugin("commonjs", [ - "app", - "auto-updater", - "browser-window", - "content-tracing", - "dialog", - "electron", - "global-shortcut", - "ipc", - "ipc-main", - "menu", - "menu-item", - "power-monitor", - "power-save-blocker", - "protocol", - "session", - "web-contents", - "tray", - "clipboard", - "crash-reporter", - "native-image", - "screen", - "shell" - ]), - new LoaderTargetPlugin(options.target) - ); - break; - case "electron-renderer": - JsonpTemplatePlugin = require("./JsonpTemplatePlugin"); - NodeTargetPlugin = require("./node/NodeTargetPlugin"); - ExternalsPlugin = require("./ExternalsPlugin"); - compiler.apply( - new JsonpTemplatePlugin(options.output), - new FunctionModulePlugin(options.output), - new NodeTargetPlugin(), - new ExternalsPlugin("commonjs", [ - "desktop-capturer", - "electron", - "ipc", - "ipc-renderer", - "remote", - "web-frame", - "clipboard", - "crash-reporter", - "native-image", - "screen", - "shell" - ]), - new LoaderTargetPlugin(options.target) - ); - break; - default: - throw new Error("Unsupported target '" + options.target + "'."); - } - } else if(options.target !== false) { - options.target(compiler); - } else { - throw new Error("Unsupported target '" + options.target + "'."); - } - - if(options.output.library || options.output.libraryTarget !== "var") { - let LibraryTemplatePlugin = require("./LibraryTemplatePlugin"); - compiler.apply(new LibraryTemplatePlugin(options.output.library, options.output.libraryTarget, options.output.umdNamedDefine, options.output.auxiliaryComment || "", options.output.libraryExport)); - } - if(options.externals) { - ExternalsPlugin = require("./ExternalsPlugin"); - compiler.apply(new ExternalsPlugin(options.output.libraryTarget, options.externals)); - } - let noSources; - let legacy; - let modern; - let comment; - if(options.devtool && (options.devtool.indexOf("sourcemap") >= 0 || options.devtool.indexOf("source-map") >= 0)) { - const hidden = options.devtool.indexOf("hidden") >= 0; - const inline = options.devtool.indexOf("inline") >= 0; - const evalWrapped = options.devtool.indexOf("eval") >= 0; - const cheap = options.devtool.indexOf("cheap") >= 0; - const moduleMaps = options.devtool.indexOf("module") >= 0; - noSources = options.devtool.indexOf("nosources") >= 0; - legacy = options.devtool.indexOf("@") >= 0; - modern = options.devtool.indexOf("#") >= 0; - comment = legacy && modern ? "\n/*\n//@ source" + "MappingURL=[url]\n//# source" + "MappingURL=[url]\n*/" : - legacy ? "\n/*\n//@ source" + "MappingURL=[url]\n*/" : - modern ? "\n//# source" + "MappingURL=[url]" : - null; - let Plugin = evalWrapped ? EvalSourceMapDevToolPlugin : SourceMapDevToolPlugin; - compiler.apply(new Plugin({ - filename: inline ? null : options.output.sourceMapFilename, - moduleFilenameTemplate: options.output.devtoolModuleFilenameTemplate, - fallbackModuleFilenameTemplate: options.output.devtoolFallbackModuleFilenameTemplate, - append: hidden ? false : comment, - module: moduleMaps ? true : cheap ? false : true, - columns: cheap ? false : true, - lineToLine: options.output.devtoolLineToLine, - noSources: noSources, - })); - } else if(options.devtool && options.devtool.indexOf("eval") >= 0) { - legacy = options.devtool.indexOf("@") >= 0; - modern = options.devtool.indexOf("#") >= 0; - comment = legacy && modern ? "\n//@ sourceURL=[url]\n//# sourceURL=[url]" : - legacy ? "\n//@ sourceURL=[url]" : - modern ? "\n//# sourceURL=[url]" : - null; - compiler.apply(new EvalDevToolModulePlugin(comment, options.output.devtoolModuleFilenameTemplate)); - } - - compiler.apply(new EntryOptionPlugin()); - compiler.applyPluginsBailResult("entry-option", options.context, options.entry); - - compiler.apply( - new CompatibilityPlugin(), - new HarmonyModulesPlugin(options.module), - new AMDPlugin(options.module, options.amd || {}), - new CommonJsPlugin(options.module), - new LoaderPlugin(), - new NodeStuffPlugin(options.node), - new RequireJsStuffPlugin(), - new APIPlugin(), - new ConstPlugin(), - new UseStrictPlugin(), - new RequireIncludePlugin(), - new RequireEnsurePlugin(), - new RequireContextPlugin(options.resolve.modules, options.resolve.extensions, options.resolve.mainFiles), - new ImportPlugin(options.module), - new SystemPlugin(options.module) - ); - - compiler.apply( - new EnsureChunkConditionsPlugin(), - new RemoveParentModulesPlugin(), - new RemoveEmptyChunksPlugin(), - new MergeDuplicateChunksPlugin(), - new FlagIncludedChunksPlugin(), - new OccurrenceOrderPlugin(true), - new FlagDependencyExportsPlugin(), - new FlagDependencyUsagePlugin() - ); - - if(options.performance) { - compiler.apply(new SizeLimitsPlugin(options.performance)); - } - - compiler.apply(new TemplatedPathPlugin()); - - compiler.apply(new RecordIdsPlugin()); - - compiler.apply(new WarnCaseSensitiveModulesPlugin()); - - if(options.cache) { - let CachePlugin = require("./CachePlugin"); - compiler.apply(new CachePlugin(typeof options.cache === "object" ? options.cache : null)); - } - - compiler.applyPlugins("after-plugins", compiler); - if(!compiler.inputFileSystem) throw new Error("No input filesystem provided"); - compiler.resolvers.normal = ResolverFactory.createResolver(Object.assign({ - fileSystem: compiler.inputFileSystem - }, options.resolve)); - compiler.resolvers.context = ResolverFactory.createResolver(Object.assign({ - fileSystem: compiler.inputFileSystem, - resolveToContext: true - }, options.resolve)); - compiler.resolvers.loader = ResolverFactory.createResolver(Object.assign({ - fileSystem: compiler.inputFileSystem - }, options.resolveLoader)); - compiler.applyPlugins("after-resolvers", compiler); - return options; - } -} - -module.exports = WebpackOptionsApply; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const OptionsApply = require("./OptionsApply"); + +const JavascriptModulesPlugin = require("./JavascriptModulesPlugin"); +const JsonModulesPlugin = require("./JsonModulesPlugin"); +const WebAssemblyModulesPlugin = require("./wasm/WebAssemblyModulesPlugin"); + +const LoaderTargetPlugin = require("./LoaderTargetPlugin"); +const FunctionModulePlugin = require("./FunctionModulePlugin"); +const EvalDevToolModulePlugin = require("./EvalDevToolModulePlugin"); +const SourceMapDevToolPlugin = require("./SourceMapDevToolPlugin"); +const EvalSourceMapDevToolPlugin = require("./EvalSourceMapDevToolPlugin"); + +const EntryOptionPlugin = require("./EntryOptionPlugin"); +const RecordIdsPlugin = require("./RecordIdsPlugin"); + +const APIPlugin = require("./APIPlugin"); +const ConstPlugin = require("./ConstPlugin"); +const RequireJsStuffPlugin = require("./RequireJsStuffPlugin"); +const NodeStuffPlugin = require("./NodeStuffPlugin"); +const CompatibilityPlugin = require("./CompatibilityPlugin"); + +const TemplatedPathPlugin = require("./TemplatedPathPlugin"); +const WarnCaseSensitiveModulesPlugin = require("./WarnCaseSensitiveModulesPlugin"); +const UseStrictPlugin = require("./UseStrictPlugin"); + +const LoaderPlugin = require("./dependencies/LoaderPlugin"); +const CommonJsPlugin = require("./dependencies/CommonJsPlugin"); +const HarmonyModulesPlugin = require("./dependencies/HarmonyModulesPlugin"); +const SystemPlugin = require("./dependencies/SystemPlugin"); +const ImportPlugin = require("./dependencies/ImportPlugin"); +const AMDPlugin = require("./dependencies/AMDPlugin"); +const RequireContextPlugin = require("./dependencies/RequireContextPlugin"); +const RequireEnsurePlugin = require("./dependencies/RequireEnsurePlugin"); +const RequireIncludePlugin = require("./dependencies/RequireIncludePlugin"); + +const WarnNoModeSetPlugin = require("./WarnNoModeSetPlugin"); + +const EnsureChunkConditionsPlugin = require("./optimize/EnsureChunkConditionsPlugin"); +const RemoveParentModulesPlugin = require("./optimize/RemoveParentModulesPlugin"); +const RemoveEmptyChunksPlugin = require("./optimize/RemoveEmptyChunksPlugin"); +const MergeDuplicateChunksPlugin = require("./optimize/MergeDuplicateChunksPlugin"); +const FlagIncludedChunksPlugin = require("./optimize/FlagIncludedChunksPlugin"); +const OccurrenceChunkOrderPlugin = require("./optimize/OccurrenceChunkOrderPlugin"); +const OccurrenceModuleOrderPlugin = require("./optimize/OccurrenceModuleOrderPlugin"); +const NaturalChunkOrderPlugin = require("./optimize/NaturalChunkOrderPlugin"); +const SideEffectsFlagPlugin = require("./optimize/SideEffectsFlagPlugin"); +const FlagDependencyUsagePlugin = require("./FlagDependencyUsagePlugin"); +const FlagDependencyExportsPlugin = require("./FlagDependencyExportsPlugin"); +const ModuleConcatenationPlugin = require("./optimize/ModuleConcatenationPlugin"); +const SplitChunksPlugin = require("./optimize/SplitChunksPlugin"); +const RuntimeChunkPlugin = require("./optimize/RuntimeChunkPlugin"); +const NoEmitOnErrorsPlugin = require("./NoEmitOnErrorsPlugin"); +const NamedModulesPlugin = require("./NamedModulesPlugin"); +const NamedChunksPlugin = require("./NamedChunksPlugin"); +const HashedModuleIdsPlugin = require("./HashedModuleIdsPlugin"); +const DefinePlugin = require("./DefinePlugin"); +const SizeLimitsPlugin = require("./performance/SizeLimitsPlugin"); +const WasmFinalizeExportsPlugin = require("./wasm/WasmFinalizeExportsPlugin"); + +class WebpackOptionsApply extends OptionsApply { + constructor() { + super(); + } + + process(options, compiler) { + let ExternalsPlugin; + compiler.outputPath = options.output.path; + compiler.recordsInputPath = options.recordsInputPath || options.recordsPath; + compiler.recordsOutputPath = + options.recordsOutputPath || options.recordsPath; + compiler.name = options.name; + compiler.dependencies = options.dependencies; + if (typeof options.target === "string") { + let JsonpTemplatePlugin; + let FetchCompileWasmTemplatePlugin; + let ReadFileCompileWasmTemplatePlugin; + let NodeSourcePlugin; + let NodeTargetPlugin; + let NodeTemplatePlugin; + + switch (options.target) { + case "web": + JsonpTemplatePlugin = require("./web/JsonpTemplatePlugin"); + FetchCompileWasmTemplatePlugin = require("./web/FetchCompileWasmTemplatePlugin"); + NodeSourcePlugin = require("./node/NodeSourcePlugin"); + new JsonpTemplatePlugin().apply(compiler); + new FetchCompileWasmTemplatePlugin({ + mangleImports: options.optimization.mangleWasmImports + }).apply(compiler); + new FunctionModulePlugin().apply(compiler); + new NodeSourcePlugin(options.node).apply(compiler); + new LoaderTargetPlugin(options.target).apply(compiler); + break; + case "webworker": { + let WebWorkerTemplatePlugin = require("./webworker/WebWorkerTemplatePlugin"); + FetchCompileWasmTemplatePlugin = require("./web/FetchCompileWasmTemplatePlugin"); + NodeSourcePlugin = require("./node/NodeSourcePlugin"); + new WebWorkerTemplatePlugin().apply(compiler); + new FetchCompileWasmTemplatePlugin({ + mangleImports: options.optimization.mangleWasmImports + }).apply(compiler); + new FunctionModulePlugin().apply(compiler); + new NodeSourcePlugin(options.node).apply(compiler); + new LoaderTargetPlugin(options.target).apply(compiler); + break; + } + case "node": + case "async-node": + NodeTemplatePlugin = require("./node/NodeTemplatePlugin"); + ReadFileCompileWasmTemplatePlugin = require("./node/ReadFileCompileWasmTemplatePlugin"); + NodeTargetPlugin = require("./node/NodeTargetPlugin"); + new NodeTemplatePlugin({ + asyncChunkLoading: options.target === "async-node" + }).apply(compiler); + new ReadFileCompileWasmTemplatePlugin({ + mangleImports: options.optimization.mangleWasmImports + }).apply(compiler); + new FunctionModulePlugin().apply(compiler); + new NodeTargetPlugin().apply(compiler); + new LoaderTargetPlugin("node").apply(compiler); + break; + case "node-webkit": + JsonpTemplatePlugin = require("./web/JsonpTemplatePlugin"); + NodeTargetPlugin = require("./node/NodeTargetPlugin"); + ExternalsPlugin = require("./ExternalsPlugin"); + new JsonpTemplatePlugin().apply(compiler); + new FunctionModulePlugin().apply(compiler); + new NodeTargetPlugin().apply(compiler); + new ExternalsPlugin("commonjs", "nw.gui").apply(compiler); + new LoaderTargetPlugin(options.target).apply(compiler); + break; + case "electron-main": + NodeTemplatePlugin = require("./node/NodeTemplatePlugin"); + NodeTargetPlugin = require("./node/NodeTargetPlugin"); + ExternalsPlugin = require("./ExternalsPlugin"); + new NodeTemplatePlugin({ + asyncChunkLoading: true + }).apply(compiler); + new FunctionModulePlugin().apply(compiler); + new NodeTargetPlugin().apply(compiler); + new ExternalsPlugin("commonjs", [ + "app", + "auto-updater", + "browser-window", + "clipboard", + "content-tracing", + "crash-reporter", + "dialog", + "electron", + "global-shortcut", + "ipc", + "ipc-main", + "menu", + "menu-item", + "native-image", + "original-fs", + "power-monitor", + "power-save-blocker", + "protocol", + "screen", + "session", + "shell", + "tray", + "web-contents" + ]).apply(compiler); + new LoaderTargetPlugin(options.target).apply(compiler); + break; + case "electron-renderer": + JsonpTemplatePlugin = require("./web/JsonpTemplatePlugin"); + FetchCompileWasmTemplatePlugin = require("./web/FetchCompileWasmTemplatePlugin"); + NodeTargetPlugin = require("./node/NodeTargetPlugin"); + ExternalsPlugin = require("./ExternalsPlugin"); + new JsonpTemplatePlugin().apply(compiler); + new FetchCompileWasmTemplatePlugin({ + mangleImports: options.optimization.mangleWasmImports + }).apply(compiler); + new FunctionModulePlugin().apply(compiler); + new NodeTargetPlugin().apply(compiler); + new ExternalsPlugin("commonjs", [ + "clipboard", + "crash-reporter", + "desktop-capturer", + "electron", + "ipc", + "ipc-renderer", + "native-image", + "original-fs", + "remote", + "screen", + "shell", + "web-frame" + ]).apply(compiler); + new LoaderTargetPlugin(options.target).apply(compiler); + break; + default: + throw new Error("Unsupported target '" + options.target + "'."); + } + } else if (options.target !== false) { + options.target(compiler); + } else { + throw new Error("Unsupported target '" + options.target + "'."); + } + + if (options.output.library || options.output.libraryTarget !== "var") { + const LibraryTemplatePlugin = require("./LibraryTemplatePlugin"); + new LibraryTemplatePlugin( + options.output.library, + options.output.libraryTarget, + options.output.umdNamedDefine, + options.output.auxiliaryComment || "", + options.output.libraryExport + ).apply(compiler); + } + if (options.externals) { + ExternalsPlugin = require("./ExternalsPlugin"); + new ExternalsPlugin( + options.output.libraryTarget, + options.externals + ).apply(compiler); + } + + let noSources; + let legacy; + let modern; + let comment; + if ( + options.devtool && + (options.devtool.includes("sourcemap") || + options.devtool.includes("source-map")) + ) { + const hidden = options.devtool.includes("hidden"); + const inline = options.devtool.includes("inline"); + const evalWrapped = options.devtool.includes("eval"); + const cheap = options.devtool.includes("cheap"); + const moduleMaps = options.devtool.includes("module"); + noSources = options.devtool.includes("nosources"); + legacy = options.devtool.includes("@"); + modern = options.devtool.includes("#"); + comment = + legacy && modern + ? "\n/*\n//@ source" + + "MappingURL=[url]\n//# source" + + "MappingURL=[url]\n*/" + : legacy + ? "\n/*\n//@ source" + "MappingURL=[url]\n*/" + : modern + ? "\n//# source" + "MappingURL=[url]" + : null; + const Plugin = evalWrapped + ? EvalSourceMapDevToolPlugin + : SourceMapDevToolPlugin; + new Plugin({ + filename: inline ? null : options.output.sourceMapFilename, + moduleFilenameTemplate: options.output.devtoolModuleFilenameTemplate, + fallbackModuleFilenameTemplate: + options.output.devtoolFallbackModuleFilenameTemplate, + append: hidden ? false : comment, + module: moduleMaps ? true : cheap ? false : true, + columns: cheap ? false : true, + lineToLine: options.output.devtoolLineToLine, + noSources: noSources, + namespace: options.output.devtoolNamespace + }).apply(compiler); + } else if (options.devtool && options.devtool.includes("eval")) { + legacy = options.devtool.includes("@"); + modern = options.devtool.includes("#"); + comment = + legacy && modern + ? "\n//@ sourceURL=[url]\n//# sourceURL=[url]" + : legacy + ? "\n//@ sourceURL=[url]" + : modern + ? "\n//# sourceURL=[url]" + : null; + new EvalDevToolModulePlugin({ + sourceUrlComment: comment, + moduleFilenameTemplate: options.output.devtoolModuleFilenameTemplate, + namespace: options.output.devtoolNamespace + }).apply(compiler); + } + + new JavascriptModulesPlugin().apply(compiler); + new JsonModulesPlugin().apply(compiler); + new WebAssemblyModulesPlugin({ + mangleImports: options.optimization.mangleWasmImports + }).apply(compiler); + + new EntryOptionPlugin().apply(compiler); + compiler.hooks.entryOption.call(options.context, options.entry); + + new CompatibilityPlugin().apply(compiler); + new HarmonyModulesPlugin(options.module).apply(compiler); + new AMDPlugin(options.module, options.amd || {}).apply(compiler); + new CommonJsPlugin(options.module).apply(compiler); + new LoaderPlugin().apply(compiler); + new NodeStuffPlugin(options.node).apply(compiler); + new RequireJsStuffPlugin().apply(compiler); + new APIPlugin().apply(compiler); + new ConstPlugin().apply(compiler); + new UseStrictPlugin().apply(compiler); + new RequireIncludePlugin().apply(compiler); + new RequireEnsurePlugin().apply(compiler); + new RequireContextPlugin( + options.resolve.modules, + options.resolve.extensions, + options.resolve.mainFiles + ).apply(compiler); + new ImportPlugin(options.module).apply(compiler); + new SystemPlugin(options.module).apply(compiler); + + if (typeof options.mode !== "string") { + new WarnNoModeSetPlugin().apply(compiler); + } + + new EnsureChunkConditionsPlugin().apply(compiler); + if (options.optimization.removeAvailableModules) { + new RemoveParentModulesPlugin().apply(compiler); + } + if (options.optimization.removeEmptyChunks) { + new RemoveEmptyChunksPlugin().apply(compiler); + } + if (options.optimization.mergeDuplicateChunks) { + new MergeDuplicateChunksPlugin().apply(compiler); + } + if (options.optimization.flagIncludedChunks) { + new FlagIncludedChunksPlugin().apply(compiler); + } + if (options.optimization.sideEffects) { + new SideEffectsFlagPlugin().apply(compiler); + } + if (options.optimization.providedExports) { + new FlagDependencyExportsPlugin().apply(compiler); + } + if (options.optimization.usedExports) { + new FlagDependencyUsagePlugin().apply(compiler); + } + if (options.optimization.concatenateModules) { + new ModuleConcatenationPlugin().apply(compiler); + } + if (options.optimization.splitChunks) { + new SplitChunksPlugin(options.optimization.splitChunks).apply(compiler); + } + if (options.optimization.runtimeChunk) { + new RuntimeChunkPlugin(options.optimization.runtimeChunk).apply(compiler); + } + if (options.optimization.noEmitOnErrors) { + new NoEmitOnErrorsPlugin().apply(compiler); + } + if (options.optimization.checkWasmTypes) { + new WasmFinalizeExportsPlugin().apply(compiler); + } + let moduleIds = options.optimization.moduleIds; + if (moduleIds === undefined) { + // TODO webpack 5 remove all these options + if (options.optimization.occurrenceOrder) { + moduleIds = "size"; + } + if (options.optimization.namedModules) { + moduleIds = "named"; + } + if (options.optimization.hashedModuleIds) { + moduleIds = "hashed"; + } + if (moduleIds === undefined) { + moduleIds = "natural"; + } + } + if (moduleIds) { + switch (moduleIds) { + case "natural": + // TODO webpack 5: see hint in Compilation.sortModules + break; + case "named": + new NamedModulesPlugin().apply(compiler); + break; + case "hashed": + new HashedModuleIdsPlugin().apply(compiler); + break; + case "size": + new OccurrenceModuleOrderPlugin({ + prioritiseInitial: true + }).apply(compiler); + break; + case "total-size": + new OccurrenceModuleOrderPlugin({ + prioritiseInitial: false + }).apply(compiler); + break; + default: + throw new Error( + `webpack bug: moduleIds: ${moduleIds} is not implemented` + ); + } + } + let chunkIds = options.optimization.chunkIds; + if (chunkIds === undefined) { + // TODO webpack 5 remove all these options + if (options.optimization.occurrenceOrder) { + // This looks weird but it's for backward-compat + // This bug already existed before adding this feature + chunkIds = "total-size"; + } + if (options.optimization.namedChunks) { + chunkIds = "named"; + } + if (chunkIds === undefined) { + chunkIds = "natural"; + } + } + if (chunkIds) { + switch (chunkIds) { + case "natural": + new NaturalChunkOrderPlugin().apply(compiler); + break; + case "named": + // TODO webapck 5: for backward-compat this need to have OccurrenceChunkOrderPlugin too + // The NamedChunksPlugin doesn't give every chunk a name + // This should be fixed, and the OccurrenceChunkOrderPlugin should be removed here. + new OccurrenceChunkOrderPlugin({ + prioritiseInitial: false + }).apply(compiler); + new NamedChunksPlugin().apply(compiler); + break; + case "size": + new OccurrenceChunkOrderPlugin({ + prioritiseInitial: true + }).apply(compiler); + break; + case "total-size": + new OccurrenceChunkOrderPlugin({ + prioritiseInitial: false + }).apply(compiler); + break; + default: + throw new Error( + `webpack bug: chunkIds: ${chunkIds} is not implemented` + ); + } + } + if (options.optimization.nodeEnv) { + new DefinePlugin({ + "process.env.NODE_ENV": JSON.stringify(options.optimization.nodeEnv) + }).apply(compiler); + } + if (options.optimization.minimize) { + for (const minimizer of options.optimization.minimizer) { + minimizer.apply(compiler); + } + } + + if (options.performance) { + new SizeLimitsPlugin(options.performance).apply(compiler); + } + + new TemplatedPathPlugin().apply(compiler); + + new RecordIdsPlugin({ + portableIds: options.optimization.portableRecords + }).apply(compiler); + + new WarnCaseSensitiveModulesPlugin().apply(compiler); + + if (options.cache) { + const CachePlugin = require("./CachePlugin"); + new CachePlugin( + typeof options.cache === "object" ? options.cache : null + ).apply(compiler); + } + + compiler.hooks.afterPlugins.call(compiler); + if (!compiler.inputFileSystem) { + throw new Error("No input filesystem provided"); + } + compiler.resolverFactory.hooks.resolveOptions + .for("normal") + .tap("WebpackOptionsApply", resolveOptions => { + return Object.assign( + { + fileSystem: compiler.inputFileSystem + }, + options.resolve, + resolveOptions + ); + }); + compiler.resolverFactory.hooks.resolveOptions + .for("context") + .tap("WebpackOptionsApply", resolveOptions => { + return Object.assign( + { + fileSystem: compiler.inputFileSystem, + resolveToContext: true + }, + options.resolve, + resolveOptions + ); + }); + compiler.resolverFactory.hooks.resolveOptions + .for("loader") + .tap("WebpackOptionsApply", resolveOptions => { + return Object.assign( + { + fileSystem: compiler.inputFileSystem + }, + options.resolveLoader, + resolveOptions + ); + }); + compiler.hooks.afterResolvers.call(compiler); + return options; + } +} + +module.exports = WebpackOptionsApply; diff --git a/node_modules/webpack/lib/WebpackOptionsDefaulter.js b/node_modules/webpack/lib/WebpackOptionsDefaulter.js index 385578f50..def82855a 100644 --- a/node_modules/webpack/lib/WebpackOptionsDefaulter.js +++ b/node_modules/webpack/lib/WebpackOptionsDefaulter.js @@ -1,129 +1,372 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const OptionsDefaulter = require("./OptionsDefaulter"); -const Template = require("./Template"); - -class WebpackOptionsDefaulter extends OptionsDefaulter { - constructor() { - super(); - this.set("devtool", false); - this.set("cache", true); - - this.set("context", process.cwd()); - this.set("target", "web"); - - this.set("module", "call", value => Object.assign({}, value)); - this.set("module.unknownContextRequest", "."); - this.set("module.unknownContextRegExp", false); - this.set("module.unknownContextRecursive", true); - this.set("module.unknownContextCritical", true); - this.set("module.exprContextRequest", "."); - this.set("module.exprContextRegExp", false); - this.set("module.exprContextRecursive", true); - this.set("module.exprContextCritical", true); - this.set("module.wrappedContextRegExp", /.*/); - this.set("module.wrappedContextRecursive", true); - this.set("module.wrappedContextCritical", false); - this.set("module.strictExportPresence", false); - this.set("module.strictThisContextOnImports", false); - this.set("module.unsafeCache", true); - - this.set("output", "call", (value, options) => { - if(typeof value === "string") { - return { - filename: value - }; - } else if(typeof value !== "object") { - return {}; - } else { - return Object.assign({}, value); - } - }); - this.set("output.filename", "[name].js"); - this.set("output.chunkFilename", "make", (options) => { - const filename = options.output.filename; - return filename.indexOf("[name]") >= 0 ? filename.replace("[name]", "[id]") : "[id]." + filename; - }); - this.set("output.library", ""); - this.set("output.hotUpdateFunction", "make", (options) => { - return Template.toIdentifier("webpackHotUpdate" + options.output.library); - }); - this.set("output.jsonpFunction", "make", (options) => { - return Template.toIdentifier("webpackJsonp" + options.output.library); - }); - this.set("output.libraryTarget", "var"); - this.set("output.path", process.cwd()); - this.set("output.sourceMapFilename", "[file].map[query]"); - this.set("output.hotUpdateChunkFilename", "[id].[hash].hot-update.js"); - this.set("output.hotUpdateMainFilename", "[hash].hot-update.json"); - this.set("output.crossOriginLoading", false); - this.set("output.chunkLoadTimeout", 120000); - this.set("output.hashFunction", "md5"); - this.set("output.hashDigest", "hex"); - this.set("output.hashDigestLength", 20); - this.set("output.devtoolLineToLine", false); - this.set("output.strictModuleExceptionHandling", false); - - this.set("node", "call", value => { - if(typeof value === "boolean") { - return value; - } else { - return Object.assign({}, value); - } - }); - this.set("node.console", false); - this.set("node.process", true); - this.set("node.global", true); - this.set("node.Buffer", true); - this.set("node.setImmediate", true); - this.set("node.__filename", "mock"); - this.set("node.__dirname", "mock"); - - this.set("performance", "call", value => { - if(typeof value === "boolean") { - return value; - } else { - return Object.assign({}, value); - } - }); - this.set("performance.maxAssetSize", 250000); - this.set("performance.maxEntrypointSize", 250000); - this.set("performance.hints", false); - - this.set("resolve", "call", value => Object.assign({}, value)); - this.set("resolve.unsafeCache", true); - this.set("resolve.modules", ["node_modules"]); - this.set("resolve.extensions", [".js", ".json"]); - this.set("resolve.mainFiles", ["index"]); - this.set("resolve.aliasFields", "make", (options) => { - if(options.target === "web" || options.target === "webworker") - return ["browser"]; - else - return []; - }); - this.set("resolve.mainFields", "make", (options) => { - if(options.target === "web" || options.target === "webworker") - return ["browser", "module", "main"]; - else - return ["module", "main"]; - }); - this.set("resolve.cacheWithContext", "make", (options) => { - return Array.isArray(options.resolve.plugins) && options.resolve.plugins.length > 0; - }); - - this.set("resolveLoader", "call", value => Object.assign({}, value)); - this.set("resolveLoader.unsafeCache", true); - this.set("resolveLoader.mainFields", ["loader", "main"]); - this.set("resolveLoader.extensions", [".js", ".json"]); - this.set("resolveLoader.mainFiles", ["index"]); - this.set("resolveLoader.cacheWithContext", "make", (options) => { - return Array.isArray(options.resolveLoader.plugins) && options.resolveLoader.plugins.length > 0; - }); - } -} - -module.exports = WebpackOptionsDefaulter; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const path = require("path"); + +const OptionsDefaulter = require("./OptionsDefaulter"); +const Template = require("./Template"); + +const isProductionLikeMode = options => { + return options.mode === "production" || !options.mode; +}; + +const isWebLikeTarget = options => { + return options.target === "web" || options.target === "webworker"; +}; + +const getDevtoolNamespace = library => { + // if options.output.library is a string + if (Array.isArray(library)) { + return library.join("."); + } else if (typeof library === "object") { + return getDevtoolNamespace(library.root); + } + return library || ""; +}; + +class WebpackOptionsDefaulter extends OptionsDefaulter { + constructor() { + super(); + + this.set("entry", "./src"); + + this.set( + "devtool", + "make", + options => (options.mode === "development" ? "eval" : false) + ); + this.set("cache", "make", options => options.mode === "development"); + + this.set("context", process.cwd()); + this.set("target", "web"); + + this.set("module", "call", value => Object.assign({}, value)); + this.set("module.unknownContextRequest", "."); + this.set("module.unknownContextRegExp", false); + this.set("module.unknownContextRecursive", true); + this.set("module.unknownContextCritical", true); + this.set("module.exprContextRequest", "."); + this.set("module.exprContextRegExp", false); + this.set("module.exprContextRecursive", true); + this.set("module.exprContextCritical", true); + this.set("module.wrappedContextRegExp", /.*/); + this.set("module.wrappedContextRecursive", true); + this.set("module.wrappedContextCritical", false); + this.set("module.strictExportPresence", false); + this.set("module.strictThisContextOnImports", false); + this.set("module.unsafeCache", "make", options => !!options.cache); + this.set("module.rules", []); + this.set("module.defaultRules", "make", options => [ + { + type: "javascript/auto", + resolve: {} + }, + { + test: /\.mjs$/i, + type: "javascript/esm", + resolve: { + mainFields: + options.target === "web" || + options.target === "webworker" || + options.target === "electron-renderer" + ? ["browser", "main"] + : ["main"] + } + }, + { + test: /\.json$/i, + type: "json" + }, + { + test: /\.wasm$/i, + type: "webassembly/experimental" + } + ]); + + this.set("output", "call", (value, options) => { + if (typeof value === "string") { + return { + filename: value + }; + } else if (typeof value !== "object") { + return {}; + } else { + return Object.assign({}, value); + } + }); + + this.set("output.filename", "[name].js"); + this.set("output.chunkFilename", "make", options => { + const filename = options.output.filename; + if (typeof filename !== "function") { + const hasName = filename.includes("[name]"); + const hasId = filename.includes("[id]"); + const hasChunkHash = filename.includes("[chunkhash]"); + // Anything changing depending on chunk is fine + if (hasChunkHash || hasName || hasId) return filename; + // Elsewise prefix "[id]." in front of the basename to make it changing + return filename.replace(/(^|\/)([^/]*(?:\?|$))/, "$1[id].$2"); + } + return "[id].js"; + }); + this.set("output.webassemblyModuleFilename", "[modulehash].module.wasm"); + this.set("output.library", ""); + this.set("output.hotUpdateFunction", "make", options => { + return Template.toIdentifier( + "webpackHotUpdate" + Template.toIdentifier(options.output.library) + ); + }); + this.set("output.jsonpFunction", "make", options => { + return Template.toIdentifier( + "webpackJsonp" + Template.toIdentifier(options.output.library) + ); + }); + this.set("output.chunkCallbackName", "make", options => { + return Template.toIdentifier( + "webpackChunk" + Template.toIdentifier(options.output.library) + ); + }); + this.set("output.globalObject", "make", options => { + switch (options.target) { + case "web": + case "electron-renderer": + case "node-webkit": + return "window"; + case "webworker": + return "self"; + case "node": + case "async-node": + case "electron-main": + return "global"; + default: + return "self"; + } + }); + this.set("output.devtoolNamespace", "make", options => { + return getDevtoolNamespace(options.output.library); + }); + this.set("output.libraryTarget", "var"); + this.set("output.path", path.join(process.cwd(), "dist")); + this.set( + "output.pathinfo", + "make", + options => options.mode === "development" + ); + this.set("output.sourceMapFilename", "[file].map[query]"); + this.set("output.hotUpdateChunkFilename", "[id].[hash].hot-update.js"); + this.set("output.hotUpdateMainFilename", "[hash].hot-update.json"); + this.set("output.crossOriginLoading", false); + this.set("output.jsonpScriptType", false); + this.set("output.chunkLoadTimeout", 120000); + this.set("output.hashFunction", "md4"); + this.set("output.hashDigest", "hex"); + this.set("output.hashDigestLength", 20); + this.set("output.devtoolLineToLine", false); + this.set("output.strictModuleExceptionHandling", false); + + this.set("node", "call", value => { + if (typeof value === "boolean") { + return value; + } else { + return Object.assign({}, value); + } + }); + this.set("node.console", false); + this.set("node.process", true); + this.set("node.global", true); + this.set("node.Buffer", true); + this.set("node.setImmediate", true); + this.set("node.__filename", "mock"); + this.set("node.__dirname", "mock"); + + this.set("performance", "call", (value, options) => { + if (value === false) return false; + if ( + value === undefined && + (!isProductionLikeMode(options) || !isWebLikeTarget(options)) + ) + return false; + return Object.assign({}, value); + }); + this.set("performance.maxAssetSize", 250000); + this.set("performance.maxEntrypointSize", 250000); + this.set( + "performance.hints", + "make", + options => (isProductionLikeMode(options) ? "warning" : false) + ); + + this.set("optimization", "call", value => Object.assign({}, value)); + this.set("optimization.removeAvailableModules", true); + this.set("optimization.removeEmptyChunks", true); + this.set("optimization.mergeDuplicateChunks", true); + this.set("optimization.flagIncludedChunks", "make", options => + isProductionLikeMode(options) + ); + // TODO webpack 5 add `moduleIds: "named"` default for development + // TODO webpack 5 add `moduleIds: "size"` default for production + // TODO webpack 5 remove optimization.occurrenceOrder + this.set("optimization.occurrenceOrder", "make", options => + isProductionLikeMode(options) + ); + this.set("optimization.sideEffects", "make", options => + isProductionLikeMode(options) + ); + this.set("optimization.providedExports", true); + this.set("optimization.usedExports", "make", options => + isProductionLikeMode(options) + ); + this.set("optimization.concatenateModules", "make", options => + isProductionLikeMode(options) + ); + this.set("optimization.splitChunks", {}); + this.set("optimization.splitChunks.hidePathInfo", "make", options => { + return isProductionLikeMode(options); + }); + this.set("optimization.splitChunks.chunks", "async"); + this.set("optimization.splitChunks.minSize", "make", options => { + return isProductionLikeMode(options) ? 30000 : 10000; + }); + this.set("optimization.splitChunks.minChunks", 1); + this.set("optimization.splitChunks.maxAsyncRequests", "make", options => { + return isProductionLikeMode(options) ? 5 : Infinity; + }); + this.set("optimization.splitChunks.automaticNameDelimiter", "~"); + this.set("optimization.splitChunks.maxInitialRequests", "make", options => { + return isProductionLikeMode(options) ? 3 : Infinity; + }); + this.set("optimization.splitChunks.name", true); + this.set("optimization.splitChunks.cacheGroups", {}); + this.set("optimization.splitChunks.cacheGroups.default", { + automaticNamePrefix: "", + reuseExistingChunk: true, + minChunks: 2, + priority: -20 + }); + this.set("optimization.splitChunks.cacheGroups.vendors", { + automaticNamePrefix: "vendors", + test: /[\\/]node_modules[\\/]/, + priority: -10 + }); + this.set("optimization.runtimeChunk", "call", value => { + if (value === "single") { + return { + name: "runtime" + }; + } + if (value === true || value === "multiple") { + return { + name: entrypoint => `runtime~${entrypoint.name}` + }; + } + return value; + }); + this.set("optimization.noEmitOnErrors", "make", options => + isProductionLikeMode(options) + ); + this.set("optimization.checkWasmTypes", "make", options => + isProductionLikeMode(options) + ); + this.set("optimization.mangleWasmImports", false); + // TODO webpack 5 remove optimization.namedModules + this.set( + "optimization.namedModules", + "make", + options => options.mode === "development" + ); + this.set("optimization.hashedModuleIds", false); + // TODO webpack 5 add `chunkIds: "named"` default for development + // TODO webpack 5 add `chunkIds: "size"` default for production + // TODO webpack 5 remove optimization.namedChunks + this.set( + "optimization.namedChunks", + "make", + options => options.mode === "development" + ); + this.set( + "optimization.portableRecords", + "make", + options => + !!( + options.recordsInputPath || + options.recordsOutputPath || + options.recordsPath + ) + ); + this.set("optimization.minimize", "make", options => + isProductionLikeMode(options) + ); + this.set("optimization.minimizer", "make", options => [ + { + apply: compiler => { + // Lazy load the uglifyjs plugin + const UglifyJsPlugin = require("uglifyjs-webpack-plugin"); + const SourceMapDevToolPlugin = require("./SourceMapDevToolPlugin"); + new UglifyJsPlugin({ + cache: true, + parallel: true, + sourceMap: + (options.devtool && /source-?map/.test(options.devtool)) || + (options.plugins && + options.plugins.some(p => p instanceof SourceMapDevToolPlugin)) + }).apply(compiler); + } + } + ]); + this.set("optimization.nodeEnv", "make", options => { + // TODO: In webpack 5, it should return `false` when mode is `none` + return options.mode || "production"; + }); + + this.set("resolve", "call", value => Object.assign({}, value)); + this.set("resolve.unsafeCache", true); + this.set("resolve.modules", ["node_modules"]); + this.set("resolve.extensions", [".wasm", ".mjs", ".js", ".json"]); + this.set("resolve.mainFiles", ["index"]); + this.set("resolve.aliasFields", "make", options => { + if ( + options.target === "web" || + options.target === "webworker" || + options.target === "electron-renderer" + ) { + return ["browser"]; + } else { + return []; + } + }); + this.set("resolve.mainFields", "make", options => { + if ( + options.target === "web" || + options.target === "webworker" || + options.target === "electron-renderer" + ) { + return ["browser", "module", "main"]; + } else { + return ["module", "main"]; + } + }); + this.set("resolve.cacheWithContext", "make", options => { + return ( + Array.isArray(options.resolve.plugins) && + options.resolve.plugins.length > 0 + ); + }); + + this.set("resolveLoader", "call", value => Object.assign({}, value)); + this.set("resolveLoader.unsafeCache", true); + this.set("resolveLoader.mainFields", ["loader", "main"]); + this.set("resolveLoader.extensions", [".js", ".json"]); + this.set("resolveLoader.mainFiles", ["index"]); + this.set("resolveLoader.cacheWithContext", "make", options => { + return ( + Array.isArray(options.resolveLoader.plugins) && + options.resolveLoader.plugins.length > 0 + ); + }); + } +} + +module.exports = WebpackOptionsDefaulter; diff --git a/node_modules/webpack/lib/WebpackOptionsValidationError.js b/node_modules/webpack/lib/WebpackOptionsValidationError.js index 4fa72d19b..d66cb2ccc 100644 --- a/node_modules/webpack/lib/WebpackOptionsValidationError.js +++ b/node_modules/webpack/lib/WebpackOptionsValidationError.js @@ -1,219 +1,344 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Gajus Kuizinas @gajus -*/ -"use strict"; - -const WebpackError = require("./WebpackError"); -const webpackOptionsSchema = require("../schemas/webpackOptionsSchema.json"); - -const getSchemaPart = (path, parents, additionalPath) => { - parents = parents || 0; - path = path.split("/"); - path = path.slice(0, path.length - parents); - if(additionalPath) { - additionalPath = additionalPath.split("/"); - path = path.concat(additionalPath); - } - let schemaPart = webpackOptionsSchema; - for(let i = 1; i < path.length; i++) { - const inner = schemaPart[path[i]]; - if(inner) - schemaPart = inner; - } - return schemaPart; -}; - -const getSchemaPartText = (schemaPart, additionalPath) => { - if(additionalPath) { - for(let i = 0; i < additionalPath.length; i++) { - const inner = schemaPart[additionalPath[i]]; - if(inner) - schemaPart = inner; - } - } - while(schemaPart.$ref) schemaPart = getSchemaPart(schemaPart.$ref); - let schemaText = WebpackOptionsValidationError.formatSchema(schemaPart); - if(schemaPart.description) - schemaText += `\n-> ${schemaPart.description}`; - return schemaText; -}; - -const getSchemaPartDescription = schemaPart => { - while(schemaPart.$ref) schemaPart = getSchemaPart(schemaPart.$ref); - if(schemaPart.description) - return `\n-> ${schemaPart.description}`; - return ""; -}; - -const filterChildren = children => { - return children.filter(err => err.keyword !== "anyOf" && err.keyword !== "allOf" && err.keyword !== "oneOf"); -}; - -const indent = (str, prefix, firstLine) => { - if(firstLine) { - return prefix + str.replace(/\n(?!$)/g, "\n" + prefix); - } else { - return str.replace(/\n(?!$)/g, `\n${prefix}`); - } -}; - -class WebpackOptionsValidationError extends WebpackError { - constructor(validationErrors) { - super(); - - this.name = "WebpackOptionsValidationError"; - this.message = "Invalid configuration object. " + - "Webpack has been initialised using a configuration object that does not match the API schema.\n" + - validationErrors.map(err => " - " + indent(WebpackOptionsValidationError.formatValidationError(err), " ", false)).join("\n"); - this.validationErrors = validationErrors; - - Error.captureStackTrace(this, this.constructor); - } - - static formatSchema(schema, prevSchemas) { - prevSchemas = prevSchemas || []; - - const formatInnerSchema = (innerSchema, addSelf) => { - if(!addSelf) return WebpackOptionsValidationError.formatSchema(innerSchema, prevSchemas); - if(prevSchemas.indexOf(innerSchema) >= 0) return "(recursive)"; - return WebpackOptionsValidationError.formatSchema(innerSchema, prevSchemas.concat(schema)); - }; - - if(schema.type === "string") { - if(schema.minLength === 1) - return "non-empty string"; - else if(schema.minLength > 1) - return `string (min length ${schema.minLength})`; - return "string"; - } else if(schema.type === "boolean") { - return "boolean"; - } else if(schema.type === "number") { - return "number"; - } else if(schema.type === "object") { - if(schema.properties) { - const required = schema.required || []; - return `object { ${Object.keys(schema.properties).map(property => { - if(required.indexOf(property) < 0) return property + "?"; - return property; - }).concat(schema.additionalProperties ? ["..."] : []).join(", ")} }`; - } - if(schema.additionalProperties) { - return `object { : ${formatInnerSchema(schema.additionalProperties)} }`; - } - return "object"; - } else if(schema.type === "array") { - return `[${formatInnerSchema(schema.items)}]`; - } - - switch(schema.instanceof) { - case "Function": - return "function"; - case "RegExp": - return "RegExp"; - } - if(schema.$ref) return formatInnerSchema(getSchemaPart(schema.$ref), true); - if(schema.allOf) return schema.allOf.map(formatInnerSchema).join(" & "); - if(schema.oneOf) return schema.oneOf.map(formatInnerSchema).join(" | "); - if(schema.anyOf) return schema.anyOf.map(formatInnerSchema).join(" | "); - if(schema.enum) return schema.enum.map(item => JSON.stringify(item)).join(" | "); - return JSON.stringify(schema, 0, 2); - } - - static formatValidationError(err) { - const dataPath = `configuration${err.dataPath}`; - if(err.keyword === "additionalProperties") { - const baseMessage = `${dataPath} has an unknown property '${err.params.additionalProperty}'. These properties are valid:\n${getSchemaPartText(err.parentSchema)}`; - if(!err.dataPath) { - switch(err.params.additionalProperty) { - case "debug": - return `${baseMessage}\n` + - "The 'debug' property was removed in webpack 2.\n" + - "Loaders should be updated to allow passing this option via loader options in module.rules.\n" + - "Until loaders are updated one can use the LoaderOptionsPlugin to switch loaders into debug mode:\n" + - "plugins: [\n" + - " new webpack.LoaderOptionsPlugin({\n" + - " debug: true\n" + - " })\n" + - "]"; - } - return baseMessage + "\n" + - "For typos: please correct them.\n" + - "For loader options: webpack 2 no longer allows custom properties in configuration.\n" + - " Loaders should be updated to allow passing options via loader options in module.rules.\n" + - " Until loaders are updated one can use the LoaderOptionsPlugin to pass these options to the loader:\n" + - " plugins: [\n" + - " new webpack.LoaderOptionsPlugin({\n" + - " // test: /\\.xxx$/, // may apply this only for some modules\n" + - " options: {\n" + - ` ${err.params.additionalProperty}: ...\n` + - " }\n" + - " })\n" + - " ]"; - } - return baseMessage; - } else if(err.keyword === "oneOf" || err.keyword === "anyOf") { - if(err.children && err.children.length > 0) { - if(err.schema.length === 1) { - const lastChild = err.children[err.children.length - 1]; - const remainingChildren = err.children.slice(0, err.children.length - 1); - return WebpackOptionsValidationError.formatValidationError(Object.assign({}, lastChild, { - children: remainingChildren, - parentSchema: Object.assign({}, err.parentSchema, lastChild.parentSchema) - })); - } - return `${dataPath} should be one of these:\n${getSchemaPartText(err.parentSchema)}\n` + - `Details:\n${filterChildren(err.children).map(err => " * " + indent(WebpackOptionsValidationError.formatValidationError(err), " ", false)).join("\n")}`; - } - return `${dataPath} should be one of these:\n${getSchemaPartText(err.parentSchema)}`; - - } else if(err.keyword === "enum") { - if(err.parentSchema && err.parentSchema.enum && err.parentSchema.enum.length === 1) { - return `${dataPath} should be ${getSchemaPartText(err.parentSchema)}`; - } - return `${dataPath} should be one of these:\n${getSchemaPartText(err.parentSchema)}`; - } else if(err.keyword === "allOf") { - return `${dataPath} should be:\n${getSchemaPartText(err.parentSchema)}`; - } else if(err.keyword === "type") { - switch(err.params.type) { - case "object": - return `${dataPath} should be an object.${getSchemaPartDescription(err.parentSchema)}`; - case "string": - return `${dataPath} should be a string.${getSchemaPartDescription(err.parentSchema)}`; - case "boolean": - return `${dataPath} should be a boolean.${getSchemaPartDescription(err.parentSchema)}`; - case "number": - return `${dataPath} should be a number.${getSchemaPartDescription(err.parentSchema)}`; - case "array": - return `${dataPath} should be an array:\n${getSchemaPartText(err.parentSchema)}`; - } - return `${dataPath} should be ${err.params.type}:\n${getSchemaPartText(err.parentSchema)}`; - } else if(err.keyword === "instanceof") { - return `${dataPath} should be an instance of ${getSchemaPartText(err.parentSchema)}`; - } else if(err.keyword === "required") { - const missingProperty = err.params.missingProperty.replace(/^\./, ""); - return `${dataPath} misses the property '${missingProperty}'.\n${getSchemaPartText(err.parentSchema, ["properties", missingProperty])}`; - } else if(err.keyword === "minimum") { - return `${dataPath} ${err.message}.${getSchemaPartDescription(err.parentSchema)}`; - } else if(err.keyword === "uniqueItems") { - return `${dataPath} should not contain the item '${err.data[err.params.i]}' twice.${getSchemaPartDescription(err.parentSchema)}`; - } else if(err.keyword === "minLength" || err.keyword === "minItems" || err.keyword === "minProperties") { - if(err.params.limit === 1) - return `${dataPath} should not be empty.${getSchemaPartDescription(err.parentSchema)}`; - else - return `${dataPath} ${err.message}${getSchemaPartDescription(err.parentSchema)}`; - } else if(err.keyword === "absolutePath") { - const baseMessage = `${dataPath}: ${err.message}${getSchemaPartDescription(err.parentSchema)}`; - if(dataPath === "configuration.output.filename") { - return `${baseMessage}\n` + - "Please use output.path to specify absolute path and output.filename for the file name."; - } - return baseMessage; - } else { - // eslint-disable-line no-fallthrough - return `${dataPath} ${err.message} (${JSON.stringify(err, 0, 2)}).\n${getSchemaPartText(err.parentSchema)}`; - } - } -} - -module.exports = WebpackOptionsValidationError; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Gajus Kuizinas @gajus +*/ +"use strict"; + +const WebpackError = require("./WebpackError"); +const webpackOptionsSchema = require("../schemas/WebpackOptions.json"); + +const getSchemaPart = (path, parents, additionalPath) => { + parents = parents || 0; + path = path.split("/"); + path = path.slice(0, path.length - parents); + if (additionalPath) { + additionalPath = additionalPath.split("/"); + path = path.concat(additionalPath); + } + let schemaPart = webpackOptionsSchema; + for (let i = 1; i < path.length; i++) { + const inner = schemaPart[path[i]]; + if (inner) schemaPart = inner; + } + return schemaPart; +}; + +const getSchemaPartText = (schemaPart, additionalPath) => { + if (additionalPath) { + for (let i = 0; i < additionalPath.length; i++) { + const inner = schemaPart[additionalPath[i]]; + if (inner) schemaPart = inner; + } + } + while (schemaPart.$ref) { + schemaPart = getSchemaPart(schemaPart.$ref); + } + let schemaText = WebpackOptionsValidationError.formatSchema(schemaPart); + if (schemaPart.description) { + schemaText += `\n-> ${schemaPart.description}`; + } + return schemaText; +}; + +const getSchemaPartDescription = schemaPart => { + while (schemaPart.$ref) { + schemaPart = getSchemaPart(schemaPart.$ref); + } + if (schemaPart.description) { + return `\n-> ${schemaPart.description}`; + } + return ""; +}; + +const filterChildren = children => { + return children.filter( + err => + err.keyword !== "anyOf" && + err.keyword !== "allOf" && + err.keyword !== "oneOf" + ); +}; + +const indent = (str, prefix, firstLine) => { + if (firstLine) { + return prefix + str.replace(/\n(?!$)/g, "\n" + prefix); + } else { + return str.replace(/\n(?!$)/g, `\n${prefix}`); + } +}; + +class WebpackOptionsValidationError extends WebpackError { + constructor(validationErrors) { + super( + "Invalid configuration object. " + + "Webpack has been initialised using a configuration object that does not match the API schema.\n" + + validationErrors + .map( + err => + " - " + + indent( + WebpackOptionsValidationError.formatValidationError(err), + " ", + false + ) + ) + .join("\n") + ); + + this.name = "WebpackOptionsValidationError"; + this.validationErrors = validationErrors; + + Error.captureStackTrace(this, this.constructor); + } + + static formatSchema(schema, prevSchemas) { + prevSchemas = prevSchemas || []; + + const formatInnerSchema = (innerSchema, addSelf) => { + if (!addSelf) { + return WebpackOptionsValidationError.formatSchema( + innerSchema, + prevSchemas + ); + } + if (prevSchemas.includes(innerSchema)) { + return "(recursive)"; + } + return WebpackOptionsValidationError.formatSchema( + innerSchema, + prevSchemas.concat(schema) + ); + }; + + if (schema.type === "string") { + if (schema.minLength === 1) { + return "non-empty string"; + } + if (schema.minLength > 1) { + return `string (min length ${schema.minLength})`; + } + return "string"; + } + if (schema.type === "boolean") { + return "boolean"; + } + if (schema.type === "number") { + return "number"; + } + if (schema.type === "object") { + if (schema.properties) { + const required = schema.required || []; + return `object { ${Object.keys(schema.properties) + .map(property => { + if (!required.includes(property)) return property + "?"; + return property; + }) + .concat(schema.additionalProperties ? ["…"] : []) + .join(", ")} }`; + } + if (schema.additionalProperties) { + return `object { : ${formatInnerSchema( + schema.additionalProperties + )} }`; + } + return "object"; + } + if (schema.type === "array") { + return `[${formatInnerSchema(schema.items)}]`; + } + + switch (schema.instanceof) { + case "Function": + return "function"; + case "RegExp": + return "RegExp"; + } + + if (schema.$ref) { + return formatInnerSchema(getSchemaPart(schema.$ref), true); + } + if (schema.allOf) { + return schema.allOf.map(formatInnerSchema).join(" & "); + } + if (schema.oneOf) { + return schema.oneOf.map(formatInnerSchema).join(" | "); + } + if (schema.anyOf) { + return schema.anyOf.map(formatInnerSchema).join(" | "); + } + if (schema.enum) { + return schema.enum.map(item => JSON.stringify(item)).join(" | "); + } + return JSON.stringify(schema, null, 2); + } + + static formatValidationError(err) { + const dataPath = `configuration${err.dataPath}`; + if (err.keyword === "additionalProperties") { + const baseMessage = `${dataPath} has an unknown property '${ + err.params.additionalProperty + }'. These properties are valid:\n${getSchemaPartText(err.parentSchema)}`; + if (!err.dataPath) { + switch (err.params.additionalProperty) { + case "debug": + return ( + `${baseMessage}\n` + + "The 'debug' property was removed in webpack 2.0.0.\n" + + "Loaders should be updated to allow passing this option via loader options in module.rules.\n" + + "Until loaders are updated one can use the LoaderOptionsPlugin to switch loaders into debug mode:\n" + + "plugins: [\n" + + " new webpack.LoaderOptionsPlugin({\n" + + " debug: true\n" + + " })\n" + + "]" + ); + } + return ( + `${baseMessage}\n` + + "For typos: please correct them.\n" + + "For loader options: webpack >= v2.0.0 no longer allows custom properties in configuration.\n" + + " Loaders should be updated to allow passing options via loader options in module.rules.\n" + + " Until loaders are updated one can use the LoaderOptionsPlugin to pass these options to the loader:\n" + + " plugins: [\n" + + " new webpack.LoaderOptionsPlugin({\n" + + " // test: /\\.xxx$/, // may apply this only for some modules\n" + + " options: {\n" + + ` ${err.params.additionalProperty}: …\n` + + " }\n" + + " })\n" + + " ]" + ); + } + return baseMessage; + } else if (err.keyword === "oneOf" || err.keyword === "anyOf") { + if (err.children && err.children.length > 0) { + if (err.schema.length === 1) { + const lastChild = err.children[err.children.length - 1]; + const remainingChildren = err.children.slice( + 0, + err.children.length - 1 + ); + return WebpackOptionsValidationError.formatValidationError( + Object.assign({}, lastChild, { + children: remainingChildren, + parentSchema: Object.assign( + {}, + err.parentSchema, + lastChild.parentSchema + ) + }) + ); + } + return ( + `${dataPath} should be one of these:\n${getSchemaPartText( + err.parentSchema + )}\n` + + `Details:\n${filterChildren(err.children) + .map( + err => + " * " + + indent( + WebpackOptionsValidationError.formatValidationError(err), + " ", + false + ) + ) + .join("\n")}` + ); + } + return `${dataPath} should be one of these:\n${getSchemaPartText( + err.parentSchema + )}`; + } else if (err.keyword === "enum") { + if ( + err.parentSchema && + err.parentSchema.enum && + err.parentSchema.enum.length === 1 + ) { + return `${dataPath} should be ${getSchemaPartText(err.parentSchema)}`; + } + return `${dataPath} should be one of these:\n${getSchemaPartText( + err.parentSchema + )}`; + } else if (err.keyword === "allOf") { + return `${dataPath} should be:\n${getSchemaPartText(err.parentSchema)}`; + } else if (err.keyword === "type") { + switch (err.params.type) { + case "object": + return `${dataPath} should be an object.${getSchemaPartDescription( + err.parentSchema + )}`; + case "string": + return `${dataPath} should be a string.${getSchemaPartDescription( + err.parentSchema + )}`; + case "boolean": + return `${dataPath} should be a boolean.${getSchemaPartDescription( + err.parentSchema + )}`; + case "number": + return `${dataPath} should be a number.${getSchemaPartDescription( + err.parentSchema + )}`; + case "array": + return `${dataPath} should be an array:\n${getSchemaPartText( + err.parentSchema + )}`; + } + return `${dataPath} should be ${err.params.type}:\n${getSchemaPartText( + err.parentSchema + )}`; + } else if (err.keyword === "instanceof") { + return `${dataPath} should be an instance of ${getSchemaPartText( + err.parentSchema + )}`; + } else if (err.keyword === "required") { + const missingProperty = err.params.missingProperty.replace(/^\./, ""); + return `${dataPath} misses the property '${missingProperty}'.\n${getSchemaPartText( + err.parentSchema, + ["properties", missingProperty] + )}`; + } else if (err.keyword === "minimum") { + return `${dataPath} ${err.message}.${getSchemaPartDescription( + err.parentSchema + )}`; + } else if (err.keyword === "uniqueItems") { + return `${dataPath} should not contain the item '${ + err.data[err.params.i] + }' twice.${getSchemaPartDescription(err.parentSchema)}`; + } else if ( + err.keyword === "minLength" || + err.keyword === "minItems" || + err.keyword === "minProperties" + ) { + if (err.params.limit === 1) { + return `${dataPath} should not be empty.${getSchemaPartDescription( + err.parentSchema + )}`; + } else { + return `${dataPath} ${err.message}${getSchemaPartDescription( + err.parentSchema + )}`; + } + } else if (err.keyword === "absolutePath") { + const baseMessage = `${dataPath}: ${ + err.message + }${getSchemaPartDescription(err.parentSchema)}`; + if (dataPath === "configuration.output.filename") { + return ( + `${baseMessage}\n` + + "Please use output.path to specify absolute path and output.filename for the file name." + ); + } + return baseMessage; + } else { + return `${dataPath} ${err.message} (${JSON.stringify( + err, + null, + 2 + )}).\n${getSchemaPartText(err.parentSchema)}`; + } + } +} + +module.exports = WebpackOptionsValidationError; diff --git a/node_modules/webpack/lib/compareLocations.js b/node_modules/webpack/lib/compareLocations.js index b8a4a118a..3840eb893 100644 --- a/node_modules/webpack/lib/compareLocations.js +++ b/node_modules/webpack/lib/compareLocations.js @@ -1,36 +1,52 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -module.exports = function compareLocations(a, b) { - if(typeof a === "string") { - if(typeof b === "string") { - if(a < b) return -1; - if(a > b) return 1; - return 0; - } else if(typeof b === "object") { - return 1; - } else { - return 0; - } - } else if(typeof a === "object") { - if(typeof b === "string") { - return -1; - } else if(typeof b === "object") { - if(a.start && b.start) { - const ap = a.start; - const bp = b.start; - if(ap.line < bp.line) return -1; - if(ap.line > bp.line) return 1; - if(ap.column < bp.column) return -1; - if(ap.column > bp.column) return 1; - } - if(a.index < b.index) return -1; - if(a.index > b.index) return 1; - return 0; - } else { - return 0; - } - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +/** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */ + +// TODO webpack 5 remove string type from a and b +/** + * Compare two locations + * @param {string|DependencyLocation} a A location node + * @param {string|DependencyLocation} b A location node + * @returns {-1|0|1} sorting comparator value + */ +module.exports = (a, b) => { + if (typeof a === "string") { + if (typeof b === "string") { + if (a < b) return -1; + if (a > b) return 1; + return 0; + } else if (typeof b === "object") { + return 1; + } else { + return 0; + } + } else if (typeof a === "object") { + if (typeof b === "string") { + return -1; + } else if (typeof b === "object") { + if ("start" in a && "start" in b) { + const ap = a.start; + const bp = b.start; + if (ap.line < bp.line) return -1; + if (ap.line > bp.line) return 1; + if (ap.column < bp.column) return -1; + if (ap.column > bp.column) return 1; + } + if ("name" in a && "name" in b) { + if (a.name < b.name) return -1; + if (a.name > b.name) return 1; + } + if ("index" in a && "index" in b) { + if (a.index < b.index) return -1; + if (a.index > b.index) return 1; + } + return 0; + } else { + return 0; + } + } +}; diff --git a/node_modules/webpack/lib/dependencies/AMDDefineDependency.js b/node_modules/webpack/lib/dependencies/AMDDefineDependency.js index f290326e9..fcec365d5 100644 --- a/node_modules/webpack/lib/dependencies/AMDDefineDependency.js +++ b/node_modules/webpack/lib/dependencies/AMDDefineDependency.js @@ -1,142 +1,137 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const NullDependency = require("./NullDependency"); - -class AMDDefineDependency extends NullDependency { - constructor(range, arrayRange, functionRange, objectRange, namedModule) { - super(); - this.range = range; - this.arrayRange = arrayRange; - this.functionRange = functionRange; - this.objectRange = objectRange; - this.namedModule = namedModule; - } - - get type() { - return "amd define"; - } -} - -AMDDefineDependency.Template = class AMDDefineDependencyTemplate { - get definitions() { - return { - f: [ - "var __WEBPACK_AMD_DEFINE_RESULT__;", - `!(__WEBPACK_AMD_DEFINE_RESULT__ = (#).call(exports, __webpack_require__, exports, module), - __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))` - ], - o: [ - "", - "!(module.exports = #)" - ], - of: [ - "var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;", - `!(__WEBPACK_AMD_DEFINE_FACTORY__ = (#), - __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? - (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : - __WEBPACK_AMD_DEFINE_FACTORY__), - __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))` - ], - af: [ - "var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;", - `!(__WEBPACK_AMD_DEFINE_ARRAY__ = #, __WEBPACK_AMD_DEFINE_RESULT__ = (#).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), - __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))` - ], - ao: [ - "", - "!(#, module.exports = #)" - ], - aof: [ - "var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;", - `!(__WEBPACK_AMD_DEFINE_ARRAY__ = #, __WEBPACK_AMD_DEFINE_FACTORY__ = (#), - __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? - (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), - __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))` - ], - lf: [ - "var XXX, XXXmodule;", - "!(XXXmodule = { id: YYY, exports: {}, loaded: false }, XXX = #.call(XXXmodule.exports, __webpack_require__, XXXmodule.exports, XXXmodule), XXXmodule.loaded = true, XXX === undefined && (XXX = XXXmodule.exports))" - ], - lo: [ - "var XXX;", - "!(XXX = #)" - ], - lof: [ - "var XXX, XXXfactory, XXXmodule;", - "!(XXXfactory = (#), (XXXmodule = { id: YYY, exports: {}, loaded: false }), XXX = (typeof XXXfactory === 'function' ? (XXXfactory.call(XXXmodule.exports, __webpack_require__, XXXmodule.exports, XXXmodule)) : XXXfactory), (XXXmodule.loaded = true), XXX === undefined && (XXX = XXXmodule.exports))" - ], - laf: [ - "var __WEBPACK_AMD_DEFINE_ARRAY__, XXX;", - "!(__WEBPACK_AMD_DEFINE_ARRAY__ = #, XXX = ((#).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)))" - ], - lao: [ - "var XXX;", - "!(#, XXX = #)" - ], - laof: [ - "var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_FACTORY__, XXX;", - `!(__WEBPACK_AMD_DEFINE_ARRAY__ = #, __WEBPACK_AMD_DEFINE_FACTORY__ = (#), - XXX = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? - (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__))` - ] - }; - } - - apply(dependency, source) { - const branch = this.branch(dependency); - const defAndText = this.definitions[branch]; - const definitions = defAndText[0]; - const text = defAndText[1]; - this.replace(dependency, source, definitions, text); - } - - localModuleVar(dependency) { - return dependency.localModule && dependency.localModule.used && dependency.localModule.variableName(); - } - - branch(dependency) { - const localModuleVar = this.localModuleVar(dependency) ? "l" : ""; - const arrayRange = dependency.arrayRange ? "a" : ""; - const objectRange = dependency.objectRange ? "o" : ""; - const functionRange = dependency.functionRange ? "f" : ""; - return localModuleVar + arrayRange + objectRange + functionRange; - } - - replace(dependency, source, definition, text) { - const localModuleVar = this.localModuleVar(dependency); - if(localModuleVar) { - text = text.replace(/XXX/g, localModuleVar.replace(/\$/g, "$$$$")); - definition = definition.replace(/XXX/g, localModuleVar.replace(/\$/g, "$$$$")); - } - - if(dependency.namedModule) { - text = text.replace(/YYY/g, JSON.stringify(dependency.namedModule)); - } - - const texts = text.split("#"); - - if(definition) source.insert(0, definition); - - let current = dependency.range[0]; - if(dependency.arrayRange) { - source.replace(current, dependency.arrayRange[0] - 1, texts.shift()); - current = dependency.arrayRange[1]; - } - - if(dependency.objectRange) { - source.replace(current, dependency.objectRange[0] - 1, texts.shift()); - current = dependency.objectRange[1]; - } else if(dependency.functionRange) { - source.replace(current, dependency.functionRange[0] - 1, texts.shift()); - current = dependency.functionRange[1]; - } - source.replace(current, dependency.range[1] - 1, texts.shift()); - if(texts.length > 0) - throw new Error("Implementation error"); - } -}; - -module.exports = AMDDefineDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const NullDependency = require("./NullDependency"); + +class AMDDefineDependency extends NullDependency { + constructor(range, arrayRange, functionRange, objectRange, namedModule) { + super(); + this.range = range; + this.arrayRange = arrayRange; + this.functionRange = functionRange; + this.objectRange = objectRange; + this.namedModule = namedModule; + this.localModule = null; + } + + get type() { + return "amd define"; + } +} + +AMDDefineDependency.Template = class AMDDefineDependencyTemplate { + get definitions() { + return { + f: [ + "var __WEBPACK_AMD_DEFINE_RESULT__;", + `!(__WEBPACK_AMD_DEFINE_RESULT__ = (#).call(exports, __webpack_require__, exports, module), + __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))` + ], + o: ["", "!(module.exports = #)"], + of: [ + "var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;", + `!(__WEBPACK_AMD_DEFINE_FACTORY__ = (#), + __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? + (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : + __WEBPACK_AMD_DEFINE_FACTORY__), + __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))` + ], + af: [ + "var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;", + `!(__WEBPACK_AMD_DEFINE_ARRAY__ = #, __WEBPACK_AMD_DEFINE_RESULT__ = (#).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), + __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))` + ], + ao: ["", "!(#, module.exports = #)"], + aof: [ + "var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;", + `!(__WEBPACK_AMD_DEFINE_ARRAY__ = #, __WEBPACK_AMD_DEFINE_FACTORY__ = (#), + __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? + (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), + __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))` + ], + lf: [ + "var XXX, XXXmodule;", + "!(XXXmodule = { id: YYY, exports: {}, loaded: false }, XXX = #.call(XXXmodule.exports, __webpack_require__, XXXmodule.exports, XXXmodule), XXXmodule.loaded = true, XXX === undefined && (XXX = XXXmodule.exports))" + ], + lo: ["var XXX;", "!(XXX = #)"], + lof: [ + "var XXX, XXXfactory, XXXmodule;", + "!(XXXfactory = (#), (XXXmodule = { id: YYY, exports: {}, loaded: false }), XXX = (typeof XXXfactory === 'function' ? (XXXfactory.call(XXXmodule.exports, __webpack_require__, XXXmodule.exports, XXXmodule)) : XXXfactory), (XXXmodule.loaded = true), XXX === undefined && (XXX = XXXmodule.exports))" + ], + laf: [ + "var __WEBPACK_AMD_DEFINE_ARRAY__, XXX;", + "!(__WEBPACK_AMD_DEFINE_ARRAY__ = #, XXX = ((#).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)))" + ], + lao: ["var XXX;", "!(#, XXX = #)"], + laof: [ + "var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_FACTORY__, XXX;", + `!(__WEBPACK_AMD_DEFINE_ARRAY__ = #, __WEBPACK_AMD_DEFINE_FACTORY__ = (#), + XXX = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? + (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__))` + ] + }; + } + + apply(dependency, source) { + const branch = this.branch(dependency); + const defAndText = this.definitions[branch]; + const definitions = defAndText[0]; + const text = defAndText[1]; + this.replace(dependency, source, definitions, text); + } + + localModuleVar(dependency) { + return ( + dependency.localModule && + dependency.localModule.used && + dependency.localModule.variableName() + ); + } + + branch(dependency) { + const localModuleVar = this.localModuleVar(dependency) ? "l" : ""; + const arrayRange = dependency.arrayRange ? "a" : ""; + const objectRange = dependency.objectRange ? "o" : ""; + const functionRange = dependency.functionRange ? "f" : ""; + return localModuleVar + arrayRange + objectRange + functionRange; + } + + replace(dependency, source, definition, text) { + const localModuleVar = this.localModuleVar(dependency); + if (localModuleVar) { + text = text.replace(/XXX/g, localModuleVar.replace(/\$/g, "$$$$")); + definition = definition.replace( + /XXX/g, + localModuleVar.replace(/\$/g, "$$$$") + ); + } + + if (dependency.namedModule) { + text = text.replace(/YYY/g, JSON.stringify(dependency.namedModule)); + } + + const texts = text.split("#"); + + if (definition) source.insert(0, definition); + + let current = dependency.range[0]; + if (dependency.arrayRange) { + source.replace(current, dependency.arrayRange[0] - 1, texts.shift()); + current = dependency.arrayRange[1]; + } + + if (dependency.objectRange) { + source.replace(current, dependency.objectRange[0] - 1, texts.shift()); + current = dependency.objectRange[1]; + } else if (dependency.functionRange) { + source.replace(current, dependency.functionRange[0] - 1, texts.shift()); + current = dependency.functionRange[1]; + } + source.replace(current, dependency.range[1] - 1, texts.shift()); + if (texts.length > 0) throw new Error("Implementation error"); + } +}; + +module.exports = AMDDefineDependency; diff --git a/node_modules/webpack/lib/dependencies/AMDDefineDependencyParserPlugin.js b/node_modules/webpack/lib/dependencies/AMDDefineDependencyParserPlugin.js index 227f68d36..95e862d12 100644 --- a/node_modules/webpack/lib/dependencies/AMDDefineDependencyParserPlugin.js +++ b/node_modules/webpack/lib/dependencies/AMDDefineDependencyParserPlugin.js @@ -1,266 +1,334 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const AMDRequireItemDependency = require("./AMDRequireItemDependency"); -const AMDRequireContextDependency = require("./AMDRequireContextDependency"); -const ConstDependency = require("./ConstDependency"); -const AMDDefineDependency = require("./AMDDefineDependency"); -const AMDRequireArrayDependency = require("./AMDRequireArrayDependency"); -const LocalModuleDependency = require("./LocalModuleDependency"); -const ContextDependencyHelpers = require("./ContextDependencyHelpers"); -const LocalModulesHelpers = require("./LocalModulesHelpers"); - -function isBoundFunctionExpression(expr) { - if(expr.type !== "CallExpression") return false; - if(expr.callee.type !== "MemberExpression") return false; - if(expr.callee.computed) return false; - if(expr.callee.object.type !== "FunctionExpression") return false; - if(expr.callee.property.type !== "Identifier") return false; - if(expr.callee.property.name !== "bind") return false; - return true; -} - -function isUnboundFunctionExpression(expr) { - if(expr.type === "FunctionExpression") return true; - if(expr.type === "ArrowFunctionExpression") return true; - return false; -} - -function isCallable(expr) { - if(isUnboundFunctionExpression(expr)) return true; - if(isBoundFunctionExpression(expr)) return true; - return false; -} - -class AMDDefineDependencyParserPlugin { - constructor(options) { - this.options = options; - } - - newDefineDependency(range, arrayRange, functionRange, objectRange, namedModule) { - return new AMDDefineDependency(range, arrayRange, functionRange, objectRange, namedModule); - } - - apply(parser) { - const options = this.options; - parser.plugin("call define", (expr) => { - let array, fn, obj, namedModule; - switch(expr.arguments.length) { - case 1: - if(isCallable(expr.arguments[0])) { - // define(f() {...}) - fn = expr.arguments[0]; - } else if(expr.arguments[0].type === "ObjectExpression") { - // define({...}) - obj = expr.arguments[0]; - } else { - // define(expr) - // unclear if function or object - obj = fn = expr.arguments[0]; - } - break; - case 2: - if(expr.arguments[0].type === "Literal") { - namedModule = expr.arguments[0].value; - // define("...", ...) - if(isCallable(expr.arguments[1])) { - // define("...", f() {...}) - fn = expr.arguments[1]; - } else if(expr.arguments[1].type === "ObjectExpression") { - // define("...", {...}) - obj = expr.arguments[1]; - } else { - // define("...", expr) - // unclear if function or object - obj = fn = expr.arguments[1]; - } - } else { - array = expr.arguments[0]; - if(isCallable(expr.arguments[1])) { - // define([...], f() {}) - fn = expr.arguments[1]; - } else if(expr.arguments[1].type === "ObjectExpression") { - // define([...], {...}) - obj = expr.arguments[1]; - } else { - // define([...], expr) - // unclear if function or object - obj = fn = expr.arguments[1]; - } - } - break; - case 3: - // define("...", [...], f() {...}) - namedModule = expr.arguments[0].value; - array = expr.arguments[1]; - if(isCallable(expr.arguments[2])) { - // define("...", [...], f() {}) - fn = expr.arguments[2]; - } else if(expr.arguments[2].type === "ObjectExpression") { - // define("...", [...], {...}) - obj = expr.arguments[2]; - } else { - // define("...", [...], expr) - // unclear if function or object - obj = fn = expr.arguments[2]; - } - break; - default: - return; - } - let fnParams = null; - let fnParamsOffset = 0; - if(fn) { - if(isUnboundFunctionExpression(fn)) fnParams = fn.params; - else if(isBoundFunctionExpression(fn)) { - fnParams = fn.callee.object.params; - fnParamsOffset = fn.arguments.length - 1; - if(fnParamsOffset < 0) fnParamsOffset = 0; - } - } - let fnRenames = Object.create(parser.scope.renames); - let identifiers; - if(array) { - identifiers = {}; - const param = parser.evaluateExpression(array); - const result = parser.applyPluginsBailResult("call define:amd:array", expr, param, identifiers, namedModule); - if(!result) return; - if(fnParams) fnParams = fnParams.slice(fnParamsOffset).filter((param, idx) => { - if(identifiers[idx]) { - fnRenames["$" + param.name] = identifiers[idx]; - return false; - } - return true; - }); - } else { - identifiers = ["require", "exports", "module"]; - if(fnParams) fnParams = fnParams.slice(fnParamsOffset).filter((param, idx) => { - if(identifiers[idx]) { - fnRenames["$" + param.name] = identifiers[idx]; - return false; - } - return true; - }); - } - let inTry; - if(fn && isUnboundFunctionExpression(fn)) { - inTry = parser.scope.inTry; - parser.inScope(fnParams, () => { - parser.scope.renames = fnRenames; - parser.scope.inTry = inTry; - if(fn.body.type === "BlockStatement") - parser.walkStatement(fn.body); - else - parser.walkExpression(fn.body); - }); - } else if(fn && isBoundFunctionExpression(fn)) { - inTry = parser.scope.inTry; - parser.inScope(fn.callee.object.params.filter((i) => ["require", "module", "exports"].indexOf(i.name) < 0), () => { - parser.scope.renames = fnRenames; - parser.scope.inTry = inTry; - if(fn.callee.object.body.type === "BlockStatement") - parser.walkStatement(fn.callee.object.body); - else - parser.walkExpression(fn.callee.object.body); - }); - if(fn.arguments) - parser.walkExpressions(fn.arguments); - } else if(fn || obj) { - parser.walkExpression(fn || obj); - } - - const dep = this.newDefineDependency( - expr.range, - array ? array.range : null, - fn ? fn.range : null, - obj ? obj.range : null, - namedModule ? namedModule : null - ); - dep.loc = expr.loc; - if(namedModule) { - dep.localModule = LocalModulesHelpers.addLocalModule(parser.state, namedModule); - } - parser.state.current.addDependency(dep); - return true; - }); - parser.plugin("call define:amd:array", (expr, param, identifiers, namedModule) => { - if(param.isArray()) { - param.items.forEach((param, idx) => { - if(param.isString() && ["require", "module", "exports"].indexOf(param.string) >= 0) - identifiers[idx] = param.string; - const result = parser.applyPluginsBailResult("call define:amd:item", expr, param, namedModule); - if(result === undefined) { - parser.applyPluginsBailResult("call define:amd:context", expr, param); - } - }); - return true; - } else if(param.isConstArray()) { - const deps = []; - param.array.forEach((request, idx) => { - let dep; - let localModule; - if(request === "require") { - identifiers[idx] = request; - dep = "__webpack_require__"; - } else if(["exports", "module"].indexOf(request) >= 0) { - identifiers[idx] = request; - dep = request; - } else if(localModule = LocalModulesHelpers.getLocalModule(parser.state, request)) { // eslint-disable-line no-cond-assign - dep = new LocalModuleDependency(localModule); - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - } else { - dep = new AMDRequireItemDependency(request); - dep.loc = expr.loc; - dep.optional = !!parser.scope.inTry; - parser.state.current.addDependency(dep); - } - deps.push(dep); - }); - const dep = new AMDRequireArrayDependency(deps, param.range); - dep.loc = expr.loc; - dep.optional = !!parser.scope.inTry; - parser.state.current.addDependency(dep); - return true; - } - }); - parser.plugin("call define:amd:item", (expr, param, namedModule) => { - if(param.isConditional()) { - param.options.forEach((param) => { - const result = parser.applyPluginsBailResult("call define:amd:item", expr, param); - if(result === undefined) { - parser.applyPluginsBailResult("call define:amd:context", expr, param); - } - }); - return true; - } else if(param.isString()) { - let dep, localModule; - if(param.string === "require") { - dep = new ConstDependency("__webpack_require__", param.range); - } else if(["require", "exports", "module"].indexOf(param.string) >= 0) { - dep = new ConstDependency(param.string, param.range); - } else if(localModule = LocalModulesHelpers.getLocalModule(parser.state, param.string, namedModule)) { // eslint-disable-line no-cond-assign - dep = new LocalModuleDependency(localModule, param.range); - } else { - dep = new AMDRequireItemDependency(param.string, param.range); - } - dep.loc = expr.loc; - dep.optional = !!parser.scope.inTry; - parser.state.current.addDependency(dep); - return true; - } - }); - parser.plugin("call define:amd:context", (expr, param) => { - const dep = ContextDependencyHelpers.create(AMDRequireContextDependency, param.range, param, expr, options); - if(!dep) return; - dep.loc = expr.loc; - dep.optional = !!parser.scope.inTry; - parser.state.current.addDependency(dep); - return true; - }); - } -} -module.exports = AMDDefineDependencyParserPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const AMDRequireItemDependency = require("./AMDRequireItemDependency"); +const AMDRequireContextDependency = require("./AMDRequireContextDependency"); +const ConstDependency = require("./ConstDependency"); +const AMDDefineDependency = require("./AMDDefineDependency"); +const AMDRequireArrayDependency = require("./AMDRequireArrayDependency"); +const LocalModuleDependency = require("./LocalModuleDependency"); +const ContextDependencyHelpers = require("./ContextDependencyHelpers"); +const LocalModulesHelpers = require("./LocalModulesHelpers"); + +const isBoundFunctionExpression = expr => { + if (expr.type !== "CallExpression") return false; + if (expr.callee.type !== "MemberExpression") return false; + if (expr.callee.computed) return false; + if (expr.callee.object.type !== "FunctionExpression") return false; + if (expr.callee.property.type !== "Identifier") return false; + if (expr.callee.property.name !== "bind") return false; + return true; +}; + +const isUnboundFunctionExpression = expr => { + if (expr.type === "FunctionExpression") return true; + if (expr.type === "ArrowFunctionExpression") return true; + return false; +}; + +const isCallable = expr => { + if (isUnboundFunctionExpression(expr)) return true; + if (isBoundFunctionExpression(expr)) return true; + return false; +}; + +class AMDDefineDependencyParserPlugin { + constructor(options) { + this.options = options; + } + + apply(parser) { + parser.hooks.call + .for("define") + .tap( + "AMDDefineDependencyParserPlugin", + this.processCallDefine.bind(this, parser) + ); + } + + processArray(parser, expr, param, identifiers, namedModule) { + if (param.isArray()) { + param.items.forEach((param, idx) => { + if ( + param.isString() && + ["require", "module", "exports"].includes(param.string) + ) + identifiers[idx] = param.string; + const result = this.processItem(parser, expr, param, namedModule); + if (result === undefined) { + this.processContext(parser, expr, param); + } + }); + return true; + } else if (param.isConstArray()) { + const deps = []; + param.array.forEach((request, idx) => { + let dep; + let localModule; + if (request === "require") { + identifiers[idx] = request; + dep = "__webpack_require__"; + } else if (["exports", "module"].includes(request)) { + identifiers[idx] = request; + dep = request; + } else if ( + (localModule = LocalModulesHelpers.getLocalModule( + parser.state, + request + )) + ) { + dep = new LocalModuleDependency(localModule, undefined, false); + dep.loc = expr.loc; + parser.state.current.addDependency(dep); + } else { + dep = this.newRequireItemDependency(request); + dep.loc = expr.loc; + dep.optional = !!parser.scope.inTry; + parser.state.current.addDependency(dep); + } + deps.push(dep); + }); + const dep = this.newRequireArrayDependency(deps, param.range); + dep.loc = expr.loc; + dep.optional = !!parser.scope.inTry; + parser.state.current.addDependency(dep); + return true; + } + } + processItem(parser, expr, param, namedModule) { + if (param.isConditional()) { + param.options.forEach(param => { + const result = this.processItem(parser, expr, param); + if (result === undefined) { + this.processContext(parser, expr, param); + } + }); + return true; + } else if (param.isString()) { + let dep, localModule; + if (param.string === "require") { + dep = new ConstDependency("__webpack_require__", param.range); + } else if (["require", "exports", "module"].includes(param.string)) { + dep = new ConstDependency(param.string, param.range); + } else if ( + (localModule = LocalModulesHelpers.getLocalModule( + parser.state, + param.string, + namedModule + )) + ) { + dep = new LocalModuleDependency(localModule, param.range, false); + } else { + dep = this.newRequireItemDependency(param.string, param.range); + } + dep.loc = expr.loc; + dep.optional = !!parser.scope.inTry; + parser.state.current.addDependency(dep); + return true; + } + } + processContext(parser, expr, param) { + const dep = ContextDependencyHelpers.create( + AMDRequireContextDependency, + param.range, + param, + expr, + this.options + ); + if (!dep) return; + dep.loc = expr.loc; + dep.optional = !!parser.scope.inTry; + parser.state.current.addDependency(dep); + return true; + } + + processCallDefine(parser, expr) { + let array, fn, obj, namedModule; + switch (expr.arguments.length) { + case 1: + if (isCallable(expr.arguments[0])) { + // define(f() {…}) + fn = expr.arguments[0]; + } else if (expr.arguments[0].type === "ObjectExpression") { + // define({…}) + obj = expr.arguments[0]; + } else { + // define(expr) + // unclear if function or object + obj = fn = expr.arguments[0]; + } + break; + case 2: + if (expr.arguments[0].type === "Literal") { + namedModule = expr.arguments[0].value; + // define("…", …) + if (isCallable(expr.arguments[1])) { + // define("…", f() {…}) + fn = expr.arguments[1]; + } else if (expr.arguments[1].type === "ObjectExpression") { + // define("…", {…}) + obj = expr.arguments[1]; + } else { + // define("…", expr) + // unclear if function or object + obj = fn = expr.arguments[1]; + } + } else { + array = expr.arguments[0]; + if (isCallable(expr.arguments[1])) { + // define([…], f() {}) + fn = expr.arguments[1]; + } else if (expr.arguments[1].type === "ObjectExpression") { + // define([…], {…}) + obj = expr.arguments[1]; + } else { + // define([…], expr) + // unclear if function or object + obj = fn = expr.arguments[1]; + } + } + break; + case 3: + // define("…", […], f() {…}) + namedModule = expr.arguments[0].value; + array = expr.arguments[1]; + if (isCallable(expr.arguments[2])) { + // define("…", […], f() {}) + fn = expr.arguments[2]; + } else if (expr.arguments[2].type === "ObjectExpression") { + // define("…", […], {…}) + obj = expr.arguments[2]; + } else { + // define("…", […], expr) + // unclear if function or object + obj = fn = expr.arguments[2]; + } + break; + default: + return; + } + let fnParams = null; + let fnParamsOffset = 0; + if (fn) { + if (isUnboundFunctionExpression(fn)) { + fnParams = fn.params; + } else if (isBoundFunctionExpression(fn)) { + fnParams = fn.callee.object.params; + fnParamsOffset = fn.arguments.length - 1; + if (fnParamsOffset < 0) { + fnParamsOffset = 0; + } + } + } + let fnRenames = parser.scope.renames.createChild(); + if (array) { + const identifiers = {}; + const param = parser.evaluateExpression(array); + const result = this.processArray( + parser, + expr, + param, + identifiers, + namedModule + ); + if (!result) return; + if (fnParams) { + fnParams = fnParams.slice(fnParamsOffset).filter((param, idx) => { + if (identifiers[idx]) { + fnRenames.set(param.name, identifiers[idx]); + return false; + } + return true; + }); + } + } else { + const identifiers = ["require", "exports", "module"]; + if (fnParams) { + fnParams = fnParams.slice(fnParamsOffset).filter((param, idx) => { + if (identifiers[idx]) { + fnRenames.set(param.name, identifiers[idx]); + return false; + } + return true; + }); + } + } + let inTry; + if (fn && isUnboundFunctionExpression(fn)) { + inTry = parser.scope.inTry; + parser.inScope(fnParams, () => { + parser.scope.renames = fnRenames; + parser.scope.inTry = inTry; + if (fn.body.type === "BlockStatement") { + parser.walkStatement(fn.body); + } else { + parser.walkExpression(fn.body); + } + }); + } else if (fn && isBoundFunctionExpression(fn)) { + inTry = parser.scope.inTry; + parser.inScope( + fn.callee.object.params.filter( + i => !["require", "module", "exports"].includes(i.name) + ), + () => { + parser.scope.renames = fnRenames; + parser.scope.inTry = inTry; + if (fn.callee.object.body.type === "BlockStatement") { + parser.walkStatement(fn.callee.object.body); + } else { + parser.walkExpression(fn.callee.object.body); + } + } + ); + if (fn.arguments) { + parser.walkExpressions(fn.arguments); + } + } else if (fn || obj) { + parser.walkExpression(fn || obj); + } + + const dep = this.newDefineDependency( + expr.range, + array ? array.range : null, + fn ? fn.range : null, + obj ? obj.range : null, + namedModule ? namedModule : null + ); + dep.loc = expr.loc; + if (namedModule) { + dep.localModule = LocalModulesHelpers.addLocalModule( + parser.state, + namedModule + ); + } + parser.state.current.addDependency(dep); + return true; + } + + newDefineDependency( + range, + arrayRange, + functionRange, + objectRange, + namedModule + ) { + return new AMDDefineDependency( + range, + arrayRange, + functionRange, + objectRange, + namedModule + ); + } + newRequireArrayDependency(depsArray, range) { + return new AMDRequireArrayDependency(depsArray, range); + } + newRequireItemDependency(request, range) { + return new AMDRequireItemDependency(request, range); + } +} +module.exports = AMDDefineDependencyParserPlugin; diff --git a/node_modules/webpack/lib/dependencies/AMDPlugin.js b/node_modules/webpack/lib/dependencies/AMDPlugin.js index 944241c23..d113491c9 100644 --- a/node_modules/webpack/lib/dependencies/AMDPlugin.js +++ b/node_modules/webpack/lib/dependencies/AMDPlugin.js @@ -1,119 +1,249 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const path = require("path"); -const AMDRequireDependency = require("./AMDRequireDependency"); -const AMDRequireItemDependency = require("./AMDRequireItemDependency"); -const AMDRequireArrayDependency = require("./AMDRequireArrayDependency"); -const AMDRequireContextDependency = require("./AMDRequireContextDependency"); -const AMDDefineDependency = require("./AMDDefineDependency"); -const UnsupportedDependency = require("./UnsupportedDependency"); -const LocalModuleDependency = require("./LocalModuleDependency"); - -const NullFactory = require("../NullFactory"); - -const AMDRequireDependenciesBlockParserPlugin = require("./AMDRequireDependenciesBlockParserPlugin"); -const AMDDefineDependencyParserPlugin = require("./AMDDefineDependencyParserPlugin"); - -const AliasPlugin = require("enhanced-resolve/lib/AliasPlugin"); - -const ParserHelpers = require("../ParserHelpers"); - -class AMDPlugin { - constructor(options, amdOptions) { - this.amdOptions = amdOptions; - this.options = options; - } - - apply(compiler) { - const options = this.options; - const amdOptions = this.amdOptions; - compiler.plugin("compilation", (compilation, params) => { - const normalModuleFactory = params.normalModuleFactory; - const contextModuleFactory = params.contextModuleFactory; - - compilation.dependencyFactories.set(AMDRequireDependency, new NullFactory()); - compilation.dependencyTemplates.set(AMDRequireDependency, new AMDRequireDependency.Template()); - - compilation.dependencyFactories.set(AMDRequireItemDependency, normalModuleFactory); - compilation.dependencyTemplates.set(AMDRequireItemDependency, new AMDRequireItemDependency.Template()); - - compilation.dependencyFactories.set(AMDRequireArrayDependency, new NullFactory()); - compilation.dependencyTemplates.set(AMDRequireArrayDependency, new AMDRequireArrayDependency.Template()); - - compilation.dependencyFactories.set(AMDRequireContextDependency, contextModuleFactory); - compilation.dependencyTemplates.set(AMDRequireContextDependency, new AMDRequireContextDependency.Template()); - - compilation.dependencyFactories.set(AMDDefineDependency, new NullFactory()); - compilation.dependencyTemplates.set(AMDDefineDependency, new AMDDefineDependency.Template()); - - compilation.dependencyFactories.set(UnsupportedDependency, new NullFactory()); - compilation.dependencyTemplates.set(UnsupportedDependency, new UnsupportedDependency.Template()); - - compilation.dependencyFactories.set(LocalModuleDependency, new NullFactory()); - compilation.dependencyTemplates.set(LocalModuleDependency, new LocalModuleDependency.Template()); - - params.normalModuleFactory.plugin("parser", (parser, parserOptions) => { - - if(typeof parserOptions.amd !== "undefined" && !parserOptions.amd) - return; - - function setExpressionToModule(outerExpr, module) { - parser.plugin("expression " + outerExpr, (expr) => { - const dep = new AMDRequireItemDependency(module, expr.range); - dep.userRequest = outerExpr; - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - return true; - }); - } - - parser.apply( - new AMDRequireDependenciesBlockParserPlugin(options), - new AMDDefineDependencyParserPlugin(options) - ); - setExpressionToModule("require.amd", "!!webpack amd options"); - setExpressionToModule("define.amd", "!!webpack amd options"); - setExpressionToModule("define", "!!webpack amd define"); - parser.plugin("expression __webpack_amd_options__", () => - parser.state.current.addVariable("__webpack_amd_options__", JSON.stringify(amdOptions))); - parser.plugin("evaluate typeof define.amd", ParserHelpers.evaluateToString(typeof amdOptions)); - parser.plugin("evaluate typeof require.amd", ParserHelpers.evaluateToString(typeof amdOptions)); - parser.plugin("evaluate Identifier define.amd", ParserHelpers.evaluateToIdentifier("define.amd", true)); - parser.plugin("evaluate Identifier require.amd", ParserHelpers.evaluateToIdentifier("require.amd", true)); - parser.plugin("typeof define", ParserHelpers.toConstantDependency(JSON.stringify("function"))); - parser.plugin("evaluate typeof define", ParserHelpers.evaluateToString("function")); - parser.plugin("can-rename define", ParserHelpers.approve); - parser.plugin("rename define", (expr) => { - const dep = new AMDRequireItemDependency("!!webpack amd define", expr.range); - dep.userRequest = "define"; - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - return false; - }); - parser.plugin("typeof require", ParserHelpers.toConstantDependency(JSON.stringify("function"))); - parser.plugin("evaluate typeof require", ParserHelpers.evaluateToString("function")); - }); - }); - compiler.plugin("after-resolvers", () => { - compiler.resolvers.normal.apply( - new AliasPlugin("described-resolve", { - name: "amdefine", - alias: path.join(__dirname, "..", "..", "buildin", "amd-define.js") - }, "resolve"), - new AliasPlugin("described-resolve", { - name: "webpack amd options", - alias: path.join(__dirname, "..", "..", "buildin", "amd-options.js") - }, "resolve"), - new AliasPlugin("described-resolve", { - name: "webpack amd define", - alias: path.join(__dirname, "..", "..", "buildin", "amd-define.js") - }, "resolve") - ); - }); - } -} -module.exports = AMDPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const path = require("path"); +const AMDRequireDependency = require("./AMDRequireDependency"); +const AMDRequireItemDependency = require("./AMDRequireItemDependency"); +const AMDRequireArrayDependency = require("./AMDRequireArrayDependency"); +const AMDRequireContextDependency = require("./AMDRequireContextDependency"); +const AMDDefineDependency = require("./AMDDefineDependency"); +const UnsupportedDependency = require("./UnsupportedDependency"); +const LocalModuleDependency = require("./LocalModuleDependency"); + +const NullFactory = require("../NullFactory"); + +const AMDRequireDependenciesBlockParserPlugin = require("./AMDRequireDependenciesBlockParserPlugin"); +const AMDDefineDependencyParserPlugin = require("./AMDDefineDependencyParserPlugin"); + +const AliasPlugin = require("enhanced-resolve/lib/AliasPlugin"); + +const ParserHelpers = require("../ParserHelpers"); + +class AMDPlugin { + constructor(options, amdOptions) { + this.amdOptions = amdOptions; + this.options = options; + } + + apply(compiler) { + const options = this.options; + const amdOptions = this.amdOptions; + compiler.hooks.compilation.tap( + "AMDPlugin", + (compilation, { contextModuleFactory, normalModuleFactory }) => { + compilation.dependencyFactories.set( + AMDRequireDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + AMDRequireDependency, + new AMDRequireDependency.Template() + ); + + compilation.dependencyFactories.set( + AMDRequireItemDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + AMDRequireItemDependency, + new AMDRequireItemDependency.Template() + ); + + compilation.dependencyFactories.set( + AMDRequireArrayDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + AMDRequireArrayDependency, + new AMDRequireArrayDependency.Template() + ); + + compilation.dependencyFactories.set( + AMDRequireContextDependency, + contextModuleFactory + ); + compilation.dependencyTemplates.set( + AMDRequireContextDependency, + new AMDRequireContextDependency.Template() + ); + + compilation.dependencyFactories.set( + AMDDefineDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + AMDDefineDependency, + new AMDDefineDependency.Template() + ); + + compilation.dependencyFactories.set( + UnsupportedDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + UnsupportedDependency, + new UnsupportedDependency.Template() + ); + + compilation.dependencyFactories.set( + LocalModuleDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + LocalModuleDependency, + new LocalModuleDependency.Template() + ); + + const handler = (parser, parserOptions) => { + if (parserOptions.amd !== undefined && !parserOptions.amd) return; + + const setExpressionToModule = (outerExpr, module) => { + parser.hooks.expression.for(outerExpr).tap("AMDPlugin", expr => { + const dep = new AMDRequireItemDependency(module, expr.range); + dep.userRequest = outerExpr; + dep.loc = expr.loc; + parser.state.current.addDependency(dep); + return true; + }); + }; + + new AMDRequireDependenciesBlockParserPlugin(options).apply(parser); + new AMDDefineDependencyParserPlugin(options).apply(parser); + + setExpressionToModule("require.amd", "!!webpack amd options"); + setExpressionToModule("define.amd", "!!webpack amd options"); + setExpressionToModule("define", "!!webpack amd define"); + + parser.hooks.expression + .for("__webpack_amd_options__") + .tap("AMDPlugin", () => + parser.state.current.addVariable( + "__webpack_amd_options__", + JSON.stringify(amdOptions) + ) + ); + parser.hooks.evaluateTypeof + .for("define.amd") + .tap( + "AMDPlugin", + ParserHelpers.evaluateToString(typeof amdOptions) + ); + parser.hooks.evaluateTypeof + .for("require.amd") + .tap( + "AMDPlugin", + ParserHelpers.evaluateToString(typeof amdOptions) + ); + parser.hooks.evaluateIdentifier + .for("define.amd") + .tap( + "AMDPlugin", + ParserHelpers.evaluateToIdentifier("define.amd", true) + ); + parser.hooks.evaluateIdentifier + .for("require.amd") + .tap( + "AMDPlugin", + ParserHelpers.evaluateToIdentifier("require.amd", true) + ); + parser.hooks.typeof + .for("define") + .tap( + "AMDPlugin", + ParserHelpers.toConstantDependency( + parser, + JSON.stringify("function") + ) + ); + parser.hooks.evaluateTypeof + .for("define") + .tap("AMDPlugin", ParserHelpers.evaluateToString("function")); + parser.hooks.canRename + .for("define") + .tap("AMDPlugin", ParserHelpers.approve); + parser.hooks.rename.for("define").tap("AMDPlugin", expr => { + const dep = new AMDRequireItemDependency( + "!!webpack amd define", + expr.range + ); + dep.userRequest = "define"; + dep.loc = expr.loc; + parser.state.current.addDependency(dep); + return false; + }); + parser.hooks.typeof + .for("require") + .tap( + "AMDPlugin", + ParserHelpers.toConstantDependency( + parser, + JSON.stringify("function") + ) + ); + parser.hooks.evaluateTypeof + .for("require") + .tap("AMDPlugin", ParserHelpers.evaluateToString("function")); + }; + + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("AMDPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("AMDPlugin", handler); + } + ); + compiler.hooks.afterResolvers.tap("AMDPlugin", () => { + compiler.resolverFactory.hooks.resolver + .for("normal") + .tap("AMDPlugin", resolver => { + new AliasPlugin( + "described-resolve", + { + name: "amdefine", + alias: path.join( + __dirname, + "..", + "..", + "buildin", + "amd-define.js" + ) + }, + "resolve" + ).apply(resolver); + new AliasPlugin( + "described-resolve", + { + name: "webpack amd options", + alias: path.join( + __dirname, + "..", + "..", + "buildin", + "amd-options.js" + ) + }, + "resolve" + ).apply(resolver); + new AliasPlugin( + "described-resolve", + { + name: "webpack amd define", + alias: path.join( + __dirname, + "..", + "..", + "buildin", + "amd-define.js" + ) + }, + "resolve" + ).apply(resolver); + }); + }); + } +} +module.exports = AMDPlugin; diff --git a/node_modules/webpack/lib/dependencies/AMDRequireArrayDependency.js b/node_modules/webpack/lib/dependencies/AMDRequireArrayDependency.js index ad77b0705..ddb9c293f 100644 --- a/node_modules/webpack/lib/dependencies/AMDRequireArrayDependency.js +++ b/node_modules/webpack/lib/dependencies/AMDRequireArrayDependency.js @@ -1,58 +1,49 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const Dependency = require("../Dependency"); -const webpackMissingModuleModule = require("./WebpackMissingModule").module; - -class AMDRequireArrayDependency extends Dependency { - constructor(depsArray, range) { - super(); - this.depsArray = depsArray; - this.range = range; - } - - get type() { - return "amd require array"; - } -} - -AMDRequireArrayDependency.Template = class AMDRequireArrayDependencyTemplate { - apply(dep, source, outputOptions, requestShortener) { - const content = this.getContent(dep, outputOptions, requestShortener); - source.replace(dep.range[0], dep.range[1] - 1, content); - } - - getContent(dep, outputOptions, requestShortener) { - const requires = dep.depsArray.map((dependency) => { - const optionalComment = this.optionalComment(outputOptions.pathinfo, requestShortener.shorten(dependency.request)); - return this.contentForDependency(dependency, optionalComment); - }); - return `[${requires.join(", ")}]`; - } - - optionalComment(pathInfo, shortenedRequest) { - if(!pathInfo) { - return ""; - } - return `/*! ${shortenedRequest} */ `; - } - - contentForDependency(dep, comment) { - if(typeof dep === "string") { - return dep; - } - - if(dep.module) { - const stringifiedId = JSON.stringify(dep.module.id); - return `__webpack_require__(${comment}${stringifiedId})`; - } else if(dep.localModule) { - return dep.localModule.variableName(); - } - - return webpackMissingModuleModule(dep.request); - } -}; - -module.exports = AMDRequireArrayDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const Dependency = require("../Dependency"); + +class AMDRequireArrayDependency extends Dependency { + constructor(depsArray, range) { + super(); + this.depsArray = depsArray; + this.range = range; + } + + get type() { + return "amd require array"; + } +} + +AMDRequireArrayDependency.Template = class AMDRequireArrayDependencyTemplate { + apply(dep, source, runtime) { + const content = this.getContent(dep, runtime); + source.replace(dep.range[0], dep.range[1] - 1, content); + } + + getContent(dep, runtime) { + const requires = dep.depsArray.map(dependency => { + return this.contentForDependency(dependency, runtime); + }); + return `[${requires.join(", ")}]`; + } + + contentForDependency(dep, runtime) { + if (typeof dep === "string") { + return dep; + } + + if (dep.localModule) { + return dep.localModule.variableName(); + } else { + return runtime.moduleExports({ + module: dep.module, + request: dep.request + }); + } + } +}; + +module.exports = AMDRequireArrayDependency; diff --git a/node_modules/webpack/lib/dependencies/AMDRequireContextDependency.js b/node_modules/webpack/lib/dependencies/AMDRequireContextDependency.js index 5305288cf..b2e60b5b9 100644 --- a/node_modules/webpack/lib/dependencies/AMDRequireContextDependency.js +++ b/node_modules/webpack/lib/dependencies/AMDRequireContextDependency.js @@ -1,20 +1,20 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ContextDependency = require("./ContextDependency"); -class AMDRequireContextDependency extends ContextDependency { - constructor(request, recursive, regExp, range, valueRange) { - super(request, recursive, regExp); - this.range = range; - this.valueRange = valueRange; - } - - get type() { - return "amd require context"; - } -} -AMDRequireContextDependency.Template = require("./ContextDependencyTemplateAsRequireCall"); -module.exports = AMDRequireContextDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const ContextDependency = require("./ContextDependency"); +class AMDRequireContextDependency extends ContextDependency { + constructor(options, range, valueRange) { + super(options); + this.range = range; + this.valueRange = valueRange; + } + + get type() { + return "amd require context"; + } +} +AMDRequireContextDependency.Template = require("./ContextDependencyTemplateAsRequireCall"); +module.exports = AMDRequireContextDependency; diff --git a/node_modules/webpack/lib/dependencies/AMDRequireDependenciesBlock.js b/node_modules/webpack/lib/dependencies/AMDRequireDependenciesBlock.js index 92f5299ee..f86191b4a 100644 --- a/node_modules/webpack/lib/dependencies/AMDRequireDependenciesBlock.js +++ b/node_modules/webpack/lib/dependencies/AMDRequireDependenciesBlock.js @@ -1,33 +1,43 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const AsyncDependenciesBlock = require("../AsyncDependenciesBlock"); -const AMDRequireDependency = require("./AMDRequireDependency"); - -module.exports = class AMDRequireDependenciesBlock extends AsyncDependenciesBlock { - constructor(expr, arrayRange, functionRange, errorCallbackRange, module, loc) { - super(null, module, loc); - this.expr = expr; - this.outerRange = expr.range; - this.arrayRange = arrayRange; - this.functionRange = functionRange; - this.errorCallbackRange = errorCallbackRange; - this.bindThis = true; - if(arrayRange && functionRange && errorCallbackRange) { - this.range = [arrayRange[0], errorCallbackRange[1]]; - } else if(arrayRange && functionRange) { - this.range = [arrayRange[0], functionRange[1]]; - } else if(arrayRange) { - this.range = arrayRange; - } else if(functionRange) { - this.range = functionRange; - } else { - this.range = expr.range; - } - const dep = new AMDRequireDependency(this); - dep.loc = loc; - this.addDependency(dep); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const AsyncDependenciesBlock = require("../AsyncDependenciesBlock"); +const AMDRequireDependency = require("./AMDRequireDependency"); + +module.exports = class AMDRequireDependenciesBlock extends AsyncDependenciesBlock { + constructor( + expr, + arrayRange, + functionRange, + errorCallbackRange, + module, + loc, + request + ) { + super(null, module, loc, request); + this.expr = expr; + this.outerRange = expr.range; + this.arrayRange = arrayRange; + this.functionBindThis = false; + this.functionRange = functionRange; + this.errorCallbackBindThis = false; + this.errorCallbackRange = errorCallbackRange; + this.bindThis = true; + if (arrayRange && functionRange && errorCallbackRange) { + this.range = [arrayRange[0], errorCallbackRange[1]]; + } else if (arrayRange && functionRange) { + this.range = [arrayRange[0], functionRange[1]]; + } else if (arrayRange) { + this.range = arrayRange; + } else if (functionRange) { + this.range = functionRange; + } else { + this.range = expr.range; + } + const dep = new AMDRequireDependency(this); + dep.loc = loc; + this.addDependency(dep); + } +}; diff --git a/node_modules/webpack/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js b/node_modules/webpack/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js index 8bd7ae425..e6826722e 100644 --- a/node_modules/webpack/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +++ b/node_modules/webpack/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js @@ -1,177 +1,272 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const AMDRequireItemDependency = require("./AMDRequireItemDependency"); -const AMDRequireArrayDependency = require("./AMDRequireArrayDependency"); -const AMDRequireContextDependency = require("./AMDRequireContextDependency"); -const AMDRequireDependenciesBlock = require("./AMDRequireDependenciesBlock"); -const UnsupportedDependency = require("./UnsupportedDependency"); -const LocalModuleDependency = require("./LocalModuleDependency"); -const ContextDependencyHelpers = require("./ContextDependencyHelpers"); -const LocalModulesHelpers = require("./LocalModulesHelpers"); -const ConstDependency = require("./ConstDependency"); -const getFunctionExpression = require("./getFunctionExpression"); -const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning"); - -class AMDRequireDependenciesBlockParserPlugin { - constructor(options) { - this.options = options; - } - - processFunctionArgument(parser, expression) { - let bindThis = true; - const fnData = getFunctionExpression(expression); - if(fnData) { - parser.inScope(fnData.fn.params.filter((i) => { - return ["require", "module", "exports"].indexOf(i.name) < 0; - }), () => { - if(fnData.fn.body.type === "BlockStatement") - parser.walkStatement(fnData.fn.body); - else - parser.walkExpression(fnData.fn.body); - }); - parser.walkExpressions(fnData.expressions); - if(fnData.needThis === false) { - bindThis = false; - } - } else { - parser.walkExpression(expression); - } - return bindThis; - } - - apply(parser) { - const options = this.options; - parser.plugin("call require", (expr) => { - let param; - let dep; - let result; - - const old = parser.state.current; - - if(expr.arguments.length >= 1) { - param = parser.evaluateExpression(expr.arguments[0]); - dep = new AMDRequireDependenciesBlock( - expr, - param.range, - (expr.arguments.length > 1) ? expr.arguments[1].range : null, - (expr.arguments.length > 2) ? expr.arguments[2].range : null, - parser.state.module, - expr.loc - ); - parser.state.current = dep; - } - - if(expr.arguments.length === 1) { - parser.inScope([], () => { - result = parser.applyPluginsBailResult("call require:amd:array", expr, param); - }); - parser.state.current = old; - if(!result) return; - parser.state.current.addBlock(dep); - return true; - } - - if(expr.arguments.length === 2 || expr.arguments.length === 3) { - try { - parser.inScope([], () => { - result = parser.applyPluginsBailResult("call require:amd:array", expr, param); - }); - if(!result) { - dep = new UnsupportedDependency("unsupported", expr.range); - old.addDependency(dep); - if(parser.state.module) - parser.state.module.errors.push(new UnsupportedFeatureWarning(parser.state.module, "Cannot statically analyse 'require(..., ...)' in line " + expr.loc.start.line)); - dep = null; - return true; - } - dep.functionBindThis = this.processFunctionArgument(parser, expr.arguments[1]); - if(expr.arguments.length === 3) { - dep.errorCallbackBindThis = this.processFunctionArgument(parser, expr.arguments[2]); - } - } finally { - parser.state.current = old; - if(dep) - parser.state.current.addBlock(dep); - } - return true; - } - }); - parser.plugin("call require:amd:array", (expr, param) => { - if(param.isArray()) { - param.items.forEach((param) => { - const result = parser.applyPluginsBailResult("call require:amd:item", expr, param); - if(result === undefined) { - parser.applyPluginsBailResult("call require:amd:context", expr, param); - } - }); - return true; - } else if(param.isConstArray()) { - const deps = []; - param.array.forEach((request) => { - let dep, localModule; - if(request === "require") { - dep = "__webpack_require__"; - } else if(["exports", "module"].indexOf(request) >= 0) { - dep = request; - } else if(localModule = LocalModulesHelpers.getLocalModule(parser.state, request)) { // eslint-disable-line no-cond-assign - dep = new LocalModuleDependency(localModule); - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - } else { - dep = new AMDRequireItemDependency(request); - dep.loc = expr.loc; - dep.optional = !!parser.scope.inTry; - parser.state.current.addDependency(dep); - } - deps.push(dep); - }); - const dep = new AMDRequireArrayDependency(deps, param.range); - dep.loc = expr.loc; - dep.optional = !!parser.scope.inTry; - parser.state.current.addDependency(dep); - return true; - } - }); - parser.plugin("call require:amd:item", (expr, param) => { - if(param.isConditional()) { - param.options.forEach((param) => { - const result = parser.applyPluginsBailResult("call require:amd:item", expr, param); - if(result === undefined) { - parser.applyPluginsBailResult("call require:amd:context", expr, param); - } - }); - return true; - } else if(param.isString()) { - let dep, localModule; - if(param.string === "require") { - dep = new ConstDependency("__webpack_require__", param.string); - } else if(param.string === "module") { - dep = new ConstDependency(parser.state.module.moduleArgument || "module", param.range); - } else if(param.string === "exports") { - dep = new ConstDependency(parser.state.module.exportsArgument || "exports", param.range); - } else if(localModule = LocalModulesHelpers.getLocalModule(parser.state, param.string)) { // eslint-disable-line no-cond-assign - dep = new LocalModuleDependency(localModule, param.range); - } else { - dep = new AMDRequireItemDependency(param.string, param.range); - } - dep.loc = expr.loc; - dep.optional = !!parser.scope.inTry; - parser.state.current.addDependency(dep); - return true; - } - }); - parser.plugin("call require:amd:context", (expr, param) => { - const dep = ContextDependencyHelpers.create(AMDRequireContextDependency, param.range, param, expr, options); - if(!dep) return; - dep.loc = expr.loc; - dep.optional = !!parser.scope.inTry; - parser.state.current.addDependency(dep); - return true; - }); - } -} -module.exports = AMDRequireDependenciesBlockParserPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const AMDRequireItemDependency = require("./AMDRequireItemDependency"); +const AMDRequireArrayDependency = require("./AMDRequireArrayDependency"); +const AMDRequireContextDependency = require("./AMDRequireContextDependency"); +const AMDRequireDependenciesBlock = require("./AMDRequireDependenciesBlock"); +const UnsupportedDependency = require("./UnsupportedDependency"); +const LocalModuleDependency = require("./LocalModuleDependency"); +const ContextDependencyHelpers = require("./ContextDependencyHelpers"); +const LocalModulesHelpers = require("./LocalModulesHelpers"); +const ConstDependency = require("./ConstDependency"); +const getFunctionExpression = require("./getFunctionExpression"); +const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning"); + +class AMDRequireDependenciesBlockParserPlugin { + constructor(options) { + this.options = options; + } + + processFunctionArgument(parser, expression) { + let bindThis = true; + const fnData = getFunctionExpression(expression); + if (fnData) { + parser.inScope( + fnData.fn.params.filter(i => { + return !["require", "module", "exports"].includes(i.name); + }), + () => { + if (fnData.fn.body.type === "BlockStatement") { + parser.walkStatement(fnData.fn.body); + } else { + parser.walkExpression(fnData.fn.body); + } + } + ); + parser.walkExpressions(fnData.expressions); + if (fnData.needThis === false) { + bindThis = false; + } + } else { + parser.walkExpression(expression); + } + return bindThis; + } + + apply(parser) { + parser.hooks.call + .for("require") + .tap( + "AMDRequireDependenciesBlockParserPlugin", + this.processCallRequire.bind(this, parser) + ); + } + + processArray(parser, expr, param) { + if (param.isArray()) { + for (const p of param.items) { + const result = this.processItem(parser, expr, p); + if (result === undefined) { + this.processContext(parser, expr, p); + } + } + return true; + } else if (param.isConstArray()) { + const deps = []; + for (const request of param.array) { + let dep, localModule; + if (request === "require") { + dep = "__webpack_require__"; + } else if (["exports", "module"].includes(request)) { + dep = request; + } else if ( + (localModule = LocalModulesHelpers.getLocalModule( + parser.state, + request + )) + ) { + dep = new LocalModuleDependency(localModule, undefined, false); + dep.loc = expr.loc; + parser.state.current.addDependency(dep); + } else { + dep = this.newRequireItemDependency(request); + dep.loc = expr.loc; + dep.optional = !!parser.scope.inTry; + parser.state.current.addDependency(dep); + } + deps.push(dep); + } + const dep = this.newRequireArrayDependency(deps, param.range); + dep.loc = expr.loc; + dep.optional = !!parser.scope.inTry; + parser.state.current.addDependency(dep); + return true; + } + } + processItem(parser, expr, param) { + if (param.isConditional()) { + for (const p of param.options) { + const result = this.processItem(parser, expr, p); + if (result === undefined) { + this.processContext(parser, expr, p); + } + } + return true; + } else if (param.isString()) { + let dep, localModule; + if (param.string === "require") { + dep = new ConstDependency("__webpack_require__", param.string); + } else if (param.string === "module") { + dep = new ConstDependency( + parser.state.module.buildInfo.moduleArgument, + param.range + ); + } else if (param.string === "exports") { + dep = new ConstDependency( + parser.state.module.buildInfo.exportsArgument, + param.range + ); + } else if ( + (localModule = LocalModulesHelpers.getLocalModule( + parser.state, + param.string + )) + ) { + dep = new LocalModuleDependency(localModule, param.range, false); + } else { + dep = this.newRequireItemDependency(param.string, param.range); + } + dep.loc = expr.loc; + dep.optional = !!parser.scope.inTry; + parser.state.current.addDependency(dep); + return true; + } + } + processContext(parser, expr, param) { + const dep = ContextDependencyHelpers.create( + AMDRequireContextDependency, + param.range, + param, + expr, + this.options + ); + if (!dep) return; + dep.loc = expr.loc; + dep.optional = !!parser.scope.inTry; + parser.state.current.addDependency(dep); + return true; + } + + processArrayForRequestString(param) { + if (param.isArray()) { + const result = param.items.map(item => + this.processItemForRequestString(item) + ); + if (result.every(Boolean)) return result.join(" "); + } else if (param.isConstArray()) { + return param.array.join(" "); + } + } + + processItemForRequestString(param) { + if (param.isConditional()) { + const result = param.options.map(item => + this.processItemForRequestString(item) + ); + if (result.every(Boolean)) return result.join("|"); + } else if (param.isString()) { + return param.string; + } + } + + processCallRequire(parser, expr) { + let param; + let dep; + let result; + + const old = parser.state.current; + + if (expr.arguments.length >= 1) { + param = parser.evaluateExpression(expr.arguments[0]); + dep = this.newRequireDependenciesBlock( + expr, + param.range, + expr.arguments.length > 1 ? expr.arguments[1].range : null, + expr.arguments.length > 2 ? expr.arguments[2].range : null, + parser.state.module, + expr.loc, + this.processArrayForRequestString(param) + ); + parser.state.current = dep; + } + + if (expr.arguments.length === 1) { + parser.inScope([], () => { + result = this.processArray(parser, expr, param); + }); + parser.state.current = old; + if (!result) return; + parser.state.current.addBlock(dep); + return true; + } + + if (expr.arguments.length === 2 || expr.arguments.length === 3) { + try { + parser.inScope([], () => { + result = this.processArray(parser, expr, param); + }); + if (!result) { + dep = new UnsupportedDependency("unsupported", expr.range); + old.addDependency(dep); + if (parser.state.module) { + parser.state.module.errors.push( + new UnsupportedFeatureWarning( + parser.state.module, + "Cannot statically analyse 'require(…, …)' in line " + + expr.loc.start.line, + expr.loc + ) + ); + } + dep = null; + return true; + } + dep.functionBindThis = this.processFunctionArgument( + parser, + expr.arguments[1] + ); + if (expr.arguments.length === 3) { + dep.errorCallbackBindThis = this.processFunctionArgument( + parser, + expr.arguments[2] + ); + } + } finally { + parser.state.current = old; + if (dep) parser.state.current.addBlock(dep); + } + return true; + } + } + + newRequireDependenciesBlock( + expr, + arrayRange, + functionRange, + errorCallbackRange, + module, + loc, + request + ) { + return new AMDRequireDependenciesBlock( + expr, + arrayRange, + functionRange, + errorCallbackRange, + module, + loc, + request + ); + } + newRequireItemDependency(request, range) { + return new AMDRequireItemDependency(request, range); + } + newRequireArrayDependency(depsArray, range) { + return new AMDRequireArrayDependency(depsArray, range); + } +} +module.exports = AMDRequireDependenciesBlockParserPlugin; diff --git a/node_modules/webpack/lib/dependencies/AMDRequireDependency.js b/node_modules/webpack/lib/dependencies/AMDRequireDependency.js index aa5b04a32..fd514e25f 100644 --- a/node_modules/webpack/lib/dependencies/AMDRequireDependency.js +++ b/node_modules/webpack/lib/dependencies/AMDRequireDependency.js @@ -1,67 +1,135 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const NullDependency = require("./NullDependency"); -const DepBlockHelpers = require("./DepBlockHelpers"); - -class AMDRequireDependency extends NullDependency { - constructor(block) { - super(); - this.block = block; - } -} - -AMDRequireDependency.Template = class AMDRequireDependencyTemplate { - apply(dep, source, outputOptions, requestShortener) { - const depBlock = dep.block; - const wrapper = DepBlockHelpers.getLoadDepBlockWrapper(depBlock, outputOptions, requestShortener, "require"); - - // has array range but no function range - if(depBlock.arrayRange && !depBlock.functionRange) { - const startBlock = wrapper[0] + "function() {"; - const endBlock = `;}${wrapper[1]}__webpack_require__.oe${wrapper[2]}`; - source.replace(depBlock.outerRange[0], depBlock.arrayRange[0] - 1, startBlock); - source.replace(depBlock.arrayRange[1], depBlock.outerRange[1] - 1, endBlock); - return; - } - - // has function range but no array range - if(depBlock.functionRange && !depBlock.arrayRange) { - const startBlock = wrapper[0] + "function() {("; - const endBlock = `.call(exports, __webpack_require__, exports, module));}${wrapper[1]}__webpack_require__.oe${wrapper[2]}`; - source.replace(depBlock.outerRange[0], depBlock.functionRange[0] - 1, startBlock); - source.replace(depBlock.functionRange[1], depBlock.outerRange[1] - 1, endBlock); - return; - } - - // has array range, function range, and errorCallbackRange - if(depBlock.arrayRange && depBlock.functionRange && depBlock.errorCallbackRange) { - const startBlock = wrapper[0] + "function() { "; - const errorRangeBlock = `}${depBlock.functionBindThis ? ".bind(this)" : ""}${wrapper[1]}`; - const endBlock = `${depBlock.errorCallbackBindThis ? ".bind(this)" : ""}${wrapper[2]}`; - - source.replace(depBlock.outerRange[0], depBlock.arrayRange[0] - 1, startBlock); - source.insert(depBlock.arrayRange[0] + 0.9, "var __WEBPACK_AMD_REQUIRE_ARRAY__ = "); - source.replace(depBlock.arrayRange[1], depBlock.functionRange[0] - 1, "; (("); - source.insert(depBlock.functionRange[1], ").apply(null, __WEBPACK_AMD_REQUIRE_ARRAY__));"); - source.replace(depBlock.functionRange[1], depBlock.errorCallbackRange[0] - 1, errorRangeBlock); - source.replace(depBlock.errorCallbackRange[1], depBlock.outerRange[1] - 1, endBlock); - return; - } - - // has array range, function range, but no errorCallbackRange - if(depBlock.arrayRange && depBlock.functionRange) { - const startBlock = wrapper[0] + "function() { "; - const endBlock = `}${depBlock.functionBindThis ? ".bind(this)" : ""}${wrapper[1]}__webpack_require__.oe${wrapper[2]}`; - source.replace(depBlock.outerRange[0], depBlock.arrayRange[0] - 1, startBlock); - source.insert(depBlock.arrayRange[0] + 0.9, "var __WEBPACK_AMD_REQUIRE_ARRAY__ = "); - source.replace(depBlock.arrayRange[1], depBlock.functionRange[0] - 1, "; (("); - source.insert(depBlock.functionRange[1], ").apply(null, __WEBPACK_AMD_REQUIRE_ARRAY__));"); - source.replace(depBlock.functionRange[1], depBlock.outerRange[1] - 1, endBlock); - } - } -}; - -module.exports = AMDRequireDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const NullDependency = require("./NullDependency"); + +class AMDRequireDependency extends NullDependency { + constructor(block) { + super(); + this.block = block; + } +} + +AMDRequireDependency.Template = class AMDRequireDependencyTemplate { + apply(dep, source, runtime) { + const depBlock = dep.block; + const promise = runtime.blockPromise({ + block: depBlock, + message: "AMD require" + }); + + // has array range but no function range + if (depBlock.arrayRange && !depBlock.functionRange) { + const startBlock = `${promise}.then(function() {`; + const endBlock = `;}).catch(${runtime.onError()})`; + source.replace( + depBlock.outerRange[0], + depBlock.arrayRange[0] - 1, + startBlock + ); + source.replace( + depBlock.arrayRange[1], + depBlock.outerRange[1] - 1, + endBlock + ); + return; + } + + // has function range but no array range + if (depBlock.functionRange && !depBlock.arrayRange) { + const startBlock = `${promise}.then((`; + const endBlock = `).bind(exports, __webpack_require__, exports, module)).catch(${runtime.onError()})`; + source.replace( + depBlock.outerRange[0], + depBlock.functionRange[0] - 1, + startBlock + ); + source.replace( + depBlock.functionRange[1], + depBlock.outerRange[1] - 1, + endBlock + ); + return; + } + + // has array range, function range, and errorCallbackRange + if ( + depBlock.arrayRange && + depBlock.functionRange && + depBlock.errorCallbackRange + ) { + const startBlock = `${promise}.then(function() { `; + const errorRangeBlock = `}${ + depBlock.functionBindThis ? ".bind(this)" : "" + }).catch(`; + const endBlock = `${ + depBlock.errorCallbackBindThis ? ".bind(this)" : "" + })`; + + source.replace( + depBlock.outerRange[0], + depBlock.arrayRange[0] - 1, + startBlock + ); + source.insert( + depBlock.arrayRange[0] + 0.9, + "var __WEBPACK_AMD_REQUIRE_ARRAY__ = " + ); + source.replace( + depBlock.arrayRange[1], + depBlock.functionRange[0] - 1, + "; (" + ); + source.insert( + depBlock.functionRange[1], + ").apply(null, __WEBPACK_AMD_REQUIRE_ARRAY__);" + ); + source.replace( + depBlock.functionRange[1], + depBlock.errorCallbackRange[0] - 1, + errorRangeBlock + ); + source.replace( + depBlock.errorCallbackRange[1], + depBlock.outerRange[1] - 1, + endBlock + ); + return; + } + + // has array range, function range, but no errorCallbackRange + if (depBlock.arrayRange && depBlock.functionRange) { + const startBlock = `${promise}.then(function() { `; + const endBlock = `}${ + depBlock.functionBindThis ? ".bind(this)" : "" + }).catch(${runtime.onError()})`; + source.replace( + depBlock.outerRange[0], + depBlock.arrayRange[0] - 1, + startBlock + ); + source.insert( + depBlock.arrayRange[0] + 0.9, + "var __WEBPACK_AMD_REQUIRE_ARRAY__ = " + ); + source.replace( + depBlock.arrayRange[1], + depBlock.functionRange[0] - 1, + "; (" + ); + source.insert( + depBlock.functionRange[1], + ").apply(null, __WEBPACK_AMD_REQUIRE_ARRAY__);" + ); + source.replace( + depBlock.functionRange[1], + depBlock.outerRange[1] - 1, + endBlock + ); + } + } +}; + +module.exports = AMDRequireDependency; diff --git a/node_modules/webpack/lib/dependencies/AMDRequireItemDependency.js b/node_modules/webpack/lib/dependencies/AMDRequireItemDependency.js index 60401d533..d033a90d8 100644 --- a/node_modules/webpack/lib/dependencies/AMDRequireItemDependency.js +++ b/node_modules/webpack/lib/dependencies/AMDRequireItemDependency.js @@ -1,22 +1,22 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ModuleDependency = require("./ModuleDependency"); -const ModuleDependencyTemplateAsRequireId = require("./ModuleDependencyTemplateAsRequireId"); - -class AMDRequireItemDependency extends ModuleDependency { - constructor(request, range) { - super(request); - this.range = range; - } - - get type() { - return "amd require"; - } -} - -AMDRequireItemDependency.Template = ModuleDependencyTemplateAsRequireId; - -module.exports = AMDRequireItemDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const ModuleDependency = require("./ModuleDependency"); +const ModuleDependencyTemplateAsRequireId = require("./ModuleDependencyTemplateAsRequireId"); + +class AMDRequireItemDependency extends ModuleDependency { + constructor(request, range) { + super(request); + this.range = range; + } + + get type() { + return "amd require"; + } +} + +AMDRequireItemDependency.Template = ModuleDependencyTemplateAsRequireId; + +module.exports = AMDRequireItemDependency; diff --git a/node_modules/webpack/lib/dependencies/CommonJsPlugin.js b/node_modules/webpack/lib/dependencies/CommonJsPlugin.js index 218cddb3d..6d441a872 100644 --- a/node_modules/webpack/lib/dependencies/CommonJsPlugin.js +++ b/node_modules/webpack/lib/dependencies/CommonJsPlugin.js @@ -1,89 +1,158 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ConstDependency = require("./ConstDependency"); -const CommonJsRequireDependency = require("./CommonJsRequireDependency"); -const CommonJsRequireContextDependency = require("./CommonJsRequireContextDependency"); -const RequireResolveDependency = require("./RequireResolveDependency"); -const RequireResolveContextDependency = require("./RequireResolveContextDependency"); -const RequireResolveHeaderDependency = require("./RequireResolveHeaderDependency"); -const RequireHeaderDependency = require("./RequireHeaderDependency"); - -const NullFactory = require("../NullFactory"); - -const RequireResolveDependencyParserPlugin = require("./RequireResolveDependencyParserPlugin"); -const CommonJsRequireDependencyParserPlugin = require("./CommonJsRequireDependencyParserPlugin"); - -const ParserHelpers = require("../ParserHelpers"); - -class CommonJsPlugin { - constructor(options) { - this.options = options; - } - - apply(compiler) { - const options = this.options; - compiler.plugin("compilation", (compilation, params) => { - const normalModuleFactory = params.normalModuleFactory; - const contextModuleFactory = params.contextModuleFactory; - - compilation.dependencyFactories.set(CommonJsRequireDependency, normalModuleFactory); - compilation.dependencyTemplates.set(CommonJsRequireDependency, new CommonJsRequireDependency.Template()); - - compilation.dependencyFactories.set(CommonJsRequireContextDependency, contextModuleFactory); - compilation.dependencyTemplates.set(CommonJsRequireContextDependency, new CommonJsRequireContextDependency.Template()); - - compilation.dependencyFactories.set(RequireResolveDependency, normalModuleFactory); - compilation.dependencyTemplates.set(RequireResolveDependency, new RequireResolveDependency.Template()); - - compilation.dependencyFactories.set(RequireResolveContextDependency, contextModuleFactory); - compilation.dependencyTemplates.set(RequireResolveContextDependency, new RequireResolveContextDependency.Template()); - - compilation.dependencyFactories.set(RequireResolveHeaderDependency, new NullFactory()); - compilation.dependencyTemplates.set(RequireResolveHeaderDependency, new RequireResolveHeaderDependency.Template()); - - compilation.dependencyFactories.set(RequireHeaderDependency, new NullFactory()); - compilation.dependencyTemplates.set(RequireHeaderDependency, new RequireHeaderDependency.Template()); - - params.normalModuleFactory.plugin("parser", (parser, parserOptions) => { - - if(typeof parserOptions.commonjs !== "undefined" && !parserOptions.commonjs) - return; - - const requireExpressions = ["require", "require.resolve", "require.resolveWeak"]; - for(let expression of requireExpressions) { - parser.plugin(`typeof ${expression}`, ParserHelpers.toConstantDependency(JSON.stringify("function"))); - parser.plugin(`evaluate typeof ${expression}`, ParserHelpers.evaluateToString("function")); - parser.plugin(`evaluate Identifier ${expression}`, ParserHelpers.evaluateToIdentifier(expression, true)); - } - - parser.plugin("evaluate typeof module", ParserHelpers.evaluateToString("object")); - parser.plugin("assign require", (expr) => { - // to not leak to global "require", we need to define a local require here. - const dep = new ConstDependency("var require;", 0); - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - parser.scope.definitions.push("require"); - return true; - }); - parser.plugin("can-rename require", () => true); - parser.plugin("rename require", (expr) => { - // define the require variable. It's still undefined, but not "not defined". - const dep = new ConstDependency("var require;", 0); - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - return false; - }); - parser.plugin("typeof module", () => true); - parser.plugin("evaluate typeof exports", ParserHelpers.evaluateToString("object")); - parser.apply( - new CommonJsRequireDependencyParserPlugin(options), - new RequireResolveDependencyParserPlugin(options) - ); - }); - }); - } -} -module.exports = CommonJsPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const ConstDependency = require("./ConstDependency"); +const CommonJsRequireDependency = require("./CommonJsRequireDependency"); +const CommonJsRequireContextDependency = require("./CommonJsRequireContextDependency"); +const RequireResolveDependency = require("./RequireResolveDependency"); +const RequireResolveContextDependency = require("./RequireResolveContextDependency"); +const RequireResolveHeaderDependency = require("./RequireResolveHeaderDependency"); +const RequireHeaderDependency = require("./RequireHeaderDependency"); + +const NullFactory = require("../NullFactory"); + +const RequireResolveDependencyParserPlugin = require("./RequireResolveDependencyParserPlugin"); +const CommonJsRequireDependencyParserPlugin = require("./CommonJsRequireDependencyParserPlugin"); + +const ParserHelpers = require("../ParserHelpers"); + +class CommonJsPlugin { + constructor(options) { + this.options = options; + } + + apply(compiler) { + const options = this.options; + compiler.hooks.compilation.tap( + "CommonJsPlugin", + (compilation, { contextModuleFactory, normalModuleFactory }) => { + compilation.dependencyFactories.set( + CommonJsRequireDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + CommonJsRequireDependency, + new CommonJsRequireDependency.Template() + ); + + compilation.dependencyFactories.set( + CommonJsRequireContextDependency, + contextModuleFactory + ); + compilation.dependencyTemplates.set( + CommonJsRequireContextDependency, + new CommonJsRequireContextDependency.Template() + ); + + compilation.dependencyFactories.set( + RequireResolveDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + RequireResolveDependency, + new RequireResolveDependency.Template() + ); + + compilation.dependencyFactories.set( + RequireResolveContextDependency, + contextModuleFactory + ); + compilation.dependencyTemplates.set( + RequireResolveContextDependency, + new RequireResolveContextDependency.Template() + ); + + compilation.dependencyFactories.set( + RequireResolveHeaderDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + RequireResolveHeaderDependency, + new RequireResolveHeaderDependency.Template() + ); + + compilation.dependencyFactories.set( + RequireHeaderDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + RequireHeaderDependency, + new RequireHeaderDependency.Template() + ); + + const handler = (parser, parserOptions) => { + if (parserOptions.commonjs !== undefined && !parserOptions.commonjs) + return; + + const requireExpressions = [ + "require", + "require.resolve", + "require.resolveWeak" + ]; + for (let expression of requireExpressions) { + parser.hooks.typeof + .for(expression) + .tap( + "CommonJsPlugin", + ParserHelpers.toConstantDependency( + parser, + JSON.stringify("function") + ) + ); + parser.hooks.evaluateTypeof + .for(expression) + .tap( + "CommonJsPlugin", + ParserHelpers.evaluateToString("function") + ); + parser.hooks.evaluateIdentifier + .for(expression) + .tap( + "CommonJsPlugin", + ParserHelpers.evaluateToIdentifier(expression, true) + ); + } + + parser.hooks.evaluateTypeof + .for("module") + .tap("CommonJsPlugin", ParserHelpers.evaluateToString("object")); + parser.hooks.assign.for("require").tap("CommonJsPlugin", expr => { + // to not leak to global "require", we need to define a local require here. + const dep = new ConstDependency("var require;", 0); + dep.loc = expr.loc; + parser.state.current.addDependency(dep); + parser.scope.definitions.add("require"); + return true; + }); + parser.hooks.canRename + .for("require") + .tap("CommonJsPlugin", () => true); + parser.hooks.rename.for("require").tap("CommonJsPlugin", expr => { + // define the require variable. It's still undefined, but not "not defined". + const dep = new ConstDependency("var require;", 0); + dep.loc = expr.loc; + parser.state.current.addDependency(dep); + return false; + }); + parser.hooks.typeof.for("module").tap("CommonJsPlugin", () => true); + parser.hooks.evaluateTypeof + .for("exports") + .tap("CommonJsPlugin", ParserHelpers.evaluateToString("object")); + + new CommonJsRequireDependencyParserPlugin(options).apply(parser); + new RequireResolveDependencyParserPlugin(options).apply(parser); + }; + + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("CommonJsPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("CommonJsPlugin", handler); + } + ); + } +} +module.exports = CommonJsPlugin; diff --git a/node_modules/webpack/lib/dependencies/CommonJsRequireContextDependency.js b/node_modules/webpack/lib/dependencies/CommonJsRequireContextDependency.js index 6e8e33f08..723a849e7 100644 --- a/node_modules/webpack/lib/dependencies/CommonJsRequireContextDependency.js +++ b/node_modules/webpack/lib/dependencies/CommonJsRequireContextDependency.js @@ -1,24 +1,23 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ContextDependency = require("./ContextDependency"); -const ContextDependencyTemplateAsRequireCall = require("./ContextDependencyTemplateAsRequireCall"); - -class CommonJsRequireContextDependency extends ContextDependency { - constructor(request, recursive, regExp, range, valueRange) { - super(request, recursive, regExp); - this.range = range; - this.valueRange = valueRange; - } - - get type() { - return "cjs require context"; - } - -} - -CommonJsRequireContextDependency.Template = ContextDependencyTemplateAsRequireCall; - -module.exports = CommonJsRequireContextDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const ContextDependency = require("./ContextDependency"); +const ContextDependencyTemplateAsRequireCall = require("./ContextDependencyTemplateAsRequireCall"); + +class CommonJsRequireContextDependency extends ContextDependency { + constructor(options, range, valueRange) { + super(options); + this.range = range; + this.valueRange = valueRange; + } + + get type() { + return "cjs require context"; + } +} + +CommonJsRequireContextDependency.Template = ContextDependencyTemplateAsRequireCall; + +module.exports = CommonJsRequireContextDependency; diff --git a/node_modules/webpack/lib/dependencies/CommonJsRequireDependency.js b/node_modules/webpack/lib/dependencies/CommonJsRequireDependency.js index bd9e68e46..29a30f343 100644 --- a/node_modules/webpack/lib/dependencies/CommonJsRequireDependency.js +++ b/node_modules/webpack/lib/dependencies/CommonJsRequireDependency.js @@ -1,22 +1,22 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ModuleDependency = require("./ModuleDependency"); -const ModuleDependencyTemplateAsId = require("./ModuleDependencyTemplateAsId"); - -class CommonJsRequireDependency extends ModuleDependency { - constructor(request, range) { - super(request); - this.range = range; - } - - get type() { - return "cjs require"; - } -} - -CommonJsRequireDependency.Template = ModuleDependencyTemplateAsId; - -module.exports = CommonJsRequireDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const ModuleDependency = require("./ModuleDependency"); +const ModuleDependencyTemplateAsId = require("./ModuleDependencyTemplateAsId"); + +class CommonJsRequireDependency extends ModuleDependency { + constructor(request, range) { + super(request); + this.range = range; + } + + get type() { + return "cjs require"; + } +} + +CommonJsRequireDependency.Template = ModuleDependencyTemplateAsId; + +module.exports = CommonJsRequireDependency; diff --git a/node_modules/webpack/lib/dependencies/CommonJsRequireDependencyParserPlugin.js b/node_modules/webpack/lib/dependencies/CommonJsRequireDependencyParserPlugin.js index 2e2fee613..875657348 100644 --- a/node_modules/webpack/lib/dependencies/CommonJsRequireDependencyParserPlugin.js +++ b/node_modules/webpack/lib/dependencies/CommonJsRequireDependencyParserPlugin.js @@ -1,89 +1,136 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const CommonJsRequireDependency = require("./CommonJsRequireDependency"); -const CommonJsRequireContextDependency = require("./CommonJsRequireContextDependency"); -const RequireHeaderDependency = require("./RequireHeaderDependency"); -const LocalModuleDependency = require("./LocalModuleDependency"); -const ContextDependencyHelpers = require("./ContextDependencyHelpers"); -const LocalModulesHelpers = require("./LocalModulesHelpers"); -const ParserHelpers = require("../ParserHelpers"); - -class CommonJsRequireDependencyParserPlugin { - constructor(options) { - this.options = options; - } - - apply(parser) { - const options = this.options; - parser.plugin("expression require.cache", ParserHelpers.toConstantDependency("__webpack_require__.c")); - parser.plugin("expression require", (expr) => { - const dep = new CommonJsRequireContextDependency(options.unknownContextRequest, options.unknownContextRecursive, options.unknownContextRegExp, expr.range); - dep.critical = options.unknownContextCritical && "require function is used in a way in which dependencies cannot be statically extracted"; - dep.loc = expr.loc; - dep.optional = !!parser.scope.inTry; - parser.state.current.addDependency(dep); - return true; - }); - parser.plugin("call require", (expr) => { - if(expr.arguments.length !== 1) return; - let localModule; - const param = parser.evaluateExpression(expr.arguments[0]); - if(param.isConditional()) { - let isExpression = false; - const prevLength = parser.state.current.dependencies.length; - const dep = new RequireHeaderDependency(expr.callee.range); - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - param.options.forEach(function(param) { - const result = parser.applyPluginsBailResult("call require:commonjs:item", expr, param); - if(result === undefined) { - isExpression = true; - } - }); - if(isExpression) { - parser.state.current.dependencies.length = prevLength; - } else { - return true; - } - } - if(param.isString() && (localModule = LocalModulesHelpers.getLocalModule(parser.state, param.string))) { - const dep = new LocalModuleDependency(localModule, expr.range); - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - return true; - } else { - const result = parser.applyPluginsBailResult("call require:commonjs:item", expr, param); - if(result === undefined) { - parser.applyPluginsBailResult("call require:commonjs:context", expr, param); - } else { - const dep = new RequireHeaderDependency(expr.callee.range); - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - } - return true; - } - }); - parser.plugin("call require:commonjs:item", (expr, param) => { - if(param.isString()) { - const dep = new CommonJsRequireDependency(param.string, param.range); - dep.loc = expr.loc; - dep.optional = !!parser.scope.inTry; - parser.state.current.addDependency(dep); - return true; - } - }); - parser.plugin("call require:commonjs:context", (expr, param) => { - const dep = ContextDependencyHelpers.create(CommonJsRequireContextDependency, expr.range, param, expr, options); - if(!dep) return; - dep.loc = expr.loc; - dep.optional = !!parser.scope.inTry; - parser.state.current.addDependency(dep); - return true; - }); - } -} -module.exports = CommonJsRequireDependencyParserPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const CommonJsRequireDependency = require("./CommonJsRequireDependency"); +const CommonJsRequireContextDependency = require("./CommonJsRequireContextDependency"); +const RequireHeaderDependency = require("./RequireHeaderDependency"); +const LocalModuleDependency = require("./LocalModuleDependency"); +const ContextDependencyHelpers = require("./ContextDependencyHelpers"); +const LocalModulesHelpers = require("./LocalModulesHelpers"); +const ParserHelpers = require("../ParserHelpers"); + +class CommonJsRequireDependencyParserPlugin { + constructor(options) { + this.options = options; + } + + apply(parser) { + const options = this.options; + + const processItem = (expr, param) => { + if (param.isString()) { + const dep = new CommonJsRequireDependency(param.string, param.range); + dep.loc = expr.loc; + dep.optional = !!parser.scope.inTry; + parser.state.current.addDependency(dep); + return true; + } + }; + const processContext = (expr, param) => { + const dep = ContextDependencyHelpers.create( + CommonJsRequireContextDependency, + expr.range, + param, + expr, + options + ); + if (!dep) return; + dep.loc = expr.loc; + dep.optional = !!parser.scope.inTry; + parser.state.current.addDependency(dep); + return true; + }; + + parser.hooks.expression + .for("require.cache") + .tap( + "CommonJsRequireDependencyParserPlugin", + ParserHelpers.toConstantDependencyWithWebpackRequire( + parser, + "__webpack_require__.c" + ) + ); + parser.hooks.expression + .for("require") + .tap("CommonJsRequireDependencyParserPlugin", expr => { + const dep = new CommonJsRequireContextDependency( + { + request: options.unknownContextRequest, + recursive: options.unknownContextRecursive, + regExp: options.unknownContextRegExp, + mode: "sync" + }, + expr.range + ); + dep.critical = + options.unknownContextCritical && + "require function is used in a way in which dependencies cannot be statically extracted"; + dep.loc = expr.loc; + dep.optional = !!parser.scope.inTry; + parser.state.current.addDependency(dep); + return true; + }); + + const createHandler = callNew => expr => { + if (expr.arguments.length !== 1) return; + let localModule; + const param = parser.evaluateExpression(expr.arguments[0]); + if (param.isConditional()) { + let isExpression = false; + const prevLength = parser.state.current.dependencies.length; + const dep = new RequireHeaderDependency(expr.callee.range); + dep.loc = expr.loc; + parser.state.current.addDependency(dep); + for (const p of param.options) { + const result = processItem(expr, p); + if (result === undefined) { + isExpression = true; + } + } + if (isExpression) { + parser.state.current.dependencies.length = prevLength; + } else { + return true; + } + } + if ( + param.isString() && + (localModule = LocalModulesHelpers.getLocalModule( + parser.state, + param.string + )) + ) { + const dep = new LocalModuleDependency(localModule, expr.range, callNew); + dep.loc = expr.loc; + parser.state.current.addDependency(dep); + return true; + } else { + const result = processItem(expr, param); + if (result === undefined) { + processContext(expr, param); + } else { + const dep = new RequireHeaderDependency(expr.callee.range); + dep.loc = expr.loc; + parser.state.current.addDependency(dep); + } + return true; + } + }; + parser.hooks.call + .for("require") + .tap("CommonJsRequireDependencyParserPlugin", createHandler(false)); + parser.hooks.new + .for("require") + .tap("CommonJsRequireDependencyParserPlugin", createHandler(true)); + parser.hooks.call + .for("module.require") + .tap("CommonJsRequireDependencyParserPlugin", createHandler(false)); + parser.hooks.new + .for("module.require") + .tap("CommonJsRequireDependencyParserPlugin", createHandler(true)); + } +} +module.exports = CommonJsRequireDependencyParserPlugin; diff --git a/node_modules/webpack/lib/dependencies/ConstDependency.js b/node_modules/webpack/lib/dependencies/ConstDependency.js index 2bf2008e5..22edb8e23 100644 --- a/node_modules/webpack/lib/dependencies/ConstDependency.js +++ b/node_modules/webpack/lib/dependencies/ConstDependency.js @@ -1,32 +1,33 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const NullDependency = require("./NullDependency"); - -class ConstDependency extends NullDependency { - constructor(expression, range) { - super(); - this.expression = expression; - this.range = range; - } - - updateHash(hash) { - hash.update(this.range + ""); - hash.update(this.expression + ""); - } -} - -ConstDependency.Template = class ConstDependencyTemplate { - apply(dep, source) { - if(typeof dep.range === "number") { - source.insert(dep.range, dep.expression); - return; - } - - source.replace(dep.range[0], dep.range[1] - 1, dep.expression); - } -}; - -module.exports = ConstDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const NullDependency = require("./NullDependency"); + +class ConstDependency extends NullDependency { + constructor(expression, range, requireWebpackRequire) { + super(); + this.expression = expression; + this.range = range; + this.requireWebpackRequire = requireWebpackRequire; + } + + updateHash(hash) { + hash.update(this.range + ""); + hash.update(this.expression + ""); + } +} + +ConstDependency.Template = class ConstDependencyTemplate { + apply(dep, source) { + if (typeof dep.range === "number") { + source.insert(dep.range, dep.expression); + return; + } + + source.replace(dep.range[0], dep.range[1] - 1, dep.expression); + } +}; + +module.exports = ConstDependency; diff --git a/node_modules/webpack/lib/dependencies/ContextDependency.js b/node_modules/webpack/lib/dependencies/ContextDependency.js index 55bc9823c..10c2fea99 100644 --- a/node_modules/webpack/lib/dependencies/ContextDependency.js +++ b/node_modules/webpack/lib/dependencies/ContextDependency.js @@ -1,49 +1,68 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const Dependency = require("../Dependency"); -const CriticalDependencyWarning = require("./CriticalDependencyWarning"); - -class ContextDependency extends Dependency { - constructor(request, recursive, regExp) { - super(); - this.request = request; - this.userRequest = request; - this.recursive = recursive; - this.regExp = regExp; - this.async = false; - - this.hadGlobalOrStickyRegExp = false; - if(this.regExp.global || this.regExp.sticky) { - this.regExp = null; - this.hadGlobalOrStickyRegExp = true; - } - - } - - isEqualResource(other) { - if(!(other instanceof ContextDependency)) - return false; - - return this.request === other.request && - this.recursive === other.recursive && - this.regExp === other.regExp && - this.async === other.async; - } - - getWarnings() { - let warnings = super.getWarnings() || []; - if(this.critical) { - warnings.push(new CriticalDependencyWarning(this.critical)); - } - if(this.hadGlobalOrStickyRegExp) { - warnings.push(new CriticalDependencyWarning("Contexts can't use RegExps with the 'g' or 'y' flags.")); - } - return warnings; - } - -} - -module.exports = ContextDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const Dependency = require("../Dependency"); +const CriticalDependencyWarning = require("./CriticalDependencyWarning"); + +const regExpToString = r => (r ? r + "" : ""); + +class ContextDependency extends Dependency { + // options: { request, recursive, regExp, include, exclude, mode, chunkName, groupOptions } + constructor(options) { + super(); + this.options = options; + this.userRequest = this.options.request; + /** @type {false | string} */ + this.critical = false; + this.hadGlobalOrStickyRegExp = false; + if (this.options.regExp.global || this.options.regExp.sticky) { + this.options.regExp = null; + this.hadGlobalOrStickyRegExp = true; + } + } + + getResourceIdentifier() { + return ( + `context${this.options.request} ${this.options.recursive} ` + + `${regExpToString(this.options.regExp)} ${regExpToString( + this.options.include + )} ${regExpToString(this.options.exclude)} ` + + `${this.options.mode} ${this.options.chunkName} ` + + `${JSON.stringify(this.options.groupOptions)}` + ); + } + + getWarnings() { + let warnings = super.getWarnings() || []; + if (this.critical) { + warnings.push(new CriticalDependencyWarning(this.critical)); + } + if (this.hadGlobalOrStickyRegExp) { + warnings.push( + new CriticalDependencyWarning( + "Contexts can't use RegExps with the 'g' or 'y' flags." + ) + ); + } + return warnings; + } +} + +// TODO remove in webpack 5 +Object.defineProperty(ContextDependency.prototype, "async", { + configurable: false, + get() { + throw new Error( + "ContextDependency.async was removed. Use ContextDependency.options.mode instead." + ); + }, + set() { + throw new Error( + "ContextDependency.async was removed. Pass options.mode to constructor instead" + ); + } +}); + +module.exports = ContextDependency; diff --git a/node_modules/webpack/lib/dependencies/ContextDependencyHelpers.js b/node_modules/webpack/lib/dependencies/ContextDependencyHelpers.js index 412cee701..2dabc3345 100644 --- a/node_modules/webpack/lib/dependencies/ContextDependencyHelpers.js +++ b/node_modules/webpack/lib/dependencies/ContextDependencyHelpers.js @@ -1,71 +1,177 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ContextDependencyHelpers = exports; - -/** - * Escapes regular expression metacharacters - * @param {string} str String to quote - * @return {string} Escaped string - */ -function quotemeta(str) { - return str.replace(/[-[\]\\/{}()*+?.^$|]/g, "\\$&"); -} - -ContextDependencyHelpers.create = function(Dep, range, param, expr, options, chunkName) { - let dep; - let prefix; - let postfix; - let prefixRange; - let valueRange; - let idx; - let context; - let regExp; - if(param.isTemplateString()) { - prefix = param.quasis[0].string; - postfix = param.quasis.length > 1 ? param.quasis[param.quasis.length - 1].string : ""; - prefixRange = [param.quasis[0].range[0], param.quasis[0].range[1]]; - valueRange = param.range; - idx = prefix.lastIndexOf("/"); - context = "."; - if(idx >= 0) { - context = prefix.substr(0, idx); - prefix = `.${prefix.substr(idx)}`; - } - // If there are more than two quasis, maybe the generated RegExp can be more precise? - regExp = new RegExp(`^${quotemeta(prefix)}${options.wrappedContextRegExp.source}${quotemeta(postfix)}$`); - dep = new Dep(context, options.wrappedContextRecursive, regExp, range, valueRange, chunkName); - dep.loc = expr.loc; - dep.replaces = [{ - range: prefixRange, - value: prefix - }]; - dep.critical = options.wrappedContextCritical && "a part of the request of a dependency is an expression"; - return dep; - } else if(param.isWrapped() && (param.prefix && param.prefix.isString() || param.postfix && param.postfix.isString())) { - prefix = param.prefix && param.prefix.isString() ? param.prefix.string : ""; - postfix = param.postfix && param.postfix.isString() ? param.postfix.string : ""; - prefixRange = param.prefix && param.prefix.isString() ? param.prefix.range : null; - valueRange = [prefixRange ? prefixRange[1] : param.range[0], param.range[1]]; - idx = prefix.lastIndexOf("/"); - context = "."; - if(idx >= 0) { - context = prefix.substr(0, idx); - prefix = `.${prefix.substr(idx)}`; - } - regExp = new RegExp(`^${quotemeta(prefix)}${options.wrappedContextRegExp.source}${quotemeta(postfix)}$`); - dep = new Dep(context, options.wrappedContextRecursive, regExp, range, valueRange, chunkName); - dep.loc = expr.loc; - dep.prepend = param.prefix && param.prefix.isString() ? prefix : null; - dep.critical = options.wrappedContextCritical && "a part of the request of a dependency is an expression"; - return dep; - } else { - dep = new Dep(options.exprContextRequest, options.exprContextRecursive, options.exprContextRegExp, range, param.range, chunkName); - dep.loc = expr.loc; - dep.critical = options.exprContextCritical && "the request of a dependency is an expression"; - return dep; - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const ContextDependencyHelpers = exports; + +/** + * Escapes regular expression metacharacters + * @param {string} str String to quote + * @returns {string} Escaped string + */ +const quotemeta = str => { + return str.replace(/[-[\]\\/{}()*+?.^$|]/g, "\\$&"); +}; + +const splitContextFromPrefix = prefix => { + const idx = prefix.lastIndexOf("/"); + let context = "."; + if (idx >= 0) { + context = prefix.substr(0, idx); + prefix = `.${prefix.substr(idx)}`; + } + return { + context, + prefix + }; +}; + +const splitQueryFromPostfix = postfix => { + const idx = postfix.indexOf("?"); + let query = ""; + if (idx >= 0) { + query = postfix.substr(idx); + postfix = postfix.substr(0, idx); + } + return { + postfix, + query + }; +}; + +ContextDependencyHelpers.create = ( + Dep, + range, + param, + expr, + options, + contextOptions +) => { + if (param.isTemplateString()) { + let prefixRaw = param.quasis[0].string; + let postfixRaw = + param.quasis.length > 1 + ? param.quasis[param.quasis.length - 1].string + : ""; + const prefixRange = [param.quasis[0].range[0], param.quasis[0].range[1]]; + const postfixRange = + param.quasis.length > 1 + ? param.quasis[param.quasis.length - 1].range + : ""; + const valueRange = param.range; + const { context, prefix } = splitContextFromPrefix(prefixRaw); + const { postfix, query } = splitQueryFromPostfix(postfixRaw); + // If there are more than two quasis, maybe the generated RegExp can be more precise? + const regExp = new RegExp( + `^${quotemeta(prefix)}${options.wrappedContextRegExp.source}${quotemeta( + postfix + )}$` + ); + const dep = new Dep( + Object.assign( + { + request: context + query, + recursive: options.wrappedContextRecursive, + regExp, + mode: "sync" + }, + contextOptions + ), + range, + valueRange + ); + dep.loc = expr.loc; + const replaces = []; + if (prefixRange && prefix !== prefixRaw) { + replaces.push({ + range: prefixRange, + value: prefix + }); + } + if (postfixRange && postfix !== postfixRaw) { + replaces.push({ + range: postfixRange, + value: postfix + }); + } + dep.replaces = replaces; + dep.critical = + options.wrappedContextCritical && + "a part of the request of a dependency is an expression"; + return dep; + } else if ( + param.isWrapped() && + ((param.prefix && param.prefix.isString()) || + (param.postfix && param.postfix.isString())) + ) { + let prefixRaw = + param.prefix && param.prefix.isString() ? param.prefix.string : ""; + let postfixRaw = + param.postfix && param.postfix.isString() ? param.postfix.string : ""; + const prefixRange = + param.prefix && param.prefix.isString() ? param.prefix.range : null; + const postfixRange = + param.postfix && param.postfix.isString() ? param.postfix.range : null; + const valueRange = param.range; + const { context, prefix } = splitContextFromPrefix(prefixRaw); + const { postfix, query } = splitQueryFromPostfix(postfixRaw); + const regExp = new RegExp( + `^${quotemeta(prefix)}${options.wrappedContextRegExp.source}${quotemeta( + postfix + )}$` + ); + const dep = new Dep( + Object.assign( + { + request: context + query, + recursive: options.wrappedContextRecursive, + regExp, + mode: "sync" + }, + contextOptions + ), + range, + valueRange + ); + dep.loc = expr.loc; + const replaces = []; + if (prefixRange && prefix !== prefixRaw) { + replaces.push({ + range: prefixRange, + value: JSON.stringify(prefix) + }); + } + if (postfixRange && postfix !== postfixRaw) { + replaces.push({ + range: postfixRange, + value: JSON.stringify(postfix) + }); + } + dep.replaces = replaces; + dep.critical = + options.wrappedContextCritical && + "a part of the request of a dependency is an expression"; + return dep; + } else { + const dep = new Dep( + Object.assign( + { + request: options.exprContextRequest, + recursive: options.exprContextRecursive, + regExp: options.exprContextRegExp, + mode: "sync" + }, + contextOptions + ), + range, + param.range + ); + dep.loc = expr.loc; + dep.critical = + options.exprContextCritical && + "the request of a dependency is an expression"; + return dep; + } +}; diff --git a/node_modules/webpack/lib/dependencies/ContextDependencyTemplateAsId.js b/node_modules/webpack/lib/dependencies/ContextDependencyTemplateAsId.js index f88f6c85c..1ee83ff99 100644 --- a/node_modules/webpack/lib/dependencies/ContextDependencyTemplateAsId.js +++ b/node_modules/webpack/lib/dependencies/ContextDependencyTemplateAsId.js @@ -1,32 +1,43 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class ContextDependencyTemplateAsId { - - apply(dep, source, outputOptions, requestShortener) { - const comment = outputOptions.pathinfo ? - "/*! " + requestShortener.shorten(dep.request) + " */ " : ""; - - if(dep.module && dep.module.dependencies && dep.module.dependencies.length > 0) { - if(dep.valueRange) { - if(Array.isArray(dep.replaces)) { - for(let i = 0; i < dep.replaces.length; i++) { - const rep = dep.replaces[i]; - source.replace(rep.range[0], rep.range[1] - 1, rep.value); - } - } - source.replace(dep.valueRange[1], dep.range[1] - 1, ")"); - source.replace(dep.range[0], dep.valueRange[0] - 1, "__webpack_require__(" + comment + JSON.stringify(dep.module.id) + ").resolve(" + (typeof dep.prepend === "string" ? JSON.stringify(dep.prepend) : "") + ""); - } else { - source.replace(dep.range[0], dep.range[1] - 1, "__webpack_require__(" + comment + JSON.stringify(dep.module.id) + ").resolve"); - } - } else { - const content = require("./WebpackMissingModule").module(dep.request); - source.replace(dep.range[0], dep.range[1] - 1, content); - } - } -} -module.exports = ContextDependencyTemplateAsId; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +class ContextDependencyTemplateAsId { + apply(dep, source, runtime) { + const moduleExports = runtime.moduleExports({ + module: dep.module, + request: dep.request + }); + + if (dep.module) { + if (dep.valueRange) { + if (Array.isArray(dep.replaces)) { + for (let i = 0; i < dep.replaces.length; i++) { + const rep = dep.replaces[i]; + source.replace(rep.range[0], rep.range[1] - 1, rep.value); + } + } + source.replace(dep.valueRange[1], dep.range[1] - 1, ")"); + // TODO webpack 5 remove `prepend` it's no longer used + source.replace( + dep.range[0], + dep.valueRange[0] - 1, + `${moduleExports}.resolve(${ + typeof dep.prepend === "string" ? JSON.stringify(dep.prepend) : "" + }` + ); + } else { + source.replace( + dep.range[0], + dep.range[1] - 1, + `${moduleExports}.resolve` + ); + } + } else { + source.replace(dep.range[0], dep.range[1] - 1, moduleExports); + } + } +} +module.exports = ContextDependencyTemplateAsId; diff --git a/node_modules/webpack/lib/dependencies/ContextDependencyTemplateAsRequireCall.js b/node_modules/webpack/lib/dependencies/ContextDependencyTemplateAsRequireCall.js index eeb135f38..6d833ac83 100644 --- a/node_modules/webpack/lib/dependencies/ContextDependencyTemplateAsRequireCall.js +++ b/node_modules/webpack/lib/dependencies/ContextDependencyTemplateAsRequireCall.js @@ -1,34 +1,39 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class ContextDependencyTemplateAsRequireCall { - - apply(dep, source, outputOptions, requestShortener) { - const comment = outputOptions.pathinfo ? - "/*! " + requestShortener.shorten(dep.request) + " */ " : ""; - - const containsDeps = dep.module && dep.module.dependencies && dep.module.dependencies.length > 0; - const isAsync = dep.module && dep.module.async; - if(dep.module && (isAsync || containsDeps)) { - if(dep.valueRange) { - if(Array.isArray(dep.replaces)) { - for(let i = 0; i < dep.replaces.length; i++) { - const rep = dep.replaces[i]; - source.replace(rep.range[0], rep.range[1] - 1, rep.value); - } - } - source.replace(dep.valueRange[1], dep.range[1] - 1, ")"); - source.replace(dep.range[0], dep.valueRange[0] - 1, "__webpack_require__(" + comment + JSON.stringify(dep.module.id) + ")(" + (typeof dep.prepend === "string" ? JSON.stringify(dep.prepend) : "") + ""); - } else { - source.replace(dep.range[0], dep.range[1] - 1, "__webpack_require__(" + comment + JSON.stringify(dep.module.id) + ")"); - } - } else { - const content = require("./WebpackMissingModule").module(dep.request); - source.replace(dep.range[0], dep.range[1] - 1, content); - } - } -} -module.exports = ContextDependencyTemplateAsRequireCall; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +class ContextDependencyTemplateAsRequireCall { + apply(dep, source, runtime) { + const moduleExports = runtime.moduleExports({ + module: dep.module, + request: dep.request + }); + + if (dep.module) { + if (dep.valueRange) { + if (Array.isArray(dep.replaces)) { + for (let i = 0; i < dep.replaces.length; i++) { + const rep = dep.replaces[i]; + source.replace(rep.range[0], rep.range[1] - 1, rep.value); + } + } + source.replace(dep.valueRange[1], dep.range[1] - 1, ")"); + // TODO webpack 5 remove `prepend` it's no longer used + source.replace( + dep.range[0], + dep.valueRange[0] - 1, + `${moduleExports}(${ + typeof dep.prepend === "string" ? JSON.stringify(dep.prepend) : "" + }` + ); + } else { + source.replace(dep.range[0], dep.range[1] - 1, moduleExports); + } + } else { + source.replace(dep.range[0], dep.range[1] - 1, moduleExports); + } + } +} +module.exports = ContextDependencyTemplateAsRequireCall; diff --git a/node_modules/webpack/lib/dependencies/ContextElementDependency.js b/node_modules/webpack/lib/dependencies/ContextElementDependency.js index 8e5fafe52..258770490 100644 --- a/node_modules/webpack/lib/dependencies/ContextElementDependency.js +++ b/node_modules/webpack/lib/dependencies/ContextElementDependency.js @@ -1,21 +1,21 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ModuleDependency = require("./ModuleDependency"); - -class ContextElementDependency extends ModuleDependency { - constructor(request, userRequest) { - super(request); - if(userRequest) { - this.userRequest = userRequest; - } - } - - get type() { - return "context element"; - } -} - -module.exports = ContextElementDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const ModuleDependency = require("./ModuleDependency"); + +class ContextElementDependency extends ModuleDependency { + constructor(request, userRequest) { + super(request); + if (userRequest) { + this.userRequest = userRequest; + } + } + + get type() { + return "context element"; + } +} + +module.exports = ContextElementDependency; diff --git a/node_modules/webpack/lib/dependencies/CriticalDependencyWarning.js b/node_modules/webpack/lib/dependencies/CriticalDependencyWarning.js index 990109782..43bd5686e 100644 --- a/node_modules/webpack/lib/dependencies/CriticalDependencyWarning.js +++ b/node_modules/webpack/lib/dependencies/CriticalDependencyWarning.js @@ -1,20 +1,20 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const WebpackError = require("../WebpackError"); - -class CriticalDependencyWarning extends WebpackError { - constructor(message) { - super(); - - this.name = "CriticalDependencyWarning"; - this.message = "Critical dependency: " + message; - - Error.captureStackTrace(this, this.constructor); - } -} - -module.exports = CriticalDependencyWarning; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const WebpackError = require("../WebpackError"); + +class CriticalDependencyWarning extends WebpackError { + constructor(message) { + super(); + + this.name = "CriticalDependencyWarning"; + this.message = "Critical dependency: " + message; + + Error.captureStackTrace(this, this.constructor); + } +} + +module.exports = CriticalDependencyWarning; diff --git a/node_modules/webpack/lib/dependencies/DelegatedExportsDependency.js b/node_modules/webpack/lib/dependencies/DelegatedExportsDependency.js index ad36acbe4..fcacedb42 100644 --- a/node_modules/webpack/lib/dependencies/DelegatedExportsDependency.js +++ b/node_modules/webpack/lib/dependencies/DelegatedExportsDependency.js @@ -1,33 +1,33 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const NullDependency = require("./NullDependency"); - -class DelegatedExportsDependency extends NullDependency { - constructor(originModule, exports) { - super(); - this.originModule = originModule; - this.exports = exports; - } - - get type() { - return "delegated exports"; - } - - getReference() { - return { - module: this.originModule, - importedNames: true - }; - } - - getExports() { - return { - exports: this.exports - }; - } -} - -module.exports = DelegatedExportsDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const DependencyReference = require("./DependencyReference"); +const NullDependency = require("./NullDependency"); + +class DelegatedExportsDependency extends NullDependency { + constructor(originModule, exports) { + super(); + this.originModule = originModule; + this.exports = exports; + } + + get type() { + return "delegated exports"; + } + + getReference() { + return new DependencyReference(this.originModule, true, false); + } + + getExports() { + return { + exports: this.exports, + dependencies: undefined + }; + } +} + +module.exports = DelegatedExportsDependency; diff --git a/node_modules/webpack/lib/dependencies/DelegatedSourceDependency.js b/node_modules/webpack/lib/dependencies/DelegatedSourceDependency.js index 86341d59a..7b0b9de5e 100644 --- a/node_modules/webpack/lib/dependencies/DelegatedSourceDependency.js +++ b/node_modules/webpack/lib/dependencies/DelegatedSourceDependency.js @@ -1,18 +1,18 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ModuleDependency = require("./ModuleDependency"); - -class DelegatedSourceDependency extends ModuleDependency { - constructor(request) { - super(request); - } - - get type() { - return "delegated source"; - } -} - -module.exports = DelegatedSourceDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const ModuleDependency = require("./ModuleDependency"); + +class DelegatedSourceDependency extends ModuleDependency { + constructor(request) { + super(request); + } + + get type() { + return "delegated source"; + } +} + +module.exports = DelegatedSourceDependency; diff --git a/node_modules/webpack/lib/dependencies/DepBlockHelpers.js b/node_modules/webpack/lib/dependencies/DepBlockHelpers.js deleted file mode 100644 index c1e48a3a5..000000000 --- a/node_modules/webpack/lib/dependencies/DepBlockHelpers.js +++ /dev/null @@ -1,39 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const DepBlockHelpers = exports; - -DepBlockHelpers.getLoadDepBlockWrapper = (depBlock, outputOptions, requestShortener, name) => { - const promiseCode = DepBlockHelpers.getDepBlockPromise(depBlock, outputOptions, requestShortener, name); - return [ - promiseCode + ".then(", - ").catch(", - ")" - ]; -}; - -DepBlockHelpers.getDepBlockPromise = (depBlock, outputOptions, requestShortener, name) => { - if(depBlock.chunks) { - const chunks = depBlock.chunks.filter(chunk => !chunk.hasRuntime() && chunk.id !== null); - const pathChunkCheck = outputOptions.pathinfo && depBlock.chunkName; - const shortChunkName = requestShortener.shorten(depBlock.chunkName); - const chunkReason = asComment(depBlock.chunkReason); - const requireChunkId = chunk => "__webpack_require__.e(" + JSON.stringify(chunk.id) + ")"; - name = asComment(name); - if(chunks.length === 1) { - const chunkId = JSON.stringify(chunks[0].id); - return `__webpack_require__.e${name}(${chunkId}${pathChunkCheck ? "/*! " + shortChunkName + " */" : ""}${chunkReason})`; - } else if(chunks.length > 0) { - return `Promise.all${name}(${pathChunkCheck ? "/*! " + shortChunkName + " */" : ""}[${chunks.map(requireChunkId).join(", ")}])`; - } - } - return "new Promise(function(resolve) { resolve(); })"; -}; - -function asComment(str) { - if(!str) return ""; - return `/* ${str} */`; -} diff --git a/node_modules/webpack/lib/dependencies/DllEntryDependency.js b/node_modules/webpack/lib/dependencies/DllEntryDependency.js index 113249de8..47c6acc0a 100644 --- a/node_modules/webpack/lib/dependencies/DllEntryDependency.js +++ b/node_modules/webpack/lib/dependencies/DllEntryDependency.js @@ -1,20 +1,20 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const Dependency = require("../Dependency"); - -class DllEntryDependency extends Dependency { - constructor(dependencies, name) { - super(); - this.dependencies = dependencies; - this.name = name; - } - - get type() { - return "dll entry"; - } -} - -module.exports = DllEntryDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const Dependency = require("../Dependency"); + +class DllEntryDependency extends Dependency { + constructor(dependencies, name) { + super(); + this.dependencies = dependencies; + this.name = name; + } + + get type() { + return "dll entry"; + } +} + +module.exports = DllEntryDependency; diff --git a/node_modules/webpack/lib/dependencies/HarmonyAcceptDependency.js b/node_modules/webpack/lib/dependencies/HarmonyAcceptDependency.js index 91998126a..f152efb8f 100644 --- a/node_modules/webpack/lib/dependencies/HarmonyAcceptDependency.js +++ b/node_modules/webpack/lib/dependencies/HarmonyAcceptDependency.js @@ -1,42 +1,45 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const NullDependency = require("./NullDependency"); -const makeHarmonyImportStatement = require("./HarmonyImportDependency").makeImportStatement; - -class HarmonyAcceptDependency extends NullDependency { - constructor(range, dependencies, hasCallback) { - super(); - this.range = range; - this.dependencies = dependencies; - this.hasCallback = hasCallback; - } - - get type() { - return "accepted harmony modules"; - } -} - -HarmonyAcceptDependency.Template = class HarmonyAcceptDependencyTemplate { - apply(dep, source, outputOptions, requestShortener) { - const content = dep.dependencies - .map(dependency => makeHarmonyImportStatement( - false, - dependency, - outputOptions, - requestShortener - )).join(""); - - if(dep.hasCallback) { - source.insert(dep.range[0], `function(__WEBPACK_OUTDATED_DEPENDENCIES__) { ${content}(`); - source.insert(dep.range[1], ")(__WEBPACK_OUTDATED_DEPENDENCIES__); }"); - return; - } - - source.insert(dep.range[1] - 0.5, `, function() { ${content} }`); - } -}; - -module.exports = HarmonyAcceptDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const NullDependency = require("./NullDependency"); +const HarmonyImportDependency = require("./HarmonyImportDependency"); + +class HarmonyAcceptDependency extends NullDependency { + constructor(range, dependencies, hasCallback) { + super(); + this.range = range; + this.dependencies = dependencies; + this.hasCallback = hasCallback; + } + + get type() { + return "accepted harmony modules"; + } +} + +HarmonyAcceptDependency.Template = class HarmonyAcceptDependencyTemplate { + apply(dep, source, runtime) { + const content = dep.dependencies + .filter(dependency => + HarmonyImportDependency.Template.isImportEmitted(dependency, source) + ) + .map(dependency => dependency.getImportStatement(true, runtime)) + .join(""); + + if (dep.hasCallback) { + source.insert( + dep.range[0], + `function(__WEBPACK_OUTDATED_DEPENDENCIES__) { ${content}(` + ); + source.insert(dep.range[1], ")(__WEBPACK_OUTDATED_DEPENDENCIES__); }"); + return; + } + + source.insert(dep.range[1] - 0.5, `, function() { ${content} }`); + } +}; + +module.exports = HarmonyAcceptDependency; diff --git a/node_modules/webpack/lib/dependencies/HarmonyAcceptImportDependency.js b/node_modules/webpack/lib/dependencies/HarmonyAcceptImportDependency.js index 8b0689ad7..62bd00cf4 100644 --- a/node_modules/webpack/lib/dependencies/HarmonyAcceptImportDependency.js +++ b/node_modules/webpack/lib/dependencies/HarmonyAcceptImportDependency.js @@ -1,22 +1,23 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const HarmonyImportDependency = require("./HarmonyImportDependency"); - -class HarmonyAcceptImportDependency extends HarmonyImportDependency { - constructor(request, importedVar, range) { - super(request, importedVar, range); - } - - get type() { - return "harmony accept"; - } -} - -HarmonyAcceptImportDependency.Template = class HarmonyAcceptImportDependencyTemplate { - apply(dep, source, outputOptions, requestShortener) {} -}; - -module.exports = HarmonyAcceptImportDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const HarmonyImportDependency = require("./HarmonyImportDependency"); + +class HarmonyAcceptImportDependency extends HarmonyImportDependency { + constructor(request, originModule, parserScope) { + super(request, originModule, NaN, parserScope); + this.weak = true; + } + + get type() { + return "harmony accept"; + } +} + +HarmonyAcceptImportDependency.Template = class HarmonyAcceptImportDependencyTemplate extends HarmonyImportDependency.Template { + apply(dep, source, runtime) {} +}; + +module.exports = HarmonyAcceptImportDependency; diff --git a/node_modules/webpack/lib/dependencies/HarmonyCompatibilityDependency.js b/node_modules/webpack/lib/dependencies/HarmonyCompatibilityDependency.js index 8bd7bb708..d6febb5ac 100644 --- a/node_modules/webpack/lib/dependencies/HarmonyCompatibilityDependency.js +++ b/node_modules/webpack/lib/dependencies/HarmonyCompatibilityDependency.js @@ -1,30 +1,31 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const NullDependency = require("./NullDependency"); - -class HarmonyCompatibilityDependency extends NullDependency { - constructor(originModule) { - super(); - this.originModule = originModule; - } - - get type() { - return "harmony export header"; - } -} - -HarmonyCompatibilityDependency.Template = class HarmonyExportDependencyTemplate { - apply(dep, source) { - const usedExports = dep.originModule.usedExports; - if(usedExports && !Array.isArray(usedExports)) { - const exportName = dep.originModule.exportsArgument || "exports"; - const content = `Object.defineProperty(${exportName}, "__esModule", { value: true });\n`; - source.insert(-10, content); - } - } -}; - -module.exports = HarmonyCompatibilityDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const NullDependency = require("./NullDependency"); + +class HarmonyCompatibilityDependency extends NullDependency { + constructor(originModule) { + super(); + this.originModule = originModule; + } + + get type() { + return "harmony export header"; + } +} + +HarmonyCompatibilityDependency.Template = class HarmonyExportDependencyTemplate { + apply(dep, source, runtime) { + const usedExports = dep.originModule.usedExports; + if (usedExports !== false && !Array.isArray(usedExports)) { + const content = runtime.defineEsModuleFlagStatement({ + exportsArgument: dep.originModule.exportsArgument + }); + source.insert(-10, content); + } + } +}; + +module.exports = HarmonyCompatibilityDependency; diff --git a/node_modules/webpack/lib/dependencies/HarmonyDetectionParserPlugin.js b/node_modules/webpack/lib/dependencies/HarmonyDetectionParserPlugin.js index 4de7afb58..062ec21a6 100644 --- a/node_modules/webpack/lib/dependencies/HarmonyDetectionParserPlugin.js +++ b/node_modules/webpack/lib/dependencies/HarmonyDetectionParserPlugin.js @@ -1,56 +1,92 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const HarmonyCompatibilityDependency = require("./HarmonyCompatibilityDependency"); - -module.exports = class HarmonyDetectionParserPlugin { - apply(parser) { - parser.plugin("program", (ast) => { - const isHarmony = ast.body.some(statement => { - return /^(Import|Export).*Declaration$/.test(statement.type); - }); - if(isHarmony) { - const module = parser.state.module; - const dep = new HarmonyCompatibilityDependency(module); - dep.loc = { - start: { - line: -1, - column: 0 - }, - end: { - line: -1, - column: 0 - }, - index: -2 - }; - module.addDependency(dep); - module.meta.harmonyModule = true; - module.strict = true; - module.exportsArgument = "__webpack_exports__"; - } - }); - const nonHarmonyIdentifiers = ["define", "exports"]; - nonHarmonyIdentifiers.forEach(identifer => { - parser.plugin(`evaluate typeof ${identifer}`, nullInHarmony); - parser.plugin(`typeof ${identifer}`, skipInHarmony); - parser.plugin(`evaluate ${identifer}`, nullInHarmony); - parser.plugin(`expression ${identifer}`, skipInHarmony); - parser.plugin(`call ${identifer}`, skipInHarmony); - }); - - function skipInHarmony() { - const module = this.state.module; - if(module && module.meta && module.meta.harmonyModule) - return true; - } - - function nullInHarmony() { - const module = this.state.module; - if(module && module.meta && module.meta.harmonyModule) - return null; - } - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const HarmonyCompatibilityDependency = require("./HarmonyCompatibilityDependency"); +const HarmonyInitDependency = require("./HarmonyInitDependency"); + +module.exports = class HarmonyDetectionParserPlugin { + apply(parser) { + parser.hooks.program.tap("HarmonyDetectionParserPlugin", ast => { + const isStrictHarmony = parser.state.module.type === "javascript/esm"; + const isHarmony = + isStrictHarmony || + ast.body.some(statement => { + return /^(Import|Export).*Declaration$/.test(statement.type); + }); + if (isHarmony) { + const module = parser.state.module; + const compatDep = new HarmonyCompatibilityDependency(module); + compatDep.loc = { + start: { + line: -1, + column: 0 + }, + end: { + line: -1, + column: 0 + }, + index: -3 + }; + module.addDependency(compatDep); + const initDep = new HarmonyInitDependency(module); + initDep.loc = { + start: { + line: -1, + column: 0 + }, + end: { + line: -1, + column: 0 + }, + index: -2 + }; + module.addDependency(initDep); + parser.state.harmonyParserScope = parser.state.harmonyParserScope || {}; + parser.scope.isStrict = true; + module.buildMeta.exportsType = "namespace"; + module.buildInfo.strict = true; + module.buildInfo.exportsArgument = "__webpack_exports__"; + if (isStrictHarmony) { + module.buildMeta.strictHarmonyModule = true; + module.buildInfo.moduleArgument = "__webpack_module__"; + } + } + }); + + const skipInHarmony = () => { + const module = parser.state.module; + if (module && module.buildMeta && module.buildMeta.exportsType) { + return true; + } + }; + + const nullInHarmony = () => { + const module = parser.state.module; + if (module && module.buildMeta && module.buildMeta.exportsType) { + return null; + } + }; + + const nonHarmonyIdentifiers = ["define", "exports"]; + for (const identifer of nonHarmonyIdentifiers) { + parser.hooks.evaluateTypeof + .for(identifer) + .tap("HarmonyDetectionParserPlugin", nullInHarmony); + parser.hooks.typeof + .for(identifer) + .tap("HarmonyDetectionParserPlugin", skipInHarmony); + parser.hooks.evaluate + .for(identifer) + .tap("HarmonyDetectionParserPlugin", nullInHarmony); + parser.hooks.expression + .for(identifer) + .tap("HarmonyDetectionParserPlugin", skipInHarmony); + parser.hooks.call + .for(identifer) + .tap("HarmonyDetectionParserPlugin", skipInHarmony); + } + } +}; diff --git a/node_modules/webpack/lib/dependencies/HarmonyExportDependencyParserPlugin.js b/node_modules/webpack/lib/dependencies/HarmonyExportDependencyParserPlugin.js index f7072ebac..6ab0c0fe1 100644 --- a/node_modules/webpack/lib/dependencies/HarmonyExportDependencyParserPlugin.js +++ b/node_modules/webpack/lib/dependencies/HarmonyExportDependencyParserPlugin.js @@ -1,87 +1,154 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const HarmonyExportExpressionDependency = require("./HarmonyExportExpressionDependency"); -const HarmonyExportHeaderDependency = require("./HarmonyExportHeaderDependency"); -const HarmonyExportSpecifierDependency = require("./HarmonyExportSpecifierDependency"); -const HarmonyExportImportedSpecifierDependency = require("./HarmonyExportImportedSpecifierDependency"); -const HarmonyImportDependency = require("./HarmonyImportDependency"); -const HarmonyModulesHelpers = require("./HarmonyModulesHelpers"); - -module.exports = class HarmonyExportDependencyParserPlugin { - apply(parser) { - parser.plugin("export", statement => { - const dep = new HarmonyExportHeaderDependency(statement.declaration && statement.declaration.range, statement.range); - dep.loc = Object.create(statement.loc); - dep.loc.index = -1; - parser.state.current.addDependency(dep); - return true; - }); - parser.plugin("export import", (statement, source) => { - const dep = new HarmonyImportDependency(source, HarmonyModulesHelpers.getNewModuleVar(parser.state, source), statement.range); - dep.loc = Object.create(statement.loc); - dep.loc.index = -1; - parser.state.current.addDependency(dep); - parser.state.lastHarmonyImport = dep; - return true; - }); - parser.plugin("export expression", (statement, expr) => { - const dep = new HarmonyExportExpressionDependency(parser.state.module, expr.range, statement.range); - dep.loc = Object.create(statement.loc); - dep.loc.index = -1; - parser.state.current.addDependency(dep); - return true; - }); - parser.plugin("export declaration", statement => {}); - parser.plugin("export specifier", (statement, id, name, idx) => { - const rename = parser.scope.renames[`$${id}`]; - let dep; - const harmonyNamedExports = parser.state.harmonyNamedExports = parser.state.harmonyNamedExports || new Set(); - harmonyNamedExports.add(name); - if(rename === "imported var") { - const settings = parser.state.harmonySpecifier[`$${id}`]; - dep = new HarmonyExportImportedSpecifierDependency(parser.state.module, settings[0], settings[1], settings[2], name, harmonyNamedExports, null); - } else { - const immutable = statement.declaration && isImmutableStatement(statement.declaration); - const hoisted = statement.declaration && isHoistedStatement(statement.declaration); - dep = new HarmonyExportSpecifierDependency(parser.state.module, id, name, !immutable || hoisted ? -2 : (statement.range[1] + 0.5), immutable); - } - dep.loc = Object.create(statement.loc); - dep.loc.index = idx; - parser.state.current.addDependency(dep); - return true; - }); - parser.plugin("export import specifier", (statement, source, id, name, idx) => { - const harmonyNamedExports = parser.state.harmonyNamedExports = parser.state.harmonyNamedExports || new Set(); - let harmonyStarExports = null; - if(name) { - harmonyNamedExports.add(name); - } else { - harmonyStarExports = parser.state.harmonyStarExports = parser.state.harmonyStarExports || []; - } - const dep = new HarmonyExportImportedSpecifierDependency(parser.state.module, parser.state.lastHarmonyImport, HarmonyModulesHelpers.getModuleVar(parser.state, source), id, name, harmonyNamedExports, harmonyStarExports && harmonyStarExports.slice()); - if(harmonyStarExports) { - harmonyStarExports.push(dep); - } - dep.loc = Object.create(statement.loc); - dep.loc.index = idx; - parser.state.current.addDependency(dep); - return true; - }); - } -}; - -function isImmutableStatement(statement) { - if(statement.type === "FunctionDeclaration") return true; - if(statement.type === "ClassDeclaration") return true; - if(statement.type === "VariableDeclaration" && statement.kind === "const") return true; - return false; -} - -function isHoistedStatement(statement) { - if(statement.type === "FunctionDeclaration") return true; - return false; -} +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const HarmonyExportExpressionDependency = require("./HarmonyExportExpressionDependency"); +const HarmonyImportSideEffectDependency = require("./HarmonyImportSideEffectDependency"); +const HarmonyExportHeaderDependency = require("./HarmonyExportHeaderDependency"); +const HarmonyExportSpecifierDependency = require("./HarmonyExportSpecifierDependency"); +const HarmonyExportImportedSpecifierDependency = require("./HarmonyExportImportedSpecifierDependency"); +const ConstDependency = require("./ConstDependency"); + +module.exports = class HarmonyExportDependencyParserPlugin { + constructor(moduleOptions) { + this.strictExportPresence = moduleOptions.strictExportPresence; + } + + apply(parser) { + parser.hooks.export.tap( + "HarmonyExportDependencyParserPlugin", + statement => { + const dep = new HarmonyExportHeaderDependency( + statement.declaration && statement.declaration.range, + statement.range + ); + dep.loc = Object.create(statement.loc); + dep.loc.index = -1; + parser.state.current.addDependency(dep); + return true; + } + ); + parser.hooks.exportImport.tap( + "HarmonyExportDependencyParserPlugin", + (statement, source) => { + parser.state.lastHarmonyImportOrder = + (parser.state.lastHarmonyImportOrder || 0) + 1; + const clearDep = new ConstDependency("", statement.range); + clearDep.loc = Object.create(statement.loc); + clearDep.loc.index = -1; + parser.state.current.addDependency(clearDep); + const sideEffectDep = new HarmonyImportSideEffectDependency( + source, + parser.state.module, + parser.state.lastHarmonyImportOrder, + parser.state.harmonyParserScope + ); + sideEffectDep.loc = Object.create(statement.loc); + sideEffectDep.loc.index = -1; + parser.state.current.addDependency(sideEffectDep); + return true; + } + ); + parser.hooks.exportExpression.tap( + "HarmonyExportDependencyParserPlugin", + (statement, expr) => { + const comments = parser.getComments([ + statement.range[0], + expr.range[0] + ]); + const dep = new HarmonyExportExpressionDependency( + parser.state.module, + expr.range, + statement.range, + comments + .map(c => { + switch (c.type) { + case "Block": + return `/*${c.value}*/`; + case "Line": + return `//${c.value}\n`; + } + return ""; + }) + .join("") + ); + dep.loc = Object.create(statement.loc); + dep.loc.index = -1; + parser.state.current.addDependency(dep); + return true; + } + ); + parser.hooks.exportDeclaration.tap( + "HarmonyExportDependencyParserPlugin", + statement => {} + ); + parser.hooks.exportSpecifier.tap( + "HarmonyExportDependencyParserPlugin", + (statement, id, name, idx) => { + const rename = parser.scope.renames.get(id); + let dep; + const harmonyNamedExports = (parser.state.harmonyNamedExports = + parser.state.harmonyNamedExports || new Set()); + harmonyNamedExports.add(name); + if (rename === "imported var") { + const settings = parser.state.harmonySpecifier.get(id); + dep = new HarmonyExportImportedSpecifierDependency( + settings.source, + parser.state.module, + settings.sourceOrder, + parser.state.harmonyParserScope, + settings.id, + name, + harmonyNamedExports, + null, + this.strictExportPresence + ); + } else { + dep = new HarmonyExportSpecifierDependency( + parser.state.module, + id, + name + ); + } + dep.loc = Object.create(statement.loc); + dep.loc.index = idx; + parser.state.current.addDependency(dep); + return true; + } + ); + parser.hooks.exportImportSpecifier.tap( + "HarmonyExportDependencyParserPlugin", + (statement, source, id, name, idx) => { + const harmonyNamedExports = (parser.state.harmonyNamedExports = + parser.state.harmonyNamedExports || new Set()); + let harmonyStarExports = null; + if (name) { + harmonyNamedExports.add(name); + } else { + harmonyStarExports = parser.state.harmonyStarExports = + parser.state.harmonyStarExports || []; + } + const dep = new HarmonyExportImportedSpecifierDependency( + source, + parser.state.module, + parser.state.lastHarmonyImportOrder, + parser.state.harmonyParserScope, + id, + name, + harmonyNamedExports, + harmonyStarExports && harmonyStarExports.slice(), + this.strictExportPresence + ); + if (harmonyStarExports) { + harmonyStarExports.push(dep); + } + dep.loc = Object.create(statement.loc); + dep.loc.index = idx; + parser.state.current.addDependency(dep); + return true; + } + ); + } +}; diff --git a/node_modules/webpack/lib/dependencies/HarmonyExportExpressionDependency.js b/node_modules/webpack/lib/dependencies/HarmonyExportExpressionDependency.js index c2d90847b..dfb499add 100644 --- a/node_modules/webpack/lib/dependencies/HarmonyExportExpressionDependency.js +++ b/node_modules/webpack/lib/dependencies/HarmonyExportExpressionDependency.js @@ -1,50 +1,58 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const NullDependency = require("./NullDependency"); - -class HarmonyExportExpressionDependency extends NullDependency { - constructor(originModule, range, rangeStatement) { - super(); - this.originModule = originModule; - this.range = range; - this.rangeStatement = rangeStatement; - } - - get type() { - return "harmony export expression"; - } - - getExports() { - return { - exports: ["default"] - }; - } -} - -HarmonyExportExpressionDependency.Template = class HarmonyExportDependencyTemplate { - apply(dep, source) { - const used = dep.originModule.isUsed("default"); - const content = this.getContent(dep.originModule, used); - - if(dep.range) { - source.replace(dep.rangeStatement[0], dep.range[0] - 1, content + "("); - source.replace(dep.range[1], dep.rangeStatement[1] - 1, ");"); - return; - } - - source.replace(dep.rangeStatement[0], dep.rangeStatement[1] - 1, content); - } - - getContent(module, used) { - const exportsName = module.exportsArgument || "exports"; - if(used) { - return `/* harmony default export */ ${exportsName}[${JSON.stringify(used)}] = `; - } - return "/* unused harmony default export */ var _unused_webpack_default_export = "; - } -}; - -module.exports = HarmonyExportExpressionDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const NullDependency = require("./NullDependency"); + +class HarmonyExportExpressionDependency extends NullDependency { + constructor(originModule, range, rangeStatement, prefix) { + super(); + this.originModule = originModule; + this.range = range; + this.rangeStatement = rangeStatement; + this.prefix = prefix; + } + + get type() { + return "harmony export expression"; + } + + getExports() { + return { + exports: ["default"], + dependencies: undefined + }; + } +} + +HarmonyExportExpressionDependency.Template = class HarmonyExportDependencyTemplate { + apply(dep, source) { + const used = dep.originModule.isUsed("default"); + const content = this.getContent(dep.originModule, used); + + if (dep.range) { + source.replace( + dep.rangeStatement[0], + dep.range[0] - 1, + content + "(" + dep.prefix + ); + source.replace(dep.range[1], dep.rangeStatement[1] - 1, ");"); + return; + } + + source.replace(dep.rangeStatement[0], dep.rangeStatement[1] - 1, content); + } + + getContent(module, used) { + const exportsName = module.exportsArgument; + if (used) { + return `/* harmony default export */ ${exportsName}[${JSON.stringify( + used + )}] = `; + } + return "/* unused harmony default export */ var _unused_webpack_default_export = "; + } +}; + +module.exports = HarmonyExportExpressionDependency; diff --git a/node_modules/webpack/lib/dependencies/HarmonyExportHeaderDependency.js b/node_modules/webpack/lib/dependencies/HarmonyExportHeaderDependency.js index 86033ce95..a0e9918bd 100644 --- a/node_modules/webpack/lib/dependencies/HarmonyExportHeaderDependency.js +++ b/node_modules/webpack/lib/dependencies/HarmonyExportHeaderDependency.js @@ -1,28 +1,30 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const NullDependency = require("./NullDependency"); - -class HarmonyExportHeaderDependency extends NullDependency { - constructor(range, rangeStatement) { - super(); - this.range = range; - this.rangeStatement = rangeStatement; - } - - get type() { - return "harmony export header"; - } -} - -HarmonyExportHeaderDependency.Template = class HarmonyExportDependencyTemplate { - apply(dep, source) { - const content = ""; - const replaceUntil = dep.range ? dep.range[0] - 1 : dep.rangeStatement[1] - 1; - source.replace(dep.rangeStatement[0], replaceUntil, content); - } -}; - -module.exports = HarmonyExportHeaderDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const NullDependency = require("./NullDependency"); + +class HarmonyExportHeaderDependency extends NullDependency { + constructor(range, rangeStatement) { + super(); + this.range = range; + this.rangeStatement = rangeStatement; + } + + get type() { + return "harmony export header"; + } +} + +HarmonyExportHeaderDependency.Template = class HarmonyExportDependencyTemplate { + apply(dep, source) { + const content = ""; + const replaceUntil = dep.range + ? dep.range[0] - 1 + : dep.rangeStatement[1] - 1; + source.replace(dep.rangeStatement[0], replaceUntil, content); + } +}; + +module.exports = HarmonyExportHeaderDependency; diff --git a/node_modules/webpack/lib/dependencies/HarmonyExportImportedSpecifierDependency.js b/node_modules/webpack/lib/dependencies/HarmonyExportImportedSpecifierDependency.js index cb1b892d2..1965d0dbb 100644 --- a/node_modules/webpack/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +++ b/node_modules/webpack/lib/dependencies/HarmonyExportImportedSpecifierDependency.js @@ -1,285 +1,645 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const NullDependency = require("./NullDependency"); - -class HarmonyExportImportedSpecifierDependency extends NullDependency { - constructor(originModule, importDependency, importedVar, id, name, activeExports, otherStarExports) { - super(); - this.originModule = originModule; - this.importDependency = importDependency; - this.importedVar = importedVar; - this.id = id; - this.name = name; - this.activeExports = activeExports; - this.otherStarExports = otherStarExports; - } - - get type() { - return "harmony export imported specifier"; - } - - getReference() { - const name = this.name; - const used = this.originModule.isUsed(name); - const importedModule = this.importDependency.module; - - if(!importedModule || !used || !this.originModule.usedExports) return null; - - const hasUsedExports = Array.isArray(this.originModule.usedExports); - - if(name) { - const nameIsNotInUsedExports = hasUsedExports && this.originModule.usedExports.indexOf(name) < 0; - if(nameIsNotInUsedExports) return null; - - // export { name as name } - if(this.id) { - return { - module: importedModule, - importedNames: [this.id] - }; - } - - // export { * as name } - return { - module: importedModule, - importedNames: true - }; - } - - const hasProvidedExports = Array.isArray(importedModule.providedExports); - const activeFromOtherStarExports = this._discoverActiveExportsFromOtherStartExports(); - - // export * - if(hasUsedExports) { - // reexport * with known used exports - const importedNames = this.originModule.usedExports.filter(id => { - if(id === "default") return false; - if(this.activeExports.has(id)) return false; - if(activeFromOtherStarExports.has(id)) return false; - if(hasProvidedExports && importedModule.providedExports.indexOf(id) < 0) return false; - - return true; - }); - - return { - module: importedModule, - importedNames - }; - } - - if(hasProvidedExports) { - return { - module: importedModule, - importedNames: importedModule.providedExports.filter(id => { - if(id === "default") return false; - if(this.activeExports.has(id)) return false; - if(activeFromOtherStarExports.has(id)) return false; - - return true; - }) - }; - } - - return { - module: importedModule, - importedNames: true, - }; - } - - _discoverActiveExportsFromOtherStartExports() { - if(!this.otherStarExports) - return new Set(); - const result = new Set(); - // try to learn impossible exports from other star exports with provided exports - for(const otherStarExport of this.otherStarExports) { - const otherImportedModule = otherStarExport.importDependency.module; - if(otherImportedModule && Array.isArray(otherImportedModule.providedExports)) { - for(const exportName of otherImportedModule.providedExports) - result.add(exportName); - } - } - return result; - } - - getExports() { - if(this.name) { - return { - exports: [this.name] - }; - } - - const importedModule = this.importDependency.module; - - if(!importedModule) { - // no imported module available - return { - exports: null - }; - } - - if(Array.isArray(importedModule.providedExports)) { - return { - exports: importedModule.providedExports.filter(id => id !== "default"), - dependencies: [importedModule] - }; - } - - if(importedModule.providedExports) { - return { - exports: true - }; - } - - return { - exports: null, - dependencies: [importedModule] - }; - } - - updateHash(hash) { - super.updateHash(hash); - const hashValue = this.getHashValue(this.importDependency.module); - hash.update(hashValue); - } - - getHashValue(importedModule) { - if(!importedModule) { - return ""; - } - - const stringifiedUsedExport = JSON.stringify(importedModule.usedExports); - const stringifiedProvidedExport = JSON.stringify(importedModule.providedExports); - return importedModule.used + stringifiedUsedExport + stringifiedProvidedExport; - } -} - -module.exports = HarmonyExportImportedSpecifierDependency; - -HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedSpecifierDependencyTemplate { - apply(dep, source, outputOptions, requestShortener) { - const content = this.getContent(dep); - source.insert(-1, content); - } - - getContent(dep) { - const name = dep.importedVar; - const used = dep.originModule.isUsed(dep.name); - const importedModule = dep.importDependency.module; - const importsExportsUnknown = !importedModule || !Array.isArray(importedModule.providedExports); - - const getReexportStatement = this.reexportStatementCreator(dep.originModule, importsExportsUnknown, name); - - // we want to rexport something, but the export isn't used - if(!used) { - return "/* unused harmony reexport " + dep.name + " */\n"; - } - - // we want to reexport the default export from a non-hamory module - const isNotAHarmonyModule = !(importedModule && (!importedModule.meta || importedModule.meta.harmonyModule)); - if(dep.name && dep.id === "default" && isNotAHarmonyModule) { - return "/* harmony reexport (default from non-hamory) */ " + getReexportStatement(JSON.stringify(used), null); - } - - // we want to reexport a key as new key - if(dep.name && dep.id) { - var idUsed = importedModule && importedModule.isUsed(dep.id); - return "/* harmony reexport (binding) */ " + getReexportStatement(JSON.stringify(used), JSON.stringify(idUsed)); - } - - // we want to reexport the module object as named export - if(dep.name) { - return "/* harmony reexport (module object) */ " + getReexportStatement(JSON.stringify(used), ""); - } - - const hasProvidedExports = importedModule && Array.isArray(importedModule.providedExports); - - const activeFromOtherStarExports = dep._discoverActiveExportsFromOtherStartExports(); - - // we know which exports are used - if(Array.isArray(dep.originModule.usedExports)) { - const items = dep.originModule.usedExports.map(id => { - if(id === "default") return; - if(dep.activeExports.has(id)) return; - if(importedModule.isProvided(id) === false) return; - if(activeFromOtherStarExports.has(id)) return; - var exportUsed = dep.originModule.isUsed(id); - var idUsed = importedModule && importedModule.isUsed(id); - return [exportUsed, idUsed]; - }).filter(Boolean); - - if(items.length === 0) { - return "/* unused harmony namespace reexport */\n"; - } - - return items.map(function(item) { - return "/* harmony namespace reexport (by used) */ " + getReexportStatement(JSON.stringify(item[0]), JSON.stringify(item[1])); - }).join(""); - } - - // not sure which exports are used, but we know which are provided - if(dep.originModule.usedExports && importedModule && hasProvidedExports) { - const items = importedModule.providedExports.map(id => { - if(id === "default") return; - if(dep.activeExports.has(id)) return; - if(activeFromOtherStarExports.has(id)) return; - var exportUsed = dep.originModule.isUsed(id); - var idUsed = importedModule && importedModule.isUsed(id); - return [exportUsed, idUsed]; - }).filter(Boolean); - - if(items.length === 0) { - return "/* empty harmony namespace reexport */\n"; - } - - return items.map(function(item) { - return "/* harmony namespace reexport (by provided) */ " + getReexportStatement(JSON.stringify(item[0]), JSON.stringify(item[1])); - }).join(""); - } - - // not sure which exports are used and provided - if(dep.originModule.usedExports) { - const activeExports = Array.from(dep.activeExports).concat(Array.from(activeFromOtherStarExports)); - let content = "/* harmony namespace reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in " + name + ") "; - - // Filter out exports which are defined by other exports - // and filter out default export because it cannot be reexported with * - if(activeExports.length > 0) - content += "if(" + JSON.stringify(activeExports.concat("default")) + ".indexOf(__WEBPACK_IMPORT_KEY__) < 0) "; - else - content += "if(__WEBPACK_IMPORT_KEY__ !== 'default') "; - const exportsName = dep.originModule.exportsArgument || "exports"; - return content + `(function(key) { __webpack_require__.d(${exportsName}, key, function() { return ${name}[key]; }) }(__WEBPACK_IMPORT_KEY__));\n`; - } - - return "/* unused harmony reexport namespace */\n"; - } - - reexportStatementCreator(module, importsExportsUnknown, name) { - const exportsName = module.exportsArgument || "exports"; - const getReexportStatement = (key, valueKey) => { - const conditional = this.getConditional(importsExportsUnknown, valueKey, name); - const returnValue = this.getReturnValue(valueKey); - return `${conditional}__webpack_require__.d(${exportsName}, ${key}, function() { return ${name}${returnValue}; });\n`; - }; - return getReexportStatement; - } - - getConditional(importsExportsUnknown, valueKey, name) { - if(!importsExportsUnknown || !valueKey) { - return ""; - } - - return `if(__webpack_require__.o(${name}, ${valueKey})) `; - } - - getReturnValue(valueKey) { - if(valueKey === null) { - return "_default.a"; - } - - return valueKey && "[" + valueKey + "]"; - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const DependencyReference = require("./DependencyReference"); +const HarmonyImportDependency = require("./HarmonyImportDependency"); +const Template = require("../Template"); +const HarmonyLinkingError = require("../HarmonyLinkingError"); + +/** @typedef {import("../Module")} Module */ + +/** @typedef {"missing"|"unused"|"empty-star"|"reexport-non-harmony-default"|"reexport-named-default"|"reexport-namespace-object"|"reexport-non-harmony-default-strict"|"reexport-fake-namespace-object"|"rexport-non-harmony-undefined"|"safe-reexport"|"checked-reexport"|"dynamic-reexport"} ExportModeType */ + +/** @type {Map} */ +const EMPTY_MAP = new Map(); + +class ExportMode { + /** + * @param {ExportModeType} type type of the mode + */ + constructor(type) { + /** @type {ExportModeType} */ + this.type = type; + /** @type {string|null} */ + this.name = null; + /** @type {Map} */ + this.map = EMPTY_MAP; + /** @type {Module|null} */ + this.module = null; + /** @type {string|null} */ + this.userRequest = null; + } +} + +const EMPTY_STAR_MODE = new ExportMode("empty-star"); + +class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { + constructor( + request, + originModule, + sourceOrder, + parserScope, + id, + name, + activeExports, + otherStarExports, + strictExportPresence + ) { + super(request, originModule, sourceOrder, parserScope); + this.id = id; + this.name = name; + this.activeExports = activeExports; + this.otherStarExports = otherStarExports; + this.strictExportPresence = strictExportPresence; + } + + get type() { + return "harmony export imported specifier"; + } + + getMode(ignoreUnused) { + const name = this.name; + const id = this.id; + const used = this.originModule.isUsed(name); + const importedModule = this._module; + + if (!importedModule) { + const mode = new ExportMode("missing"); + mode.userRequest = this.userRequest; + return mode; + } + + if ( + !ignoreUnused && + (name ? !used : this.originModule.usedExports === false) + ) { + const mode = new ExportMode("unused"); + mode.name = name || "*"; + return mode; + } + + const strictHarmonyModule = this.originModule.buildMeta.strictHarmonyModule; + if (name && id === "default" && importedModule.buildMeta) { + if (!importedModule.buildMeta.exportsType) { + const mode = new ExportMode( + strictHarmonyModule + ? "reexport-non-harmony-default-strict" + : "reexport-non-harmony-default" + ); + mode.name = name; + mode.module = importedModule; + return mode; + } else if (importedModule.buildMeta.exportsType === "named") { + const mode = new ExportMode("reexport-named-default"); + mode.name = name; + mode.module = importedModule; + return mode; + } + } + + const isNotAHarmonyModule = + importedModule.buildMeta && !importedModule.buildMeta.exportsType; + if (name) { + let mode; + if (id) { + // export { name as name } + if (isNotAHarmonyModule && strictHarmonyModule) { + mode = new ExportMode("rexport-non-harmony-undefined"); + mode.name = name; + } else { + mode = new ExportMode("safe-reexport"); + mode.map = new Map([[name, id]]); + } + } else { + // export { * as name } + if (isNotAHarmonyModule && strictHarmonyModule) { + mode = new ExportMode("reexport-fake-namespace-object"); + mode.name = name; + } else { + mode = new ExportMode("reexport-namespace-object"); + mode.name = name; + } + } + mode.module = importedModule; + return mode; + } + + const hasUsedExports = Array.isArray(this.originModule.usedExports); + const hasProvidedExports = Array.isArray( + importedModule.buildMeta.providedExports + ); + const activeFromOtherStarExports = this._discoverActiveExportsFromOtherStartExports(); + + // export * + if (hasUsedExports) { + // reexport * with known used exports + if (hasProvidedExports) { + const map = new Map( + this.originModule.usedExports + .filter(id => { + if (id === "default") return false; + if (this.activeExports.has(id)) return false; + if (activeFromOtherStarExports.has(id)) return false; + if (!importedModule.buildMeta.providedExports.includes(id)) + return false; + return true; + }) + .map(item => [item, item]) + ); + + if (map.size === 0) { + return EMPTY_STAR_MODE; + } + + const mode = new ExportMode("safe-reexport"); + mode.module = importedModule; + mode.map = map; + return mode; + } + + const map = new Map( + this.originModule.usedExports + .filter(id => { + if (id === "default") return false; + if (this.activeExports.has(id)) return false; + if (activeFromOtherStarExports.has(id)) return false; + + return true; + }) + .map(item => [item, item]) + ); + + if (map.size === 0) { + return EMPTY_STAR_MODE; + } + + const mode = new ExportMode("checked-reexport"); + mode.module = importedModule; + mode.map = map; + return mode; + } + + if (hasProvidedExports) { + const map = new Map( + importedModule.buildMeta.providedExports + .filter(id => { + if (id === "default") return false; + if (this.activeExports.has(id)) return false; + if (activeFromOtherStarExports.has(id)) return false; + + return true; + }) + .map(item => [item, item]) + ); + + if (map.size === 0) { + return EMPTY_STAR_MODE; + } + + const mode = new ExportMode("safe-reexport"); + mode.module = importedModule; + mode.map = map; + return mode; + } + + const mode = new ExportMode("dynamic-reexport"); + mode.module = importedModule; + return mode; + } + + getReference() { + const mode = this.getMode(false); + + switch (mode.type) { + case "missing": + case "unused": + case "empty-star": + return null; + + case "reexport-non-harmony-default": + case "reexport-named-default": + return new DependencyReference( + mode.module, + ["default"], + false, + this.sourceOrder + ); + + case "reexport-namespace-object": + case "reexport-non-harmony-default-strict": + case "reexport-fake-namespace-object": + case "rexport-non-harmony-undefined": + return new DependencyReference( + mode.module, + true, + false, + this.sourceOrder + ); + + case "safe-reexport": + case "checked-reexport": + return new DependencyReference( + mode.module, + Array.from(mode.map.values()), + false, + this.sourceOrder + ); + + case "dynamic-reexport": + return new DependencyReference( + mode.module, + true, + false, + this.sourceOrder + ); + + default: + throw new Error(`Unknown mode ${mode.type}`); + } + } + + _discoverActiveExportsFromOtherStartExports() { + if (!this.otherStarExports) return new Set(); + const result = new Set(); + // try to learn impossible exports from other star exports with provided exports + for (const otherStarExport of this.otherStarExports) { + const otherImportedModule = otherStarExport._module; + if ( + otherImportedModule && + Array.isArray(otherImportedModule.buildMeta.providedExports) + ) { + for (const exportName of otherImportedModule.buildMeta + .providedExports) { + result.add(exportName); + } + } + } + return result; + } + + getExports() { + if (this.name) { + return { + exports: [this.name], + dependencies: undefined + }; + } + + const importedModule = this.module; + + if (!importedModule) { + // no imported module available + return { + exports: null, + dependencies: undefined + }; + } + + if (Array.isArray(importedModule.buildMeta.providedExports)) { + return { + exports: importedModule.buildMeta.providedExports.filter( + id => id !== "default" + ), + dependencies: [importedModule] + }; + } + + if (importedModule.buildMeta.providedExports) { + return { + exports: true, + dependencies: undefined + }; + } + + return { + exports: null, + dependencies: [importedModule] + }; + } + + getWarnings() { + if ( + this.strictExportPresence || + this.originModule.buildMeta.strictHarmonyModule + ) { + return []; + } + return this._getErrors(); + } + + getErrors() { + if ( + this.strictExportPresence || + this.originModule.buildMeta.strictHarmonyModule + ) { + return this._getErrors(); + } + return []; + } + + _getErrors() { + const importedModule = this._module; + if (!importedModule) { + return; + } + + if (!importedModule.buildMeta || !importedModule.buildMeta.exportsType) { + // It's not an harmony module + if ( + this.originModule.buildMeta.strictHarmonyModule && + this.id !== "default" + ) { + // In strict harmony modules we only support the default export + const exportName = this.id + ? `the named export '${this.id}'` + : "the namespace object"; + return [ + new HarmonyLinkingError( + `Can't reexport ${exportName} from non EcmaScript module (only default export is available)` + ) + ]; + } + return; + } + + if (!this.id) { + return; + } + + if (importedModule.isProvided(this.id) !== false) { + // It's provided or we are not sure + return; + } + + // We are sure that it's not provided + const idIsNotNameMessage = + this.id !== this.name ? ` (reexported as '${this.name}')` : ""; + const errorMessage = `"export '${ + this.id + }'${idIsNotNameMessage} was not found in '${this.userRequest}'`; + return [new HarmonyLinkingError(errorMessage)]; + } + + updateHash(hash) { + super.updateHash(hash); + const hashValue = this.getHashValue(this._module); + hash.update(hashValue); + } + + getHashValue(importedModule) { + if (!importedModule) { + return ""; + } + + const stringifiedUsedExport = JSON.stringify(importedModule.usedExports); + const stringifiedProvidedExport = JSON.stringify( + importedModule.buildMeta.providedExports + ); + return ( + importedModule.used + stringifiedUsedExport + stringifiedProvidedExport + ); + } +} + +module.exports = HarmonyExportImportedSpecifierDependency; + +HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedSpecifierDependencyTemplate extends HarmonyImportDependency.Template { + harmonyInit(dep, source, runtime, dependencyTemplates) { + super.harmonyInit(dep, source, runtime, dependencyTemplates); + const content = this.getContent(dep); + source.insert(-1, content); + } + + getHarmonyInitOrder(dep) { + if (dep.name) { + const used = dep.originModule.isUsed(dep.name); + if (!used) return NaN; + } else { + const importedModule = dep._module; + + const activeFromOtherStarExports = dep._discoverActiveExportsFromOtherStartExports(); + + if (Array.isArray(dep.originModule.usedExports)) { + // we know which exports are used + + const unused = dep.originModule.usedExports.every(id => { + if (id === "default") return true; + if (dep.activeExports.has(id)) return true; + if (importedModule.isProvided(id) === false) return true; + if (activeFromOtherStarExports.has(id)) return true; + return false; + }); + if (unused) return NaN; + } else if ( + dep.originModule.usedExports && + importedModule && + Array.isArray(importedModule.buildMeta.providedExports) + ) { + // not sure which exports are used, but we know which are provided + + const unused = importedModule.buildMeta.providedExports.every(id => { + if (id === "default") return true; + if (dep.activeExports.has(id)) return true; + if (activeFromOtherStarExports.has(id)) return true; + return false; + }); + if (unused) return NaN; + } + } + return super.getHarmonyInitOrder(dep); + } + + getContent(dep) { + const mode = dep.getMode(false); + const module = dep.originModule; + const importedModule = dep._module; + const importVar = dep.getImportVar(); + + switch (mode.type) { + case "missing": + return `throw new Error(${JSON.stringify( + `Cannot find module '${mode.userRequest}'` + )});\n`; + + case "unused": + return `${Template.toNormalComment( + `unused harmony reexport ${mode.name}` + )}\n`; + + case "reexport-non-harmony-default": + return ( + "/* harmony reexport (default from non-harmony) */ " + + this.getReexportStatement( + module, + module.isUsed(mode.name), + importVar, + null + ) + ); + + case "reexport-named-default": + return ( + "/* harmony reexport (default from named exports) */ " + + this.getReexportStatement( + module, + module.isUsed(mode.name), + importVar, + "" + ) + ); + + case "reexport-fake-namespace-object": + return ( + "/* harmony reexport (fake namespace object from non-harmony) */ " + + this.getReexportFakeNamespaceObjectStatement( + module, + module.isUsed(mode.name), + importVar + ) + ); + + case "rexport-non-harmony-undefined": + return ( + "/* harmony reexport (non default export from non-harmony) */ " + + this.getReexportStatement( + module, + module.isUsed(mode.name), + "undefined", + "" + ) + ); + + case "reexport-non-harmony-default-strict": + return ( + "/* harmony reexport (default from non-harmony) */ " + + this.getReexportStatement( + module, + module.isUsed(mode.name), + importVar, + "" + ) + ); + + case "reexport-namespace-object": + return ( + "/* harmony reexport (module object) */ " + + this.getReexportStatement( + module, + module.isUsed(mode.name), + importVar, + "" + ) + ); + + case "empty-star": + return "/* empty/unused harmony star reexport */"; + + case "safe-reexport": + return Array.from(mode.map.entries()) + .map(item => { + return ( + "/* harmony reexport (safe) */ " + + this.getReexportStatement( + module, + module.isUsed(item[0]), + importVar, + importedModule.isUsed(item[1]) + ) + + "\n" + ); + }) + .join(""); + + case "checked-reexport": + return Array.from(mode.map.entries()) + .map(item => { + return ( + "/* harmony reexport (checked) */ " + + this.getConditionalReexportStatement( + module, + item[0], + importVar, + item[1] + ) + + "\n" + ); + }) + .join(""); + + case "dynamic-reexport": { + const activeExports = new Set([ + ...dep.activeExports, + ...dep._discoverActiveExportsFromOtherStartExports() + ]); + let content = + "/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in " + + importVar + + ") "; + + // Filter out exports which are defined by other exports + // and filter out default export because it cannot be reexported with * + if (activeExports.size > 0) { + content += + "if(" + + JSON.stringify(Array.from(activeExports).concat("default")) + + ".indexOf(__WEBPACK_IMPORT_KEY__) < 0) "; + } else { + content += "if(__WEBPACK_IMPORT_KEY__ !== 'default') "; + } + const exportsName = dep.originModule.exportsArgument; + return ( + content + + `(function(key) { __webpack_require__.d(${exportsName}, key, function() { return ${importVar}[key]; }) }(__WEBPACK_IMPORT_KEY__));\n` + ); + } + + default: + throw new Error(`Unknown mode ${mode.type}`); + } + } + + getReexportStatement(module, key, name, valueKey) { + const exportsName = module.exportsArgument; + const returnValue = this.getReturnValue(name, valueKey); + return `__webpack_require__.d(${exportsName}, ${JSON.stringify( + key + )}, function() { return ${returnValue}; });\n`; + } + + getReexportFakeNamespaceObjectStatement(module, key, name) { + const exportsName = module.exportsArgument; + return `__webpack_require__.d(${exportsName}, ${JSON.stringify( + key + )}, function() { return __webpack_require__.t(${name}); });\n`; + } + + getConditionalReexportStatement(module, key, name, valueKey) { + if (valueKey === false) { + return "/* unused export */\n"; + } + const exportsName = module.exportsArgument; + const returnValue = this.getReturnValue(name, valueKey); + return `if(__webpack_require__.o(${name}, ${JSON.stringify( + valueKey + )})) __webpack_require__.d(${exportsName}, ${JSON.stringify( + key + )}, function() { return ${returnValue}; });\n`; + } + + getReturnValue(name, valueKey) { + if (valueKey === null) { + return `${name}_default.a`; + } + if (valueKey === "") { + return name; + } + if (valueKey === false) { + return "/* unused export */ undefined"; + } + + return `${name}[${JSON.stringify(valueKey)}]`; + } +}; diff --git a/node_modules/webpack/lib/dependencies/HarmonyExportSpecifierDependency.js b/node_modules/webpack/lib/dependencies/HarmonyExportSpecifierDependency.js index 33c253f4b..1bf6a3fe6 100644 --- a/node_modules/webpack/lib/dependencies/HarmonyExportSpecifierDependency.js +++ b/node_modules/webpack/lib/dependencies/HarmonyExportSpecifierDependency.js @@ -1,54 +1,54 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const NullDependency = require("./NullDependency"); - -class HarmonyExportSpecifierDependency extends NullDependency { - constructor(originModule, id, name, position, immutable) { - super(); - this.originModule = originModule; - this.id = id; - this.name = name; - this.position = position; - this.immutable = immutable; - } - - get type() { - return "harmony export specifier"; - } - - getExports() { - return { - exports: [this.name] - }; - } -} - -HarmonyExportSpecifierDependency.Template = class HarmonyExportSpecifierDependencyTemplate { - apply(dep, source) { - const content = this.getPrefix(dep) + this.getContent(dep); - source.insert(dep.position, content); - } - - getPrefix(dep) { - return dep.position > 0 ? "\n" : ""; - } - - getContent(dep) { - const used = dep.originModule.isUsed(dep.name); - if(!used) { - return `/* unused harmony export ${(dep.name || "namespace")} */\n`; - } - - const exportsName = dep.originModule.exportsArgument || "exports"; - if(dep.immutable) { - return `/* harmony export (immutable) */ ${exportsName}[${JSON.stringify(used)}] = ${dep.id};\n`; - } - - return `/* harmony export (binding) */ __webpack_require__.d(${exportsName}, ${JSON.stringify(used)}, function() { return ${dep.id}; });\n`; - } -}; - -module.exports = HarmonyExportSpecifierDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const NullDependency = require("./NullDependency"); + +class HarmonyExportSpecifierDependency extends NullDependency { + constructor(originModule, id, name) { + super(); + this.originModule = originModule; + this.id = id; + this.name = name; + } + + get type() { + return "harmony export specifier"; + } + + getExports() { + return { + exports: [this.name], + dependencies: undefined + }; + } +} + +HarmonyExportSpecifierDependency.Template = class HarmonyExportSpecifierDependencyTemplate { + apply(dep, source) {} + + getHarmonyInitOrder(dep) { + return 0; + } + + harmonyInit(dep, source, runtime) { + const content = this.getContent(dep); + source.insert(-1, content); + } + + getContent(dep) { + const used = dep.originModule.isUsed(dep.name); + if (!used) { + return `/* unused harmony export ${dep.name || "namespace"} */\n`; + } + + const exportsName = dep.originModule.exportsArgument; + + return `/* harmony export (binding) */ __webpack_require__.d(${exportsName}, ${JSON.stringify( + used + )}, function() { return ${dep.id}; });\n`; + } +}; + +module.exports = HarmonyExportSpecifierDependency; diff --git a/node_modules/webpack/lib/dependencies/HarmonyImportDependency.js b/node_modules/webpack/lib/dependencies/HarmonyImportDependency.js index d31ef2dc8..97fd9bf6c 100644 --- a/node_modules/webpack/lib/dependencies/HarmonyImportDependency.js +++ b/node_modules/webpack/lib/dependencies/HarmonyImportDependency.js @@ -1,72 +1,109 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ModuleDependency = require("./ModuleDependency"); - -class HarmonyImportDependency extends ModuleDependency { - constructor(request, importedVar, range) { - super(request); - this.range = range; - this.importedVar = importedVar; - } - - get type() { - return "harmony import"; - } - - getReference() { - if(!this.module) return null; - - return { - module: this.module, - importedNames: false - }; - } - - updateHash(hash) { - super.updateHash(hash); - hash.update((this.module && (!this.module.meta || this.module.meta.harmonyModule)) + ""); - } -} - -HarmonyImportDependency.Template = class HarmonyImportDependencyTemplate { - apply(dep, source, outputOptions, requestShortener) { - const content = makeImportStatement(true, dep, outputOptions, requestShortener); - source.replace(dep.range[0], dep.range[1] - 1, ""); - source.insert(-1, content); - } -}; - -function getOptionalComment(pathinfo, shortenedRequest) { - if(!pathinfo) { - return ""; - } - return `/*! ${shortenedRequest} */ `; -} - -function makeImportStatement(declare, dep, outputOptions, requestShortener) { - const comment = getOptionalComment(outputOptions.pathinfo, requestShortener.shorten(dep.request)); - const declaration = declare ? "var " : ""; - const newline = declare ? "\n" : " "; - - if(!dep.module) { - const stringifiedError = JSON.stringify(`Cannot find module "${dep.request}"`); - return `throw new Error(${stringifiedError});${newline}`; - } - - if(dep.importedVar) { - const isHarmonyModule = dep.module.meta && dep.module.meta.harmonyModule; - const content = `/* harmony import */ ${declaration}${dep.importedVar} = __webpack_require__(${comment}${JSON.stringify(dep.module.id)});${newline}`; - if(isHarmonyModule) { - return content; - } - return `${content}/* harmony import */ ${declaration}${dep.importedVar}_default = __webpack_require__.n(${dep.importedVar});${newline}`; - } - - return ""; -} -HarmonyImportDependency.makeImportStatement = makeImportStatement; - -module.exports = HarmonyImportDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const DependencyReference = require("./DependencyReference"); +const ModuleDependency = require("./ModuleDependency"); +const Template = require("../Template"); + +class HarmonyImportDependency extends ModuleDependency { + constructor(request, originModule, sourceOrder, parserScope) { + super(request); + this.redirectedModule = undefined; + this.originModule = originModule; + this.sourceOrder = sourceOrder; + this.parserScope = parserScope; + } + + get _module() { + return this.redirectedModule || this.module; + } + + getReference() { + if (!this._module) return null; + return new DependencyReference( + this._module, + false, + this.weak, + this.sourceOrder + ); + } + + getImportVar() { + let importVarMap = this.parserScope.importVarMap; + if (!importVarMap) this.parserScope.importVarMap = importVarMap = new Map(); + let importVar = importVarMap.get(this._module); + if (importVar) return importVar; + importVar = `${Template.toIdentifier( + `${this.userRequest}` + )}__WEBPACK_IMPORTED_MODULE_${importVarMap.size}__`; + importVarMap.set(this._module, importVar); + return importVar; + } + + getImportStatement(update, runtime) { + return runtime.importStatement({ + update, + module: this._module, + importVar: this.getImportVar(), + request: this.request, + originModule: this.originModule + }); + } + + updateHash(hash) { + super.updateHash(hash); + const importedModule = this._module; + hash.update( + (importedModule && + (!importedModule.buildMeta || importedModule.buildMeta.exportsType)) + + "" + ); + hash.update((importedModule && importedModule.id) + ""); + } + + disconnect() { + super.disconnect(); + this.redirectedModule = undefined; + } +} + +module.exports = HarmonyImportDependency; + +const importEmittedMap = new WeakMap(); + +HarmonyImportDependency.Template = class HarmonyImportDependencyTemplate { + apply(dep, source, runtime) { + // no-op + } + + getHarmonyInitOrder(dep) { + return dep.sourceOrder; + } + + static isImportEmitted(dep, source) { + let sourceInfo = importEmittedMap.get(source); + if (!sourceInfo) return false; + const key = dep._module || dep.request; + return key && sourceInfo.emittedImports.get(key); + } + + harmonyInit(dep, source, runtime, dependencyTemplates) { + let sourceInfo = importEmittedMap.get(source); + if (!sourceInfo) { + importEmittedMap.set( + source, + (sourceInfo = { + emittedImports: new Map() + }) + ); + } + const key = dep._module || dep.request; + if (key && sourceInfo.emittedImports.get(key)) return; + sourceInfo.emittedImports.set(key, true); + const content = dep.getImportStatement(false, runtime); + source.insert(-1, content); + } +}; diff --git a/node_modules/webpack/lib/dependencies/HarmonyImportDependencyParserPlugin.js b/node_modules/webpack/lib/dependencies/HarmonyImportDependencyParserPlugin.js index 3b867f616..7f9fcde20 100644 --- a/node_modules/webpack/lib/dependencies/HarmonyImportDependencyParserPlugin.js +++ b/node_modules/webpack/lib/dependencies/HarmonyImportDependencyParserPlugin.js @@ -1,124 +1,222 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const HarmonyImportDependency = require("./HarmonyImportDependency"); -const HarmonyImportSpecifierDependency = require("./HarmonyImportSpecifierDependency"); -const HarmonyAcceptImportDependency = require("./HarmonyAcceptImportDependency"); -const HarmonyAcceptDependency = require("./HarmonyAcceptDependency"); -const HarmonyModulesHelpers = require("./HarmonyModulesHelpers"); - -module.exports = class HarmonyImportDependencyParserPlugin { - constructor(moduleOptions) { - this.strictExportPresence = moduleOptions.strictExportPresence; - this.strictThisContextOnImports = moduleOptions.strictThisContextOnImports; - } - - apply(parser) { - parser.plugin("import", (statement, source) => { - const dep = new HarmonyImportDependency(source, HarmonyModulesHelpers.getNewModuleVar(parser.state, source), statement.range); - dep.loc = statement.loc; - parser.state.current.addDependency(dep); - parser.state.lastHarmonyImport = dep; - return true; - }); - parser.plugin("import specifier", (statement, source, id, name) => { - parser.scope.definitions.length--; - parser.scope.renames[`$${name}`] = "imported var"; - if(!parser.state.harmonySpecifier) parser.state.harmonySpecifier = {}; - parser.state.harmonySpecifier[`$${name}`] = [parser.state.lastHarmonyImport, HarmonyModulesHelpers.getModuleVar(parser.state, source), id]; - return true; - }); - parser.plugin("expression imported var", (expr) => { - const name = expr.name; - const settings = parser.state.harmonySpecifier[`$${name}`]; - const dep = new HarmonyImportSpecifierDependency(settings[0], settings[1], settings[2], name, expr.range, this.strictExportPresence); - dep.shorthand = parser.scope.inShorthand; - dep.directImport = true; - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - return true; - }); - parser.plugin("expression imported var.*", (expr) => { - const name = expr.object.name; - const settings = parser.state.harmonySpecifier[`$${name}`]; - if(settings[2] !== null) - return false; - const dep = new HarmonyImportSpecifierDependency(settings[0], settings[1], expr.property.name || expr.property.value, name, expr.range, this.strictExportPresence); - dep.shorthand = parser.scope.inShorthand; - dep.directImport = false; - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - return true; - }); - if(this.strictThisContextOnImports) { - // only in case when we strictly follow the spec we need a special case here - parser.plugin("call imported var.*", (expr) => { - if(expr.callee.type !== "MemberExpression") return; - if(expr.callee.object.type !== "Identifier") return; - const name = expr.callee.object.name; - const settings = parser.state.harmonySpecifier[`$${name}`]; - if(settings[2] !== null) - return false; - const dep = new HarmonyImportSpecifierDependency(settings[0], settings[1], expr.callee.property.name || expr.callee.property.value, name, expr.callee.range, this.strictExportPresence); - dep.shorthand = parser.scope.inShorthand; - dep.directImport = false; - dep.namespaceObjectAsContext = true; - dep.loc = expr.callee.loc; - parser.state.current.addDependency(dep); - if(expr.arguments) - parser.walkExpressions(expr.arguments); - return true; - }); - } - parser.plugin("call imported var", (expr) => { - const args = expr.arguments; - const fullExpr = expr; - expr = expr.callee; - if(expr.type !== "Identifier") return; - const name = expr.name; - const settings = parser.state.harmonySpecifier[`$${name}`]; - const dep = new HarmonyImportSpecifierDependency(settings[0], settings[1], settings[2], name, expr.range, this.strictExportPresence); - dep.directImport = true; - dep.callArgs = args; - dep.call = fullExpr; - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - if(args) - parser.walkExpressions(args); - return true; - }); - parser.plugin("hot accept callback", (expr, requests) => { - const dependencies = requests - .filter(request => HarmonyModulesHelpers.checkModuleVar(parser.state, request)) - .map(request => { - const dep = new HarmonyAcceptImportDependency(request, HarmonyModulesHelpers.getModuleVar(parser.state, request), expr.range); - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - return dep; - }); - if(dependencies.length > 0) { - const dep = new HarmonyAcceptDependency(expr.range, dependencies, true); - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - } - }); - parser.plugin("hot accept without callback", (expr, requests) => { - const dependencies = requests - .filter(request => HarmonyModulesHelpers.checkModuleVar(parser.state, request)) - .map(request => { - const dep = new HarmonyAcceptImportDependency(request, HarmonyModulesHelpers.getModuleVar(parser.state, request), expr.range); - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - return dep; - }); - if(dependencies.length > 0) { - const dep = new HarmonyAcceptDependency(expr.range, dependencies, false); - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - } - }); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const { SyncBailHook } = require("tapable"); +const HarmonyImportSideEffectDependency = require("./HarmonyImportSideEffectDependency"); +const HarmonyImportSpecifierDependency = require("./HarmonyImportSpecifierDependency"); +const HarmonyAcceptImportDependency = require("./HarmonyAcceptImportDependency"); +const HarmonyAcceptDependency = require("./HarmonyAcceptDependency"); +const ConstDependency = require("./ConstDependency"); + +module.exports = class HarmonyImportDependencyParserPlugin { + constructor(moduleOptions) { + this.strictExportPresence = moduleOptions.strictExportPresence; + this.strictThisContextOnImports = moduleOptions.strictThisContextOnImports; + } + + apply(parser) { + parser.hooks.import.tap( + "HarmonyImportDependencyParserPlugin", + (statement, source) => { + parser.state.lastHarmonyImportOrder = + (parser.state.lastHarmonyImportOrder || 0) + 1; + const clearDep = new ConstDependency("", statement.range); + clearDep.loc = statement.loc; + parser.state.module.addDependency(clearDep); + const sideEffectDep = new HarmonyImportSideEffectDependency( + source, + parser.state.module, + parser.state.lastHarmonyImportOrder, + parser.state.harmonyParserScope + ); + sideEffectDep.loc = statement.loc; + parser.state.module.addDependency(sideEffectDep); + return true; + } + ); + parser.hooks.importSpecifier.tap( + "HarmonyImportDependencyParserPlugin", + (statement, source, id, name) => { + parser.scope.definitions.delete(name); + parser.scope.renames.set(name, "imported var"); + if (!parser.state.harmonySpecifier) { + parser.state.harmonySpecifier = new Map(); + } + parser.state.harmonySpecifier.set(name, { + source, + id, + sourceOrder: parser.state.lastHarmonyImportOrder + }); + return true; + } + ); + parser.hooks.expression + .for("imported var") + .tap("HarmonyImportDependencyParserPlugin", expr => { + const name = expr.name; + const settings = parser.state.harmonySpecifier.get(name); + const dep = new HarmonyImportSpecifierDependency( + settings.source, + parser.state.module, + settings.sourceOrder, + parser.state.harmonyParserScope, + settings.id, + name, + expr.range, + this.strictExportPresence + ); + dep.shorthand = parser.scope.inShorthand; + dep.directImport = true; + dep.loc = expr.loc; + parser.state.module.addDependency(dep); + return true; + }); + parser.hooks.expressionAnyMember + .for("imported var") + .tap("HarmonyImportDependencyParserPlugin", expr => { + const name = expr.object.name; + const settings = parser.state.harmonySpecifier.get(name); + if (settings.id !== null) return false; + const dep = new HarmonyImportSpecifierDependency( + settings.source, + parser.state.module, + settings.sourceOrder, + parser.state.harmonyParserScope, + expr.property.name || expr.property.value, + name, + expr.range, + this.strictExportPresence + ); + dep.shorthand = parser.scope.inShorthand; + dep.directImport = false; + dep.loc = expr.loc; + parser.state.module.addDependency(dep); + return true; + }); + if (this.strictThisContextOnImports) { + // only in case when we strictly follow the spec we need a special case here + parser.hooks.callAnyMember + .for("imported var") + .tap("HarmonyImportDependencyParserPlugin", expr => { + if (expr.callee.type !== "MemberExpression") return; + if (expr.callee.object.type !== "Identifier") return; + const name = expr.callee.object.name; + const settings = parser.state.harmonySpecifier.get(name); + if (settings.id !== null) return false; + const dep = new HarmonyImportSpecifierDependency( + settings.source, + parser.state.module, + settings.sourceOrder, + parser.state.harmonyParserScope, + expr.callee.property.name || expr.callee.property.value, + name, + expr.callee.range, + this.strictExportPresence + ); + dep.shorthand = parser.scope.inShorthand; + dep.directImport = false; + dep.namespaceObjectAsContext = true; + dep.loc = expr.callee.loc; + parser.state.module.addDependency(dep); + if (expr.arguments) parser.walkExpressions(expr.arguments); + return true; + }); + } + parser.hooks.call + .for("imported var") + .tap("HarmonyImportDependencyParserPlugin", expr => { + const args = expr.arguments; + const fullExpr = expr; + expr = expr.callee; + if (expr.type !== "Identifier") return; + const name = expr.name; + const settings = parser.state.harmonySpecifier.get(name); + const dep = new HarmonyImportSpecifierDependency( + settings.source, + parser.state.module, + settings.sourceOrder, + parser.state.harmonyParserScope, + settings.id, + name, + expr.range, + this.strictExportPresence + ); + dep.directImport = true; + dep.callArgs = args; + dep.call = fullExpr; + dep.loc = expr.loc; + parser.state.module.addDependency(dep); + if (args) parser.walkExpressions(args); + return true; + }); + // TODO webpack 5: refactor this, no custom hooks + if (!parser.hooks.hotAcceptCallback) { + parser.hooks.hotAcceptCallback = new SyncBailHook([ + "expression", + "requests" + ]); + } + if (!parser.hooks.hotAcceptWithoutCallback) { + parser.hooks.hotAcceptWithoutCallback = new SyncBailHook([ + "expression", + "requests" + ]); + } + parser.hooks.hotAcceptCallback.tap( + "HarmonyImportDependencyParserPlugin", + (expr, requests) => { + const harmonyParserScope = parser.state.harmonyParserScope; + if (!harmonyParserScope) { + // This is not a harmony module, skip it + return; + } + const dependencies = requests.map(request => { + const dep = new HarmonyAcceptImportDependency( + request, + parser.state.module, + harmonyParserScope + ); + dep.loc = expr.loc; + parser.state.module.addDependency(dep); + return dep; + }); + if (dependencies.length > 0) { + const dep = new HarmonyAcceptDependency( + expr.range, + dependencies, + true + ); + dep.loc = expr.loc; + parser.state.module.addDependency(dep); + } + } + ); + parser.hooks.hotAcceptWithoutCallback.tap( + "HarmonyImportDependencyParserPlugin", + (expr, requests) => { + const dependencies = requests.map(request => { + const dep = new HarmonyAcceptImportDependency( + request, + parser.state.module, + parser.state.harmonyParserScope + ); + dep.loc = expr.loc; + parser.state.module.addDependency(dep); + return dep; + }); + if (dependencies.length > 0) { + const dep = new HarmonyAcceptDependency( + expr.range, + dependencies, + false + ); + dep.loc = expr.loc; + parser.state.module.addDependency(dep); + } + } + ); + } +}; diff --git a/node_modules/webpack/lib/dependencies/HarmonyImportSpecifierDependency.js b/node_modules/webpack/lib/dependencies/HarmonyImportSpecifierDependency.js index 083019291..769711932 100644 --- a/node_modules/webpack/lib/dependencies/HarmonyImportSpecifierDependency.js +++ b/node_modules/webpack/lib/dependencies/HarmonyImportSpecifierDependency.js @@ -1,129 +1,167 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const NullDependency = require("./NullDependency"); - -class HarmonyImportSpecifierDependency extends NullDependency { - constructor(importDependency, importedVar, id, name, range, strictExportPresence) { - super(); - this.importDependency = importDependency; - this.importedVar = importedVar; - this.id = id; - this.name = name; - this.range = range; - this.strictExportPresence = strictExportPresence; - this.namespaceObjectAsContext = false; - this.callArgs = undefined; - this.call = undefined; - this.directImport = undefined; - } - - get type() { - return "harmony import specifier"; - } - - getReference() { - if(!this.importDependency.module) return null; - return { - module: this.importDependency.module, - importedNames: this.id && !this.namespaceObjectAsContext ? [this.id] : true - }; - } - - getWarnings() { - if(this.strictExportPresence) { - return []; - } - return this._getErrors(); - } - - getErrors() { - if(this.strictExportPresence) { - return this._getErrors(); - } - return []; - } - - _getErrors() { - const importedModule = this.importDependency.module; - if(!importedModule || !importedModule.meta || !importedModule.meta.harmonyModule) { - return; - } - - if(!this.id) { - return; - } - - if(importedModule.isProvided(this.id) !== false) { - return; - } - - const idIsNotNameMessage = this.id !== this.name ? ` (imported as '${this.name}')` : ""; - const errorMessage = `"export '${this.id}'${idIsNotNameMessage} was not found in '${this.importDependency.userRequest}'`; - const err = new Error(errorMessage); - err.hideStack = true; - return [err]; - } - - updateHash(hash) { - super.updateHash(hash); - const importedModule = this.importDependency.module; - hash.update((importedModule && importedModule.id) + ""); - hash.update((importedModule && this.id) + ""); - hash.update((importedModule && this.importedVar) + ""); - hash.update((importedModule && this.id && importedModule.isUsed(this.id)) + ""); - hash.update((importedModule && (!importedModule.meta || importedModule.meta.harmonyModule)) + ""); - hash.update((importedModule && (importedModule.used + JSON.stringify(importedModule.usedExports))) + ""); - } -} - -HarmonyImportSpecifierDependency.Template = class HarmonyImportSpecifierDependencyTemplate { - apply(dep, source) { - const content = this.getContent(dep); - source.replace(dep.range[0], dep.range[1] - 1, content); - } - - getContent(dep) { - const importedModule = dep.importDependency.module; - const defaultImport = dep.directImport && dep.id === "default" && !(importedModule && (!importedModule.meta || importedModule.meta.harmonyModule)); - const shortHandPrefix = this.getShortHandPrefix(dep); - const importedVar = dep.importedVar; - const importedVarSuffix = this.getImportVarSuffix(dep, defaultImport, importedModule); - - if(dep.call && defaultImport) { - return `${shortHandPrefix}${importedVar}_default()`; - } - - if(dep.call && dep.id) { - return `${shortHandPrefix}Object(${importedVar}${importedVarSuffix})`; - } - - return `${shortHandPrefix}${importedVar}${importedVarSuffix}`; - } - - getImportVarSuffix(dep, defaultImport, importedModule) { - if(defaultImport) { - return "_default.a"; - } - - if(dep.id) { - const used = importedModule ? importedModule.isUsed(dep.id) : dep.id; - const optionalComment = dep.id !== used ? " /* " + dep.id + " */" : ""; - return `[${JSON.stringify(used)}${optionalComment}]`; - } - - return ""; - } - - getShortHandPrefix(dep) { - if(!dep.shorthand) { - return ""; - } - - return dep.name + ": "; - } -}; - -module.exports = HarmonyImportSpecifierDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const DependencyReference = require("./DependencyReference"); +const HarmonyImportDependency = require("./HarmonyImportDependency"); +const HarmonyLinkingError = require("../HarmonyLinkingError"); + +class HarmonyImportSpecifierDependency extends HarmonyImportDependency { + constructor( + request, + originModule, + sourceOrder, + parserScope, + id, + name, + range, + strictExportPresence + ) { + super(request, originModule, sourceOrder, parserScope); + this.id = id === null ? null : `${id}`; + this.redirectedId = undefined; + this.name = name; + this.range = range; + this.strictExportPresence = strictExportPresence; + this.namespaceObjectAsContext = false; + this.callArgs = undefined; + this.call = undefined; + this.directImport = undefined; + this.shorthand = undefined; + } + + get type() { + return "harmony import specifier"; + } + + get _id() { + return this.redirectedId || this.id; + } + + getReference() { + if (!this._module) return null; + return new DependencyReference( + this._module, + this._id && !this.namespaceObjectAsContext ? [this._id] : true, + false, + this.sourceOrder + ); + } + + getWarnings() { + if ( + this.strictExportPresence || + this.originModule.buildMeta.strictHarmonyModule + ) { + return []; + } + return this._getErrors(); + } + + getErrors() { + if ( + this.strictExportPresence || + this.originModule.buildMeta.strictHarmonyModule + ) { + return this._getErrors(); + } + return []; + } + + _getErrors() { + const importedModule = this._module; + if (!importedModule) { + return; + } + + if (!importedModule.buildMeta || !importedModule.buildMeta.exportsType) { + // It's not an harmony module + if ( + this.originModule.buildMeta.strictHarmonyModule && + this._id !== "default" + ) { + // In strict harmony modules we only support the default export + const exportName = this._id + ? `the named export '${this._id}'` + : "the namespace object"; + return [ + new HarmonyLinkingError( + `Can't import ${exportName} from non EcmaScript module (only default export is available)` + ) + ]; + } + return; + } + + if (!this._id) { + return; + } + + if (importedModule.isProvided(this._id) !== false) { + // It's provided or we are not sure + return; + } + + // We are sure that it's not provided + const idIsNotNameMessage = + this._id !== this.name ? ` (imported as '${this.name}')` : ""; + const errorMessage = `"export '${ + this._id + }'${idIsNotNameMessage} was not found in '${this.userRequest}'`; + return [new HarmonyLinkingError(errorMessage)]; + } + + // implement this method to allow the occurrence order plugin to count correctly + getNumberOfIdOccurrences() { + return 0; + } + + updateHash(hash) { + super.updateHash(hash); + const importedModule = this._module; + hash.update((importedModule && this._id) + ""); + hash.update( + (importedModule && this._id && importedModule.isUsed(this._id)) + "" + ); + hash.update( + (importedModule && + (!importedModule.buildMeta || importedModule.buildMeta.exportsType)) + + "" + ); + hash.update( + (importedModule && + importedModule.used + JSON.stringify(importedModule.usedExports)) + "" + ); + } + + disconnect() { + super.disconnect(); + this.redirectedId = undefined; + } +} + +HarmonyImportSpecifierDependency.Template = class HarmonyImportSpecifierDependencyTemplate extends HarmonyImportDependency.Template { + apply(dep, source, runtime) { + super.apply(dep, source, runtime); + const content = this.getContent(dep, runtime); + source.replace(dep.range[0], dep.range[1] - 1, content); + } + + getContent(dep, runtime) { + const exportExpr = runtime.exportFromImport({ + module: dep._module, + request: dep.request, + exportName: dep._id, + originModule: dep.originModule, + asiSafe: dep.shorthand, + isCall: dep.call, + callContext: !dep.directImport, + importVar: dep.getImportVar() + }); + return dep.shorthand ? `${dep.name}: ${exportExpr}` : exportExpr; + } +}; + +module.exports = HarmonyImportSpecifierDependency; diff --git a/node_modules/webpack/lib/dependencies/HarmonyModulesHelpers.js b/node_modules/webpack/lib/dependencies/HarmonyModulesHelpers.js deleted file mode 100644 index 10ee7e27e..000000000 --- a/node_modules/webpack/lib/dependencies/HarmonyModulesHelpers.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class HarmonyModulesHelpers { - - static getModuleVar(state, request) { - if(!state.harmonyModules) state.harmonyModules = []; - let idx = state.harmonyModules.indexOf(request); - if(idx < 0) { - idx = state.harmonyModules.length; - state.harmonyModules.push(request); - } - return `__WEBPACK_IMPORTED_MODULE_${idx}_${request.replace(/[^A-Za-z0-9_]/g, "_").replace(/__+/g, "_")}__`; - } - - static getNewModuleVar(state, request) { - if(state.harmonyModules && state.harmonyModules.indexOf(request) >= 0) - return null; - return this.getModuleVar(state, request); - } - - static checkModuleVar(state, request) { - if(!state.harmonyModules || state.harmonyModules.indexOf(request) < 0) - return null; - return this.getModuleVar(state, request); - } -} - -module.exports = HarmonyModulesHelpers; diff --git a/node_modules/webpack/lib/dependencies/HarmonyModulesPlugin.js b/node_modules/webpack/lib/dependencies/HarmonyModulesPlugin.js index 896d8a2bb..43a8d4c0c 100644 --- a/node_modules/webpack/lib/dependencies/HarmonyModulesPlugin.js +++ b/node_modules/webpack/lib/dependencies/HarmonyModulesPlugin.js @@ -1,72 +1,143 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const HarmonyImportDependency = require("./HarmonyImportDependency"); -const HarmonyImportSpecifierDependency = require("./HarmonyImportSpecifierDependency"); -const HarmonyCompatiblilityDependency = require("./HarmonyCompatibilityDependency"); -const HarmonyExportHeaderDependency = require("./HarmonyExportHeaderDependency"); -const HarmonyExportExpressionDependency = require("./HarmonyExportExpressionDependency"); -const HarmonyExportSpecifierDependency = require("./HarmonyExportSpecifierDependency"); -const HarmonyExportImportedSpecifierDependency = require("./HarmonyExportImportedSpecifierDependency"); -const HarmonyAcceptDependency = require("./HarmonyAcceptDependency"); -const HarmonyAcceptImportDependency = require("./HarmonyAcceptImportDependency"); - -const NullFactory = require("../NullFactory"); - -const HarmonyDetectionParserPlugin = require("./HarmonyDetectionParserPlugin"); -const HarmonyImportDependencyParserPlugin = require("./HarmonyImportDependencyParserPlugin"); -const HarmonyExportDependencyParserPlugin = require("./HarmonyExportDependencyParserPlugin"); - -class HarmonyModulesPlugin { - constructor(options) { - this.options = options; - } - - apply(compiler) { - compiler.plugin("compilation", (compilation, params) => { - const normalModuleFactory = params.normalModuleFactory; - - compilation.dependencyFactories.set(HarmonyImportDependency, normalModuleFactory); - compilation.dependencyTemplates.set(HarmonyImportDependency, new HarmonyImportDependency.Template()); - - compilation.dependencyFactories.set(HarmonyImportSpecifierDependency, new NullFactory()); - compilation.dependencyTemplates.set(HarmonyImportSpecifierDependency, new HarmonyImportSpecifierDependency.Template()); - - compilation.dependencyFactories.set(HarmonyCompatiblilityDependency, new NullFactory()); - compilation.dependencyTemplates.set(HarmonyCompatiblilityDependency, new HarmonyCompatiblilityDependency.Template()); - - compilation.dependencyFactories.set(HarmonyExportHeaderDependency, new NullFactory()); - compilation.dependencyTemplates.set(HarmonyExportHeaderDependency, new HarmonyExportHeaderDependency.Template()); - - compilation.dependencyFactories.set(HarmonyExportExpressionDependency, new NullFactory()); - compilation.dependencyTemplates.set(HarmonyExportExpressionDependency, new HarmonyExportExpressionDependency.Template()); - - compilation.dependencyFactories.set(HarmonyExportSpecifierDependency, new NullFactory()); - compilation.dependencyTemplates.set(HarmonyExportSpecifierDependency, new HarmonyExportSpecifierDependency.Template()); - - compilation.dependencyFactories.set(HarmonyExportImportedSpecifierDependency, new NullFactory()); - compilation.dependencyTemplates.set(HarmonyExportImportedSpecifierDependency, new HarmonyExportImportedSpecifierDependency.Template()); - - compilation.dependencyFactories.set(HarmonyAcceptDependency, new NullFactory()); - compilation.dependencyTemplates.set(HarmonyAcceptDependency, new HarmonyAcceptDependency.Template()); - - compilation.dependencyFactories.set(HarmonyAcceptImportDependency, normalModuleFactory); - compilation.dependencyTemplates.set(HarmonyAcceptImportDependency, new HarmonyAcceptImportDependency.Template()); - - params.normalModuleFactory.plugin("parser", (parser, parserOptions) => { - - if(typeof parserOptions.harmony !== "undefined" && !parserOptions.harmony) - return; - - parser.apply( - new HarmonyDetectionParserPlugin(), - new HarmonyImportDependencyParserPlugin(this.options), - new HarmonyExportDependencyParserPlugin() - ); - }); - }); - } -} -module.exports = HarmonyModulesPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const HarmonyCompatibilityDependency = require("./HarmonyCompatibilityDependency"); +const HarmonyInitDependency = require("./HarmonyInitDependency"); +const HarmonyImportSpecifierDependency = require("./HarmonyImportSpecifierDependency"); +const HarmonyImportSideEffectDependency = require("./HarmonyImportSideEffectDependency"); +const HarmonyExportHeaderDependency = require("./HarmonyExportHeaderDependency"); +const HarmonyExportExpressionDependency = require("./HarmonyExportExpressionDependency"); +const HarmonyExportSpecifierDependency = require("./HarmonyExportSpecifierDependency"); +const HarmonyExportImportedSpecifierDependency = require("./HarmonyExportImportedSpecifierDependency"); +const HarmonyAcceptDependency = require("./HarmonyAcceptDependency"); +const HarmonyAcceptImportDependency = require("./HarmonyAcceptImportDependency"); + +const NullFactory = require("../NullFactory"); + +const HarmonyDetectionParserPlugin = require("./HarmonyDetectionParserPlugin"); +const HarmonyImportDependencyParserPlugin = require("./HarmonyImportDependencyParserPlugin"); +const HarmonyExportDependencyParserPlugin = require("./HarmonyExportDependencyParserPlugin"); +const HarmonyTopLevelThisParserPlugin = require("./HarmonyTopLevelThisParserPlugin"); + +class HarmonyModulesPlugin { + constructor(options) { + this.options = options; + } + + apply(compiler) { + compiler.hooks.compilation.tap( + "HarmonyModulesPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set( + HarmonyCompatibilityDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + HarmonyCompatibilityDependency, + new HarmonyCompatibilityDependency.Template() + ); + + compilation.dependencyFactories.set( + HarmonyInitDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + HarmonyInitDependency, + new HarmonyInitDependency.Template() + ); + + compilation.dependencyFactories.set( + HarmonyImportSideEffectDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + HarmonyImportSideEffectDependency, + new HarmonyImportSideEffectDependency.Template() + ); + + compilation.dependencyFactories.set( + HarmonyImportSpecifierDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + HarmonyImportSpecifierDependency, + new HarmonyImportSpecifierDependency.Template() + ); + + compilation.dependencyFactories.set( + HarmonyExportHeaderDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + HarmonyExportHeaderDependency, + new HarmonyExportHeaderDependency.Template() + ); + + compilation.dependencyFactories.set( + HarmonyExportExpressionDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + HarmonyExportExpressionDependency, + new HarmonyExportExpressionDependency.Template() + ); + + compilation.dependencyFactories.set( + HarmonyExportSpecifierDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + HarmonyExportSpecifierDependency, + new HarmonyExportSpecifierDependency.Template() + ); + + compilation.dependencyFactories.set( + HarmonyExportImportedSpecifierDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + HarmonyExportImportedSpecifierDependency, + new HarmonyExportImportedSpecifierDependency.Template() + ); + + compilation.dependencyFactories.set( + HarmonyAcceptDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + HarmonyAcceptDependency, + new HarmonyAcceptDependency.Template() + ); + + compilation.dependencyFactories.set( + HarmonyAcceptImportDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + HarmonyAcceptImportDependency, + new HarmonyAcceptImportDependency.Template() + ); + + const handler = (parser, parserOptions) => { + if (parserOptions.harmony !== undefined && !parserOptions.harmony) + return; + + new HarmonyDetectionParserPlugin().apply(parser); + new HarmonyImportDependencyParserPlugin(this.options).apply(parser); + new HarmonyExportDependencyParserPlugin(this.options).apply(parser); + new HarmonyTopLevelThisParserPlugin().apply(parser); + }; + + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("HarmonyModulesPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/esm") + .tap("HarmonyModulesPlugin", handler); + } + ); + } +} +module.exports = HarmonyModulesPlugin; diff --git a/node_modules/webpack/lib/dependencies/ImportContextDependency.js b/node_modules/webpack/lib/dependencies/ImportContextDependency.js index d7f378c5c..f25a28a15 100644 --- a/node_modules/webpack/lib/dependencies/ImportContextDependency.js +++ b/node_modules/webpack/lib/dependencies/ImportContextDependency.js @@ -1,25 +1,23 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ContextDependency = require("./ContextDependency"); -const ContextDependencyTemplateAsRequireCall = require("./ContextDependencyTemplateAsRequireCall"); - -class ImportContextDependency extends ContextDependency { - constructor(request, recursive, regExp, range, valueRange, chunkName) { - super(request, recursive, regExp); - this.range = range; - this.valueRange = valueRange; - this.chunkName = chunkName; - } - - get type() { - return "import() context"; - } - -} - -ImportContextDependency.Template = ContextDependencyTemplateAsRequireCall; - -module.exports = ImportContextDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const ContextDependency = require("./ContextDependency"); +const ContextDependencyTemplateAsRequireCall = require("./ContextDependencyTemplateAsRequireCall"); + +class ImportContextDependency extends ContextDependency { + constructor(options, range, valueRange) { + super(options); + this.range = range; + this.valueRange = valueRange; + } + + get type() { + return `import() context ${this.options.mode}`; + } +} + +ImportContextDependency.Template = ContextDependencyTemplateAsRequireCall; + +module.exports = ImportContextDependency; diff --git a/node_modules/webpack/lib/dependencies/ImportDependenciesBlock.js b/node_modules/webpack/lib/dependencies/ImportDependenciesBlock.js index 2797276b9..61e6bb272 100644 --- a/node_modules/webpack/lib/dependencies/ImportDependenciesBlock.js +++ b/node_modules/webpack/lib/dependencies/ImportDependenciesBlock.js @@ -1,17 +1,18 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const AsyncDependenciesBlock = require("../AsyncDependenciesBlock"); -const ImportDependency = require("./ImportDependency"); - -module.exports = class ImportDependenciesBlock extends AsyncDependenciesBlock { - constructor(request, range, chunkName, module, loc) { - super(chunkName, module, loc); - this.range = range; - const dep = new ImportDependency(request, this); - dep.loc = loc; - this.addDependency(dep); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const AsyncDependenciesBlock = require("../AsyncDependenciesBlock"); +const ImportDependency = require("./ImportDependency"); + +module.exports = class ImportDependenciesBlock extends AsyncDependenciesBlock { + // TODO webpack 5 reorganize arguments + constructor(request, range, groupOptions, module, loc, originModule) { + super(groupOptions, module, loc, request); + this.range = range; + const dep = new ImportDependency(request, originModule, this); + dep.loc = loc; + this.addDependency(dep); + } +}; diff --git a/node_modules/webpack/lib/dependencies/ImportDependency.js b/node_modules/webpack/lib/dependencies/ImportDependency.js index 4c2667756..520bed218 100644 --- a/node_modules/webpack/lib/dependencies/ImportDependency.js +++ b/node_modules/webpack/lib/dependencies/ImportDependency.js @@ -1,54 +1,34 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ModuleDependency = require("./ModuleDependency"); -const DepBlockHelpers = require("./DepBlockHelpers"); -const webpackMissingPromiseModule = require("./WebpackMissingModule").promise; - -class ImportDependency extends ModuleDependency { - constructor(request, block) { - super(request); - this.block = block; - } - - get type() { - return "import()"; - } -} - -ImportDependency.Template = class ImportDependencyTemplate { - apply(dep, source, outputOptions, requestShortener) { - const depBlock = dep.block; - const promise = DepBlockHelpers.getDepBlockPromise(depBlock, outputOptions, requestShortener, "import()"); - const comment = this.getOptionalComment(outputOptions.pathinfo, requestShortener.shorten(dep.request)); - - const content = this.getContent(promise, dep, comment); - source.replace(depBlock.range[0], depBlock.range[1] - 1, content); - } - - getOptionalComment(pathinfo, shortenedRequest) { - if(!pathinfo) { - return ""; - } - - return `/*! ${shortenedRequest} */ `; - } - - getContent(promise, dep, comment) { - if(promise && dep.module) { - const stringifiedId = JSON.stringify(dep.module.id); - return `${promise}.then(__webpack_require__.bind(null, ${comment}${stringifiedId}))`; - } - - if(dep.module) { - const stringifiedId = JSON.stringify(dep.module.id); - return `new Promise(function(resolve) { resolve(__webpack_require__(${comment}${stringifiedId})); })`; - } - - return webpackMissingPromiseModule(dep.request); - } -}; - -module.exports = ImportDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const ModuleDependency = require("./ModuleDependency"); + +class ImportDependency extends ModuleDependency { + constructor(request, originModule, block) { + super(request); + this.originModule = originModule; + this.block = block; + } + + get type() { + return "import()"; + } +} + +ImportDependency.Template = class ImportDependencyTemplate { + apply(dep, source, runtime) { + const content = runtime.moduleNamespacePromise({ + block: dep.block, + module: dep.module, + request: dep.request, + strict: dep.originModule.buildMeta.strictHarmonyModule, + message: "import()" + }); + + source.replace(dep.block.range[0], dep.block.range[1] - 1, content); + } +}; + +module.exports = ImportDependency; diff --git a/node_modules/webpack/lib/dependencies/ImportEagerContextDependency.js b/node_modules/webpack/lib/dependencies/ImportEagerContextDependency.js deleted file mode 100644 index a4b7388bc..000000000 --- a/node_modules/webpack/lib/dependencies/ImportEagerContextDependency.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ImportContextDependency = require("./ImportContextDependency"); -const ContextDependencyTemplateAsRequireCall = require("./ContextDependencyTemplateAsRequireCall"); - -class ImportEagerContextDependency extends ImportContextDependency { - constructor(request, recursive, regExp, range, valueRange, chunkName) { - super(request, recursive, regExp, range, valueRange, chunkName); - this.async = "eager"; - } - - get type() { - return "import() context eager"; - } -} - -ImportEagerContextDependency.Template = ContextDependencyTemplateAsRequireCall; - -module.exports = ImportEagerContextDependency; diff --git a/node_modules/webpack/lib/dependencies/ImportEagerDependency.js b/node_modules/webpack/lib/dependencies/ImportEagerDependency.js index 9e1c2ace1..0671d5dc0 100644 --- a/node_modules/webpack/lib/dependencies/ImportEagerDependency.js +++ b/node_modules/webpack/lib/dependencies/ImportEagerDependency.js @@ -1,46 +1,32 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ModuleDependency = require("./ModuleDependency"); -const webpackMissingPromiseModule = require("./WebpackMissingModule").promise; - -class ImportEagerDependency extends ModuleDependency { - constructor(request, range) { - super(request); - this.range = range; - } - - get type() { - return "import()"; - } -} - -ImportEagerDependency.Template = class ImportEagerDependencyTemplate { - apply(dep, source, outputOptions, requestShortener) { - const comment = this.getOptionalComment(outputOptions.pathinfo, requestShortener.shorten(dep.request)); - - const content = this.getContent(dep, comment); - source.replace(dep.range[0], dep.range[1] - 1, content); - } - - getOptionalComment(pathinfo, shortenedRequest) { - if(!pathinfo) { - return ""; - } - - return `/*! ${shortenedRequest} */ `; - } - - getContent(dep, comment) { - if(dep.module) { - const stringifiedId = JSON.stringify(dep.module.id); - return `new Promise(function(resolve) { resolve(__webpack_require__(${comment}${stringifiedId})); })`; - } - - return webpackMissingPromiseModule(dep.request); - } -}; - -module.exports = ImportEagerDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const ModuleDependency = require("./ModuleDependency"); + +class ImportEagerDependency extends ModuleDependency { + constructor(request, originModule, range) { + super(request); + this.originModule = originModule; + this.range = range; + } + + get type() { + return "import() eager"; + } +} + +ImportEagerDependency.Template = class ImportEagerDependencyTemplate { + apply(dep, source, runtime) { + const content = runtime.moduleNamespacePromise({ + module: dep.module, + request: dep.request, + strict: dep.originModule.buildMeta.strictHarmonyModule, + message: "import() eager" + }); + source.replace(dep.range[0], dep.range[1] - 1, content); + } +}; + +module.exports = ImportEagerDependency; diff --git a/node_modules/webpack/lib/dependencies/ImportLazyContextDependency.js b/node_modules/webpack/lib/dependencies/ImportLazyContextDependency.js deleted file mode 100644 index b6f9187c9..000000000 --- a/node_modules/webpack/lib/dependencies/ImportLazyContextDependency.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ImportContextDependency = require("./ImportContextDependency"); -const ContextDependencyTemplateAsRequireCall = require("./ContextDependencyTemplateAsRequireCall"); - -class ImportLazyContextDependency extends ImportContextDependency { - constructor(request, recursive, regExp, range, valueRange, chunkName) { - super(request, recursive, regExp, range, valueRange, chunkName); - this.async = "lazy"; - } - - get type() { - return "import() context lazy"; - } -} - -ImportLazyContextDependency.Template = ContextDependencyTemplateAsRequireCall; - -module.exports = ImportLazyContextDependency; diff --git a/node_modules/webpack/lib/dependencies/ImportLazyOnceContextDependency.js b/node_modules/webpack/lib/dependencies/ImportLazyOnceContextDependency.js deleted file mode 100644 index 607ac3f2d..000000000 --- a/node_modules/webpack/lib/dependencies/ImportLazyOnceContextDependency.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ImportContextDependency = require("./ImportContextDependency"); -const ContextDependencyTemplateAsRequireCall = require("./ContextDependencyTemplateAsRequireCall"); - -class ImportLazyOnceContextDependency extends ImportContextDependency { - constructor(request, recursive, regExp, range, valueRange, chunkName) { - super(request, recursive, regExp, range, valueRange, chunkName); - this.async = "lazy-once"; - } - - get type() { - return "import() context lazy-once"; - } -} - -ImportLazyOnceContextDependency.Template = ContextDependencyTemplateAsRequireCall; - -module.exports = ImportLazyOnceContextDependency; diff --git a/node_modules/webpack/lib/dependencies/ImportParserPlugin.js b/node_modules/webpack/lib/dependencies/ImportParserPlugin.js index a775571b2..86c6b7438 100644 --- a/node_modules/webpack/lib/dependencies/ImportParserPlugin.js +++ b/node_modules/webpack/lib/dependencies/ImportParserPlugin.js @@ -1,89 +1,263 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ImportEagerContextDependency = require("./ImportEagerContextDependency"); -const ImportWeakDependency = require("./ImportWeakDependency"); -const ImportWeakContextDependency = require("./ImportWeakContextDependency"); -const ImportLazyOnceContextDependency = require("./ImportLazyOnceContextDependency"); -const ImportLazyContextDependency = require("./ImportLazyContextDependency"); -const ImportDependenciesBlock = require("./ImportDependenciesBlock"); -const ImportEagerDependency = require("./ImportEagerDependency"); -const ContextDependencyHelpers = require("./ContextDependencyHelpers"); -const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning"); - -class ImportParserPlugin { - constructor(options) { - this.options = options; - } - - apply(parser) { - const options = this.options; - - parser.plugin(["call System.import", "import-call"], (expr) => { - if(expr.arguments.length !== 1) - throw new Error("Incorrect number of arguments provided to 'import(module: string) -> Promise'."); - - const param = parser.evaluateExpression(expr.arguments[0]); - - let chunkName = null; - let mode = "lazy"; - - const importOptions = parser.getCommentOptions(expr.range); - if(importOptions) { - if(typeof importOptions.webpackChunkName !== "undefined") { - if(typeof importOptions.webpackChunkName !== "string") - parser.state.module.warnings.push(new UnsupportedFeatureWarning(parser.state.module, `\`webpackChunkName\` expected a string, but received: ${importOptions.webpackChunkName}.`)); - else - chunkName = importOptions.webpackChunkName; - } - if(typeof importOptions.webpackMode !== "undefined") { - if(typeof importOptions.webpackMode !== "string") - parser.state.module.warnings.push(new UnsupportedFeatureWarning(parser.state.module, `\`webpackMode\` expected a string, but received: ${importOptions.webpackMode}.`)); - else - mode = importOptions.webpackMode; - } - } - - if(param.isString()) { - if(mode !== "lazy" && mode !== "eager" && mode !== "weak") { - parser.state.module.warnings.push(new UnsupportedFeatureWarning(parser.state.module, `\`webpackMode\` expected 'lazy', 'eager' or 'weak', but received: ${mode}.`)); - } - - if(mode === "eager") { - const dep = new ImportEagerDependency(param.string, expr.range); - parser.state.current.addDependency(dep); - } else if(mode === "weak") { - const dep = new ImportWeakDependency(param.string, expr.range); - parser.state.current.addDependency(dep); - } else { - const depBlock = new ImportDependenciesBlock(param.string, expr.range, chunkName, parser.state.module, expr.loc); - parser.state.current.addBlock(depBlock); - } - return true; - } else { - if(mode !== "lazy" && mode !== "lazy-once" && mode !== "eager" && mode !== "weak") { - parser.state.module.warnings.push(new UnsupportedFeatureWarning(parser.state.module, `\`webpackMode\` expected 'lazy', 'lazy-once', 'eager' or 'weak', but received: ${mode}.`)); - } - - let Dep = ImportLazyContextDependency; - if(mode === "eager") { - Dep = ImportEagerContextDependency; - } else if(mode === "weak") { - Dep = ImportWeakContextDependency; - } else if(mode === "lazy-once") { - Dep = ImportLazyOnceContextDependency; - } - const dep = ContextDependencyHelpers.create(Dep, expr.range, param, expr, options, chunkName); - if(!dep) return; - dep.loc = expr.loc; - dep.optional = !!parser.scope.inTry; - parser.state.current.addDependency(dep); - return true; - } - }); - } -} -module.exports = ImportParserPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const ImportContextDependency = require("./ImportContextDependency"); +const ImportWeakDependency = require("./ImportWeakDependency"); +const ImportDependenciesBlock = require("./ImportDependenciesBlock"); +const ImportEagerDependency = require("./ImportEagerDependency"); +const ContextDependencyHelpers = require("./ContextDependencyHelpers"); +const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning"); +const CommentCompilationWarning = require("../CommentCompilationWarning"); + +class ImportParserPlugin { + constructor(options) { + this.options = options; + } + + apply(parser) { + parser.hooks.importCall.tap("ImportParserPlugin", expr => { + if (expr.arguments.length !== 1) { + throw new Error( + "Incorrect number of arguments provided to 'import(module: string) -> Promise'." + ); + } + + const param = parser.evaluateExpression(expr.arguments[0]); + + let chunkName = null; + let mode = "lazy"; + let include = null; + let exclude = null; + const groupOptions = {}; + + const { + options: importOptions, + errors: commentErrors + } = parser.parseCommentOptions(expr.range); + + if (commentErrors) { + for (const e of commentErrors) { + const { comment } = e; + parser.state.module.warnings.push( + new CommentCompilationWarning( + `Compilation error while processing magic comment(-s): /*${ + comment.value + }*/: ${e.message}`, + parser.state.module, + comment.loc + ) + ); + } + } + + if (importOptions) { + if (importOptions.webpackIgnore !== undefined) { + if (typeof importOptions.webpackIgnore !== "boolean") { + parser.state.module.warnings.push( + new UnsupportedFeatureWarning( + parser.state.module, + `\`webpackIgnore\` expected a boolean, but received: ${ + importOptions.webpackIgnore + }.`, + expr.loc + ) + ); + } else { + // Do not instrument `import()` is `webpackIgnore` is `true` + if (importOptions.webpackIgnore) { + return false; + } + } + } + if (importOptions.webpackChunkName !== undefined) { + if (typeof importOptions.webpackChunkName !== "string") { + parser.state.module.warnings.push( + new UnsupportedFeatureWarning( + parser.state.module, + `\`webpackChunkName\` expected a string, but received: ${ + importOptions.webpackChunkName + }.`, + expr.loc + ) + ); + } else { + chunkName = importOptions.webpackChunkName; + } + } + if (importOptions.webpackMode !== undefined) { + if (typeof importOptions.webpackMode !== "string") { + parser.state.module.warnings.push( + new UnsupportedFeatureWarning( + parser.state.module, + `\`webpackMode\` expected a string, but received: ${ + importOptions.webpackMode + }.`, + expr.loc + ) + ); + } else { + mode = importOptions.webpackMode; + } + } + if (importOptions.webpackPrefetch !== undefined) { + if (importOptions.webpackPrefetch === true) { + groupOptions.prefetchOrder = 0; + } else if (typeof importOptions.webpackPrefetch === "number") { + groupOptions.prefetchOrder = importOptions.webpackPrefetch; + } else { + parser.state.module.warnings.push( + new UnsupportedFeatureWarning( + parser.state.module, + `\`webpackPrefetch\` expected true or a number, but received: ${ + importOptions.webpackPrefetch + }.`, + expr.loc + ) + ); + } + } + if (importOptions.webpackPreload !== undefined) { + if (importOptions.webpackPreload === true) { + groupOptions.preloadOrder = 0; + } else if (typeof importOptions.webpackPreload === "number") { + groupOptions.preloadOrder = importOptions.webpackPreload; + } else { + parser.state.module.warnings.push( + new UnsupportedFeatureWarning( + parser.state.module, + `\`webpackPreload\` expected true or a number, but received: ${ + importOptions.webpackPreload + }.`, + expr.loc + ) + ); + } + } + if (importOptions.webpackInclude !== undefined) { + if ( + !importOptions.webpackInclude || + importOptions.webpackInclude.constructor.name !== "RegExp" + ) { + parser.state.module.warnings.push( + new UnsupportedFeatureWarning( + parser.state.module, + `\`webpackInclude\` expected a regular expression, but received: ${ + importOptions.webpackInclude + }.`, + expr.loc + ) + ); + } else { + include = new RegExp(importOptions.webpackInclude); + } + } + if (importOptions.webpackExclude !== undefined) { + if ( + !importOptions.webpackExclude || + importOptions.webpackExclude.constructor.name !== "RegExp" + ) { + parser.state.module.warnings.push( + new UnsupportedFeatureWarning( + parser.state.module, + `\`webpackExclude\` expected a regular expression, but received: ${ + importOptions.webpackExclude + }.`, + expr.loc + ) + ); + } else { + exclude = new RegExp(importOptions.webpackExclude); + } + } + } + + if (param.isString()) { + if (mode !== "lazy" && mode !== "eager" && mode !== "weak") { + parser.state.module.warnings.push( + new UnsupportedFeatureWarning( + parser.state.module, + `\`webpackMode\` expected 'lazy', 'eager' or 'weak', but received: ${mode}.`, + expr.loc + ) + ); + } + + if (mode === "eager") { + const dep = new ImportEagerDependency( + param.string, + parser.state.module, + expr.range + ); + parser.state.current.addDependency(dep); + } else if (mode === "weak") { + const dep = new ImportWeakDependency( + param.string, + parser.state.module, + expr.range + ); + parser.state.current.addDependency(dep); + } else { + const depBlock = new ImportDependenciesBlock( + param.string, + expr.range, + Object.assign(groupOptions, { + name: chunkName + }), + parser.state.module, + expr.loc, + parser.state.module + ); + parser.state.current.addBlock(depBlock); + } + return true; + } else { + if ( + mode !== "lazy" && + mode !== "lazy-once" && + mode !== "eager" && + mode !== "weak" + ) { + parser.state.module.warnings.push( + new UnsupportedFeatureWarning( + parser.state.module, + `\`webpackMode\` expected 'lazy', 'lazy-once', 'eager' or 'weak', but received: ${mode}.`, + expr.loc + ) + ); + mode = "lazy"; + } + + if (mode === "weak") { + mode = "async-weak"; + } + const dep = ContextDependencyHelpers.create( + ImportContextDependency, + expr.range, + param, + expr, + this.options, + { + chunkName, + groupOptions, + include, + exclude, + mode, + namespaceObject: parser.state.module.buildMeta.strictHarmonyModule + ? "strict" + : true + } + ); + if (!dep) return; + dep.loc = expr.loc; + dep.optional = !!parser.scope.inTry; + parser.state.current.addDependency(dep); + return true; + } + }); + } +} + +module.exports = ImportParserPlugin; diff --git a/node_modules/webpack/lib/dependencies/ImportPlugin.js b/node_modules/webpack/lib/dependencies/ImportPlugin.js index 27118bbcf..164719259 100644 --- a/node_modules/webpack/lib/dependencies/ImportPlugin.js +++ b/node_modules/webpack/lib/dependencies/ImportPlugin.js @@ -1,60 +1,79 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ImportDependency = require("./ImportDependency"); -const ImportEagerDependency = require("./ImportEagerDependency"); -const ImportWeakDependency = require("./ImportWeakDependency"); -const ImportEagerContextDependency = require("./ImportEagerContextDependency"); -const ImportWeakContextDependency = require("./ImportWeakContextDependency"); -const ImportLazyOnceContextDependency = require("./ImportLazyOnceContextDependency"); -const ImportLazyContextDependency = require("./ImportLazyContextDependency"); -const ImportParserPlugin = require("./ImportParserPlugin"); - -class ImportPlugin { - constructor(options) { - this.options = options; - } - - apply(compiler) { - const options = this.options; - compiler.plugin("compilation", (compilation, params) => { - const normalModuleFactory = params.normalModuleFactory; - const contextModuleFactory = params.contextModuleFactory; - - compilation.dependencyFactories.set(ImportDependency, normalModuleFactory); - compilation.dependencyTemplates.set(ImportDependency, new ImportDependency.Template()); - - compilation.dependencyFactories.set(ImportEagerDependency, normalModuleFactory); - compilation.dependencyTemplates.set(ImportEagerDependency, new ImportEagerDependency.Template()); - - compilation.dependencyFactories.set(ImportWeakDependency, normalModuleFactory); - compilation.dependencyTemplates.set(ImportWeakDependency, new ImportWeakDependency.Template()); - - compilation.dependencyFactories.set(ImportEagerContextDependency, contextModuleFactory); - compilation.dependencyTemplates.set(ImportEagerContextDependency, new ImportEagerContextDependency.Template()); - - compilation.dependencyFactories.set(ImportWeakContextDependency, contextModuleFactory); - compilation.dependencyTemplates.set(ImportWeakContextDependency, new ImportWeakContextDependency.Template()); - - compilation.dependencyFactories.set(ImportLazyOnceContextDependency, contextModuleFactory); - compilation.dependencyTemplates.set(ImportLazyOnceContextDependency, new ImportLazyOnceContextDependency.Template()); - - compilation.dependencyFactories.set(ImportLazyContextDependency, contextModuleFactory); - compilation.dependencyTemplates.set(ImportLazyContextDependency, new ImportLazyContextDependency.Template()); - - normalModuleFactory.plugin("parser", (parser, parserOptions) => { - - if(typeof parserOptions.import !== "undefined" && !parserOptions.import) - return; - - parser.apply( - new ImportParserPlugin(options) - ); - }); - }); - } -} -module.exports = ImportPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const ImportDependency = require("./ImportDependency"); +const ImportEagerDependency = require("./ImportEagerDependency"); +const ImportWeakDependency = require("./ImportWeakDependency"); +const ImportContextDependency = require("./ImportContextDependency"); +const ImportParserPlugin = require("./ImportParserPlugin"); + +class ImportPlugin { + constructor(options) { + this.options = options; + } + + apply(compiler) { + const options = this.options; + compiler.hooks.compilation.tap( + "ImportPlugin", + (compilation, { contextModuleFactory, normalModuleFactory }) => { + compilation.dependencyFactories.set( + ImportDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + ImportDependency, + new ImportDependency.Template() + ); + + compilation.dependencyFactories.set( + ImportEagerDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + ImportEagerDependency, + new ImportEagerDependency.Template() + ); + + compilation.dependencyFactories.set( + ImportWeakDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + ImportWeakDependency, + new ImportWeakDependency.Template() + ); + + compilation.dependencyFactories.set( + ImportContextDependency, + contextModuleFactory + ); + compilation.dependencyTemplates.set( + ImportContextDependency, + new ImportContextDependency.Template() + ); + + const handler = (parser, parserOptions) => { + if (parserOptions.import !== undefined && !parserOptions.import) + return; + + new ImportParserPlugin(options).apply(parser); + }; + + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("ImportPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("ImportPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/esm") + .tap("ImportPlugin", handler); + } + ); + } +} +module.exports = ImportPlugin; diff --git a/node_modules/webpack/lib/dependencies/ImportWeakContextDependency.js b/node_modules/webpack/lib/dependencies/ImportWeakContextDependency.js deleted file mode 100644 index f6c19613e..000000000 --- a/node_modules/webpack/lib/dependencies/ImportWeakContextDependency.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ImportContextDependency = require("./ImportContextDependency"); -const ContextDependencyTemplateAsRequireCall = require("./ContextDependencyTemplateAsRequireCall"); - -class ImportWeakContextDependency extends ImportContextDependency { - constructor(request, recursive, regExp, range, valueRange, chunkName) { - super(request, recursive, regExp, range, valueRange, chunkName); - this.async = "async-weak"; - } - - get type() { - return "import() context weak"; - } -} - -ImportWeakContextDependency.Template = ContextDependencyTemplateAsRequireCall; - -module.exports = ImportWeakContextDependency; diff --git a/node_modules/webpack/lib/dependencies/ImportWeakDependency.js b/node_modules/webpack/lib/dependencies/ImportWeakDependency.js index ccad2d92c..d48400001 100644 --- a/node_modules/webpack/lib/dependencies/ImportWeakDependency.js +++ b/node_modules/webpack/lib/dependencies/ImportWeakDependency.js @@ -1,47 +1,34 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ModuleDependency = require("./ModuleDependency"); -const webpackMissingPromiseModule = require("./WebpackMissingModule").promise; - -class ImportWeakDependency extends ModuleDependency { - constructor(request, range) { - super(request); - this.range = range; - this.weak = true; - } - - get type() { - return "import() weak"; - } -} - -ImportWeakDependency.Template = class ImportDependencyTemplate { - apply(dep, source, outputOptions, requestShortener) { - const comment = this.getOptionalComment(outputOptions.pathinfo, requestShortener.shorten(dep.request)); - - const content = this.getContent(dep, comment); - source.replace(dep.range[0], dep.range[1] - 1, content); - } - - getOptionalComment(pathinfo, shortenedRequest) { - if(!pathinfo) { - return ""; - } - - return `/*! ${shortenedRequest} */ `; - } - - getContent(dep, comment) { - if(dep.module) { - const stringifiedId = JSON.stringify(dep.module.id); - return `Promise.resolve(${comment}${stringifiedId}).then(function(id) { if(!__webpack_require__.m[id]) throw new Error("Module '" + id + "' is not available (weak dependency)"); return __webpack_require__(id); })`; - } - - return webpackMissingPromiseModule(dep.request); - } -}; - -module.exports = ImportWeakDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const ModuleDependency = require("./ModuleDependency"); + +class ImportWeakDependency extends ModuleDependency { + constructor(request, originModule, range) { + super(request); + this.originModule = originModule; + this.range = range; + this.weak = true; + } + + get type() { + return "import() weak"; + } +} + +ImportWeakDependency.Template = class ImportDependencyTemplate { + apply(dep, source, runtime) { + const content = runtime.moduleNamespacePromise({ + module: dep.module, + request: dep.request, + strict: dep.originModule.buildMeta.strictHarmonyModule, + message: "import() weak", + weak: true + }); + source.replace(dep.range[0], dep.range[1] - 1, content); + } +}; + +module.exports = ImportWeakDependency; diff --git a/node_modules/webpack/lib/dependencies/LoaderDependency.js b/node_modules/webpack/lib/dependencies/LoaderDependency.js index 4b5aff7c5..9d0876bce 100644 --- a/node_modules/webpack/lib/dependencies/LoaderDependency.js +++ b/node_modules/webpack/lib/dependencies/LoaderDependency.js @@ -1,18 +1,21 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ModuleDependency = require("./ModuleDependency"); - -class LoaderDependency extends ModuleDependency { - constructor(request) { - super(request); - } - - get type() { - return "loader"; - } -} - -module.exports = LoaderDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const ModuleDependency = require("./ModuleDependency"); + +class LoaderDependency extends ModuleDependency { + /** + * @param {string} request request string + */ + constructor(request) { + super(request); + } + + get type() { + return "loader"; + } +} + +module.exports = LoaderDependency; diff --git a/node_modules/webpack/lib/dependencies/LoaderPlugin.js b/node_modules/webpack/lib/dependencies/LoaderPlugin.js index a565ebbc4..c781d0636 100644 --- a/node_modules/webpack/lib/dependencies/LoaderPlugin.js +++ b/node_modules/webpack/lib/dependencies/LoaderPlugin.js @@ -1,60 +1,117 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const LoaderDependency = require("./LoaderDependency"); - -class LoaderPlugin { - - apply(compiler) { - compiler.plugin("compilation", (compilation, params) => { - const normalModuleFactory = params.normalModuleFactory; - - compilation.dependencyFactories.set(LoaderDependency, normalModuleFactory); - }); - compiler.plugin("compilation", (compilation) => { - compilation.plugin("normal-module-loader", (loaderContext, module) => { - loaderContext.loadModule = function loadModule(request, callback) { - const dep = new LoaderDependency(request); - dep.loc = request; - compilation.addModuleDependencies(module, [ - [dep] - ], true, "lm", false, (err) => { - if(err) return callback(err); - - if(!dep.module) return callback(new Error("Cannot load the module")); - if(dep.module.building) dep.module.building.push(next); - else next(); - - function next(err) { - if(err) return callback(err); - - if(dep.module.error) return callback(dep.module.error); - if(!dep.module._source) throw new Error("The module created for a LoaderDependency must have a property _source"); - let source, map; - const moduleSource = dep.module._source; - if(moduleSource.sourceAndMap) { - const sourceAndMap = moduleSource.sourceAndMap(); - map = sourceAndMap.map; - source = sourceAndMap.source; - } else { - map = moduleSource.map(); - source = moduleSource.source(); - } - if(dep.module.fileDependencies) { - dep.module.fileDependencies.forEach((dep) => loaderContext.addDependency(dep)); - } - if(dep.module.contextDependencies) { - dep.module.contextDependencies.forEach((dep) => loaderContext.addContextDependency(dep)); - } - return callback(null, source, map, dep.module); - } - }); - }; - }); - }); - } -} -module.exports = LoaderPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const LoaderDependency = require("./LoaderDependency"); +const NormalModule = require("../NormalModule"); + +/** @typedef {import("../Module")} Module */ + +/** + * @callback LoadModuleCallback + * @param {Error=} err error object + * @param {string=} source source code + * @param {object=} map source map + * @param {Module=} module loaded module if successful + */ + +class LoaderPlugin { + apply(compiler) { + compiler.hooks.compilation.tap( + "LoaderPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set( + LoaderDependency, + normalModuleFactory + ); + } + ); + + compiler.hooks.compilation.tap("LoaderPlugin", compilation => { + compilation.hooks.normalModuleLoader.tap( + "LoaderPlugin", + (loaderContext, module) => { + /** + * @param {string} request the request string to load the module from + * @param {LoadModuleCallback} callback callback returning the loaded module or error + * @returns {void} + */ + loaderContext.loadModule = (request, callback) => { + const dep = new LoaderDependency(request); + dep.loc = { + name: request + }; + const factory = compilation.dependencyFactories.get( + dep.constructor + ); + if (factory === undefined) { + return callback( + new Error( + `No module factory available for dependency type: ${ + dep.constructor.name + }` + ) + ); + } + compilation.semaphore.release(); + compilation.addModuleDependencies( + module, + [ + { + factory, + dependencies: [dep] + } + ], + true, + "lm", + true, + err => { + compilation.semaphore.acquire(() => { + if (err) { + return callback(err); + } + if (!dep.module) { + return callback(new Error("Cannot load the module")); + } + // TODO consider removing this in webpack 5 + if (dep.module instanceof NormalModule && dep.module.error) { + return callback(dep.module.error); + } + if (!dep.module._source) { + throw new Error( + "The module created for a LoaderDependency must have a property _source" + ); + } + let source, map; + const moduleSource = dep.module._source; + if (moduleSource.sourceAndMap) { + const sourceAndMap = moduleSource.sourceAndMap(); + map = sourceAndMap.map; + source = sourceAndMap.source; + } else { + map = moduleSource.map(); + source = moduleSource.source(); + } + if (dep.module.buildInfo.fileDependencies) { + for (const d of dep.module.buildInfo.fileDependencies) { + loaderContext.addDependency(d); + } + } + if (dep.module.buildInfo.contextDependencies) { + for (const d of dep.module.buildInfo.contextDependencies) { + loaderContext.addContextDependency(d); + } + } + return callback(null, source, map, dep.module); + }); + } + ); + }; + } + ); + }); + } +} +module.exports = LoaderPlugin; diff --git a/node_modules/webpack/lib/dependencies/LocalModule.js b/node_modules/webpack/lib/dependencies/LocalModule.js index 7245828cb..06e5385fb 100644 --- a/node_modules/webpack/lib/dependencies/LocalModule.js +++ b/node_modules/webpack/lib/dependencies/LocalModule.js @@ -1,23 +1,23 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class LocalModule { - constructor(module, name, idx) { - this.module = module; - this.name = name; - this.idx = idx; - this.used = false; - } - - flagUsed() { - this.used = true; - } - - variableName() { - return "__WEBPACK_LOCAL_MODULE_" + this.idx + "__"; - } -} -module.exports = LocalModule; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +class LocalModule { + constructor(module, name, idx) { + this.module = module; + this.name = name; + this.idx = idx; + this.used = false; + } + + flagUsed() { + this.used = true; + } + + variableName() { + return "__WEBPACK_LOCAL_MODULE_" + this.idx + "__"; + } +} +module.exports = LocalModule; diff --git a/node_modules/webpack/lib/dependencies/LocalModuleDependency.js b/node_modules/webpack/lib/dependencies/LocalModuleDependency.js index 0358dca26..5d1e56bb9 100644 --- a/node_modules/webpack/lib/dependencies/LocalModuleDependency.js +++ b/node_modules/webpack/lib/dependencies/LocalModuleDependency.js @@ -1,24 +1,28 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const NullDependency = require("./NullDependency"); - -class LocalModuleDependency extends NullDependency { - constructor(localModule, range) { - super(); - localModule.flagUsed(); - this.localModule = localModule; - this.range = range; - } -} - -LocalModuleDependency.Template = class LocalModuleDependencyTemplate { - apply(dep, source) { - if(!dep.range) return; - source.replace(dep.range[0], dep.range[1] - 1, dep.localModule.variableName()); - } -}; - -module.exports = LocalModuleDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const NullDependency = require("./NullDependency"); + +class LocalModuleDependency extends NullDependency { + constructor(localModule, range, callNew) { + super(); + localModule.flagUsed(); + this.localModule = localModule; + this.range = range; + this.callNew = callNew; + } +} + +LocalModuleDependency.Template = class LocalModuleDependencyTemplate { + apply(dep, source) { + if (!dep.range) return; + const moduleInstance = dep.callNew + ? `new (function () { return ${dep.localModule.variableName()}; })()` + : dep.localModule.variableName(); + source.replace(dep.range[0], dep.range[1] - 1, moduleInstance); + } +}; + +module.exports = LocalModuleDependency; diff --git a/node_modules/webpack/lib/dependencies/LocalModulesHelpers.js b/node_modules/webpack/lib/dependencies/LocalModulesHelpers.js index 0742f6cd4..056622704 100644 --- a/node_modules/webpack/lib/dependencies/LocalModulesHelpers.js +++ b/node_modules/webpack/lib/dependencies/LocalModulesHelpers.js @@ -1,46 +1,52 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const LocalModule = require("./LocalModule"); -const LocalModulesHelpers = exports; - -const lookup = (parent, mod) => { - if(mod.charAt(0) !== ".") return mod; - - var path = parent.split("/"), - segs = mod.split("/"); - path.pop(); - - for(let i = 0; i < segs.length; i++) { - const seg = segs[i]; - if(seg === "..") path.pop(); - else if(seg !== ".") path.push(seg); - } - - return path.join("/"); -}; - -LocalModulesHelpers.addLocalModule = (state, name) => { - if(!state.localModules) state.localModules = []; - const m = new LocalModule(state.module, name, state.localModules.length); - state.localModules.push(m); - return m; -}; - -LocalModulesHelpers.getLocalModule = (state, name, namedModule) => { - if(!state.localModules) return null; - if(namedModule) { - // resolve dependency name relative to the defining named module - name = lookup(namedModule, name); - } - for(let i = 0; i < state.localModules.length; i++) { - if(state.localModules[i].name === name) - return state.localModules[i]; - } - return null; -}; - -module.exports = LocalModulesHelpers; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const LocalModule = require("./LocalModule"); +const LocalModulesHelpers = exports; + +const lookup = (parent, mod) => { + if (mod.charAt(0) !== ".") return mod; + + var path = parent.split("/"); + var segs = mod.split("/"); + path.pop(); + + for (let i = 0; i < segs.length; i++) { + const seg = segs[i]; + if (seg === "..") { + path.pop(); + } else if (seg !== ".") { + path.push(seg); + } + } + + return path.join("/"); +}; + +LocalModulesHelpers.addLocalModule = (state, name) => { + if (!state.localModules) { + state.localModules = []; + } + const m = new LocalModule(state.module, name, state.localModules.length); + state.localModules.push(m); + return m; +}; + +LocalModulesHelpers.getLocalModule = (state, name, namedModule) => { + if (!state.localModules) return null; + if (namedModule) { + // resolve dependency name relative to the defining named module + name = lookup(namedModule, name); + } + for (let i = 0; i < state.localModules.length; i++) { + if (state.localModules[i].name === name) { + return state.localModules[i]; + } + } + return null; +}; + +module.exports = LocalModulesHelpers; diff --git a/node_modules/webpack/lib/dependencies/ModuleDependency.js b/node_modules/webpack/lib/dependencies/ModuleDependency.js index b8cfb47bc..f325e7a98 100644 --- a/node_modules/webpack/lib/dependencies/ModuleDependency.js +++ b/node_modules/webpack/lib/dependencies/ModuleDependency.js @@ -1,23 +1,23 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const Dependency = require("../Dependency"); - -class ModuleDependency extends Dependency { - constructor(request) { - super(); - this.request = request; - this.userRequest = request; - } - - isEqualResource(other) { - if(!(other instanceof ModuleDependency)) - return false; - - return this.request === other.request; - } -} - -module.exports = ModuleDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const Dependency = require("../Dependency"); + +class ModuleDependency extends Dependency { + /** + * @param {string} request request path which needs resolving + */ + constructor(request) { + super(); + this.request = request; + this.userRequest = request; + } + + getResourceIdentifier() { + return `module${this.request}`; + } +} + +module.exports = ModuleDependency; diff --git a/node_modules/webpack/lib/dependencies/ModuleDependencyTemplateAsId.js b/node_modules/webpack/lib/dependencies/ModuleDependencyTemplateAsId.js index a83924819..82bc6b5d6 100644 --- a/node_modules/webpack/lib/dependencies/ModuleDependencyTemplateAsId.js +++ b/node_modules/webpack/lib/dependencies/ModuleDependencyTemplateAsId.js @@ -1,21 +1,17 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class ModuleDependencyTemplateAsId { - - apply(dep, source, outputOptions, requestShortener) { - if(!dep.range) return; - const comment = outputOptions.pathinfo ? - `/*! ${requestShortener.shorten(dep.request)} */ ` : ""; - let content; - if(dep.module) - content = comment + JSON.stringify(dep.module.id); - else - content = require("./WebpackMissingModule").module(dep.request); - source.replace(dep.range[0], dep.range[1] - 1, content); - } -} -module.exports = ModuleDependencyTemplateAsId; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +class ModuleDependencyTemplateAsId { + apply(dep, source, runtime) { + if (!dep.range) return; + const content = runtime.moduleId({ + module: dep.module, + request: dep.request + }); + source.replace(dep.range[0], dep.range[1] - 1, content); + } +} +module.exports = ModuleDependencyTemplateAsId; diff --git a/node_modules/webpack/lib/dependencies/ModuleDependencyTemplateAsRequireId.js b/node_modules/webpack/lib/dependencies/ModuleDependencyTemplateAsRequireId.js index 863ed3b31..db74b895f 100644 --- a/node_modules/webpack/lib/dependencies/ModuleDependencyTemplateAsRequireId.js +++ b/node_modules/webpack/lib/dependencies/ModuleDependencyTemplateAsRequireId.js @@ -1,21 +1,17 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class ModuleDependencyTemplateAsRequireId { - - apply(dep, source, outputOptions, requestShortener) { - if(!dep.range) return; - const comment = outputOptions.pathinfo ? - `/*! ${requestShortener.shorten(dep.request)} */ ` : ""; - let content; - if(dep.module) - content = `__webpack_require__(${comment}${JSON.stringify(dep.module.id)})`; - else - content = require("./WebpackMissingModule").module(dep.request); - source.replace(dep.range[0], dep.range[1] - 1, content); - } -} -module.exports = ModuleDependencyTemplateAsRequireId; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +class ModuleDependencyTemplateAsRequireId { + apply(dep, source, runtime) { + if (!dep.range) return; + const content = runtime.moduleExports({ + module: dep.module, + request: dep.request + }); + source.replace(dep.range[0], dep.range[1] - 1, content); + } +} +module.exports = ModuleDependencyTemplateAsRequireId; diff --git a/node_modules/webpack/lib/dependencies/ModuleHotAcceptDependency.js b/node_modules/webpack/lib/dependencies/ModuleHotAcceptDependency.js index 4297e57d8..403f7f1a0 100644 --- a/node_modules/webpack/lib/dependencies/ModuleHotAcceptDependency.js +++ b/node_modules/webpack/lib/dependencies/ModuleHotAcceptDependency.js @@ -1,23 +1,23 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ModuleDependency = require("./ModuleDependency"); -const ModuleDependencyTemplateAsId = require("./ModuleDependencyTemplateAsId"); - -class ModuleHotAcceptDependency extends ModuleDependency { - constructor(request, range) { - super(request); - this.range = range; - this.weak = true; - } - - get type() { - return "module.hot.accept"; - } -} - -ModuleHotAcceptDependency.Template = ModuleDependencyTemplateAsId; - -module.exports = ModuleHotAcceptDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const ModuleDependency = require("./ModuleDependency"); +const ModuleDependencyTemplateAsId = require("./ModuleDependencyTemplateAsId"); + +class ModuleHotAcceptDependency extends ModuleDependency { + constructor(request, range) { + super(request); + this.range = range; + this.weak = true; + } + + get type() { + return "module.hot.accept"; + } +} + +ModuleHotAcceptDependency.Template = ModuleDependencyTemplateAsId; + +module.exports = ModuleHotAcceptDependency; diff --git a/node_modules/webpack/lib/dependencies/ModuleHotDeclineDependency.js b/node_modules/webpack/lib/dependencies/ModuleHotDeclineDependency.js index cab86cecb..49bf0af98 100644 --- a/node_modules/webpack/lib/dependencies/ModuleHotDeclineDependency.js +++ b/node_modules/webpack/lib/dependencies/ModuleHotDeclineDependency.js @@ -1,23 +1,23 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ModuleDependency = require("./ModuleDependency"); -const ModuleDependencyTemplateAsId = require("./ModuleDependencyTemplateAsId"); - -class ModuleHotDeclineDependency extends ModuleDependency { - constructor(request, range) { - super(request); - this.range = range; - this.weak = true; - } - - get type() { - return "module.hot.decline"; - } -} - -ModuleHotDeclineDependency.Template = ModuleDependencyTemplateAsId; - -module.exports = ModuleHotDeclineDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const ModuleDependency = require("./ModuleDependency"); +const ModuleDependencyTemplateAsId = require("./ModuleDependencyTemplateAsId"); + +class ModuleHotDeclineDependency extends ModuleDependency { + constructor(request, range) { + super(request); + this.range = range; + this.weak = true; + } + + get type() { + return "module.hot.decline"; + } +} + +ModuleHotDeclineDependency.Template = ModuleDependencyTemplateAsId; + +module.exports = ModuleHotDeclineDependency; diff --git a/node_modules/webpack/lib/dependencies/MultiEntryDependency.js b/node_modules/webpack/lib/dependencies/MultiEntryDependency.js index 6196b95a5..712d3ff1f 100644 --- a/node_modules/webpack/lib/dependencies/MultiEntryDependency.js +++ b/node_modules/webpack/lib/dependencies/MultiEntryDependency.js @@ -1,20 +1,25 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const Dependency = require("../Dependency"); - -class MultiEntryDependency extends Dependency { - constructor(dependencies, name) { - super(); - this.dependencies = dependencies; - this.name = name; - } - - get type() { - return "multi entry"; - } -} - -module.exports = MultiEntryDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +/** @typedef {import("./SingleEntryDependency")} SingleEntryDependency */ +const Dependency = require("../Dependency"); + +class MultiEntryDependency extends Dependency { + /** + * @param {SingleEntryDependency[]} dependencies an array of SingleEntryDependencies + * @param {string} name entry name + */ + constructor(dependencies, name) { + super(); + this.dependencies = dependencies; + this.name = name; + } + + get type() { + return "multi entry"; + } +} + +module.exports = MultiEntryDependency; diff --git a/node_modules/webpack/lib/dependencies/NullDependency.js b/node_modules/webpack/lib/dependencies/NullDependency.js index 5d389e67e..585f5fc0c 100644 --- a/node_modules/webpack/lib/dependencies/NullDependency.js +++ b/node_modules/webpack/lib/dependencies/NullDependency.js @@ -1,24 +1,20 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const Dependency = require("../Dependency"); - -class NullDependency extends Dependency { - get type() { - return "null"; - } - - isEqualResource() { - return false; - } - - updateHash() {} -} - -NullDependency.Template = class NullDependencyTemplate { - apply() {} -}; - -module.exports = NullDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const Dependency = require("../Dependency"); + +class NullDependency extends Dependency { + get type() { + return "null"; + } + + updateHash() {} +} + +NullDependency.Template = class NullDependencyTemplate { + apply() {} +}; + +module.exports = NullDependency; diff --git a/node_modules/webpack/lib/dependencies/PrefetchDependency.js b/node_modules/webpack/lib/dependencies/PrefetchDependency.js index 98ca185b8..7107d83c1 100644 --- a/node_modules/webpack/lib/dependencies/PrefetchDependency.js +++ b/node_modules/webpack/lib/dependencies/PrefetchDependency.js @@ -1,18 +1,18 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ModuleDependency = require("./ModuleDependency"); - -class PrefetchDependency extends ModuleDependency { - constructor(request) { - super(request); - } - - get type() { - return "prefetch"; - } -} - -module.exports = PrefetchDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const ModuleDependency = require("./ModuleDependency"); + +class PrefetchDependency extends ModuleDependency { + constructor(request) { + super(request); + } + + get type() { + return "prefetch"; + } +} + +module.exports = PrefetchDependency; diff --git a/node_modules/webpack/lib/dependencies/RequireContextDependency.js b/node_modules/webpack/lib/dependencies/RequireContextDependency.js index e37b1b54c..fd2e728fb 100644 --- a/node_modules/webpack/lib/dependencies/RequireContextDependency.js +++ b/node_modules/webpack/lib/dependencies/RequireContextDependency.js @@ -1,26 +1,22 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ContextDependency = require("./ContextDependency"); -const ModuleDependencyTemplateAsRequireId = require("./ModuleDependencyTemplateAsRequireId"); - -class RequireContextDependency extends ContextDependency { - constructor(request, recursive, regExp, asyncMode, range) { - super(request, recursive, regExp); - this.range = range; - - if(asyncMode) { - this.async = asyncMode; - } - } - - get type() { - return "require.context"; - } -} - -RequireContextDependency.Template = ModuleDependencyTemplateAsRequireId; - -module.exports = RequireContextDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const ContextDependency = require("./ContextDependency"); +const ModuleDependencyTemplateAsRequireId = require("./ModuleDependencyTemplateAsRequireId"); + +class RequireContextDependency extends ContextDependency { + constructor(options, range) { + super(options); + this.range = range; + } + + get type() { + return "require.context"; + } +} + +RequireContextDependency.Template = ModuleDependencyTemplateAsRequireId; + +module.exports = RequireContextDependency; diff --git a/node_modules/webpack/lib/dependencies/RequireContextDependencyParserPlugin.js b/node_modules/webpack/lib/dependencies/RequireContextDependencyParserPlugin.js index 04a8b25b9..1071fc01d 100644 --- a/node_modules/webpack/lib/dependencies/RequireContextDependencyParserPlugin.js +++ b/node_modules/webpack/lib/dependencies/RequireContextDependencyParserPlugin.js @@ -1,50 +1,56 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const RequireContextDependency = require("./RequireContextDependency"); - -module.exports = class RequireContextDependencyParserPlugin { - apply(parser) { - parser.plugin("call require.context", expr => { - let regExp = /^\.\/.*$/; - let recursive = true; - let asyncMode; - switch(expr.arguments.length) { - case 4: - { - const asyncModeExpr = parser.evaluateExpression(expr.arguments[3]); - if(!asyncModeExpr.isString()) return; - asyncMode = asyncModeExpr.string; - } - // falls through - case 3: - { - const regExpExpr = parser.evaluateExpression(expr.arguments[2]); - if(!regExpExpr.isRegExp()) return; - regExp = regExpExpr.regExp; - } - // falls through - case 2: - { - const recursiveExpr = parser.evaluateExpression(expr.arguments[1]); - if(!recursiveExpr.isBoolean()) return; - recursive = recursiveExpr.bool; - } - // falls through - case 1: - { - const requestExpr = parser.evaluateExpression(expr.arguments[0]); - if(!requestExpr.isString()) return; - const dep = new RequireContextDependency(requestExpr.string, recursive, regExp, asyncMode, expr.range); - dep.loc = expr.loc; - dep.optional = parser.scope.inTry; - parser.state.current.addDependency(dep); - return true; - } - } - }); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const RequireContextDependency = require("./RequireContextDependency"); + +module.exports = class RequireContextDependencyParserPlugin { + apply(parser) { + parser.hooks.call + .for("require.context") + .tap("RequireContextDependencyParserPlugin", expr => { + let regExp = /^\.\/.*$/; + let recursive = true; + let mode = "sync"; + switch (expr.arguments.length) { + case 4: { + const modeExpr = parser.evaluateExpression(expr.arguments[3]); + if (!modeExpr.isString()) return; + mode = modeExpr.string; + } + // falls through + case 3: { + const regExpExpr = parser.evaluateExpression(expr.arguments[2]); + if (!regExpExpr.isRegExp()) return; + regExp = regExpExpr.regExp; + } + // falls through + case 2: { + const recursiveExpr = parser.evaluateExpression(expr.arguments[1]); + if (!recursiveExpr.isBoolean()) return; + recursive = recursiveExpr.bool; + } + // falls through + case 1: { + const requestExpr = parser.evaluateExpression(expr.arguments[0]); + if (!requestExpr.isString()) return; + const dep = new RequireContextDependency( + { + request: requestExpr.string, + recursive, + regExp, + mode + }, + expr.range + ); + dep.loc = expr.loc; + dep.optional = parser.scope.inTry; + parser.state.current.addDependency(dep); + return true; + } + } + }); + } +}; diff --git a/node_modules/webpack/lib/dependencies/RequireContextPlugin.js b/node_modules/webpack/lib/dependencies/RequireContextPlugin.js index 3e08729d3..4e44e8711 100644 --- a/node_modules/webpack/lib/dependencies/RequireContextPlugin.js +++ b/node_modules/webpack/lib/dependencies/RequireContextPlugin.js @@ -1,96 +1,143 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const RequireContextDependency = require("./RequireContextDependency"); -const ContextElementDependency = require("./ContextElementDependency"); - -const RequireContextDependencyParserPlugin = require("./RequireContextDependencyParserPlugin"); - -class RequireContextPlugin { - constructor(modulesDirectories, extensions, mainFiles) { - if(!Array.isArray(modulesDirectories)) - throw new Error("modulesDirectories must be an array"); - if(!Array.isArray(extensions)) - throw new Error("extensions must be an array"); - this.modulesDirectories = modulesDirectories; - this.extensions = extensions; - this.mainFiles = mainFiles; - } - - apply(compiler) { - compiler.plugin("compilation", (compilation, params) => { - const contextModuleFactory = params.contextModuleFactory; - const normalModuleFactory = params.normalModuleFactory; - - compilation.dependencyFactories.set(RequireContextDependency, contextModuleFactory); - compilation.dependencyTemplates.set(RequireContextDependency, new RequireContextDependency.Template()); - - compilation.dependencyFactories.set(ContextElementDependency, normalModuleFactory); - - params.normalModuleFactory.plugin("parser", (parser, parserOptions) => { - - if(typeof parserOptions.requireContext !== "undefined" && !parserOptions.requireContext) - return; - - parser.apply(new RequireContextDependencyParserPlugin()); - }); - - params.contextModuleFactory.plugin("alternatives", (items, callback) => { - if(items.length === 0) return callback(null, items); - - callback(null, items.map((obj) => { - return this.extensions.filter((ext) => { - const l = obj.request.length; - return l > ext.length && obj.request.substr(l - ext.length, l) === ext; - }).map((ext) => { - const l = obj.request.length; - return { - context: obj.context, - request: obj.request.substr(0, l - ext.length) - }; - }).concat(obj); - }).reduce((a, b) => a.concat(b), [])); - }); - - params.contextModuleFactory.plugin("alternatives", (items, callback) => { - if(items.length === 0) return callback(null, items); - - callback(null, items.map((obj) => { - return this.mainFiles.filter((mainFile) => { - const l = obj.request.length; - return l > mainFile.length + 1 && obj.request.substr(l - mainFile.length - 1, l) === "/" + mainFile; - }).map((mainFile) => { - const l = obj.request.length; - return [{ - context: obj.context, - request: obj.request.substr(0, l - mainFile.length) - }, { - context: obj.context, - request: obj.request.substr(0, l - mainFile.length - 1) - }]; - }).reduce((a, b) => a.concat(b), []).concat(obj); - }).reduce((a, b) => a.concat(b), [])); - }); - - params.contextModuleFactory.plugin("alternatives", (items, callback) => { - if(items.length === 0) return callback(null, items); - - callback(null, items.map((obj) => { - for(let i = 0; i < this.modulesDirectories.length; i++) { - const dir = this.modulesDirectories[i]; - const idx = obj.request.indexOf("./" + dir + "/"); - if(idx === 0) { - obj.request = obj.request.slice(dir.length + 3); - break; - } - } - return obj; - })); - }); - }); - } -} -module.exports = RequireContextPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const RequireContextDependency = require("./RequireContextDependency"); +const ContextElementDependency = require("./ContextElementDependency"); + +const RequireContextDependencyParserPlugin = require("./RequireContextDependencyParserPlugin"); + +class RequireContextPlugin { + constructor(modulesDirectories, extensions, mainFiles) { + if (!Array.isArray(modulesDirectories)) { + throw new Error("modulesDirectories must be an array"); + } + if (!Array.isArray(extensions)) { + throw new Error("extensions must be an array"); + } + this.modulesDirectories = modulesDirectories; + this.extensions = extensions; + this.mainFiles = mainFiles; + } + + apply(compiler) { + compiler.hooks.compilation.tap( + "RequireContextPlugin", + (compilation, { contextModuleFactory, normalModuleFactory }) => { + compilation.dependencyFactories.set( + RequireContextDependency, + contextModuleFactory + ); + compilation.dependencyTemplates.set( + RequireContextDependency, + new RequireContextDependency.Template() + ); + + compilation.dependencyFactories.set( + ContextElementDependency, + normalModuleFactory + ); + + const handler = (parser, parserOptions) => { + if ( + parserOptions.requireContext !== undefined && + !parserOptions.requireContext + ) + return; + + new RequireContextDependencyParserPlugin().apply(parser); + }; + + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("RequireContextPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("RequireContextPlugin", handler); + + contextModuleFactory.hooks.alternatives.tap( + "RequireContextPlugin", + items => { + if (items.length === 0) return items; + return items + .map(obj => { + return this.extensions + .filter(ext => { + const l = obj.request.length; + return ( + l > ext.length && + obj.request.substr(l - ext.length, l) === ext + ); + }) + .map(ext => { + const l = obj.request.length; + return { + context: obj.context, + request: obj.request.substr(0, l - ext.length) + }; + }) + .concat(obj); + }) + .reduce((a, b) => a.concat(b), []); + } + ); + + contextModuleFactory.hooks.alternatives.tap( + "RequireContextPlugin", + items => { + if (items.length === 0) return items; + return items + .map(obj => { + return this.mainFiles + .filter(mainFile => { + const l = obj.request.length; + return ( + l > mainFile.length + 1 && + obj.request.substr(l - mainFile.length - 1, l) === + "/" + mainFile + ); + }) + .map(mainFile => { + const l = obj.request.length; + return [ + { + context: obj.context, + request: obj.request.substr(0, l - mainFile.length) + }, + { + context: obj.context, + request: obj.request.substr(0, l - mainFile.length - 1) + } + ]; + }) + .reduce((a, b) => a.concat(b), []) + .concat(obj); + }) + .reduce((a, b) => a.concat(b), []); + } + ); + + contextModuleFactory.hooks.alternatives.tap( + "RequireContextPlugin", + items => { + if (items.length === 0) return items; + return items.map(obj => { + for (let i = 0; i < this.modulesDirectories.length; i++) { + const dir = this.modulesDirectories[i]; + const idx = obj.request.indexOf("./" + dir + "/"); + if (idx === 0) { + obj.request = obj.request.slice(dir.length + 3); + break; + } + } + return obj; + }); + } + ); + } + ); + } +} +module.exports = RequireContextPlugin; diff --git a/node_modules/webpack/lib/dependencies/RequireEnsureDependenciesBlock.js b/node_modules/webpack/lib/dependencies/RequireEnsureDependenciesBlock.js index 4d72b07ab..2a5dde704 100644 --- a/node_modules/webpack/lib/dependencies/RequireEnsureDependenciesBlock.js +++ b/node_modules/webpack/lib/dependencies/RequireEnsureDependenciesBlock.js @@ -1,22 +1,33 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const AsyncDependenciesBlock = require("../AsyncDependenciesBlock"); -const RequireEnsureDependency = require("./RequireEnsureDependency"); - -module.exports = class RequireEnsureDependenciesBlock extends AsyncDependenciesBlock { - constructor(expr, successExpression, errorExpression, chunkName, chunkNameRange, module, loc) { - super(chunkName, module, loc); - this.expr = expr; - const successBodyRange = successExpression && successExpression.body && successExpression.body.range; - if(successBodyRange) { - this.range = [successBodyRange[0] + 1, successBodyRange[1] - 1]; - } - this.chunkNameRange = chunkNameRange; - const dep = new RequireEnsureDependency(this); - dep.loc = loc; - this.addDependency(dep); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const AsyncDependenciesBlock = require("../AsyncDependenciesBlock"); +const RequireEnsureDependency = require("./RequireEnsureDependency"); + +module.exports = class RequireEnsureDependenciesBlock extends AsyncDependenciesBlock { + constructor( + expr, + successExpression, + errorExpression, + chunkName, + chunkNameRange, + module, + loc + ) { + super(chunkName, module, loc, null); + this.expr = expr; + const successBodyRange = + successExpression && + successExpression.body && + successExpression.body.range; + if (successBodyRange) { + this.range = [successBodyRange[0] + 1, successBodyRange[1] - 1]; + } + this.chunkNameRange = chunkNameRange; + const dep = new RequireEnsureDependency(this); + dep.loc = loc; + this.addDependency(dep); + } +}; diff --git a/node_modules/webpack/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js b/node_modules/webpack/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js index 73b7d0c8c..213eaac0a 100644 --- a/node_modules/webpack/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +++ b/node_modules/webpack/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js @@ -1,102 +1,116 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const RequireEnsureDependenciesBlock = require("./RequireEnsureDependenciesBlock"); -const RequireEnsureItemDependency = require("./RequireEnsureItemDependency"); -const getFunctionExpression = require("./getFunctionExpression"); - -module.exports = class RequireEnsureDependenciesBlockParserPlugin { - apply(parser) { - parser.plugin("call require.ensure", expr => { - let chunkName = null; - let chunkNameRange = null; - let errorExpressionArg = null; - let errorExpression = null; - switch(expr.arguments.length) { - case 4: - { - const chunkNameExpr = parser.evaluateExpression(expr.arguments[3]); - if(!chunkNameExpr.isString()) return; - chunkNameRange = chunkNameExpr.range; - chunkName = chunkNameExpr.string; - } - // falls through - case 3: - { - errorExpressionArg = expr.arguments[2]; - errorExpression = getFunctionExpression(errorExpressionArg); - - if(!errorExpression && !chunkName) { - const chunkNameExpr = parser.evaluateExpression(expr.arguments[2]); - if(!chunkNameExpr.isString()) return; - chunkNameRange = chunkNameExpr.range; - chunkName = chunkNameExpr.string; - } - } - // falls through - case 2: - { - const dependenciesExpr = parser.evaluateExpression(expr.arguments[0]); - const dependenciesItems = dependenciesExpr.isArray() ? dependenciesExpr.items : [dependenciesExpr]; - const successExpressionArg = expr.arguments[1]; - const successExpression = getFunctionExpression(successExpressionArg); - - if(successExpression) { - parser.walkExpressions(successExpression.expressions); - } - if(errorExpression) { - parser.walkExpressions(errorExpression.expressions); - } - - const dep = new RequireEnsureDependenciesBlock(expr, - successExpression ? successExpression.fn : successExpressionArg, - errorExpression ? errorExpression.fn : errorExpressionArg, - chunkName, chunkNameRange, parser.state.module, expr.loc); - const old = parser.state.current; - parser.state.current = dep; - try { - let failed = false; - parser.inScope([], () => { - dependenciesItems.forEach(ee => { - if(ee.isString()) { - const edep = new RequireEnsureItemDependency(ee.string, ee.range); - edep.loc = dep.loc; - dep.addDependency(edep); - } else { - failed = true; - } - }); - }); - if(failed) { - return; - } - if(successExpression) { - if(successExpression.fn.body.type === "BlockStatement") - parser.walkStatement(successExpression.fn.body); - else - parser.walkExpression(successExpression.fn.body); - } - old.addBlock(dep); - } finally { - parser.state.current = old; - } - if(!successExpression) { - parser.walkExpression(successExpressionArg); - } - if(errorExpression) { - if(errorExpression.fn.body.type === "BlockStatement") - parser.walkStatement(errorExpression.fn.body); - else - parser.walkExpression(errorExpression.fn.body); - } else if(errorExpressionArg) { - parser.walkExpression(errorExpressionArg); - } - return true; - } - } - }); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const RequireEnsureDependenciesBlock = require("./RequireEnsureDependenciesBlock"); +const RequireEnsureItemDependency = require("./RequireEnsureItemDependency"); +const getFunctionExpression = require("./getFunctionExpression"); + +module.exports = class RequireEnsureDependenciesBlockParserPlugin { + apply(parser) { + parser.hooks.call + .for("require.ensure") + .tap("RequireEnsureDependenciesBlockParserPlugin", expr => { + let chunkName = null; + let chunkNameRange = null; + let errorExpressionArg = null; + let errorExpression = null; + switch (expr.arguments.length) { + case 4: { + const chunkNameExpr = parser.evaluateExpression(expr.arguments[3]); + if (!chunkNameExpr.isString()) return; + chunkNameRange = chunkNameExpr.range; + chunkName = chunkNameExpr.string; + } + // falls through + case 3: { + errorExpressionArg = expr.arguments[2]; + errorExpression = getFunctionExpression(errorExpressionArg); + + if (!errorExpression && !chunkName) { + const chunkNameExpr = parser.evaluateExpression( + expr.arguments[2] + ); + if (!chunkNameExpr.isString()) return; + chunkNameRange = chunkNameExpr.range; + chunkName = chunkNameExpr.string; + } + } + // falls through + case 2: { + const dependenciesExpr = parser.evaluateExpression( + expr.arguments[0] + ); + const dependenciesItems = dependenciesExpr.isArray() + ? dependenciesExpr.items + : [dependenciesExpr]; + const successExpressionArg = expr.arguments[1]; + const successExpression = getFunctionExpression( + successExpressionArg + ); + + if (successExpression) { + parser.walkExpressions(successExpression.expressions); + } + if (errorExpression) { + parser.walkExpressions(errorExpression.expressions); + } + + const dep = new RequireEnsureDependenciesBlock( + expr, + successExpression ? successExpression.fn : successExpressionArg, + errorExpression ? errorExpression.fn : errorExpressionArg, + chunkName, + chunkNameRange, + parser.state.module, + expr.loc + ); + const old = parser.state.current; + parser.state.current = dep; + try { + let failed = false; + parser.inScope([], () => { + for (const ee of dependenciesItems) { + if (ee.isString()) { + const edep = new RequireEnsureItemDependency(ee.string); + edep.loc = dep.loc; + dep.addDependency(edep); + } else { + failed = true; + } + } + }); + if (failed) { + return; + } + if (successExpression) { + if (successExpression.fn.body.type === "BlockStatement") { + parser.walkStatement(successExpression.fn.body); + } else { + parser.walkExpression(successExpression.fn.body); + } + } + old.addBlock(dep); + } finally { + parser.state.current = old; + } + if (!successExpression) { + parser.walkExpression(successExpressionArg); + } + if (errorExpression) { + if (errorExpression.fn.body.type === "BlockStatement") { + parser.walkStatement(errorExpression.fn.body); + } else { + parser.walkExpression(errorExpression.fn.body); + } + } else if (errorExpressionArg) { + parser.walkExpression(errorExpressionArg); + } + return true; + } + } + }); + } +}; diff --git a/node_modules/webpack/lib/dependencies/RequireEnsureDependency.js b/node_modules/webpack/lib/dependencies/RequireEnsureDependency.js index 65a9c8a3f..840130519 100644 --- a/node_modules/webpack/lib/dependencies/RequireEnsureDependency.js +++ b/node_modules/webpack/lib/dependencies/RequireEnsureDependency.js @@ -1,38 +1,58 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const NullDependency = require("./NullDependency"); -const DepBlockHelpers = require("./DepBlockHelpers"); - -class RequireEnsureDependency extends NullDependency { - constructor(block) { - super(); - this.block = block; - } - - get type() { - return "require.ensure"; - } -} - -RequireEnsureDependency.Template = class RequireEnsureDependencyTemplate { - apply(dep, source, outputOptions, requestShortener) { - const depBlock = dep.block; - const wrapper = DepBlockHelpers.getLoadDepBlockWrapper(depBlock, outputOptions, requestShortener, "require.ensure"); - const errorCallbackExists = depBlock.expr.arguments.length === 4 || (!depBlock.chunkName && depBlock.expr.arguments.length === 3); - const startBlock = wrapper[0] + "("; - const middleBlock = `).bind(null, __webpack_require__)${wrapper[1]}`; - const endBlock = `${middleBlock}__webpack_require__.oe${wrapper[2]}`; - source.replace(depBlock.expr.range[0], depBlock.expr.arguments[1].range[0] - 1, startBlock); - if(errorCallbackExists) { - source.replace(depBlock.expr.arguments[1].range[1], depBlock.expr.arguments[2].range[0] - 1, middleBlock); - source.replace(depBlock.expr.arguments[2].range[1], depBlock.expr.range[1] - 1, wrapper[2]); - } else { - source.replace(depBlock.expr.arguments[1].range[1], depBlock.expr.range[1] - 1, endBlock); - } - } -}; - -module.exports = RequireEnsureDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const NullDependency = require("./NullDependency"); + +class RequireEnsureDependency extends NullDependency { + constructor(block) { + super(); + this.block = block; + } + + get type() { + return "require.ensure"; + } +} + +RequireEnsureDependency.Template = class RequireEnsureDependencyTemplate { + apply(dep, source, runtime) { + const depBlock = dep.block; + const promise = runtime.blockPromise({ + block: depBlock, + message: "require.ensure" + }); + const errorCallbackExists = + depBlock.expr.arguments.length === 4 || + (!depBlock.chunkName && depBlock.expr.arguments.length === 3); + const startBlock = `${promise}.then((`; + const middleBlock = ").bind(null, __webpack_require__)).catch("; + const endBlock = `).bind(null, __webpack_require__)).catch(${runtime.onError()})`; + source.replace( + depBlock.expr.range[0], + depBlock.expr.arguments[1].range[0] - 1, + startBlock + ); + if (errorCallbackExists) { + source.replace( + depBlock.expr.arguments[1].range[1], + depBlock.expr.arguments[2].range[0] - 1, + middleBlock + ); + source.replace( + depBlock.expr.arguments[2].range[1], + depBlock.expr.range[1] - 1, + ")" + ); + } else { + source.replace( + depBlock.expr.arguments[1].range[1], + depBlock.expr.range[1] - 1, + endBlock + ); + } + } +}; + +module.exports = RequireEnsureDependency; diff --git a/node_modules/webpack/lib/dependencies/RequireEnsureItemDependency.js b/node_modules/webpack/lib/dependencies/RequireEnsureItemDependency.js index ca2b699ae..b4b620bf0 100644 --- a/node_modules/webpack/lib/dependencies/RequireEnsureItemDependency.js +++ b/node_modules/webpack/lib/dependencies/RequireEnsureItemDependency.js @@ -1,21 +1,21 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ModuleDependency = require("./ModuleDependency"); -const NullDependency = require("./NullDependency"); - -class RequireEnsureItemDependency extends ModuleDependency { - constructor(request) { - super(request); - } - - get type() { - return "require.ensure item"; - } -} - -RequireEnsureItemDependency.Template = NullDependency.Template; - -module.exports = RequireEnsureItemDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const ModuleDependency = require("./ModuleDependency"); +const NullDependency = require("./NullDependency"); + +class RequireEnsureItemDependency extends ModuleDependency { + constructor(request) { + super(request); + } + + get type() { + return "require.ensure item"; + } +} + +RequireEnsureItemDependency.Template = NullDependency.Template; + +module.exports = RequireEnsureItemDependency; diff --git a/node_modules/webpack/lib/dependencies/RequireEnsurePlugin.js b/node_modules/webpack/lib/dependencies/RequireEnsurePlugin.js index b8a66727d..c818e91bc 100644 --- a/node_modules/webpack/lib/dependencies/RequireEnsurePlugin.js +++ b/node_modules/webpack/lib/dependencies/RequireEnsurePlugin.js @@ -1,40 +1,74 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const RequireEnsureItemDependency = require("./RequireEnsureItemDependency"); -const RequireEnsureDependency = require("./RequireEnsureDependency"); - -const NullFactory = require("../NullFactory"); - -const RequireEnsureDependenciesBlockParserPlugin = require("./RequireEnsureDependenciesBlockParserPlugin"); - -const ParserHelpers = require("../ParserHelpers"); - -class RequireEnsurePlugin { - - apply(compiler) { - compiler.plugin("compilation", (compilation, params) => { - const normalModuleFactory = params.normalModuleFactory; - - compilation.dependencyFactories.set(RequireEnsureItemDependency, normalModuleFactory); - compilation.dependencyTemplates.set(RequireEnsureItemDependency, new RequireEnsureItemDependency.Template()); - - compilation.dependencyFactories.set(RequireEnsureDependency, new NullFactory()); - compilation.dependencyTemplates.set(RequireEnsureDependency, new RequireEnsureDependency.Template()); - - params.normalModuleFactory.plugin("parser", (parser, parserOptions) => { - - if(typeof parserOptions.requireEnsure !== "undefined" && !parserOptions.requireEnsure) - return; - - parser.apply(new RequireEnsureDependenciesBlockParserPlugin()); - parser.plugin("evaluate typeof require.ensure", ParserHelpers.evaluateToString("function")); - parser.plugin("typeof require.ensure", ParserHelpers.toConstantDependency(JSON.stringify("function"))); - }); - }); - } -} -module.exports = RequireEnsurePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const RequireEnsureItemDependency = require("./RequireEnsureItemDependency"); +const RequireEnsureDependency = require("./RequireEnsureDependency"); + +const NullFactory = require("../NullFactory"); + +const RequireEnsureDependenciesBlockParserPlugin = require("./RequireEnsureDependenciesBlockParserPlugin"); + +const ParserHelpers = require("../ParserHelpers"); + +class RequireEnsurePlugin { + apply(compiler) { + compiler.hooks.compilation.tap( + "RequireEnsurePlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set( + RequireEnsureItemDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + RequireEnsureItemDependency, + new RequireEnsureItemDependency.Template() + ); + + compilation.dependencyFactories.set( + RequireEnsureDependency, + new NullFactory() + ); + compilation.dependencyTemplates.set( + RequireEnsureDependency, + new RequireEnsureDependency.Template() + ); + + const handler = (parser, parserOptions) => { + if ( + parserOptions.requireEnsure !== undefined && + !parserOptions.requireEnsure + ) + return; + + new RequireEnsureDependenciesBlockParserPlugin().apply(parser); + parser.hooks.evaluateTypeof + .for("require.ensure") + .tap( + "RequireEnsurePlugin", + ParserHelpers.evaluateToString("function") + ); + parser.hooks.typeof + .for("require.ensure") + .tap( + "RequireEnsurePlugin", + ParserHelpers.toConstantDependency( + parser, + JSON.stringify("function") + ) + ); + }; + + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("RequireEnsurePlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("RequireEnsurePlugin", handler); + } + ); + } +} +module.exports = RequireEnsurePlugin; diff --git a/node_modules/webpack/lib/dependencies/RequireHeaderDependency.js b/node_modules/webpack/lib/dependencies/RequireHeaderDependency.js index 7ba24ca0b..6dddd0623 100644 --- a/node_modules/webpack/lib/dependencies/RequireHeaderDependency.js +++ b/node_modules/webpack/lib/dependencies/RequireHeaderDependency.js @@ -1,26 +1,26 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const NullDependency = require("./NullDependency"); - -class RequireHeaderDependency extends NullDependency { - constructor(range) { - super(); - if(!Array.isArray(range)) throw new Error("range must be valid"); - this.range = range; - } -} - -RequireHeaderDependency.Template = class RequireHeaderDependencyTemplate { - apply(dep, source) { - source.replace(dep.range[0], dep.range[1] - 1, "__webpack_require__"); - } - - applyAsTemplateArgument(name, dep, source) { - source.replace(dep.range[0], dep.range[1] - 1, "require"); - } -}; - -module.exports = RequireHeaderDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const NullDependency = require("./NullDependency"); + +class RequireHeaderDependency extends NullDependency { + constructor(range) { + super(); + if (!Array.isArray(range)) throw new Error("range must be valid"); + this.range = range; + } +} + +RequireHeaderDependency.Template = class RequireHeaderDependencyTemplate { + apply(dep, source) { + source.replace(dep.range[0], dep.range[1] - 1, "__webpack_require__"); + } + + applyAsTemplateArgument(name, dep, source) { + source.replace(dep.range[0], dep.range[1] - 1, "require"); + } +}; + +module.exports = RequireHeaderDependency; diff --git a/node_modules/webpack/lib/dependencies/RequireIncludeDependency.js b/node_modules/webpack/lib/dependencies/RequireIncludeDependency.js index 1c7829990..9eca57628 100644 --- a/node_modules/webpack/lib/dependencies/RequireIncludeDependency.js +++ b/node_modules/webpack/lib/dependencies/RequireIncludeDependency.js @@ -1,41 +1,39 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ModuleDependency = require("./ModuleDependency"); - -class RequireIncludeDependency extends ModuleDependency { - constructor(request, range) { - super(request); - this.range = range; - } - - getReference() { - if(!this.module) return null; - return { - module: this.module, - importedNames: [] // This doesn't use any export - }; - } - - get type() { - return "require.include"; - } -} - -RequireIncludeDependency.Template = class RequireIncludeDependencyTemplate { - apply(dep, source, outputOptions, requestShortener) { - const comment = this.getOptionalComment(outputOptions.pathinfo && dep.module, requestShortener.shorten(dep.request)); - source.replace(dep.range[0], dep.range[1] - 1, `undefined${comment}`); - } - - getOptionalComment(shouldHaveComment, shortenedRequest) { - if(shouldHaveComment) { - return ""; - } - return `/*! require.include ${shortenedRequest} */`; - } -}; - -module.exports = RequireIncludeDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const DependencyReference = require("./DependencyReference"); +const ModuleDependency = require("./ModuleDependency"); +const Template = require("../Template"); + +class RequireIncludeDependency extends ModuleDependency { + constructor(request, range) { + super(request); + this.range = range; + } + + getReference() { + if (!this.module) return null; + // This doesn't use any export + return new DependencyReference(this.module, [], false); + } + + get type() { + return "require.include"; + } +} + +RequireIncludeDependency.Template = class RequireIncludeDependencyTemplate { + apply(dep, source, runtime) { + const comment = runtime.outputOptions.pathinfo + ? Template.toComment( + `require.include ${runtime.requestShortener.shorten(dep.request)}` + ) + : ""; + source.replace(dep.range[0], dep.range[1] - 1, `undefined${comment}`); + } +}; + +module.exports = RequireIncludeDependency; diff --git a/node_modules/webpack/lib/dependencies/RequireIncludeDependencyParserPlugin.js b/node_modules/webpack/lib/dependencies/RequireIncludeDependencyParserPlugin.js index b7b233145..117e20451 100644 --- a/node_modules/webpack/lib/dependencies/RequireIncludeDependencyParserPlugin.js +++ b/node_modules/webpack/lib/dependencies/RequireIncludeDependencyParserPlugin.js @@ -1,21 +1,23 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const RequireIncludeDependency = require("./RequireIncludeDependency"); - -module.exports = class RequireIncludeDependencyParserPlugin { - apply(parser) { - parser.plugin("call require.include", expr => { - if(expr.arguments.length !== 1) return; - const param = parser.evaluateExpression(expr.arguments[0]); - if(!param.isString()) return; - const dep = new RequireIncludeDependency(param.string, expr.range); - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - return true; - }); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const RequireIncludeDependency = require("./RequireIncludeDependency"); + +module.exports = class RequireIncludeDependencyParserPlugin { + apply(parser) { + parser.hooks.call + .for("require.include") + .tap("RequireIncludeDependencyParserPlugin", expr => { + if (expr.arguments.length !== 1) return; + const param = parser.evaluateExpression(expr.arguments[0]); + if (!param.isString()) return; + const dep = new RequireIncludeDependency(param.string, expr.range); + dep.loc = expr.loc; + parser.state.current.addDependency(dep); + return true; + }); + } +}; diff --git a/node_modules/webpack/lib/dependencies/RequireIncludePlugin.js b/node_modules/webpack/lib/dependencies/RequireIncludePlugin.js index f80e9b91f..e7d535bc3 100644 --- a/node_modules/webpack/lib/dependencies/RequireIncludePlugin.js +++ b/node_modules/webpack/lib/dependencies/RequireIncludePlugin.js @@ -1,33 +1,61 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const RequireIncludeDependency = require("./RequireIncludeDependency"); -const RequireIncludeDependencyParserPlugin = require("./RequireIncludeDependencyParserPlugin"); - -const ParserHelpers = require("../ParserHelpers"); - -class RequireIncludePlugin { - - apply(compiler) { - compiler.plugin("compilation", (compilation, params) => { - const normalModuleFactory = params.normalModuleFactory; - - compilation.dependencyFactories.set(RequireIncludeDependency, normalModuleFactory); - compilation.dependencyTemplates.set(RequireIncludeDependency, new RequireIncludeDependency.Template()); - - params.normalModuleFactory.plugin("parser", (parser, parserOptions) => { - - if(typeof parserOptions.requireInclude !== "undefined" && !parserOptions.requireInclude) - return; - - parser.apply(new RequireIncludeDependencyParserPlugin()); - parser.plugin("evaluate typeof require.include", ParserHelpers.evaluateToString("function")); - parser.plugin("typeof require.include", ParserHelpers.toConstantDependency(JSON.stringify("function"))); - }); - }); - } -} -module.exports = RequireIncludePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const RequireIncludeDependency = require("./RequireIncludeDependency"); +const RequireIncludeDependencyParserPlugin = require("./RequireIncludeDependencyParserPlugin"); + +const ParserHelpers = require("../ParserHelpers"); + +class RequireIncludePlugin { + apply(compiler) { + compiler.hooks.compilation.tap( + "RequireIncludePlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set( + RequireIncludeDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + RequireIncludeDependency, + new RequireIncludeDependency.Template() + ); + + const handler = (parser, parserOptions) => { + if ( + parserOptions.requireInclude !== undefined && + !parserOptions.requireInclude + ) + return; + + new RequireIncludeDependencyParserPlugin().apply(parser); + parser.hooks.evaluateTypeof + .for("require.include") + .tap( + "RequireIncludePlugin", + ParserHelpers.evaluateToString("function") + ); + parser.hooks.typeof + .for("require.include") + .tap( + "RequireIncludePlugin", + ParserHelpers.toConstantDependency( + parser, + JSON.stringify("function") + ) + ); + }; + + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("RequireIncludePlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("RequireIncludePlugin", handler); + } + ); + } +} +module.exports = RequireIncludePlugin; diff --git a/node_modules/webpack/lib/dependencies/RequireResolveContextDependency.js b/node_modules/webpack/lib/dependencies/RequireResolveContextDependency.js index f53e94768..cc40451c9 100644 --- a/node_modules/webpack/lib/dependencies/RequireResolveContextDependency.js +++ b/node_modules/webpack/lib/dependencies/RequireResolveContextDependency.js @@ -1,24 +1,23 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ContextDependency = require("./ContextDependency"); -const ContextDependencyTemplateAsId = require("./ContextDependencyTemplateAsId"); - -class RequireResolveContextDependency extends ContextDependency { - constructor(request, recursive, regExp, range, valueRange) { - super(request, recursive, regExp); - this.range = range; - this.valueRange = valueRange; - } - - get type() { - return "amd require context"; - } - -} - -RequireResolveContextDependency.Template = ContextDependencyTemplateAsId; - -module.exports = RequireResolveContextDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const ContextDependency = require("./ContextDependency"); +const ContextDependencyTemplateAsId = require("./ContextDependencyTemplateAsId"); + +class RequireResolveContextDependency extends ContextDependency { + constructor(options, range, valueRange) { + super(options); + this.range = range; + this.valueRange = valueRange; + } + + get type() { + return "amd require context"; + } +} + +RequireResolveContextDependency.Template = ContextDependencyTemplateAsId; + +module.exports = RequireResolveContextDependency; diff --git a/node_modules/webpack/lib/dependencies/RequireResolveDependency.js b/node_modules/webpack/lib/dependencies/RequireResolveDependency.js index 72ac48aab..3933baa4b 100644 --- a/node_modules/webpack/lib/dependencies/RequireResolveDependency.js +++ b/node_modules/webpack/lib/dependencies/RequireResolveDependency.js @@ -1,22 +1,22 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ModuleDependency = require("./ModuleDependency"); -const ModuleDependencyAsId = require("./ModuleDependencyTemplateAsId"); - -class RequireResolveDependency extends ModuleDependency { - constructor(request, range) { - super(request); - this.range = range; - } - - get type() { - return "require.resolve"; - } -} - -RequireResolveDependency.Template = ModuleDependencyAsId; - -module.exports = RequireResolveDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const ModuleDependency = require("./ModuleDependency"); +const ModuleDependencyAsId = require("./ModuleDependencyTemplateAsId"); + +class RequireResolveDependency extends ModuleDependency { + constructor(request, range) { + super(request); + this.range = range; + } + + get type() { + return "require.resolve"; + } +} + +RequireResolveDependency.Template = ModuleDependencyAsId; + +module.exports = RequireResolveDependency; diff --git a/node_modules/webpack/lib/dependencies/RequireResolveDependencyParserPlugin.js b/node_modules/webpack/lib/dependencies/RequireResolveDependencyParserPlugin.js index 85451cf95..4c51ddf6a 100644 --- a/node_modules/webpack/lib/dependencies/RequireResolveDependencyParserPlugin.js +++ b/node_modules/webpack/lib/dependencies/RequireResolveDependencyParserPlugin.js @@ -1,71 +1,85 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const RequireResolveDependency = require("./RequireResolveDependency"); -const RequireResolveContextDependency = require("./RequireResolveContextDependency"); -const RequireResolveHeaderDependency = require("./RequireResolveHeaderDependency"); -const ContextDependencyHelpers = require("./ContextDependencyHelpers"); - -class RequireResolveDependencyParserPlugin { - constructor(options) { - this.options = options; - } - - apply(parser) { - const options = this.options; - parser.plugin("call require.resolve", (expr) => { - return parser.applyPluginsBailResult("call require.resolve(Weak)", expr, false); - }); - parser.plugin("call require.resolveWeak", (expr) => { - return parser.applyPluginsBailResult("call require.resolve(Weak)", expr, true); - }); - parser.plugin("call require.resolve(Weak)", (expr, weak) => { - if(expr.arguments.length !== 1) return; - const param = parser.evaluateExpression(expr.arguments[0]); - if(param.isConditional()) { - param.options.forEach((option) => { - const result = parser.applyPluginsBailResult("call require.resolve(Weak):item", expr, option, weak); - if(result === undefined) { - parser.applyPluginsBailResult("call require.resolve(Weak):context", expr, option, weak); - } - }); - const dep = new RequireResolveHeaderDependency(expr.callee.range); - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - return true; - } else { - const result = parser.applyPluginsBailResult("call require.resolve(Weak):item", expr, param, weak); - if(result === undefined) { - parser.applyPluginsBailResult("call require.resolve(Weak):context", expr, param, weak); - } - const dep = new RequireResolveHeaderDependency(expr.callee.range); - dep.loc = expr.loc; - parser.state.current.addDependency(dep); - return true; - } - }); - parser.plugin("call require.resolve(Weak):item", (expr, param, weak) => { - if(param.isString()) { - const dep = new RequireResolveDependency(param.string, param.range); - dep.loc = expr.loc; - dep.optional = !!parser.scope.inTry; - dep.weak = weak; - parser.state.current.addDependency(dep); - return true; - } - }); - parser.plugin("call require.resolve(Weak):context", (expr, param, weak) => { - const dep = ContextDependencyHelpers.create(RequireResolveContextDependency, param.range, param, expr, options); - if(!dep) return; - dep.loc = expr.loc; - dep.optional = !!parser.scope.inTry; - dep.async = weak ? "weak" : false; - parser.state.current.addDependency(dep); - return true; - }); - } -} -module.exports = RequireResolveDependencyParserPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const RequireResolveDependency = require("./RequireResolveDependency"); +const RequireResolveContextDependency = require("./RequireResolveContextDependency"); +const RequireResolveHeaderDependency = require("./RequireResolveHeaderDependency"); +const ContextDependencyHelpers = require("./ContextDependencyHelpers"); + +class RequireResolveDependencyParserPlugin { + constructor(options) { + this.options = options; + } + + apply(parser) { + const options = this.options; + + const process = (expr, weak) => { + if (expr.arguments.length !== 1) return; + const param = parser.evaluateExpression(expr.arguments[0]); + if (param.isConditional()) { + for (const option of param.options) { + const result = processItem(expr, option, weak); + if (result === undefined) { + processContext(expr, option, weak); + } + } + const dep = new RequireResolveHeaderDependency(expr.callee.range); + dep.loc = expr.loc; + parser.state.current.addDependency(dep); + return true; + } else { + const result = processItem(expr, param, weak); + if (result === undefined) { + processContext(expr, param, weak); + } + const dep = new RequireResolveHeaderDependency(expr.callee.range); + dep.loc = expr.loc; + parser.state.current.addDependency(dep); + return true; + } + }; + const processItem = (expr, param, weak) => { + if (param.isString()) { + const dep = new RequireResolveDependency(param.string, param.range); + dep.loc = expr.loc; + dep.optional = !!parser.scope.inTry; + dep.weak = weak; + parser.state.current.addDependency(dep); + return true; + } + }; + const processContext = (expr, param, weak) => { + const dep = ContextDependencyHelpers.create( + RequireResolveContextDependency, + param.range, + param, + expr, + options, + { + mode: weak ? "weak" : "sync" + } + ); + if (!dep) return; + dep.loc = expr.loc; + dep.optional = !!parser.scope.inTry; + parser.state.current.addDependency(dep); + return true; + }; + + parser.hooks.call + .for("require.resolve") + .tap("RequireResolveDependencyParserPlugin", expr => { + return process(expr, false); + }); + parser.hooks.call + .for("require.resolveWeak") + .tap("RequireResolveDependencyParserPlugin", expr => { + return process(expr, true); + }); + } +} +module.exports = RequireResolveDependencyParserPlugin; diff --git a/node_modules/webpack/lib/dependencies/RequireResolveHeaderDependency.js b/node_modules/webpack/lib/dependencies/RequireResolveHeaderDependency.js index d96ff7ddb..05fe86d69 100644 --- a/node_modules/webpack/lib/dependencies/RequireResolveHeaderDependency.js +++ b/node_modules/webpack/lib/dependencies/RequireResolveHeaderDependency.js @@ -1,26 +1,26 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const NullDependency = require("./NullDependency"); - -class RequireResolveHeaderDependency extends NullDependency { - constructor(range) { - super(); - if(!Array.isArray(range)) throw new Error("range must be valid"); - this.range = range; - } -} - -RequireResolveHeaderDependency.Template = class RequireResolveHeaderDependencyTemplate { - apply(dep, source) { - source.replace(dep.range[0], dep.range[1] - 1, "/*require.resolve*/"); - } - - applyAsTemplateArgument(name, dep, source) { - source.replace(dep.range[0], dep.range[1] - 1, "/*require.resolve*/"); - } -}; - -module.exports = RequireResolveHeaderDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const NullDependency = require("./NullDependency"); + +class RequireResolveHeaderDependency extends NullDependency { + constructor(range) { + super(); + if (!Array.isArray(range)) throw new Error("range must be valid"); + this.range = range; + } +} + +RequireResolveHeaderDependency.Template = class RequireResolveHeaderDependencyTemplate { + apply(dep, source) { + source.replace(dep.range[0], dep.range[1] - 1, "/*require.resolve*/"); + } + + applyAsTemplateArgument(name, dep, source) { + source.replace(dep.range[0], dep.range[1] - 1, "/*require.resolve*/"); + } +}; + +module.exports = RequireResolveHeaderDependency; diff --git a/node_modules/webpack/lib/dependencies/SingleEntryDependency.js b/node_modules/webpack/lib/dependencies/SingleEntryDependency.js index 02ccd8986..75a8c080f 100644 --- a/node_modules/webpack/lib/dependencies/SingleEntryDependency.js +++ b/node_modules/webpack/lib/dependencies/SingleEntryDependency.js @@ -1,18 +1,21 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ModuleDependency = require("./ModuleDependency"); - -class SingleEntryDependency extends ModuleDependency { - constructor(request) { - super(request); - } - - get type() { - return "single entry"; - } -} - -module.exports = SingleEntryDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const ModuleDependency = require("./ModuleDependency"); + +class SingleEntryDependency extends ModuleDependency { + /** + * @param {string} request request path for entry + */ + constructor(request) { + super(request); + } + + get type() { + return "single entry"; + } +} + +module.exports = SingleEntryDependency; diff --git a/node_modules/webpack/lib/dependencies/SystemPlugin.js b/node_modules/webpack/lib/dependencies/SystemPlugin.js index dd457ae7c..0e3419b57 100644 --- a/node_modules/webpack/lib/dependencies/SystemPlugin.js +++ b/node_modules/webpack/lib/dependencies/SystemPlugin.js @@ -1,44 +1,122 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ParserHelpers = require("../ParserHelpers"); - -class SystemPlugin { - constructor(options) { - this.options = options; - } - - apply(compiler) { - compiler.plugin("compilation", (compilation, params) => { - params.normalModuleFactory.plugin("parser", (parser, parserOptions) => { - - if(typeof parserOptions.system !== "undefined" && !parserOptions.system) - return; - - function setNotSupported(name) { - parser.plugin("evaluate typeof " + name, ParserHelpers.evaluateToString("undefined")); - parser.plugin("expression " + name, - ParserHelpers.expressionIsUnsupported(name + " is not supported by webpack.") - ); - } - - parser.plugin("typeof System.import", ParserHelpers.toConstantDependency(JSON.stringify("function"))); - parser.plugin("evaluate typeof System.import", ParserHelpers.evaluateToString("function")); - parser.plugin("typeof System", ParserHelpers.toConstantDependency(JSON.stringify("object"))); - parser.plugin("evaluate typeof System", ParserHelpers.evaluateToString("object")); - - setNotSupported("System.set"); - setNotSupported("System.get"); - setNotSupported("System.register"); - parser.plugin("expression System", function() { - const systemPolyfillRequire = ParserHelpers.requireFileAsExpression( - this.state.module.context, require.resolve("../../buildin/system.js")); - return ParserHelpers.addParsedVariableToModule(this, "System", systemPolyfillRequire); - }); - }); - }); - } -} -module.exports = SystemPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const ParserHelpers = require("../ParserHelpers"); +const WebpackError = require("../WebpackError"); + +class SystemPlugin { + constructor(options) { + this.options = options; + } + + apply(compiler) { + compiler.hooks.compilation.tap( + "SystemPlugin", + (compilation, { normalModuleFactory }) => { + const handler = (parser, parserOptions) => { + if (parserOptions.system !== undefined && !parserOptions.system) + return; + + const shouldWarn = parserOptions.system === undefined; + + const setNotSupported = name => { + parser.hooks.evaluateTypeof + .for(name) + .tap("SystemPlugin", ParserHelpers.evaluateToString("undefined")); + parser.hooks.expression + .for(name) + .tap( + "SystemPlugin", + ParserHelpers.expressionIsUnsupported( + parser, + name + " is not supported by webpack." + ) + ); + }; + + parser.hooks.typeof + .for("System.import") + .tap( + "SystemPlugin", + ParserHelpers.toConstantDependency( + parser, + JSON.stringify("function") + ) + ); + parser.hooks.evaluateTypeof + .for("System.import") + .tap("SystemPlugin", ParserHelpers.evaluateToString("function")); + parser.hooks.typeof + .for("System") + .tap( + "SystemPlugin", + ParserHelpers.toConstantDependency( + parser, + JSON.stringify("object") + ) + ); + parser.hooks.evaluateTypeof + .for("System") + .tap("SystemPlugin", ParserHelpers.evaluateToString("object")); + + setNotSupported("System.set"); + setNotSupported("System.get"); + setNotSupported("System.register"); + + parser.hooks.expression.for("System").tap("SystemPlugin", () => { + const systemPolyfillRequire = ParserHelpers.requireFileAsExpression( + parser.state.module.context, + require.resolve("../../buildin/system") + ); + return ParserHelpers.addParsedVariableToModule( + parser, + "System", + systemPolyfillRequire + ); + }); + + parser.hooks.call.for("System.import").tap("SystemPlugin", expr => { + if (shouldWarn) { + parser.state.module.warnings.push( + new SystemImportDeprecationWarning( + parser.state.module, + expr.loc + ) + ); + } + + return parser.hooks.importCall.call(expr); + }); + }; + + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("SystemPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("SystemPlugin", handler); + } + ); + } +} + +class SystemImportDeprecationWarning extends WebpackError { + constructor(module, loc) { + super( + "System.import() is deprecated and will be removed soon. Use import() instead.\n" + + "For more info visit https://webpack.js.org/guides/code-splitting/" + ); + + this.name = "SystemImportDeprecationWarning"; + + this.module = module; + this.loc = loc; + + Error.captureStackTrace(this, this.constructor); + } +} + +module.exports = SystemPlugin; diff --git a/node_modules/webpack/lib/dependencies/UnsupportedDependency.js b/node_modules/webpack/lib/dependencies/UnsupportedDependency.js index 48f0971b6..614af783e 100644 --- a/node_modules/webpack/lib/dependencies/UnsupportedDependency.js +++ b/node_modules/webpack/lib/dependencies/UnsupportedDependency.js @@ -1,23 +1,27 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const NullDependency = require("./NullDependency"); -const webpackMissingModule = require("./WebpackMissingModule").module; - -class UnsupportedDependency extends NullDependency { - constructor(request, range) { - super(); - this.request = request; - this.range = range; - } -} - -UnsupportedDependency.Template = class UnsupportedDependencyTemplate { - apply(dep, source, outputOptions, requestShortener) { - source.replace(dep.range[0], dep.range[1], webpackMissingModule(dep.request)); - } -}; - -module.exports = UnsupportedDependency; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const NullDependency = require("./NullDependency"); +const webpackMissingModule = require("./WebpackMissingModule").module; + +class UnsupportedDependency extends NullDependency { + constructor(request, range) { + super(); + this.request = request; + this.range = range; + } +} + +UnsupportedDependency.Template = class UnsupportedDependencyTemplate { + apply(dep, source, runtime) { + source.replace( + dep.range[0], + dep.range[1], + webpackMissingModule(dep.request) + ); + } +}; + +module.exports = UnsupportedDependency; diff --git a/node_modules/webpack/lib/dependencies/WebpackMissingModule.js b/node_modules/webpack/lib/dependencies/WebpackMissingModule.js index 64e76cffb..a55c9ec08 100644 --- a/node_modules/webpack/lib/dependencies/WebpackMissingModule.js +++ b/node_modules/webpack/lib/dependencies/WebpackMissingModule.js @@ -1,18 +1,20 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const toErrorCode = err => `var e = new Error(${JSON.stringify(err)}); e.code = 'MODULE_NOT_FOUND';`; - -exports.module = request => `!(function webpackMissingModule() { ${exports.moduleCode(request)} }())`; - -exports.promise = (request) => { - const errorCode = toErrorCode(`Cannot find module "${request}"`); - return `Promise.reject(function webpackMissingModule() { ${errorCode}; return e; }())`; -}; - -exports.moduleCode = (request) => { - const errorCode = toErrorCode(`Cannot find module "${request}"`); - return `${errorCode} throw e;`; -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const toErrorCode = err => + `var e = new Error(${JSON.stringify(err)}); e.code = 'MODULE_NOT_FOUND';`; + +exports.module = request => + `!(function webpackMissingModule() { ${exports.moduleCode(request)} }())`; + +exports.promise = request => { + const errorCode = toErrorCode(`Cannot find module '${request}'`); + return `Promise.reject(function webpackMissingModule() { ${errorCode} return e; }())`; +}; + +exports.moduleCode = request => { + const errorCode = toErrorCode(`Cannot find module '${request}'`); + return `${errorCode} throw e;`; +}; diff --git a/node_modules/webpack/lib/dependencies/getFunctionExpression.js b/node_modules/webpack/lib/dependencies/getFunctionExpression.js index cc32585ab..0e73840e5 100644 --- a/node_modules/webpack/lib/dependencies/getFunctionExpression.js +++ b/node_modules/webpack/lib/dependencies/getFunctionExpression.js @@ -1,44 +1,52 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -module.exports = function(expr) { - // - if(expr.type === "FunctionExpression" || expr.type === "ArrowFunctionExpression") { - return { - fn: expr, - expressions: [], - needThis: false - }; - } - - // .bind() - if(expr.type === "CallExpression" && - expr.callee.type === "MemberExpression" && - expr.callee.object.type === "FunctionExpression" && - expr.callee.property.type === "Identifier" && - expr.callee.property.name === "bind" && - expr.arguments.length === 1) { - return { - fn: expr.callee.object, - expressions: [expr.arguments[0]] - }; - } - // (function(_this) {return })(this) (Coffeescript) - if(expr.type === "CallExpression" && - expr.callee.type === "FunctionExpression" && - expr.callee.body.type === "BlockStatement" && - expr.arguments.length === 1 && - expr.arguments[0].type === "ThisExpression" && - expr.callee.body.body && - expr.callee.body.body.length === 1 && - expr.callee.body.body[0].type === "ReturnStatement" && - expr.callee.body.body[0].argument && - expr.callee.body.body[0].argument.type === "FunctionExpression") { - return { - fn: expr.callee.body.body[0].argument, - expressions: [], - needThis: true - }; - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +module.exports = expr => { + // + if ( + expr.type === "FunctionExpression" || + expr.type === "ArrowFunctionExpression" + ) { + return { + fn: expr, + expressions: [], + needThis: false + }; + } + + // .bind() + if ( + expr.type === "CallExpression" && + expr.callee.type === "MemberExpression" && + expr.callee.object.type === "FunctionExpression" && + expr.callee.property.type === "Identifier" && + expr.callee.property.name === "bind" && + expr.arguments.length === 1 + ) { + return { + fn: expr.callee.object, + expressions: [expr.arguments[0]], + needThis: undefined + }; + } + // (function(_this) {return })(this) (Coffeescript) + if ( + expr.type === "CallExpression" && + expr.callee.type === "FunctionExpression" && + expr.callee.body.type === "BlockStatement" && + expr.arguments.length === 1 && + expr.arguments[0].type === "ThisExpression" && + expr.callee.body.body && + expr.callee.body.body.length === 1 && + expr.callee.body.body[0].type === "ReturnStatement" && + expr.callee.body.body[0].argument && + expr.callee.body.body[0].argument.type === "FunctionExpression" + ) { + return { + fn: expr.callee.body.body[0].argument, + expressions: [], + needThis: true + }; + } +}; diff --git a/node_modules/webpack/lib/formatLocation.js b/node_modules/webpack/lib/formatLocation.js index 046887f6f..f608cd496 100644 --- a/node_modules/webpack/lib/formatLocation.js +++ b/node_modules/webpack/lib/formatLocation.js @@ -1,54 +1,75 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ - -"use strict"; - -const formatPosition = (pos) => { - if(pos === null) - return ""; - const typeOfPos = typeof pos; - switch(typeOfPos) { - case "string": - return pos; - case "number": - return `${pos}`; - case "object": - if(typeof pos.line === "number" && typeof pos.column === "number") - return `${pos.line}:${pos.column}`; - else if(typeof pos.line === "number") - return `${pos.line}:?`; - else if(typeof pos.index === "number") - return `+${pos.index}`; - else - return ""; - default: - return ""; - } -}; - -const formatLocation = (loc) => { - if(loc === null) - return ""; - const typeOfLoc = typeof loc; - switch(typeOfLoc) { - case "string": - return loc; - case "number": - return `${loc}`; - case "object": - if(loc.start && loc.end) { - if(typeof loc.start.line === "number" && typeof loc.end.line === "number" && typeof loc.end.column === "number" && loc.start.line === loc.end.line) - return `${formatPosition(loc.start)}-${loc.end.column}`; - return `${formatPosition(loc.start)}-${formatPosition(loc.end)}`; - } - if(loc.start) - return formatPosition(loc.start); - return formatPosition(loc); - default: - return ""; - } -}; - -module.exports = formatLocation; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ + +"use strict"; + +/** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */ +/** @typedef {import("./Dependency").SourcePosition} SourcePosition */ + +// TODO webpack 5: pos must be SourcePosition +/** + * @param {SourcePosition|DependencyLocation|string} pos position + * @returns {string} formatted position + */ +const formatPosition = pos => { + if (pos === null) return ""; + // TODO webpack 5: Simplify this + if (typeof pos === "string") return pos; + if (typeof pos === "number") return `${pos}`; + if (typeof pos === "object") { + if ("line" in pos && "column" in pos) { + return `${pos.line}:${pos.column}`; + } else if ("line" in pos) { + return `${pos.line}:?`; + } else if ("index" in pos) { + // TODO webpack 5 remove this case + return `+${pos.index}`; + } else { + return ""; + } + } + return ""; +}; + +// TODO webpack 5: loc must be DependencyLocation +/** + * @param {DependencyLocation|SourcePosition|string} loc location + * @returns {string} formatted location + */ +const formatLocation = loc => { + if (loc === null) return ""; + // TODO webpack 5: Simplify this + if (typeof loc === "string") return loc; + if (typeof loc === "number") return `${loc}`; + if (typeof loc === "object") { + if ("start" in loc && loc.start && "end" in loc && loc.end) { + if ( + typeof loc.start === "object" && + typeof loc.start.line === "number" && + typeof loc.end === "object" && + typeof loc.end.line === "number" && + typeof loc.end.column === "number" && + loc.start.line === loc.end.line + ) { + return `${formatPosition(loc.start)}-${loc.end.column}`; + } else { + return `${formatPosition(loc.start)}-${formatPosition(loc.end)}`; + } + } + if ("start" in loc && loc.start) { + return formatPosition(loc.start); + } + if ("name" in loc && "index" in loc) { + return `${loc.name}[${loc.index}]`; + } + if ("name" in loc) { + return loc.name; + } + return formatPosition(loc); + } + return ""; +}; + +module.exports = formatLocation; diff --git a/node_modules/webpack/lib/node/NodeChunkTemplatePlugin.js b/node_modules/webpack/lib/node/NodeChunkTemplatePlugin.js index dd5e0e354..292182a97 100644 --- a/node_modules/webpack/lib/node/NodeChunkTemplatePlugin.js +++ b/node_modules/webpack/lib/node/NodeChunkTemplatePlugin.js @@ -1,27 +1,31 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ - -"use strict"; - -const ConcatSource = require("webpack-sources").ConcatSource; - -class NodeChunkTemplatePlugin { - - apply(chunkTemplate) { - chunkTemplate.plugin("render", function(modules, chunk) { - const source = new ConcatSource(); - source.add(`exports.ids = ${JSON.stringify(chunk.ids)};\nexports.modules = `); - source.add(modules); - source.add(";"); - return source; - }); - chunkTemplate.plugin("hash", function(hash) { - hash.update("node"); - hash.update("3"); - }); - } -} - -module.exports = NodeChunkTemplatePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ + +"use strict"; + +const { ConcatSource } = require("webpack-sources"); + +class NodeChunkTemplatePlugin { + apply(chunkTemplate) { + chunkTemplate.hooks.render.tap( + "NodeChunkTemplatePlugin", + (modules, chunk) => { + const source = new ConcatSource(); + source.add( + `exports.ids = ${JSON.stringify(chunk.ids)};\nexports.modules = ` + ); + source.add(modules); + source.add(";"); + return source; + } + ); + chunkTemplate.hooks.hash.tap("NodeChunkTemplatePlugin", hash => { + hash.update("node"); + hash.update("3"); + }); + } +} + +module.exports = NodeChunkTemplatePlugin; diff --git a/node_modules/webpack/lib/node/NodeEnvironmentPlugin.js b/node_modules/webpack/lib/node/NodeEnvironmentPlugin.js index b8200a3ca..3f76bffa5 100644 --- a/node_modules/webpack/lib/node/NodeEnvironmentPlugin.js +++ b/node_modules/webpack/lib/node/NodeEnvironmentPlugin.js @@ -1,25 +1,28 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const NodeWatchFileSystem = require("./NodeWatchFileSystem"); -const NodeOutputFileSystem = require("./NodeOutputFileSystem"); -const NodeJsInputFileSystem = require("enhanced-resolve/lib/NodeJsInputFileSystem"); -const CachedInputFileSystem = require("enhanced-resolve/lib/CachedInputFileSystem"); - -class NodeEnvironmentPlugin { - apply(compiler) { - compiler.inputFileSystem = new CachedInputFileSystem(new NodeJsInputFileSystem(), 60000); - const inputFileSystem = compiler.inputFileSystem; - compiler.outputFileSystem = new NodeOutputFileSystem(); - compiler.watchFileSystem = new NodeWatchFileSystem(compiler.inputFileSystem); - compiler.plugin("before-run", (compiler, callback) => { - if(compiler.inputFileSystem === inputFileSystem) - inputFileSystem.purge(); - callback(); - }); - } -} -module.exports = NodeEnvironmentPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const NodeWatchFileSystem = require("./NodeWatchFileSystem"); +const NodeOutputFileSystem = require("./NodeOutputFileSystem"); +const NodeJsInputFileSystem = require("enhanced-resolve/lib/NodeJsInputFileSystem"); +const CachedInputFileSystem = require("enhanced-resolve/lib/CachedInputFileSystem"); + +class NodeEnvironmentPlugin { + apply(compiler) { + compiler.inputFileSystem = new CachedInputFileSystem( + new NodeJsInputFileSystem(), + 60000 + ); + const inputFileSystem = compiler.inputFileSystem; + compiler.outputFileSystem = new NodeOutputFileSystem(); + compiler.watchFileSystem = new NodeWatchFileSystem( + compiler.inputFileSystem + ); + compiler.hooks.beforeRun.tap("NodeEnvironmentPlugin", compiler => { + if (compiler.inputFileSystem === inputFileSystem) inputFileSystem.purge(); + }); + } +} +module.exports = NodeEnvironmentPlugin; diff --git a/node_modules/webpack/lib/node/NodeHotUpdateChunkTemplatePlugin.js b/node_modules/webpack/lib/node/NodeHotUpdateChunkTemplatePlugin.js index 52239f7b6..bbd2e12a6 100644 --- a/node_modules/webpack/lib/node/NodeHotUpdateChunkTemplatePlugin.js +++ b/node_modules/webpack/lib/node/NodeHotUpdateChunkTemplatePlugin.js @@ -1,27 +1,36 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ConcatSource = require("webpack-sources").ConcatSource; - -class NodeHotUpdateChunkTemplatePlugin { - - apply(hotUpdateChunkTemplate) { - hotUpdateChunkTemplate.plugin("render", (modulesSource, modules, removedModules, hash, id) => { - const source = new ConcatSource(); - source.add("exports.id = " + JSON.stringify(id) + ";\nexports.modules = "); - source.add(modulesSource); - source.add(";"); - return source; - }); - hotUpdateChunkTemplate.plugin("hash", function(hash) { - hash.update("NodeHotUpdateChunkTemplatePlugin"); - hash.update("3"); - hash.update(this.outputOptions.hotUpdateFunction + ""); - hash.update(this.outputOptions.library + ""); - }); - } -} -module.exports = NodeHotUpdateChunkTemplatePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const { ConcatSource } = require("webpack-sources"); + +class NodeHotUpdateChunkTemplatePlugin { + apply(hotUpdateChunkTemplate) { + hotUpdateChunkTemplate.hooks.render.tap( + "NodeHotUpdateChunkTemplatePlugin", + (modulesSource, modules, removedModules, hash, id) => { + const source = new ConcatSource(); + source.add( + "exports.id = " + JSON.stringify(id) + ";\nexports.modules = " + ); + source.add(modulesSource); + source.add(";"); + return source; + } + ); + hotUpdateChunkTemplate.hooks.hash.tap( + "NodeHotUpdateChunkTemplatePlugin", + hash => { + hash.update("NodeHotUpdateChunkTemplatePlugin"); + hash.update("3"); + hash.update( + hotUpdateChunkTemplate.outputOptions.hotUpdateFunction + "" + ); + hash.update(hotUpdateChunkTemplate.outputOptions.library + ""); + } + ); + } +} +module.exports = NodeHotUpdateChunkTemplatePlugin; diff --git a/node_modules/webpack/lib/node/NodeMainTemplate.runtime.js b/node_modules/webpack/lib/node/NodeMainTemplate.runtime.js index 2725e2e79..d34388bf7 100644 --- a/node_modules/webpack/lib/node/NodeMainTemplate.runtime.js +++ b/node_modules/webpack/lib/node/NodeMainTemplate.runtime.js @@ -1,24 +1,27 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -/*global installedChunks $hotChunkFilename$ hotAddUpdateChunk $hotMainFilename$ */ -module.exports = function() { - function hotDownloadUpdateChunk(chunkId) { // eslint-disable-line no-unused-vars - var chunk = require("./" + $hotChunkFilename$); - hotAddUpdateChunk(chunk.id, chunk.modules); - } - - function hotDownloadManifest() { // eslint-disable-line no-unused-vars - try { - var update = require("./" + $hotMainFilename$); - } catch(e) { - return Promise.resolve(); - } - return Promise.resolve(update); - } - - function hotDisposeChunk(chunkId) { //eslint-disable-line no-unused-vars - delete installedChunks[chunkId]; - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +/*global installedChunks $hotChunkFilename$ hotAddUpdateChunk $hotMainFilename$ */ +module.exports = function() { + // eslint-disable-next-line no-unused-vars + function hotDownloadUpdateChunk(chunkId) { + var chunk = require("./" + $hotChunkFilename$); + hotAddUpdateChunk(chunk.id, chunk.modules); + } + + // eslint-disable-next-line no-unused-vars + function hotDownloadManifest() { + try { + var update = require("./" + $hotMainFilename$); + } catch (e) { + return Promise.resolve(); + } + return Promise.resolve(update); + } + + //eslint-disable-next-line no-unused-vars + function hotDisposeChunk(chunkId) { + delete installedChunks[chunkId]; + } +}; diff --git a/node_modules/webpack/lib/node/NodeMainTemplateAsync.runtime.js b/node_modules/webpack/lib/node/NodeMainTemplateAsync.runtime.js index 673cfafd0..35eb47b66 100644 --- a/node_modules/webpack/lib/node/NodeMainTemplateAsync.runtime.js +++ b/node_modules/webpack/lib/node/NodeMainTemplateAsync.runtime.js @@ -1,40 +1,44 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -/*global installedChunks $hotChunkFilename$ $require$ hotAddUpdateChunk $hotMainFilename$ */ -module.exports = function() { - function hotDownloadUpdateChunk(chunkId) { // eslint-disable-line no-unused-vars - var filename = require("path").join(__dirname, $hotChunkFilename$); - require("fs").readFile(filename, "utf-8", function(err, content) { - if(err) { - if($require$.onError) - return $require$.oe(err); - else - throw err; - } - var chunk = {}; - require("vm").runInThisContext("(function(exports) {" + content + "\n})", filename)(chunk); - hotAddUpdateChunk(chunk.id, chunk.modules); - }); - } - - function hotDownloadManifest() { // eslint-disable-line no-unused-vars - var filename = require("path").join(__dirname, $hotMainFilename$); - return new Promise(function(resolve, reject) { - require("fs").readFile(filename, "utf-8", function(err, content) { - if(err) return resolve(); - try { - var update = JSON.parse(content); - } catch(e) { - return reject(e); - } - resolve(update); - }); - }); - } - - function hotDisposeChunk(chunkId) { //eslint-disable-line no-unused-vars - delete installedChunks[chunkId]; - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +/*global installedChunks $hotChunkFilename$ $require$ hotAddUpdateChunk $hotMainFilename$ */ +module.exports = function() { + // eslint-disable-next-line no-unused-vars + function hotDownloadUpdateChunk(chunkId) { + var filename = require("path").join(__dirname, $hotChunkFilename$); + require("fs").readFile(filename, "utf-8", function(err, content) { + if (err) { + if ($require$.onError) return $require$.oe(err); + throw err; + } + var chunk = {}; + require("vm").runInThisContext( + "(function(exports) {" + content + "\n})", + { filename: filename } + )(chunk); + hotAddUpdateChunk(chunk.id, chunk.modules); + }); + } + + // eslint-disable-next-line no-unused-vars + function hotDownloadManifest() { + var filename = require("path").join(__dirname, $hotMainFilename$); + return new Promise(function(resolve, reject) { + require("fs").readFile(filename, "utf-8", function(err, content) { + if (err) return resolve(); + try { + var update = JSON.parse(content); + } catch (e) { + return reject(e); + } + resolve(update); + }); + }); + } + + // eslint-disable-next-line no-unused-vars + function hotDisposeChunk(chunkId) { + delete installedChunks[chunkId]; + } +}; diff --git a/node_modules/webpack/lib/node/NodeMainTemplatePlugin.js b/node_modules/webpack/lib/node/NodeMainTemplatePlugin.js index 9a64b57b5..a27029699 100644 --- a/node_modules/webpack/lib/node/NodeMainTemplatePlugin.js +++ b/node_modules/webpack/lib/node/NodeMainTemplatePlugin.js @@ -1,183 +1,321 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const Template = require("../Template"); - -module.exports = class NodeMainTemplatePlugin { - constructor(asyncChunkLoading) { - this.asyncChunkLoading = asyncChunkLoading; - } - - apply(mainTemplate) { - const asyncChunkLoading = this.asyncChunkLoading; - mainTemplate.plugin("local-vars", function(source, chunk) { - if(chunk.chunks.length > 0) { - return this.asString([ - source, - "", - "// object to store loaded chunks", - "// \"0\" means \"already loaded\"", - "var installedChunks = {", - this.indent(chunk.ids.map((id) => `${id}: 0`).join(",\n")), - "};" - ]); - } - return source; - }); - mainTemplate.plugin("require-extensions", function(source, chunk) { - if(chunk.chunks.length > 0) { - return this.asString([ - source, - "", - "// uncatched error handler for webpack runtime", - `${this.requireFn}.oe = function(err) {`, - this.indent([ - "process.nextTick(function() {", - this.indent("throw err; // catch this error by using System.import().catch()"), - "});" - ]), - "};" - ]); - } - return source; - }); - mainTemplate.plugin("require-ensure", function(_, chunk, hash) { - const chunkFilename = this.outputOptions.chunkFilename; - const chunkMaps = chunk.getChunkMaps(); - const insertMoreModules = [ - "var moreModules = chunk.modules, chunkIds = chunk.ids;", - "for(var moduleId in moreModules) {", - this.indent(this.renderAddModule(hash, chunk, "moduleId", "moreModules[moduleId]")), - "}" - ]; - if(asyncChunkLoading) { - return this.asString([ - "// \"0\" is the signal for \"already loaded\"", - "if(installedChunks[chunkId] === 0)", - this.indent([ - "return Promise.resolve();" - ]), - "// array of [resolve, reject, promise] means \"currently loading\"", - "if(installedChunks[chunkId])", - this.indent([ - "return installedChunks[chunkId][2];" - ]), - "// load the chunk and return promise to it", - "var promise = new Promise(function(resolve, reject) {", - this.indent([ - "installedChunks[chunkId] = [resolve, reject];", - "var filename = __dirname + " + this.applyPluginsWaterfall("asset-path", JSON.stringify(`/${chunkFilename}`), { - hash: `" + ${this.renderCurrentHashCode(hash)} + "`, - hashWithLength: (length) => `" + ${this.renderCurrentHashCode(hash, length)} + "`, - chunk: { - id: "\" + chunkId + \"", - hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`, - hashWithLength: (length) => { - const shortChunkHashMap = {}; - Object.keys(chunkMaps.hash).forEach((chunkId) => { - if(typeof chunkMaps.hash[chunkId] === "string") - shortChunkHashMap[chunkId] = chunkMaps.hash[chunkId].substr(0, length); - }); - return `" + ${JSON.stringify(shortChunkHashMap)}[chunkId] + "`; - }, - name: `" + (${JSON.stringify(chunkMaps.name)}[chunkId]||chunkId) + "` - } - }) + ";", - "require('fs').readFile(filename, 'utf-8', function(err, content) {", - this.indent([ - "if(err) return reject(err);", - "var chunk = {};", - "require('vm').runInThisContext('(function(exports, require, __dirname, __filename) {' + content + '\\n})', filename)" + - "(chunk, require, require('path').dirname(filename), filename);" - ].concat(insertMoreModules).concat([ - "var callbacks = [];", - "for(var i = 0; i < chunkIds.length; i++) {", - this.indent([ - "if(installedChunks[chunkIds[i]])", - this.indent([ - "callbacks = callbacks.concat(installedChunks[chunkIds[i]][0]);" - ]), - "installedChunks[chunkIds[i]] = 0;" - ]), - "}", - "for(i = 0; i < callbacks.length; i++)", - this.indent("callbacks[i]();") - ])), - "});" - ]), - "});", - "return installedChunks[chunkId][2] = promise;" - ]); - } else { - const request = this.applyPluginsWaterfall("asset-path", JSON.stringify(`./${chunkFilename}`), { - hash: `" + ${this.renderCurrentHashCode(hash)} + "`, - hashWithLength: (length) => `" + ${this.renderCurrentHashCode(hash, length)} + "`, - chunk: { - id: "\" + chunkId + \"", - hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`, - hashWithLength: (length) => { - const shortChunkHashMap = {}; - Object.keys(chunkMaps.hash).forEach((chunkId) => { - if(typeof chunkMaps.hash[chunkId] === "string") - shortChunkHashMap[chunkId] = chunkMaps.hash[chunkId].substr(0, length); - }); - return `" + ${JSON.stringify(shortChunkHashMap)}[chunkId] + "`; - }, - name: `" + (${JSON.stringify(chunkMaps.name)}[chunkId]||chunkId) + "` - } - }); - return this.asString([ - "// \"0\" is the signal for \"already loaded\"", - "if(installedChunks[chunkId] !== 0) {", - this.indent([ - `var chunk = require(${request});` - ].concat(insertMoreModules).concat([ - "for(var i = 0; i < chunkIds.length; i++)", - this.indent("installedChunks[chunkIds[i]] = 0;") - ])), - "}", - "return Promise.resolve();" - ]); - } - }); - mainTemplate.plugin("hot-bootstrap", function(source, chunk, hash) { - const hotUpdateChunkFilename = this.outputOptions.hotUpdateChunkFilename; - const hotUpdateMainFilename = this.outputOptions.hotUpdateMainFilename; - const chunkMaps = chunk.getChunkMaps(); - const currentHotUpdateChunkFilename = this.applyPluginsWaterfall("asset-path", JSON.stringify(hotUpdateChunkFilename), { - hash: `" + ${this.renderCurrentHashCode(hash)} + "`, - hashWithLength: (length) => `" + ${this.renderCurrentHashCode(hash, length)} + "`, - chunk: { - id: "\" + chunkId + \"", - hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`, - hashWithLength: (length) => { - const shortChunkHashMap = {}; - Object.keys(chunkMaps.hash).forEach((chunkId) => { - if(typeof chunkMaps.hash[chunkId] === "string") - shortChunkHashMap[chunkId] = chunkMaps.hash[chunkId].substr(0, length); - }); - return `" + ${JSON.stringify(shortChunkHashMap)}[chunkId] + "`; - }, - name: `" + (${JSON.stringify(chunkMaps.name)}[chunkId]||chunkId) + "` - } - }); - const currentHotUpdateMainFilename = this.applyPluginsWaterfall("asset-path", JSON.stringify(hotUpdateMainFilename), { - hash: `" + ${this.renderCurrentHashCode(hash)} + "`, - hashWithLength: (length) => `" + ${this.renderCurrentHashCode(hash, length)} + "` - }); - return Template.getFunctionContent(asyncChunkLoading ? require("./NodeMainTemplateAsync.runtime.js") : require("./NodeMainTemplate.runtime.js")) - .replace(/\$require\$/g, this.requireFn) - .replace(/\$hotMainFilename\$/g, currentHotUpdateMainFilename) - .replace(/\$hotChunkFilename\$/g, currentHotUpdateChunkFilename); - }); - mainTemplate.plugin("hash", function(hash) { - hash.update("node"); - hash.update("3"); - hash.update(this.outputOptions.filename + ""); - hash.update(this.outputOptions.chunkFilename + ""); - }); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const Template = require("../Template"); + +module.exports = class NodeMainTemplatePlugin { + constructor(asyncChunkLoading) { + this.asyncChunkLoading = asyncChunkLoading; + } + + apply(mainTemplate) { + const needChunkOnDemandLoadingCode = chunk => { + for (const chunkGroup of chunk.groupsIterable) { + if (chunkGroup.getNumberOfChildren() > 0) return true; + } + return false; + }; + const asyncChunkLoading = this.asyncChunkLoading; + mainTemplate.hooks.localVars.tap( + "NodeMainTemplatePlugin", + (source, chunk) => { + if (needChunkOnDemandLoadingCode(chunk)) { + return Template.asString([ + source, + "", + "// object to store loaded chunks", + '// "0" means "already loaded"', + "var installedChunks = {", + Template.indent( + chunk.ids.map(id => `${JSON.stringify(id)}: 0`).join(",\n") + ), + "};" + ]); + } + return source; + } + ); + mainTemplate.hooks.requireExtensions.tap( + "NodeMainTemplatePlugin", + (source, chunk) => { + if (needChunkOnDemandLoadingCode(chunk)) { + return Template.asString([ + source, + "", + "// uncaught error handler for webpack runtime", + `${mainTemplate.requireFn}.oe = function(err) {`, + Template.indent([ + "process.nextTick(function() {", + Template.indent( + "throw err; // catch this error by using import().catch()" + ), + "});" + ]), + "};" + ]); + } + return source; + } + ); + mainTemplate.hooks.requireEnsure.tap( + "NodeMainTemplatePlugin", + (source, chunk, hash) => { + const chunkFilename = mainTemplate.outputOptions.chunkFilename; + const chunkMaps = chunk.getChunkMaps(); + const insertMoreModules = [ + "var moreModules = chunk.modules, chunkIds = chunk.ids;", + "for(var moduleId in moreModules) {", + Template.indent( + mainTemplate.renderAddModule( + hash, + chunk, + "moduleId", + "moreModules[moduleId]" + ) + ), + "}" + ]; + if (asyncChunkLoading) { + return Template.asString([ + source, + "", + "// ReadFile + VM.run chunk loading for javascript", + "", + "var installedChunkData = installedChunks[chunkId];", + 'if(installedChunkData !== 0) { // 0 means "already installed".', + Template.indent([ + '// array of [resolve, reject, promise] means "currently loading"', + "if(installedChunkData) {", + Template.indent(["promises.push(installedChunkData[2]);"]), + "} else {", + Template.indent([ + "// load the chunk and return promise to it", + "var promise = new Promise(function(resolve, reject) {", + Template.indent([ + "installedChunkData = installedChunks[chunkId] = [resolve, reject];", + "var filename = require('path').join(__dirname, " + + mainTemplate.getAssetPath( + JSON.stringify(`/${chunkFilename}`), + { + hash: `" + ${mainTemplate.renderCurrentHashCode( + hash + )} + "`, + hashWithLength: length => + `" + ${mainTemplate.renderCurrentHashCode( + hash, + length + )} + "`, + chunk: { + id: '" + chunkId + "', + hash: `" + ${JSON.stringify( + chunkMaps.hash + )}[chunkId] + "`, + hashWithLength: length => { + const shortChunkHashMap = {}; + for (const chunkId of Object.keys(chunkMaps.hash)) { + if (typeof chunkMaps.hash[chunkId] === "string") { + shortChunkHashMap[chunkId] = chunkMaps.hash[ + chunkId + ].substr(0, length); + } + } + return `" + ${JSON.stringify( + shortChunkHashMap + )}[chunkId] + "`; + }, + contentHash: { + javascript: `" + ${JSON.stringify( + chunkMaps.contentHash.javascript + )}[chunkId] + "` + }, + contentHashWithLength: { + javascript: length => { + const shortContentHashMap = {}; + const contentHash = + chunkMaps.contentHash.javascript; + for (const chunkId of Object.keys(contentHash)) { + if (typeof contentHash[chunkId] === "string") { + shortContentHashMap[chunkId] = contentHash[ + chunkId + ].substr(0, length); + } + } + return `" + ${JSON.stringify( + shortContentHashMap + )}[chunkId] + "`; + } + }, + name: `" + (${JSON.stringify( + chunkMaps.name + )}[chunkId]||chunkId) + "` + }, + contentHashType: "javascript" + } + ) + + ");", + "require('fs').readFile(filename, 'utf-8', function(err, content) {", + Template.indent( + [ + "if(err) return reject(err);", + "var chunk = {};", + "require('vm').runInThisContext('(function(exports, require, __dirname, __filename) {' + content + '\\n})', filename)" + + "(chunk, require, require('path').dirname(filename), filename);" + ] + .concat(insertMoreModules) + .concat([ + "var callbacks = [];", + "for(var i = 0; i < chunkIds.length; i++) {", + Template.indent([ + "if(installedChunks[chunkIds[i]])", + Template.indent([ + "callbacks = callbacks.concat(installedChunks[chunkIds[i]][0]);" + ]), + "installedChunks[chunkIds[i]] = 0;" + ]), + "}", + "for(i = 0; i < callbacks.length; i++)", + Template.indent("callbacks[i]();") + ]) + ), + "});" + ]), + "});", + "promises.push(installedChunkData[2] = promise);" + ]), + "}" + ]), + "}" + ]); + } else { + const request = mainTemplate.getAssetPath( + JSON.stringify(`./${chunkFilename}`), + { + hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, + hashWithLength: length => + `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`, + chunk: { + id: '" + chunkId + "', + hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`, + hashWithLength: length => { + const shortChunkHashMap = {}; + for (const chunkId of Object.keys(chunkMaps.hash)) { + if (typeof chunkMaps.hash[chunkId] === "string") { + shortChunkHashMap[chunkId] = chunkMaps.hash[ + chunkId + ].substr(0, length); + } + } + return `" + ${JSON.stringify( + shortChunkHashMap + )}[chunkId] + "`; + }, + contentHash: { + javascript: `" + ${JSON.stringify( + chunkMaps.contentHash.javascript + )}[chunkId] + "` + }, + contentHashWithLength: { + javascript: length => { + const shortContentHashMap = {}; + const contentHash = chunkMaps.contentHash.javascript; + for (const chunkId of Object.keys(contentHash)) { + if (typeof contentHash[chunkId] === "string") { + shortContentHashMap[chunkId] = contentHash[ + chunkId + ].substr(0, length); + } + } + return `" + ${JSON.stringify( + shortContentHashMap + )}[chunkId] + "`; + } + }, + name: `" + (${JSON.stringify( + chunkMaps.name + )}[chunkId]||chunkId) + "` + }, + contentHashType: "javascript" + } + ); + return Template.asString([ + source, + "", + "// require() chunk loading for javascript", + "", + '// "0" is the signal for "already loaded"', + "if(installedChunks[chunkId] !== 0) {", + Template.indent( + [`var chunk = require(${request});`] + .concat(insertMoreModules) + .concat([ + "for(var i = 0; i < chunkIds.length; i++)", + Template.indent("installedChunks[chunkIds[i]] = 0;") + ]) + ), + "}" + ]); + } + } + ); + mainTemplate.hooks.hotBootstrap.tap( + "NodeMainTemplatePlugin", + (source, chunk, hash) => { + const hotUpdateChunkFilename = + mainTemplate.outputOptions.hotUpdateChunkFilename; + const hotUpdateMainFilename = + mainTemplate.outputOptions.hotUpdateMainFilename; + const chunkMaps = chunk.getChunkMaps(); + const currentHotUpdateChunkFilename = mainTemplate.getAssetPath( + JSON.stringify(hotUpdateChunkFilename), + { + hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, + hashWithLength: length => + `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`, + chunk: { + id: '" + chunkId + "', + hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`, + hashWithLength: length => { + const shortChunkHashMap = {}; + for (const chunkId of Object.keys(chunkMaps.hash)) { + if (typeof chunkMaps.hash[chunkId] === "string") { + shortChunkHashMap[chunkId] = chunkMaps.hash[chunkId].substr( + 0, + length + ); + } + } + return `" + ${JSON.stringify(shortChunkHashMap)}[chunkId] + "`; + }, + name: `" + (${JSON.stringify( + chunkMaps.name + )}[chunkId]||chunkId) + "` + } + } + ); + const currentHotUpdateMainFilename = mainTemplate.getAssetPath( + JSON.stringify(hotUpdateMainFilename), + { + hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, + hashWithLength: length => + `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "` + } + ); + return Template.getFunctionContent( + asyncChunkLoading + ? require("./NodeMainTemplateAsync.runtime") + : require("./NodeMainTemplate.runtime") + ) + .replace(/\$require\$/g, mainTemplate.requireFn) + .replace(/\$hotMainFilename\$/g, currentHotUpdateMainFilename) + .replace(/\$hotChunkFilename\$/g, currentHotUpdateChunkFilename); + } + ); + mainTemplate.hooks.hash.tap("NodeMainTemplatePlugin", hash => { + hash.update("node"); + hash.update("4"); + }); + } +}; diff --git a/node_modules/webpack/lib/node/NodeOutputFileSystem.js b/node_modules/webpack/lib/node/NodeOutputFileSystem.js index 5a6e328e1..2789b576a 100644 --- a/node_modules/webpack/lib/node/NodeOutputFileSystem.js +++ b/node_modules/webpack/lib/node/NodeOutputFileSystem.js @@ -1,22 +1,22 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const fs = require("fs"); -const path = require("path"); -const mkdirp = require("mkdirp"); - -class NodeOutputFileSystem { - constructor() { - this.mkdirp = mkdirp; - this.mkdir = fs.mkdir.bind(fs); - this.rmdir = fs.rmdir.bind(fs); - this.unlink = fs.unlink.bind(fs); - this.writeFile = fs.writeFile.bind(fs); - this.join = path.join.bind(path); - } -} - -module.exports = NodeOutputFileSystem; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const fs = require("fs"); +const path = require("path"); +const mkdirp = require("mkdirp"); + +class NodeOutputFileSystem { + constructor() { + this.mkdirp = mkdirp; + this.mkdir = fs.mkdir.bind(fs); + this.rmdir = fs.rmdir.bind(fs); + this.unlink = fs.unlink.bind(fs); + this.writeFile = fs.writeFile.bind(fs); + this.join = path.join.bind(path); + } +} + +module.exports = NodeOutputFileSystem; diff --git a/node_modules/webpack/lib/node/NodeSourcePlugin.js b/node_modules/webpack/lib/node/NodeSourcePlugin.js index 986160028..d5505f6f5 100644 --- a/node_modules/webpack/lib/node/NodeSourcePlugin.js +++ b/node_modules/webpack/lib/node/NodeSourcePlugin.js @@ -1,88 +1,144 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const AliasPlugin = require("enhanced-resolve/lib/AliasPlugin"); -const ParserHelpers = require("../ParserHelpers"); -const nodeLibsBrowser = require("node-libs-browser"); - -module.exports = class NodeSourcePlugin { - constructor(options) { - this.options = options; - } - apply(compiler) { - const options = this.options; - if(options === false) // allow single kill switch to turn off this plugin - return; - - function getPathToModule(module, type) { - if(type === true || (type === undefined && nodeLibsBrowser[module])) { - if(!nodeLibsBrowser[module]) throw new Error(`No browser version for node.js core module ${module} available`); - return nodeLibsBrowser[module]; - } else if(type === "mock") { - return require.resolve(`node-libs-browser/mock/${module}`); - } else if(type === "empty") { - return require.resolve("node-libs-browser/mock/empty"); - } else return module; - } - - function addExpression(parser, name, module, type, suffix) { - suffix = suffix || ""; - parser.plugin(`expression ${name}`, function() { - if(this.state.module && this.state.module.resource === getPathToModule(module, type)) return; - const mockModule = ParserHelpers.requireFileAsExpression(this.state.module.context, getPathToModule(module, type)); - return ParserHelpers.addParsedVariableToModule(this, name, mockModule + suffix); - }); - } - - compiler.plugin("compilation", function(compilation, params) { - params.normalModuleFactory.plugin("parser", function(parser, parserOptions) { - - if(parserOptions.node === false) - return; - - let localOptions = options; - if(parserOptions.node) - localOptions = Object.assign({}, localOptions, parserOptions.node); - - if(localOptions.global) { - parser.plugin("expression global", function() { - const retrieveGlobalModule = ParserHelpers.requireFileAsExpression(this.state.module.context, require.resolve("../../buildin/global.js")); - return ParserHelpers.addParsedVariableToModule(this, "global", retrieveGlobalModule); - }); - } - if(localOptions.process) { - const processType = localOptions.process; - addExpression(parser, "process", "process", processType); - } - if(localOptions.console) { - const consoleType = localOptions.console; - addExpression(parser, "console", "console", consoleType); - } - const bufferType = localOptions.Buffer; - if(bufferType) { - addExpression(parser, "Buffer", "buffer", bufferType, ".Buffer"); - } - if(localOptions.setImmediate) { - const setImmediateType = localOptions.setImmediate; - addExpression(parser, "setImmediate", "timers", setImmediateType, ".setImmediate"); - addExpression(parser, "clearImmediate", "timers", setImmediateType, ".clearImmediate"); - } - }); - }); - compiler.plugin("after-resolvers", (compiler) => { - Object.keys(nodeLibsBrowser).forEach((lib) => { - if(options[lib] !== false) { - compiler.resolvers.normal.apply( - new AliasPlugin("described-resolve", { - name: lib, - onlyModule: true, - alias: getPathToModule(lib, options[lib]) - }, "resolve") - ); - } - }); - }); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const AliasPlugin = require("enhanced-resolve/lib/AliasPlugin"); +const ParserHelpers = require("../ParserHelpers"); +const nodeLibsBrowser = require("node-libs-browser"); + +module.exports = class NodeSourcePlugin { + constructor(options) { + this.options = options; + } + apply(compiler) { + const options = this.options; + if (options === false) { + // allow single kill switch to turn off this plugin + return; + } + + const getPathToModule = (module, type) => { + if (type === true || (type === undefined && nodeLibsBrowser[module])) { + if (!nodeLibsBrowser[module]) { + throw new Error( + `No browser version for node.js core module ${module} available` + ); + } + return nodeLibsBrowser[module]; + } else if (type === "mock") { + return require.resolve(`node-libs-browser/mock/${module}`); + } else if (type === "empty") { + return require.resolve("node-libs-browser/mock/empty"); + } else { + return module; + } + }; + + const addExpression = (parser, name, module, type, suffix) => { + suffix = suffix || ""; + parser.hooks.expression.for(name).tap("NodeSourcePlugin", () => { + if ( + parser.state.module && + parser.state.module.resource === getPathToModule(module, type) + ) + return; + const mockModule = ParserHelpers.requireFileAsExpression( + parser.state.module.context, + getPathToModule(module, type) + ); + return ParserHelpers.addParsedVariableToModule( + parser, + name, + mockModule + suffix + ); + }); + }; + + compiler.hooks.compilation.tap( + "NodeSourcePlugin", + (compilation, { normalModuleFactory }) => { + const handler = (parser, parserOptions) => { + if (parserOptions.node === false) return; + + let localOptions = options; + if (parserOptions.node) { + localOptions = Object.assign({}, localOptions, parserOptions.node); + } + if (localOptions.global) { + parser.hooks.expression + .for("global") + .tap("NodeSourcePlugin", () => { + const retrieveGlobalModule = ParserHelpers.requireFileAsExpression( + parser.state.module.context, + require.resolve("../../buildin/global") + ); + return ParserHelpers.addParsedVariableToModule( + parser, + "global", + retrieveGlobalModule + ); + }); + } + if (localOptions.process) { + const processType = localOptions.process; + addExpression(parser, "process", "process", processType); + } + if (localOptions.console) { + const consoleType = localOptions.console; + addExpression(parser, "console", "console", consoleType); + } + const bufferType = localOptions.Buffer; + if (bufferType) { + addExpression(parser, "Buffer", "buffer", bufferType, ".Buffer"); + } + if (localOptions.setImmediate) { + const setImmediateType = localOptions.setImmediate; + addExpression( + parser, + "setImmediate", + "timers", + setImmediateType, + ".setImmediate" + ); + addExpression( + parser, + "clearImmediate", + "timers", + setImmediateType, + ".clearImmediate" + ); + } + }; + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("NodeSourcePlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("NodeSourcePlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/esm") + .tap("NodeSourcePlugin", handler); + } + ); + compiler.hooks.afterResolvers.tap("NodeSourcePlugin", compiler => { + for (const lib of Object.keys(nodeLibsBrowser)) { + if (options[lib] !== false) { + compiler.resolverFactory.hooks.resolver + .for("normal") + .tap("NodeSourcePlugin", resolver => { + new AliasPlugin( + "described-resolve", + { + name: lib, + onlyModule: true, + alias: getPathToModule(lib, options[lib]) + }, + "resolve" + ).apply(resolver); + }); + } + } + }); + } +}; diff --git a/node_modules/webpack/lib/node/NodeTargetPlugin.js b/node_modules/webpack/lib/node/NodeTargetPlugin.js index 528a28570..b76b70690 100644 --- a/node_modules/webpack/lib/node/NodeTargetPlugin.js +++ b/node_modules/webpack/lib/node/NodeTargetPlugin.js @@ -1,15 +1,19 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ExternalsPlugin = require("../ExternalsPlugin"); - -class NodeTargetPlugin { - apply(compiler) { - new ExternalsPlugin("commonjs", Object.keys(process.binding("natives"))).apply(compiler); - } -} - -module.exports = NodeTargetPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const ExternalsPlugin = require("../ExternalsPlugin"); + +const builtins = + // eslint-disable-next-line node/no-unsupported-features/node-builtins + require("module").builtinModules || Object.keys(process.binding("natives")); + +class NodeTargetPlugin { + apply(compiler) { + new ExternalsPlugin("commonjs", builtins).apply(compiler); + } +} + +module.exports = NodeTargetPlugin; diff --git a/node_modules/webpack/lib/node/NodeTemplatePlugin.js b/node_modules/webpack/lib/node/NodeTemplatePlugin.js index ed17d1937..cdb1076b9 100644 --- a/node_modules/webpack/lib/node/NodeTemplatePlugin.js +++ b/node_modules/webpack/lib/node/NodeTemplatePlugin.js @@ -1,27 +1,31 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ - -"use strict"; - -const NodeMainTemplatePlugin = require("./NodeMainTemplatePlugin"); -const NodeChunkTemplatePlugin = require("./NodeChunkTemplatePlugin"); -const NodeHotUpdateChunkTemplatePlugin = require("./NodeHotUpdateChunkTemplatePlugin"); - -class NodeTemplatePlugin { - constructor(options) { - options = options || {}; - this.asyncChunkLoading = options.asyncChunkLoading; - } - - apply(compiler) { - compiler.plugin("this-compilation", (compilation) => { - compilation.mainTemplate.apply(new NodeMainTemplatePlugin(this.asyncChunkLoading)); - compilation.chunkTemplate.apply(new NodeChunkTemplatePlugin()); - compilation.hotUpdateChunkTemplate.apply(new NodeHotUpdateChunkTemplatePlugin()); - }); - } -} - -module.exports = NodeTemplatePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ + +"use strict"; + +const NodeMainTemplatePlugin = require("./NodeMainTemplatePlugin"); +const NodeChunkTemplatePlugin = require("./NodeChunkTemplatePlugin"); +const NodeHotUpdateChunkTemplatePlugin = require("./NodeHotUpdateChunkTemplatePlugin"); + +class NodeTemplatePlugin { + constructor(options) { + options = options || {}; + this.asyncChunkLoading = options.asyncChunkLoading; + } + + apply(compiler) { + compiler.hooks.thisCompilation.tap("NodeTemplatePlugin", compilation => { + new NodeMainTemplatePlugin(this.asyncChunkLoading).apply( + compilation.mainTemplate + ); + new NodeChunkTemplatePlugin().apply(compilation.chunkTemplate); + new NodeHotUpdateChunkTemplatePlugin().apply( + compilation.hotUpdateChunkTemplate + ); + }); + } +} + +module.exports = NodeTemplatePlugin; diff --git a/node_modules/webpack/lib/node/NodeWatchFileSystem.js b/node_modules/webpack/lib/node/NodeWatchFileSystem.js index 1c13a9b29..62d8532cd 100644 --- a/node_modules/webpack/lib/node/NodeWatchFileSystem.js +++ b/node_modules/webpack/lib/node/NodeWatchFileSystem.js @@ -1,72 +1,99 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const Watchpack = require("watchpack"); - -class NodeWatchFileSystem { - constructor(inputFileSystem) { - this.inputFileSystem = inputFileSystem; - this.watcherOptions = { - aggregateTimeout: 0 - }; - this.watcher = new Watchpack(this.watcherOptions); - } - - watch(files, dirs, missing, startTime, options, callback, callbackUndelayed) { - if(!Array.isArray(files)) - throw new Error("Invalid arguments: 'files'"); - if(!Array.isArray(dirs)) - throw new Error("Invalid arguments: 'dirs'"); - if(!Array.isArray(missing)) - throw new Error("Invalid arguments: 'missing'"); - if(typeof callback !== "function") - throw new Error("Invalid arguments: 'callback'"); - if(typeof startTime !== "number" && startTime) - throw new Error("Invalid arguments: 'startTime'"); - if(typeof options !== "object") - throw new Error("Invalid arguments: 'options'"); - if(typeof callbackUndelayed !== "function" && callbackUndelayed) - throw new Error("Invalid arguments: 'callbackUndelayed'"); - const oldWatcher = this.watcher; - this.watcher = new Watchpack(options); - - if(callbackUndelayed) - this.watcher.once("change", callbackUndelayed); - - this.watcher.once("aggregated", (changes, removals) => { - changes = changes.concat(removals); - if(this.inputFileSystem && this.inputFileSystem.purge) { - this.inputFileSystem.purge(changes); - } - const times = this.watcher.getTimes(); - callback(null, - changes.filter(file => files.indexOf(file) >= 0).sort(), - changes.filter(file => dirs.indexOf(file) >= 0).sort(), - changes.filter(file => missing.indexOf(file) >= 0).sort(), times, times); - }); - - this.watcher.watch(files.concat(missing), dirs.concat(missing), startTime); - - if(oldWatcher) { - oldWatcher.close(); - } - return { - close: () => { - if(this.watcher) { - this.watcher.close(); - this.watcher = null; - } - }, - pause: () => { - if(this.watcher) { - this.watcher.pause(); - } - } - }; - } -} - -module.exports = NodeWatchFileSystem; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const Watchpack = require("watchpack"); +const objectToMap = require("../util/objectToMap"); + +class NodeWatchFileSystem { + constructor(inputFileSystem) { + this.inputFileSystem = inputFileSystem; + this.watcherOptions = { + aggregateTimeout: 0 + }; + this.watcher = new Watchpack(this.watcherOptions); + } + + watch(files, dirs, missing, startTime, options, callback, callbackUndelayed) { + if (!Array.isArray(files)) { + throw new Error("Invalid arguments: 'files'"); + } + if (!Array.isArray(dirs)) { + throw new Error("Invalid arguments: 'dirs'"); + } + if (!Array.isArray(missing)) { + throw new Error("Invalid arguments: 'missing'"); + } + if (typeof callback !== "function") { + throw new Error("Invalid arguments: 'callback'"); + } + if (typeof startTime !== "number" && startTime) { + throw new Error("Invalid arguments: 'startTime'"); + } + if (typeof options !== "object") { + throw new Error("Invalid arguments: 'options'"); + } + if (typeof callbackUndelayed !== "function" && callbackUndelayed) { + throw new Error("Invalid arguments: 'callbackUndelayed'"); + } + const oldWatcher = this.watcher; + this.watcher = new Watchpack(options); + + if (callbackUndelayed) { + this.watcher.once("change", callbackUndelayed); + } + + this.watcher.once("aggregated", (changes, removals) => { + changes = changes.concat(removals); + if (this.inputFileSystem && this.inputFileSystem.purge) { + this.inputFileSystem.purge(changes); + } + const times = objectToMap(this.watcher.getTimes()); + callback( + null, + changes.filter(file => files.includes(file)).sort(), + changes.filter(file => dirs.includes(file)).sort(), + changes.filter(file => missing.includes(file)).sort(), + times, + times + ); + }); + + this.watcher.watch(files.concat(missing), dirs.concat(missing), startTime); + + if (oldWatcher) { + oldWatcher.close(); + } + return { + close: () => { + if (this.watcher) { + this.watcher.close(); + this.watcher = null; + } + }, + pause: () => { + if (this.watcher) { + this.watcher.pause(); + } + }, + getFileTimestamps: () => { + if (this.watcher) { + return objectToMap(this.watcher.getTimes()); + } else { + return new Map(); + } + }, + getContextTimestamps: () => { + if (this.watcher) { + return objectToMap(this.watcher.getTimes()); + } else { + return new Map(); + } + } + }; + } +} + +module.exports = NodeWatchFileSystem; diff --git a/node_modules/webpack/lib/optimize/AggressiveMergingPlugin.js b/node_modules/webpack/lib/optimize/AggressiveMergingPlugin.js index dc14ac300..e3a4c37ee 100644 --- a/node_modules/webpack/lib/optimize/AggressiveMergingPlugin.js +++ b/node_modules/webpack/lib/optimize/AggressiveMergingPlugin.js @@ -1,115 +1,87 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class AggressiveMergingPlugin { - constructor(options) { - if(options !== undefined && typeof options !== "object" || Array.isArray(options)) { - throw new Error("Argument should be an options object. To use defaults, pass in nothing.\nFor more info on options, see https://webpack.js.org/plugins/"); - } - this.options = options || {}; - } - - apply(compiler) { - const options = this.options; - const minSizeReduce = options.minSizeReduce || 1.5; - - function getParentsWeight(chunk) { - return chunk.parents.map((p) => { - return p.isInitial() ? options.entryChunkMultiplicator || 10 : 1; - }).reduce((a, b) => { - return a + b; - }, 0); - } - compiler.plugin("this-compilation", (compilation) => { - compilation.plugin("optimize-chunks-advanced", (chunks) => { - let combinations = []; - chunks.forEach((a, idx) => { - if(a.isInitial()) return; - for(let i = 0; i < idx; i++) { - const b = chunks[i]; - if(b.isInitial()) continue; - combinations.push({ - a, - b, - improvement: undefined - }); - } - }); - - combinations.forEach((pair) => { - const a = pair.b.size({ - chunkOverhead: 0 - }); - const b = pair.a.size({ - chunkOverhead: 0 - }); - const ab = pair.b.integratedSize(pair.a, { - chunkOverhead: 0 - }); - let newSize; - if(ab === false) { - pair.improvement = false; - return; - } else if(options.moveToParents) { - const aOnly = ab - b; - const bOnly = ab - a; - const common = a + b - ab; - newSize = common + getParentsWeight(pair.b) * aOnly + getParentsWeight(pair.a) * bOnly; - } else { - newSize = ab; - } - - pair.improvement = (a + b) / newSize; - }); - combinations = combinations.filter((pair) => { - return pair.improvement !== false; - }); - combinations.sort((a, b) => { - return b.improvement - a.improvement; - }); - - const pair = combinations[0]; - - if(!pair) return; - if(pair.improvement < minSizeReduce) return; - - if(options.moveToParents) { - const commonModules = pair.b.modules.filter((m) => { - return pair.a.modules.indexOf(m) >= 0; - }); - const aOnlyModules = pair.b.modules.filter((m) => { - return commonModules.indexOf(m) < 0; - }); - const bOnlyModules = pair.a.modules.filter((m) => { - return commonModules.indexOf(m) < 0; - }); - aOnlyModules.forEach((m) => { - pair.b.removeModule(m); - m.removeChunk(pair.b); - pair.b.parents.forEach((c) => { - c.addModule(m); - m.addChunk(c); - }); - }); - bOnlyModules.forEach((m) => { - pair.a.removeModule(m); - m.removeChunk(pair.a); - pair.a.parents.forEach((c) => { - c.addModule(m); - m.addChunk(c); - }); - }); - } - if(pair.b.integrate(pair.a, "aggressive-merge")) { - chunks.splice(chunks.indexOf(pair.a), 1); - return true; - } - }); - }); - } -} - -module.exports = AggressiveMergingPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +class AggressiveMergingPlugin { + constructor(options) { + if ( + (options !== undefined && typeof options !== "object") || + Array.isArray(options) + ) { + throw new Error( + "Argument should be an options object. To use defaults, pass in nothing.\nFor more info on options, see https://webpack.js.org/plugins/" + ); + } + this.options = options || {}; + } + + apply(compiler) { + const options = this.options; + const minSizeReduce = options.minSizeReduce || 1.5; + + compiler.hooks.thisCompilation.tap( + "AggressiveMergingPlugin", + compilation => { + compilation.hooks.optimizeChunksAdvanced.tap( + "AggressiveMergingPlugin", + chunks => { + let combinations = []; + chunks.forEach((a, idx) => { + if (a.canBeInitial()) return; + for (let i = 0; i < idx; i++) { + const b = chunks[i]; + if (b.canBeInitial()) continue; + combinations.push({ + a, + b, + improvement: undefined + }); + } + }); + + for (const pair of combinations) { + const a = pair.b.size({ + chunkOverhead: 0 + }); + const b = pair.a.size({ + chunkOverhead: 0 + }); + const ab = pair.b.integratedSize(pair.a, { + chunkOverhead: 0 + }); + let newSize; + if (ab === false) { + pair.improvement = false; + return; + } else { + newSize = ab; + } + + pair.improvement = (a + b) / newSize; + } + combinations = combinations.filter(pair => { + return pair.improvement !== false; + }); + combinations.sort((a, b) => { + return b.improvement - a.improvement; + }); + + const pair = combinations[0]; + + if (!pair) return; + if (pair.improvement < minSizeReduce) return; + + if (pair.b.integrate(pair.a, "aggressive-merge")) { + chunks.splice(chunks.indexOf(pair.a), 1); + return true; + } + } + ); + } + ); + } +} + +module.exports = AggressiveMergingPlugin; diff --git a/node_modules/webpack/lib/optimize/AggressiveSplittingPlugin.js b/node_modules/webpack/lib/optimize/AggressiveSplittingPlugin.js index b6f566a1c..9aec3644b 100644 --- a/node_modules/webpack/lib/optimize/AggressiveSplittingPlugin.js +++ b/node_modules/webpack/lib/optimize/AggressiveSplittingPlugin.js @@ -1,195 +1,287 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const identifierUtils = require("../util/identifier"); - -function moveModuleBetween(oldChunk, newChunk) { - return function(module) { - oldChunk.moveModule(module, newChunk); - }; -} - -function isNotAEntryModule(entryModule) { - return function(module) { - return entryModule !== module; - }; -} - -function copyWithReason(obj) { - const newObj = {}; - Object.keys(obj).forEach((key) => { - newObj[key] = obj[key]; - }); - if(!newObj.reasons || newObj.reasons.indexOf("aggressive-splitted") < 0) - newObj.reasons = (newObj.reasons || []).concat("aggressive-splitted"); - return newObj; -} - -class AggressiveSplittingPlugin { - constructor(options) { - this.options = options || {}; - if(typeof this.options.minSize !== "number") this.options.minSize = 30 * 1024; - if(typeof this.options.maxSize !== "number") this.options.maxSize = 50 * 1024; - if(typeof this.options.chunkOverhead !== "number") this.options.chunkOverhead = 0; - if(typeof this.options.entryChunkMultiplicator !== "number") this.options.entryChunkMultiplicator = 1; - } - apply(compiler) { - compiler.plugin("this-compilation", (compilation) => { - compilation.plugin("optimize-chunks-advanced", (chunks) => { - // Precompute stuff - const nameToModuleMap = new Map(); - compilation.modules.forEach(m => { - const name = identifierUtils.makePathsRelative(compiler.context, m.identifier(), compilation.cache); - nameToModuleMap.set(name, m); - }); - - const savedSplits = compilation.records && compilation.records.aggressiveSplits || []; - const usedSplits = compilation._aggressiveSplittingSplits ? - savedSplits.concat(compilation._aggressiveSplittingSplits) : savedSplits; - - const minSize = this.options.minSize; - const maxSize = this.options.maxSize; - // 1. try to restore to recorded splitting - for(let j = 0; j < usedSplits.length; j++) { - const splitData = usedSplits[j]; - const selectedModules = splitData.modules.map(name => nameToModuleMap.get(name)); - - // Does the modules exist at all? - if(selectedModules.every(Boolean)) { - - // Find all chunks containing all modules in the split - for(let i = 0; i < chunks.length; i++) { - const chunk = chunks[i]; - - // Cheap check if chunk is suitable at all - if(chunk.getNumberOfModules() < splitData.modules.length) - continue; - - // Check if all modules are in the chunk - if(selectedModules.every(m => chunk.containsModule(m))) { - - // Is chunk identical to the split or do we need to split it? - if(chunk.getNumberOfModules() > splitData.modules.length) { - // split the chunk into two parts - const newChunk = compilation.addChunk(); - selectedModules.forEach(moveModuleBetween(chunk, newChunk)); - chunk.split(newChunk); - chunk.name = null; - newChunk._fromAggressiveSplitting = true; - if(j < savedSplits.length) - newChunk._fromAggressiveSplittingIndex = j; - if(splitData.id !== null && splitData.id !== undefined) { - newChunk.id = splitData.id; - } - newChunk.origins = chunk.origins.map(copyWithReason); - chunk.origins = chunk.origins.map(copyWithReason); - return true; - } else { // chunk is identical to the split - if(j < savedSplits.length) - chunk._fromAggressiveSplittingIndex = j; - chunk.name = null; - if(splitData.id !== null && splitData.id !== undefined) { - chunk.id = splitData.id; - } - } - } - } - } - } - - // 2. for any other chunk which isn't splitted yet, split it - for(let i = 0; i < chunks.length; i++) { - const chunk = chunks[i]; - const size = chunk.size(this.options); - if(size > maxSize && chunk.getNumberOfModules() > 1) { - const newChunk = compilation.addChunk(); - const modules = chunk.getModules() - .filter(isNotAEntryModule(chunk.entryModule)) - .sort((a, b) => { - a = a.identifier(); - b = b.identifier(); - if(a > b) return 1; - if(a < b) return -1; - return 0; - }); - for(let k = 0; k < modules.length; k++) { - chunk.moveModule(modules[k], newChunk); - const newSize = newChunk.size(this.options); - const chunkSize = chunk.size(this.options); - // break early if it's fine - if(chunkSize < maxSize && newSize < maxSize && newSize >= minSize && chunkSize >= minSize) - break; - if(newSize > maxSize && k === 0) { - // break if there is a single module which is bigger than maxSize - break; - } - if(newSize > maxSize || chunkSize < minSize) { - // move it back - newChunk.moveModule(modules[k], chunk); - // check if it's fine now - if(newSize < maxSize && newSize >= minSize && chunkSize >= minSize) - break; - } - } - if(newChunk.getNumberOfModules() > 0) { - chunk.split(newChunk); - chunk.name = null; - newChunk.origins = chunk.origins.map(copyWithReason); - chunk.origins = chunk.origins.map(copyWithReason); - compilation._aggressiveSplittingSplits = (compilation._aggressiveSplittingSplits || []).concat({ - modules: newChunk.mapModules(m => identifierUtils.makePathsRelative(compiler.context, m.identifier(), compilation.cache)) - }); - return true; - } else { - chunks.splice(chunks.indexOf(newChunk), 1); - } - } - } - }); - compilation.plugin("record-hash", (records) => { - // 3. save to made splittings to records - const minSize = this.options.minSize; - if(!records.aggressiveSplits) records.aggressiveSplits = []; - compilation.chunks.forEach((chunk) => { - if(chunk.hasEntryModule()) return; - const size = chunk.size(this.options); - const incorrectSize = size < minSize; - const modules = chunk.mapModules(m => identifierUtils.makePathsRelative(compiler.context, m.identifier(), compilation.cache)); - if(typeof chunk._fromAggressiveSplittingIndex === "undefined") { - if(incorrectSize) return; - chunk.recorded = true; - records.aggressiveSplits.push({ - modules: modules, - hash: chunk.hash, - id: chunk.id - }); - } else { - const splitData = records.aggressiveSplits[chunk._fromAggressiveSplittingIndex]; - if(splitData.hash !== chunk.hash || incorrectSize) { - if(chunk._fromAggressiveSplitting) { - chunk._aggressiveSplittingInvalid = true; - splitData.invalid = true; - } else { - splitData.hash = chunk.hash; - } - } - } - }); - records.aggressiveSplits = records.aggressiveSplits.filter((splitData) => { - return !splitData.invalid; - }); - }); - compilation.plugin("need-additional-seal", (callback) => { - const invalid = compilation.chunks.some((chunk) => { - return chunk._aggressiveSplittingInvalid; - }); - if(invalid) - return true; - }); - }); - } -} -module.exports = AggressiveSplittingPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const identifierUtils = require("../util/identifier"); +const { intersect } = require("../util/SetHelpers"); +const validateOptions = require("schema-utils"); +const schema = require("../../schemas/plugins/optimize/AggressiveSplittingPlugin.json"); + +const moveModuleBetween = (oldChunk, newChunk) => { + return module => { + oldChunk.moveModule(module, newChunk); + }; +}; + +const isNotAEntryModule = entryModule => { + return module => { + return entryModule !== module; + }; +}; + +class AggressiveSplittingPlugin { + constructor(options) { + validateOptions(schema, options || {}, "Aggressive Splitting Plugin"); + + this.options = options || {}; + if (typeof this.options.minSize !== "number") { + this.options.minSize = 30 * 1024; + } + if (typeof this.options.maxSize !== "number") { + this.options.maxSize = 50 * 1024; + } + if (typeof this.options.chunkOverhead !== "number") { + this.options.chunkOverhead = 0; + } + if (typeof this.options.entryChunkMultiplicator !== "number") { + this.options.entryChunkMultiplicator = 1; + } + } + apply(compiler) { + compiler.hooks.thisCompilation.tap( + "AggressiveSplittingPlugin", + compilation => { + let needAdditionalSeal = false; + let newSplits; + let fromAggressiveSplittingSet; + let chunkSplitDataMap; + compilation.hooks.optimize.tap("AggressiveSplittingPlugin", () => { + newSplits = []; + fromAggressiveSplittingSet = new Set(); + chunkSplitDataMap = new Map(); + }); + compilation.hooks.optimizeChunksAdvanced.tap( + "AggressiveSplittingPlugin", + chunks => { + // Precompute stuff + const nameToModuleMap = new Map(); + const moduleToNameMap = new Map(); + for (const m of compilation.modules) { + const name = identifierUtils.makePathsRelative( + compiler.context, + m.identifier(), + compilation.cache + ); + nameToModuleMap.set(name, m); + moduleToNameMap.set(m, name); + } + + // Check used chunk ids + const usedIds = new Set(); + for (const chunk of chunks) { + usedIds.add(chunk.id); + } + + const recordedSplits = + (compilation.records && compilation.records.aggressiveSplits) || + []; + const usedSplits = newSplits + ? recordedSplits.concat(newSplits) + : recordedSplits; + + const minSize = this.options.minSize; + const maxSize = this.options.maxSize; + + const applySplit = splitData => { + // Cannot split if id is already taken + if (splitData.id !== undefined && usedIds.has(splitData.id)) { + return false; + } + + // Get module objects from names + const selectedModules = splitData.modules.map(name => + nameToModuleMap.get(name) + ); + + // Does the modules exist at all? + if (!selectedModules.every(Boolean)) return false; + + // Check if size matches (faster than waiting for hash) + const size = selectedModules.reduce( + (sum, m) => sum + m.size(), + 0 + ); + if (size !== splitData.size) return false; + + // get chunks with all modules + const selectedChunks = intersect( + selectedModules.map(m => new Set(m.chunksIterable)) + ); + + // No relevant chunks found + if (selectedChunks.size === 0) return false; + + // The found chunk is already the split or similar + if ( + selectedChunks.size === 1 && + Array.from(selectedChunks)[0].getNumberOfModules() === + selectedModules.length + ) { + const chunk = Array.from(selectedChunks)[0]; + if (fromAggressiveSplittingSet.has(chunk)) return false; + fromAggressiveSplittingSet.add(chunk); + chunkSplitDataMap.set(chunk, splitData); + return true; + } + + // split the chunk into two parts + const newChunk = compilation.addChunk(); + newChunk.chunkReason = "aggressive splitted"; + for (const chunk of selectedChunks) { + selectedModules.forEach(moveModuleBetween(chunk, newChunk)); + chunk.split(newChunk); + chunk.name = null; + } + fromAggressiveSplittingSet.add(newChunk); + chunkSplitDataMap.set(newChunk, splitData); + + if (splitData.id !== null && splitData.id !== undefined) { + newChunk.id = splitData.id; + } + return true; + }; + + // try to restore to recorded splitting + let changed = false; + for (let j = 0; j < usedSplits.length; j++) { + const splitData = usedSplits[j]; + if (applySplit(splitData)) changed = true; + } + + // for any chunk which isn't splitted yet, split it and create a new entry + // start with the biggest chunk + const sortedChunks = chunks.slice().sort((a, b) => { + const diff1 = b.modulesSize() - a.modulesSize(); + if (diff1) return diff1; + const diff2 = a.getNumberOfModules() - b.getNumberOfModules(); + if (diff2) return diff2; + const modulesA = Array.from(a.modulesIterable); + const modulesB = Array.from(b.modulesIterable); + modulesA.sort(); + modulesB.sort(); + const aI = modulesA[Symbol.iterator](); + const bI = modulesB[Symbol.iterator](); + // eslint-disable-next-line no-constant-condition + while (true) { + const aItem = aI.next(); + const bItem = bI.next(); + if (aItem.done) return 0; + const aModuleIdentifier = aItem.value.identifier(); + const bModuleIdentifier = bItem.value.identifier(); + if (aModuleIdentifier > bModuleIdentifier) return -1; + if (aModuleIdentifier < bModuleIdentifier) return 1; + } + }); + for (const chunk of sortedChunks) { + if (fromAggressiveSplittingSet.has(chunk)) continue; + const size = chunk.modulesSize(); + if (size > maxSize && chunk.getNumberOfModules() > 1) { + const modules = chunk + .getModules() + .filter(isNotAEntryModule(chunk.entryModule)) + .sort((a, b) => { + a = a.identifier(); + b = b.identifier(); + if (a > b) return 1; + if (a < b) return -1; + return 0; + }); + const selectedModules = []; + let selectedModulesSize = 0; + for (let k = 0; k < modules.length; k++) { + const module = modules[k]; + const newSize = selectedModulesSize + module.size(); + if (newSize > maxSize && selectedModulesSize >= minSize) { + break; + } + selectedModulesSize = newSize; + selectedModules.push(module); + } + if (selectedModules.length === 0) continue; + const splitData = { + modules: selectedModules + .map(m => moduleToNameMap.get(m)) + .sort(), + size: selectedModulesSize + }; + + if (applySplit(splitData)) { + newSplits = (newSplits || []).concat(splitData); + changed = true; + } + } + } + if (changed) return true; + } + ); + compilation.hooks.recordHash.tap( + "AggressiveSplittingPlugin", + records => { + // 4. save made splittings to records + const allSplits = new Set(); + const invalidSplits = new Set(); + + // Check if some splittings are invalid + // We remove invalid splittings and try again + for (const chunk of compilation.chunks) { + const splitData = chunkSplitDataMap.get(chunk); + if (splitData !== undefined) { + if (splitData.hash && chunk.hash !== splitData.hash) { + // Split was successful, but hash doesn't equal + // We can throw away the split since it's useless now + invalidSplits.add(splitData); + } + } + } + + if (invalidSplits.size > 0) { + records.aggressiveSplits = records.aggressiveSplits.filter( + splitData => !invalidSplits.has(splitData) + ); + needAdditionalSeal = true; + } else { + // set hash and id values on all (new) splittings + for (const chunk of compilation.chunks) { + const splitData = chunkSplitDataMap.get(chunk); + if (splitData !== undefined) { + splitData.hash = chunk.hash; + splitData.id = chunk.id; + allSplits.add(splitData); + // set flag for stats + chunk.recorded = true; + } + } + + // Also add all unused historial splits (after the used ones) + // They can still be used in some future compilation + const recordedSplits = + compilation.records && compilation.records.aggressiveSplits; + if (recordedSplits) { + for (const splitData of recordedSplits) { + if (!invalidSplits.has(splitData)) allSplits.add(splitData); + } + } + + // record all splits + records.aggressiveSplits = Array.from(allSplits); + + needAdditionalSeal = false; + } + } + ); + compilation.hooks.needAdditionalSeal.tap( + "AggressiveSplittingPlugin", + () => { + if (needAdditionalSeal) { + needAdditionalSeal = false; + return true; + } + } + ); + } + ); + } +} +module.exports = AggressiveSplittingPlugin; diff --git a/node_modules/webpack/lib/optimize/ChunkModuleIdRangePlugin.js b/node_modules/webpack/lib/optimize/ChunkModuleIdRangePlugin.js index 262014dc5..f507e426c 100644 --- a/node_modules/webpack/lib/optimize/ChunkModuleIdRangePlugin.js +++ b/node_modules/webpack/lib/optimize/ChunkModuleIdRangePlugin.js @@ -1,53 +1,68 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -class ChunkModuleIdRangePlugin { - constructor(options) { - this.options = options; - } - apply(compiler) { - const options = this.options; - compiler.plugin("compilation", (compilation) => { - compilation.plugin("module-ids", (modules) => { - const chunk = this.chunks.find((chunk) => chunk.name === options.name); - if(!chunk) throw new Error("ChunkModuleIdRangePlugin: Chunk with name '" + options.name + "' was not found"); - let currentId = options.start; - let chunkModules; - if(options.order) { - chunkModules = chunk.modules.slice(); - switch(options.order) { - case "index": - chunkModules.sort((a, b) => { - return a.index - b.index; - }); - break; - case "index2": - chunkModules.sort((a, b) => { - return a.index2 - b.index2; - }); - break; - default: - throw new Error("ChunkModuleIdRangePlugin: unexpected value of order"); - } - - } else { - chunkModules = modules.filter((m) => { - return m.chunks.indexOf(chunk) >= 0; - }); - } - - for(let i = 0; i < chunkModules.length; i++) { - const m = chunkModules[i]; - if(m.id === null) { - m.id = currentId++; - } - if(options.end && currentId > options.end) - break; - } - }); - }); - } -} -module.exports = ChunkModuleIdRangePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const sortByIndex = (a, b) => { + return a.index - b.index; +}; + +const sortByIndex2 = (a, b) => { + return a.index2 - b.index2; +}; + +class ChunkModuleIdRangePlugin { + constructor(options) { + this.options = options; + } + + apply(compiler) { + const options = this.options; + compiler.hooks.compilation.tap("ChunkModuleIdRangePlugin", compilation => { + compilation.hooks.moduleIds.tap("ChunkModuleIdRangePlugin", modules => { + const chunk = compilation.chunks.find( + chunk => chunk.name === options.name + ); + if (!chunk) { + throw new Error( + `ChunkModuleIdRangePlugin: Chunk with name '${ + options.name + }"' was not found` + ); + } + + let chunkModules; + if (options.order) { + chunkModules = Array.from(chunk.modulesIterable); + switch (options.order) { + case "index": + chunkModules.sort(sortByIndex); + break; + case "index2": + chunkModules.sort(sortByIndex2); + break; + default: + throw new Error( + "ChunkModuleIdRangePlugin: unexpected value of order" + ); + } + } else { + chunkModules = modules.filter(m => { + return m.chunksIterable.has(chunk); + }); + } + + let currentId = options.start || 0; + for (let i = 0; i < chunkModules.length; i++) { + const m = chunkModules[i]; + if (m.id === null) { + m.id = currentId++; + } + if (options.end && currentId > options.end) break; + } + }); + }); + } +} +module.exports = ChunkModuleIdRangePlugin; diff --git a/node_modules/webpack/lib/optimize/CommonsChunkPlugin.js b/node_modules/webpack/lib/optimize/CommonsChunkPlugin.js deleted file mode 100644 index c0e438a40..000000000 --- a/node_modules/webpack/lib/optimize/CommonsChunkPlugin.js +++ /dev/null @@ -1,404 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -let nextIdent = 0; - -class CommonsChunkPlugin { - constructor(options) { - if(arguments.length > 1) { - throw new Error(`Deprecation notice: CommonsChunkPlugin now only takes a single argument. Either an options -object *or* the name of the chunk. -Example: if your old code looked like this: - new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.bundle.js') -You would change it to: - new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', filename: 'vendor.bundle.js' }) -The available options are: - name: string - names: string[] - filename: string - minChunks: number - chunks: string[] - children: boolean - async: boolean - minSize: number`); - } - - const normalizedOptions = this.normalizeOptions(options); - - this.chunkNames = normalizedOptions.chunkNames; - this.filenameTemplate = normalizedOptions.filenameTemplate; - this.minChunks = normalizedOptions.minChunks; - this.selectedChunks = normalizedOptions.selectedChunks; - this.children = normalizedOptions.children; - this.deepChildren = normalizedOptions.deepChildren; - this.async = normalizedOptions.async; - this.minSize = normalizedOptions.minSize; - this.ident = __filename + (nextIdent++); - } - - normalizeOptions(options) { - if(Array.isArray(options)) { - return { - chunkNames: options, - }; - } - - if(typeof options === "string") { - return { - chunkNames: [options], - }; - } - - // options.children and options.chunk may not be used together - if(options.children && options.chunks) { - throw new Error("You can't and it does not make any sense to use \"children\" and \"chunk\" options together."); - } - - /** - * options.async and options.filename are also not possible together - * as filename specifies how the chunk is called but "async" implies - * that webpack will take care of loading this file. - */ - if(options.async && options.filename) { - throw new Error(`You can not specify a filename if you use the "async" option. -You can however specify the name of the async chunk by passing the desired string as the "async" option.`); - } - - /** - * Make sure this is either an array or undefined. - * "name" can be a string and - * "names" a string or an array - */ - const chunkNames = options.name || options.names ? [].concat(options.name || options.names) : undefined; - return { - chunkNames: chunkNames, - filenameTemplate: options.filename, - minChunks: options.minChunks, - selectedChunks: options.chunks, - children: options.children, - deepChildren: options.deepChildren, - async: options.async, - minSize: options.minSize - }; - } - - apply(compiler) { - compiler.plugin("this-compilation", (compilation) => { - compilation.plugin(["optimize-chunks", "optimize-extracted-chunks"], (chunks) => { - // only optimize once - if(compilation[this.ident]) return; - compilation[this.ident] = true; - - /** - * Creates a list of "common"" chunks based on the options. - * The list is made up of preexisting or newly created chunks. - * - If chunk has the name as specified in the chunkNames it is put in the list - * - If no chunk with the name as given in chunkNames exists a new chunk is created and added to the list - * - * These chunks are the "targets" for extracted modules. - */ - const targetChunks = this.getTargetChunks(chunks, compilation, this.chunkNames, this.children, this.async); - - // iterate over all our new chunks - targetChunks.forEach((targetChunk, idx) => { - - /** - * These chunks are subject to get "common" modules extracted and moved to the common chunk - */ - const affectedChunks = this.getAffectedChunks(compilation, chunks, targetChunk, targetChunks, idx, this.selectedChunks, this.async, this.children, this.deepChildren); - - // bail if no chunk is affected - if(!affectedChunks) { - return; - } - - // If we are async create an async chunk now - // override the "commonChunk" with the newly created async one and use it as commonChunk from now on - let asyncChunk; - if(this.async) { - // If async chunk is one of the affected chunks, just use it - asyncChunk = affectedChunks.filter(c => c.name === this.async)[0]; - // Elsewise create a new one - if(!asyncChunk) { - asyncChunk = this.createAsyncChunk( - compilation, - targetChunks.length <= 1 || typeof this.async !== "string" ? this.async : - targetChunk.name ? `${this.async}-${targetChunk.name}` : - true, - targetChunk - ); - } - targetChunk = asyncChunk; - } - - /** - * Check which modules are "common" and could be extracted to a "common" chunk - */ - const extractableModules = this.getExtractableModules(this.minChunks, affectedChunks, targetChunk); - - // If the minSize option is set check if the size extracted from the chunk is reached - // else bail out here. - // As all modules/commons are interlinked with each other, common modules would be extracted - // if we reach this mark at a later common chunk. (quirky I guess). - if(this.minSize) { - const modulesSize = this.calculateModulesSize(extractableModules); - // if too small, bail - if(modulesSize < this.minSize) - return; - } - - // Remove modules that are moved to commons chunk from their original chunks - // return all chunks that are affected by having modules removed - we need them later (apparently) - const chunksWithExtractedModules = this.extractModulesAndReturnAffectedChunks(extractableModules, affectedChunks); - - // connect all extracted modules with the common chunk - this.addExtractedModulesToTargetChunk(targetChunk, extractableModules); - - // set filenameTemplate for chunk - if(this.filenameTemplate) - targetChunk.filenameTemplate = this.filenameTemplate; - - // if we are async connect the blocks of the "reallyUsedChunk" - the ones that had modules removed - - // with the commonChunk and get the origins for the asyncChunk (remember "asyncChunk === commonChunk" at this moment). - // bail out - if(this.async) { - this.moveExtractedChunkBlocksToTargetChunk(chunksWithExtractedModules, targetChunk); - asyncChunk.origins = this.extractOriginsOfChunksWithExtractedModules(chunksWithExtractedModules); - return; - } - - // we are not in "async" mode - // connect used chunks with commonChunk - shouldnt this be reallyUsedChunks here? - this.makeTargetChunkParentOfAffectedChunks(affectedChunks, targetChunk); - }); - return true; - }); - }); - } - - getTargetChunks(allChunks, compilation, chunkNames, children, asyncOption) { - const asyncOrNoSelectedChunk = children || asyncOption; - - // we have specified chunk names - if(chunkNames) { - // map chunks by chunkName for quick access - const allChunksNameMap = allChunks.reduce((map, chunk) => { - if(chunk.name) { - map.set(chunk.name, chunk); - } - return map; - }, new Map()); - - // Ensure we have a chunk per specified chunk name. - // Reuse existing chunks if possible - return chunkNames.map(chunkName => { - if(allChunksNameMap.has(chunkName)) { - return allChunksNameMap.get(chunkName); - } - // add the filtered chunks to the compilation - return compilation.addChunk(chunkName); - }); - } - - // we dont have named chunks specified, so we just take all of them - if(asyncOrNoSelectedChunk) { - return allChunks; - } - - /** - * No chunk name(s) was specified nor is this an async/children commons chunk - */ - throw new Error(`You did not specify any valid target chunk settings. -Take a look at the "name"/"names" or async/children option.`); - } - - getAffectedUnnamedChunks(affectedChunks, targetChunk, rootChunk, asyncOption, deepChildrenOption) { - let chunks = targetChunk.chunks; - chunks && chunks.forEach((chunk) => { - if(chunk.isInitial()) { - return; - } - // If all the parents of a chunk are either - // a) the target chunk we started with - // b) themselves affected chunks - // we can assume that this chunk is an affected chunk too, as there is no way a chunk that - // isn't only depending on the target chunk is a parent of the chunk tested - if(asyncOption || chunk.parents.every((parentChunk) => parentChunk === rootChunk || affectedChunks.has(parentChunk))) { - // This check not only dedupes the affectedChunks but also guarantees we avoid endless loops - if(!affectedChunks.has(chunk)) { - // We mutate the affected chunks before going deeper, so the deeper levels and other branches - // have the information of this chunk being affected for their assertion if a chunk should - // not be affected - affectedChunks.add(chunk); - - // We recurse down to all the children of the chunk, applying the same assumption. - // This guarantees that if a chunk should be an affected chunk, - // at the latest the last connection to the same chunk meets the - // condition to add it to the affected chunks. - if(deepChildrenOption === true) { - this.getAffectedUnnamedChunks(affectedChunks, chunk, rootChunk, asyncOption, deepChildrenOption); - } - } - } - }); - } - - getAffectedChunks(compilation, allChunks, targetChunk, targetChunks, currentIndex, selectedChunks, asyncOption, childrenOption, deepChildrenOption) { - const asyncOrNoSelectedChunk = childrenOption || asyncOption; - - if(Array.isArray(selectedChunks)) { - return allChunks.filter(chunk => { - const notCommmonChunk = chunk !== targetChunk; - const isSelectedChunk = selectedChunks.indexOf(chunk.name) > -1; - return notCommmonChunk && isSelectedChunk; - }); - } - - if(asyncOrNoSelectedChunk) { - let affectedChunks = new Set(); - this.getAffectedUnnamedChunks(affectedChunks, targetChunk, targetChunk, asyncOption, deepChildrenOption); - return Array.from(affectedChunks); - } - - /** - * past this point only entry chunks are allowed to become commonChunks - */ - if(targetChunk.parents.length > 0) { - compilation.errors.push(new Error("CommonsChunkPlugin: While running in normal mode it's not allowed to use a non-entry chunk (" + targetChunk.name + ")")); - return; - } - - /** - * If we find a "targetchunk" that is also a normal chunk (meaning it is probably specified as an entry) - * and the current target chunk comes after that and the found chunk has a runtime* - * make that chunk be an 'affected' chunk of the current target chunk. - * - * To understand what that means take a look at the "examples/chunkhash", this basically will - * result in the runtime to be extracted to the current target chunk. - * - * *runtime: the "runtime" is the "webpack"-block you may have seen in the bundles that resolves modules etc. - */ - return allChunks.filter((chunk) => { - const found = targetChunks.indexOf(chunk); - if(found >= currentIndex) return false; - return chunk.hasRuntime(); - }); - } - - createAsyncChunk(compilation, asyncOption, targetChunk) { - const asyncChunk = compilation.addChunk(typeof asyncOption === "string" ? asyncOption : undefined); - asyncChunk.chunkReason = "async commons chunk"; - asyncChunk.extraAsync = true; - asyncChunk.addParent(targetChunk); - targetChunk.addChunk(asyncChunk); - return asyncChunk; - } - - // If minChunks is a function use that - // otherwhise check if a module is used at least minChunks or 2 or usedChunks.length time - getModuleFilter(minChunks, targetChunk, usedChunksLength) { - if(typeof minChunks === "function") { - return minChunks; - } - const minCount = (minChunks || Math.max(2, usedChunksLength)); - const isUsedAtLeastMinTimes = (module, count) => count >= minCount; - return isUsedAtLeastMinTimes; - } - - getExtractableModules(minChunks, usedChunks, targetChunk) { - if(minChunks === Infinity) { - return []; - } - - // count how many chunks contain a module - const commonModulesToCountMap = usedChunks.reduce((map, chunk) => { - for(const module of chunk.modulesIterable) { - const count = map.has(module) ? map.get(module) : 0; - map.set(module, count + 1); - } - return map; - }, new Map()); - - // filter by minChunks - const moduleFilterCount = this.getModuleFilter(minChunks, targetChunk, usedChunks.length); - // filter by condition - const moduleFilterCondition = (module, chunk) => { - if(!module.chunkCondition) { - return true; - } - return module.chunkCondition(chunk); - }; - - return Array.from(commonModulesToCountMap).filter(entry => { - const module = entry[0]; - const count = entry[1]; - // if the module passes both filters, keep it. - return moduleFilterCount(module, count) && moduleFilterCondition(module, targetChunk); - }).map(entry => entry[0]); - } - - calculateModulesSize(modules) { - return modules.reduce((totalSize, module) => totalSize + module.size(), 0); - } - - extractModulesAndReturnAffectedChunks(reallyUsedModules, usedChunks) { - return reallyUsedModules.reduce((affectedChunksSet, module) => { - for(const chunk of usedChunks) { - // removeChunk returns true if the chunk was contained and succesfully removed - // false if the module did not have a connection to the chunk in question - if(module.removeChunk(chunk)) { - affectedChunksSet.add(chunk); - } - } - return affectedChunksSet; - }, new Set()); - } - - addExtractedModulesToTargetChunk(chunk, modules) { - for(const module of modules) { - chunk.addModule(module); - module.addChunk(chunk); - } - } - - makeTargetChunkParentOfAffectedChunks(usedChunks, commonChunk) { - for(const chunk of usedChunks) { - // set commonChunk as new sole parent - chunk.parents = [commonChunk]; - // add chunk to commonChunk - commonChunk.addChunk(chunk); - - for(const entrypoint of chunk.entrypoints) { - entrypoint.insertChunk(commonChunk, chunk); - } - } - } - - moveExtractedChunkBlocksToTargetChunk(chunks, targetChunk) { - for(const chunk of chunks) { - if(chunk === targetChunk) continue; - for(const block of chunk.blocks) { - if(block.chunks.indexOf(targetChunk) === -1) { - block.chunks.unshift(targetChunk); - } - targetChunk.addBlock(block); - } - } - } - - extractOriginsOfChunksWithExtractedModules(chunks) { - const origins = []; - for(const chunk of chunks) { - for(const origin of chunk.origins) { - const newOrigin = Object.create(origin); - newOrigin.reasons = (origin.reasons || []).concat("async commons"); - origins.push(newOrigin); - } - } - return origins; - } -} - -module.exports = CommonsChunkPlugin; diff --git a/node_modules/webpack/lib/optimize/ConcatenatedModule.js b/node_modules/webpack/lib/optimize/ConcatenatedModule.js index bfb772496..52d33e6f3 100644 --- a/node_modules/webpack/lib/optimize/ConcatenatedModule.js +++ b/node_modules/webpack/lib/optimize/ConcatenatedModule.js @@ -1,827 +1,1495 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const Module = require("../Module"); -const Template = require("../Template"); -const Parser = require("../Parser"); -const crypto = require("crypto"); -const acorn = require("acorn"); -const escope = require("escope"); -const ReplaceSource = require("webpack-sources/lib/ReplaceSource"); -const ConcatSource = require("webpack-sources/lib/ConcatSource"); -const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency"); -const HarmonyImportSpecifierDependency = require("../dependencies/HarmonyImportSpecifierDependency"); -const HarmonyExportSpecifierDependency = require("../dependencies/HarmonyExportSpecifierDependency"); -const HarmonyExportExpressionDependency = require("../dependencies/HarmonyExportExpressionDependency"); -const HarmonyExportImportedSpecifierDependency = require("../dependencies/HarmonyExportImportedSpecifierDependency"); -const HarmonyCompatibilityDependency = require("../dependencies/HarmonyCompatibilityDependency"); - -function ensureNsObjSource(info, moduleToInfoMap, requestShortener) { - if(!info.hasNamespaceObject) { - info.hasNamespaceObject = true; - const name = info.exportMap.get(true); - const nsObj = [`var ${name} = {};`]; - for(const exportName of info.module.providedExports) { - const finalName = getFinalName(info, exportName, moduleToInfoMap, requestShortener, false); - nsObj.push(`__webpack_require__.d(${name}, ${JSON.stringify(exportName)}, function() { return ${finalName}; });`); - } - info.namespaceObjectSource = nsObj.join("\n") + "\n"; - } -} - -function getExternalImport(importedModule, info, exportName, asCall) { - if(exportName === true) return info.name; - const used = importedModule.isUsed(exportName); - if(!used) return "/* unused reexport */undefined"; - if(info.interop && exportName === "default") { - return asCall ? `${info.interopName}()` : `${info.interopName}.a`; - } - // TODO use Template.toNormalComment when merging with pure-module - const comment = used !== exportName ? ` /* ${exportName} */` : ""; - const reference = `${info.name}[${JSON.stringify(used)}${comment}]`; - if(asCall) - return `Object(${reference})`; - return reference; -} - -function getFinalName(info, exportName, moduleToInfoMap, requestShortener, asCall) { - switch(info.type) { - case "concatenated": - { - const directExport = info.exportMap.get(exportName); - if(directExport) { - if(exportName === true) - ensureNsObjSource(info, moduleToInfoMap, requestShortener); - const name = info.internalNames.get(directExport); - if(!name) - throw new Error(`The export "${directExport}" in "${info.module.readableIdentifier(requestShortener)}" has no internal name`); - return name; - } - const reexport = info.reexportMap.get(exportName); - if(reexport) { - const refInfo = moduleToInfoMap.get(reexport.module); - if(refInfo) { - // module is in the concatenation - return getFinalName(refInfo, reexport.exportName, moduleToInfoMap, requestShortener, asCall); - } - } - const problem = `Cannot get final name for export "${exportName}" in "${info.module.readableIdentifier(requestShortener)}"` + - ` (known exports: ${Array.from(info.exportMap.keys()).filter(name => name !== true).join(" ")}, ` + - `known reexports: ${Array.from(info.reexportMap.keys()).join(" ")})`; - // TODO use Template.toNormalComment when merging with pure-module - return `/* ${problem} */ undefined`; - } - case "external": - { - const importedModule = info.module; - return getExternalImport(importedModule, info, exportName, asCall); - } - } -} - -function getSymbolsFromScope(s, untilScope) { - const allUsedNames = new Set(); - let scope = s; - while(scope) { - if(untilScope === scope) break; - scope.variables.forEach(variable => allUsedNames.add(variable.name)); - scope = scope.upper; - } - return allUsedNames; -} - -function getAllReferences(variable) { - let set = variable.references; - // Look for inner scope variables too (like in class Foo { t() { Foo } }) - const identifiers = new Set(variable.identifiers); - for(const scope of variable.scope.childScopes) { - for(const innerVar of scope.variables) { - if(innerVar.identifiers.some(id => identifiers.has(id))) { - set = set.concat(innerVar.references); - break; - } - } - } - return set; -} - -function reduceSet(a, b) { - for(const item of b) - a.add(item); - return a; -} - -function getPathInAst(ast, node) { - if(ast === node) { - return []; - } - const nr = node.range; - var i; - if(Array.isArray(ast)) { - for(i = 0; i < ast.length; i++) { - const enterResult = enterNode(ast[i]); - if(typeof enterResult !== "undefined") - return enterResult; - } - } else if(ast && typeof ast === "object") { - const keys = Object.keys(ast); - for(i = 0; i < keys.length; i++) { - const value = ast[keys[i]]; - if(Array.isArray(value)) { - const pathResult = getPathInAst(value, node); - if(typeof pathResult !== "undefined") - return pathResult; - } else if(value && typeof value === "object") { - const enterResult = enterNode(value); - if(typeof enterResult !== "undefined") - return enterResult; - } - } - } - - function enterNode(n) { - const r = n.range; - if(r) { - if(r[0] <= nr[0] && r[1] >= nr[1]) { - const path = getPathInAst(n, node); - if(path) { - path.push(n); - return path; - } - } - } - return undefined; - } -} - -class ConcatenatedModule extends Module { - constructor(rootModule, modules) { - super(); - super.setChunks(rootModule._chunks); - this.rootModule = rootModule; - this.usedExports = rootModule.usedExports; - this.providedExports = rootModule.providedExports; - this.optimizationBailout = rootModule.optimizationBailout; - this.used = rootModule.used; - this.index = rootModule.index; - this.index2 = rootModule.index2; - this.depth = rootModule.depth; - this.built = modules.some(m => m.built); - this.cacheable = modules.every(m => m.cacheable); - const modulesSet = new Set(modules); - this.reasons = rootModule.reasons.filter(reason => !(reason.dependency instanceof HarmonyImportDependency) || !modulesSet.has(reason.module)); - this.meta = rootModule.meta; - this.moduleArgument = rootModule.moduleArgument; - this.exportsArgument = rootModule.exportsArgument; - this.strict = true; - this._numberOfConcatenatedModules = modules.length; - - this.dependencies = []; - this.dependenciesWarnings = []; - this.dependenciesErrors = []; - this.fileDependencies = []; - this.contextDependencies = []; - this.warnings = []; - this.errors = []; - this.assets = {}; - this._orderedConcatenationList = this._createOrderedConcatenationList(rootModule, modulesSet); - for(const info of this._orderedConcatenationList) { - if(info.type === "concatenated") { - const m = info.module; - - // populate dependencies - m.dependencies.filter(dep => !(dep instanceof HarmonyImportDependency) || !modulesSet.has(dep.module)) - .forEach(d => this.dependencies.push(d)); - // populate dep warning - m.dependenciesWarnings.forEach(depWarning => this.dependenciesWarnings.push(depWarning)); - // populate dep errors - m.dependenciesErrors.forEach(depError => this.dependenciesErrors.push(depError)); - // populate file dependencies - if(m.fileDependencies) m.fileDependencies.forEach(file => this.fileDependencies.push(file)); - // populate context dependencies - if(m.contextDependencies) m.contextDependencies.forEach(context => this.contextDependencies.push(context)); - // populate warnings - m.warnings.forEach(warning => this.warnings.push(warning)); - // populate errors - m.errors.forEach(error => this.errors.push(error)); - - Object.assign(this.assets, m.assets); - } - } - this._identifier = this._createIdentifier(); - } - - get modules() { - return this._orderedConcatenationList - .filter(info => info.type === "concatenated") - .map(info => info.module); - } - - identifier() { - return this._identifier; - } - - readableIdentifier(requestShortener) { - return this.rootModule.readableIdentifier(requestShortener) + ` + ${this._numberOfConcatenatedModules - 1} modules`; - } - - libIdent(options) { - return this.rootModule.libIdent(options); - } - - nameForCondition() { - return this.rootModule.nameForCondition(); - } - - build(options, compilation, resolver, fs, callback) { - throw new Error("Cannot build this module. It should be already built."); - } - - size() { - // Guess size from embedded modules - return this._orderedConcatenationList.reduce((sum, info) => { - switch(info.type) { - case "concatenated": - return sum + info.module.size(); - case "external": - return sum + 5; - } - return sum; - }, 0); - } - - _createOrderedConcatenationList(rootModule, modulesSet) { - const list = []; - const set = new Set(); - - function getConcatenatedImports(module) { - // TODO need changes when merging with the pure-module branch - const allDeps = module.dependencies - .filter(dep => dep instanceof HarmonyImportDependency && dep.module); - - return allDeps.map(dep => () => dep.module); - } - - function enterModule(getModule) { - const module = getModule(); - if(set.has(module)) return; - set.add(module); - if(modulesSet.has(module)) { - const imports = getConcatenatedImports(module); - imports.forEach(enterModule); - list.push({ - type: "concatenated", - module - }); - } else { - list.push({ - type: "external", - get module() { - // We need to use a getter here, because the module in the dependency - // could be replaced by some other process (i. e. also replaced with a - // concatenated module) - return getModule(); - } - }); - } - } - - enterModule(() => rootModule); - - return list; - } - - _createIdentifier() { - let orderedConcatenationListIdentifiers = ""; - for(let i = 0; i < this._orderedConcatenationList.length; i++) { - if(this._orderedConcatenationList[i].type === "concatenated") { - orderedConcatenationListIdentifiers += this._orderedConcatenationList[i].module.identifier(); - orderedConcatenationListIdentifiers += " "; - } - } - const hash = crypto.createHash("md5"); - hash.update(orderedConcatenationListIdentifiers); - return this.rootModule.identifier() + " " + hash.digest("hex"); - } - - source(dependencyTemplates, outputOptions, requestShortener) { - // Metainfo for each module - const modulesWithInfo = this._orderedConcatenationList.map((info, idx) => { - switch(info.type) { - case "concatenated": - { - const exportMap = new Map(); - const reexportMap = new Map(); - info.module.dependencies.forEach(dep => { - if(dep instanceof HarmonyExportSpecifierDependency) { - if(!exportMap.has(dep.name)) - exportMap.set(dep.name, dep.id); - } else if(dep instanceof HarmonyExportExpressionDependency) { - if(!exportMap.has("default")) - exportMap.set("default", "__WEBPACK_MODULE_DEFAULT_EXPORT__"); - } else if(dep instanceof HarmonyExportImportedSpecifierDependency) { - const exportName = dep.name; - const importName = dep.id; - const importedModule = dep.importDependency.module; - if(exportName && importName) { - if(!reexportMap.has(exportName)) { - reexportMap.set(exportName, { - module: importedModule, - exportName: importName, - dependency: dep - }); - } - } else if(exportName) { - if(!reexportMap.has(exportName)) { - reexportMap.set(exportName, { - module: importedModule, - exportName: true, - dependency: dep - }); - } - } else if(importedModule) { - importedModule.providedExports.forEach(name => { - if(dep.activeExports.has(name) || name === "default") - return; - if(!reexportMap.has(name)) { - reexportMap.set(name, { - module: importedModule, - exportName: name, - dependency: dep - }); - } - }); - } - } - }); - return { - type: "concatenated", - module: info.module, - index: idx, - ast: undefined, - source: undefined, - globalScope: undefined, - moduleScope: undefined, - internalNames: new Map(), - exportMap: exportMap, - reexportMap: reexportMap, - hasNamespaceObject: false, - namespaceObjectSource: null - }; - } - case "external": - return { - type: "external", - module: info.module, - index: idx, - name: undefined, - interopName: undefined, - interop: undefined - }; - default: - throw new Error(`Unsupported concatenation entry type ${info.type}`); - } - }); - - // Create mapping from module to info - const moduleToInfoMap = new Map(); - modulesWithInfo.forEach(m => moduleToInfoMap.set(m.module, m)); - - // Configure template decorators for dependencies - const innerDependencyTemplates = new Map(dependencyTemplates); - - innerDependencyTemplates.set(HarmonyImportSpecifierDependency, new HarmonyImportSpecifierDependencyConcatenatedTemplate( - dependencyTemplates.get(HarmonyImportSpecifierDependency), - moduleToInfoMap - )); - innerDependencyTemplates.set(HarmonyImportDependency, new HarmonyImportDependencyConcatenatedTemplate( - dependencyTemplates.get(HarmonyImportDependency), - moduleToInfoMap - )); - innerDependencyTemplates.set(HarmonyExportSpecifierDependency, new HarmonyExportSpecifierDependencyConcatenatedTemplate( - dependencyTemplates.get(HarmonyExportSpecifierDependency), - this.rootModule - )); - innerDependencyTemplates.set(HarmonyExportExpressionDependency, new HarmonyExportExpressionDependencyConcatenatedTemplate( - dependencyTemplates.get(HarmonyExportExpressionDependency), - this.rootModule, - moduleToInfoMap - )); - innerDependencyTemplates.set(HarmonyExportImportedSpecifierDependency, new HarmonyExportImportedSpecifierDependencyConcatenatedTemplate( - dependencyTemplates.get(HarmonyExportImportedSpecifierDependency), - this.rootModule, - moduleToInfoMap - )); - innerDependencyTemplates.set(HarmonyCompatibilityDependency, new HarmonyCompatibilityDependencyConcatenatedTemplate( - dependencyTemplates.get(HarmonyCompatibilityDependency), - this.rootModule, - moduleToInfoMap - )); - innerDependencyTemplates.set("hash", innerDependencyTemplates.get("hash") + this.rootModule.identifier()); - - // Generate source code and analyse scopes - // Prepare a ReplaceSource for the final source - modulesWithInfo.forEach(info => { - if(info.type === "concatenated") { - const m = info.module; - const source = m.source(innerDependencyTemplates, outputOptions, requestShortener); - const code = source.source(); - let ast; - try { - ast = acorn.parse(code, { - ranges: true, - locations: true, - ecmaVersion: Parser.ECMA_VERSION, - sourceType: "module" - }); - } catch(err) { - if(err.loc && typeof err.loc === "object" && typeof err.loc.line === "number") { - const lineNumber = err.loc.line; - const lines = code.split("\n"); - err.message += "\n| " + lines.slice(Math.max(0, lineNumber - 3), lineNumber + 2).join("\n| "); - } - throw err; - } - const scopeManager = escope.analyze(ast, { - ecmaVersion: 6, - sourceType: "module", - optimistic: true, - ignoreEval: true, - impliedStrict: true - }); - const globalScope = scopeManager.acquire(ast); - const moduleScope = globalScope.childScopes[0]; - const resultSource = new ReplaceSource(source); - info.ast = ast; - info.source = resultSource; - info.globalScope = globalScope; - info.moduleScope = moduleScope; - } - }); - - // List of all used names to avoid conflicts - const allUsedNames = new Set([ - "__WEBPACK_MODULE_DEFAULT_EXPORT__", // avoid using this internal name - - "abstract", "arguments", "async", "await", "boolean", "break", "byte", "case", "catch", "char", "class", - "const", "continue", "debugger", "default", "delete", "do", "double", "else", "enum", "eval", - "export", "extends", "false", "final", "finally", "float", "for", "function", "goto", "if", - "implements", "import", "in", "instanceof", "int", "interface", "let", "long", "native", "new", - "null", "package", "private", "protected", "public", "return", "short", "static", "super", - "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "typeof", - "var", "void", "volatile", "while", "with", "yield", - - "module", "__dirname", "__filename", "exports", - - "Array", "Date", "eval", "function", "hasOwnProperty", "Infinity", "isFinite", "isNaN", - "isPrototypeOf", "length", "Math", "NaN", "name", "Number", "Object", "prototype", "String", - "toString", "undefined", "valueOf", - - "alert", "all", "anchor", "anchors", "area", "assign", "blur", "button", "checkbox", - "clearInterval", "clearTimeout", "clientInformation", "close", "closed", "confirm", "constructor", - "crypto", "decodeURI", "decodeURIComponent", "defaultStatus", "document", "element", "elements", - "embed", "embeds", "encodeURI", "encodeURIComponent", "escape", "event", "fileUpload", "focus", - "form", "forms", "frame", "innerHeight", "innerWidth", "layer", "layers", "link", "location", - "mimeTypes", "navigate", "navigator", "frames", "frameRate", "hidden", "history", "image", - "images", "offscreenBuffering", "open", "opener", "option", "outerHeight", "outerWidth", - "packages", "pageXOffset", "pageYOffset", "parent", "parseFloat", "parseInt", "password", "pkcs11", - "plugin", "prompt", "propertyIsEnum", "radio", "reset", "screenX", "screenY", "scroll", "secure", - "select", "self", "setInterval", "setTimeout", "status", "submit", "taint", "text", "textarea", - "top", "unescape", "untaint", "window", - - "onblur", "onclick", "onerror", "onfocus", "onkeydown", "onkeypress", "onkeyup", "onmouseover", - "onload", "onmouseup", "onmousedown", "onsubmit" - ]); - - // get all global names - modulesWithInfo.forEach(info => { - if(info.globalScope) { - info.globalScope.through.forEach(reference => { - const name = reference.identifier.name; - if(/^__WEBPACK_MODULE_REFERENCE__\d+_([\da-f]+|ns)(_call)?__$/.test(name)) { - for(const s of getSymbolsFromScope(reference.from, info.moduleScope)) { - allUsedNames.add(s); - } - } else { - allUsedNames.add(name); - } - }); - } - }); - - // generate names for symbols - modulesWithInfo.forEach(info => { - switch(info.type) { - case "concatenated": - { - const namespaceObjectName = this.findNewName("namespaceObject", allUsedNames, null, info.module.readableIdentifier(requestShortener)); - allUsedNames.add(namespaceObjectName); - info.internalNames.set(namespaceObjectName, namespaceObjectName); - info.exportMap.set(true, namespaceObjectName); - info.moduleScope.variables.forEach(variable => { - const name = variable.name; - if(allUsedNames.has(name)) { - const references = getAllReferences(variable); - const symbolsInReferences = references.map(ref => getSymbolsFromScope(ref.from, info.moduleScope)).reduce(reduceSet, new Set()); - const newName = this.findNewName(name, allUsedNames, symbolsInReferences, info.module.readableIdentifier(requestShortener)); - allUsedNames.add(newName); - info.internalNames.set(name, newName); - const source = info.source; - const allIdentifiers = new Set(references.map(r => r.identifier).concat(variable.identifiers)); - for(const identifier of allIdentifiers) { - const r = identifier.range; - const path = getPathInAst(info.ast, identifier); - if(path && path.length > 1 && path[1].type === "Property" && path[1].shorthand) { - source.insert(r[1], `: ${newName}`); - } else { - source.replace(r[0], r[1] - 1, newName); - } - } - } else { - allUsedNames.add(name); - info.internalNames.set(name, name); - } - }); - break; - } - case "external": - { - info.interop = info.module.meta && !info.module.meta.harmonyModule; - const externalName = this.findNewName("", allUsedNames, null, info.module.readableIdentifier(requestShortener)); - allUsedNames.add(externalName); - info.name = externalName; - if(info.interop) { - const externalNameInterop = this.findNewName("default", allUsedNames, null, info.module.readableIdentifier(requestShortener)); - allUsedNames.add(externalNameInterop); - info.interopName = externalNameInterop; - } - break; - } - } - }); - - // Find and replace referenced to modules - modulesWithInfo.forEach(info => { - if(info.type === "concatenated") { - info.globalScope.through.forEach(reference => { - const name = reference.identifier.name; - const match = /^__WEBPACK_MODULE_REFERENCE__(\d+)_([\da-f]+|ns)(_call)?__$/.exec(name); - if(match) { - const referencedModule = modulesWithInfo[+match[1]]; - let exportName; - if(match[2] === "ns") { - exportName = true; - } else { - const exportData = match[2]; - exportName = new Buffer(exportData, "hex").toString("utf-8"); // eslint-disable-line node/no-deprecated-api - } - const asCall = !!match[3]; - const finalName = getFinalName(referencedModule, exportName, moduleToInfoMap, requestShortener, asCall); - const r = reference.identifier.range; - const source = info.source; - source.replace(r[0], r[1] - 1, finalName); - } - }); - } - }); - - const result = new ConcatSource(); - - // add harmony compatibility flag (must be first because of possible circular dependencies) - const usedExports = this.rootModule.usedExports; - if(usedExports === true) { - result.add(`Object.defineProperty(${this.exportsArgument || "exports"}, "__esModule", { value: true });\n`); - } - - // define required namespace objects (must be before evaluation modules) - modulesWithInfo.forEach(info => { - if(info.namespaceObjectSource) { - result.add(info.namespaceObjectSource); - } - }); - - // evaluate modules in order - modulesWithInfo.forEach(info => { - switch(info.type) { - case "concatenated": - result.add(`\n// CONCATENATED MODULE: ${info.module.readableIdentifier(requestShortener)}\n`); - result.add(info.source); - break; - case "external": - result.add(`\n// EXTERNAL MODULE: ${info.module.readableIdentifier(requestShortener)}\n`); - result.add(`var ${info.name} = __webpack_require__(${JSON.stringify(info.module.id)});\n`); - if(info.interop) { - result.add(`var ${info.interopName} = /*#__PURE__*/__webpack_require__.n(${info.name});\n`); - } - break; - default: - throw new Error(`Unsupported concatenation entry type ${info.type}`); - } - }); - - return result; - } - - findNewName(oldName, usedNamed1, usedNamed2, extraInfo) { - let name = oldName; - - if(name === "__WEBPACK_MODULE_DEFAULT_EXPORT__") - name = ""; - - // Remove uncool stuff - extraInfo = extraInfo.replace(/\.+\/|(\/index)?\.([a-zA-Z0-9]{1,4})($|\s|\?)|\s*\+\s*\d+\s*modules/g, ""); - - const splittedInfo = extraInfo.split("/"); - while(splittedInfo.length) { - name = splittedInfo.pop() + (name ? "_" + name : ""); - const nameIdent = Template.toIdentifier(name); - if(!usedNamed1.has(nameIdent) && (!usedNamed2 || !usedNamed2.has(nameIdent))) return nameIdent; - } - - let i = 0; - let nameWithNumber = Template.toIdentifier(`${name}_${i}`); - while(usedNamed1.has(nameWithNumber) || (usedNamed2 && usedNamed2.has(nameWithNumber))) { - i++; - nameWithNumber = Template.toIdentifier(`${name}_${i}`); - } - return nameWithNumber; - } - - updateHash(hash) { - for(const info of this._orderedConcatenationList) { - switch(info.type) { - case "concatenated": - info.module.updateHash(hash); - break; - case "external": - hash.update(`${info.module.id}`); - break; - } - } - super.updateHash(hash); - } - -} - -class HarmonyImportSpecifierDependencyConcatenatedTemplate { - constructor(originalTemplate, modulesMap) { - this.originalTemplate = originalTemplate; - this.modulesMap = modulesMap; - } - - apply(dep, source, outputOptions, requestShortener, dependencyTemplates) { - const module = dep.importDependency.module; - const info = this.modulesMap.get(module); - if(!info) { - this.originalTemplate.apply(dep, source, outputOptions, requestShortener, dependencyTemplates); - return; - } - let content; - if(dep.id === null) { - content = `__WEBPACK_MODULE_REFERENCE__${info.index}_ns__`; - } else if(dep.namespaceObjectAsContext) { - content = `__WEBPACK_MODULE_REFERENCE__${info.index}_ns__[${JSON.stringify(dep.id)}]`; - } else { - const exportData = new Buffer(dep.id, "utf-8").toString("hex"); // eslint-disable-line node/no-deprecated-api - content = `__WEBPACK_MODULE_REFERENCE__${info.index}_${exportData}${dep.call ? "_call" : ""}__`; - } - if(dep.shorthand) { - content = dep.name + ": " + content; - } - source.replace(dep.range[0], dep.range[1] - 1, content); - } -} - -class HarmonyImportDependencyConcatenatedTemplate { - constructor(originalTemplate, modulesMap) { - this.originalTemplate = originalTemplate; - this.modulesMap = modulesMap; - } - - apply(dep, source, outputOptions, requestShortener, dependencyTemplates) { - const module = dep.module; - const info = this.modulesMap.get(module); - if(!info) { - this.originalTemplate.apply(dep, source, outputOptions, requestShortener, dependencyTemplates); - return; - } - source.replace(dep.range[0], dep.range[1] - 1, ""); - } -} - -class HarmonyExportSpecifierDependencyConcatenatedTemplate { - constructor(originalTemplate, rootModule) { - this.originalTemplate = originalTemplate; - this.rootModule = rootModule; - } - - apply(dep, source, outputOptions, requestShortener, dependencyTemplates) { - if(dep.originModule === this.rootModule) { - this.originalTemplate.apply(dep, source, outputOptions, requestShortener, dependencyTemplates); - } - } -} - -class HarmonyExportExpressionDependencyConcatenatedTemplate { - constructor(originalTemplate, rootModule) { - this.originalTemplate = originalTemplate; - this.rootModule = rootModule; - } - - apply(dep, source, outputOptions, requestShortener, dependencyTemplates) { - let content = "/* harmony default export */ var __WEBPACK_MODULE_DEFAULT_EXPORT__ = "; - if(dep.originModule === this.rootModule) { - const used = dep.originModule.isUsed("default"); - const exportsName = dep.originModule.exportsArgument || "exports"; - if(used) content += `${exportsName}[${JSON.stringify(used)}] = `; - } - - if(dep.range) { - source.replace(dep.rangeStatement[0], dep.range[0] - 1, content + "("); - source.replace(dep.range[1], dep.rangeStatement[1] - 1, ");"); - return; - } - - source.replace(dep.rangeStatement[0], dep.rangeStatement[1] - 1, content); - } -} - -class HarmonyExportImportedSpecifierDependencyConcatenatedTemplate { - constructor(originalTemplate, rootModule, modulesMap) { - this.originalTemplate = originalTemplate; - this.rootModule = rootModule; - this.modulesMap = modulesMap; - } - - getExports(dep) { - const importModule = dep.importDependency.module; - if(dep.id) { - // export { named } from "module" - return [{ - name: dep.name, - id: dep.id, - module: importModule - }]; - } - if(dep.name) { - // export * as abc from "module" - return [{ - name: dep.name, - id: true, - module: importModule - }]; - } - // export * from "module" - return importModule.providedExports.filter(exp => exp !== "default" && !dep.activeExports.has(exp)).map(exp => { - return { - name: exp, - id: exp, - module: importModule - }; - }); - } - - apply(dep, source, outputOptions, requestShortener, dependencyTemplates) { - if(dep.originModule === this.rootModule) { - if(this.modulesMap.get(dep.importDependency.module)) { - const exportDefs = this.getExports(dep); - exportDefs.forEach(def => { - const info = this.modulesMap.get(def.module); - const used = dep.originModule.isUsed(def.name); - if(!used) { - source.insert(-1, `/* unused concated harmony import ${dep.name} */\n`); - } - let finalName; - if(def.id === true) { - finalName = `__WEBPACK_MODULE_REFERENCE__${info.index}_ns__`; - } else { - const exportData = new Buffer(def.id, "utf-8").toString("hex"); // eslint-disable-line node/no-deprecated-api - finalName = `__WEBPACK_MODULE_REFERENCE__${info.index}_${exportData}__`; - } - const exportsName = this.rootModule.exportsArgument || "exports"; - const content = `/* concated harmony reexport */__webpack_require__.d(${exportsName}, ${JSON.stringify(used)}, function() { return ${finalName}; });\n`; - source.insert(-1, content); - }); - } else { - this.originalTemplate.apply(dep, source, outputOptions, requestShortener, dependencyTemplates); - } - } - } -} - -class HarmonyCompatibilityDependencyConcatenatedTemplate { - constructor(originalTemplate, rootModule, modulesMap) { - this.originalTemplate = originalTemplate; - this.rootModule = rootModule; - this.modulesMap = modulesMap; - } - - apply(dep, source, outputOptions, requestShortener, dependencyTemplates) { - // do nothing - } -} - -module.exports = ConcatenatedModule; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const Module = require("../Module"); +const Template = require("../Template"); +const Parser = require("../Parser"); +const eslintScope = require("eslint-scope"); +const { ConcatSource, ReplaceSource } = require("webpack-sources"); +const DependencyReference = require("../dependencies/DependencyReference"); +const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency"); +const HarmonyImportSideEffectDependency = require("../dependencies/HarmonyImportSideEffectDependency"); +const HarmonyImportSpecifierDependency = require("../dependencies/HarmonyImportSpecifierDependency"); +const HarmonyExportSpecifierDependency = require("../dependencies/HarmonyExportSpecifierDependency"); +const HarmonyExportExpressionDependency = require("../dependencies/HarmonyExportExpressionDependency"); +const HarmonyExportImportedSpecifierDependency = require("../dependencies/HarmonyExportImportedSpecifierDependency"); +const HarmonyCompatibilityDependency = require("../dependencies/HarmonyCompatibilityDependency"); +const createHash = require("../util/createHash"); + +/** @typedef {import("../Dependency")} Dependency */ +/** @typedef {import("../Compilation")} Compilation */ +/** @typedef {import("../util/createHash").Hash} Hash */ + +/** + * @typedef {Object} ConcatenationEntry + * @property {"concatenated" | "external"} type + * @property {Module} module + */ + +const ensureNsObjSource = ( + info, + moduleToInfoMap, + requestShortener, + strictHarmonyModule +) => { + if (!info.hasNamespaceObject) { + info.hasNamespaceObject = true; + const name = info.exportMap.get(true); + const nsObj = [`var ${name} = {};`, `__webpack_require__.r(${name});`]; + for (const exportName of info.module.buildMeta.providedExports) { + const finalName = getFinalName( + info, + exportName, + moduleToInfoMap, + requestShortener, + false, + strictHarmonyModule + ); + nsObj.push( + `__webpack_require__.d(${name}, ${JSON.stringify( + exportName + )}, function() { return ${finalName}; });` + ); + } + info.namespaceObjectSource = nsObj.join("\n") + "\n"; + } +}; + +const getExternalImport = ( + importedModule, + info, + exportName, + asCall, + strictHarmonyModule +) => { + const used = importedModule.isUsed(exportName); + if (!used) return "/* unused reexport */undefined"; + const comment = + used !== exportName ? ` ${Template.toNormalComment(exportName)}` : ""; + switch (importedModule.buildMeta.exportsType) { + case "named": + if (exportName === "default") { + return info.name; + } else if (exportName === true) { + info.interopNamespaceObjectUsed = true; + return info.interopNamespaceObjectName; + } else { + break; + } + case "namespace": + if (exportName === true) { + return info.name; + } else { + break; + } + default: + if (strictHarmonyModule) { + if (exportName === "default") { + return info.name; + } else if (exportName === true) { + info.interopNamespaceObjectUsed = true; + return info.interopNamespaceObjectName; + } else { + return "/* non-default import from non-esm module */undefined"; + } + } else { + if (exportName === "default") { + info.interopDefaultAccessUsed = true; + return asCall + ? `${info.interopDefaultAccessName}()` + : `${info.interopDefaultAccessName}.a`; + } else if (exportName === true) { + return info.name; + } else { + break; + } + } + } + const reference = `${info.name}[${JSON.stringify(used)}${comment}]`; + if (asCall) return `Object(${reference})`; + return reference; +}; + +const getFinalName = ( + info, + exportName, + moduleToInfoMap, + requestShortener, + asCall, + strictHarmonyModule, + alreadyVisited = new Set() +) => { + switch (info.type) { + case "concatenated": { + const directExport = info.exportMap.get(exportName); + if (directExport) { + if (exportName === true) { + ensureNsObjSource( + info, + moduleToInfoMap, + requestShortener, + strictHarmonyModule + ); + } else if (!info.module.isUsed(exportName)) { + return "/* unused export */ undefined"; + } + if (info.globalExports.has(directExport)) { + return directExport; + } + const name = info.internalNames.get(directExport); + if (!name) { + throw new Error( + `The export "${directExport}" in "${info.module.readableIdentifier( + requestShortener + )}" has no internal name` + ); + } + return name; + } + const reexport = info.reexportMap.get(exportName); + if (reexport) { + if (alreadyVisited.has(reexport)) { + throw new Error( + `Circular reexports ${Array.from( + alreadyVisited, + e => + `"${e.module.readableIdentifier(requestShortener)}".${ + e.exportName + }` + ).join( + " --> " + )} -(circular)-> "${reexport.module.readableIdentifier( + requestShortener + )}".${reexport.exportName}` + ); + } + alreadyVisited.add(reexport); + const refInfo = moduleToInfoMap.get(reexport.module); + if (refInfo) { + // module is in the concatenation + return getFinalName( + refInfo, + reexport.exportName, + moduleToInfoMap, + requestShortener, + asCall, + strictHarmonyModule, + alreadyVisited + ); + } + } + const problem = + `Cannot get final name for export "${exportName}" in "${info.module.readableIdentifier( + requestShortener + )}"` + + ` (known exports: ${Array.from(info.exportMap.keys()) + .filter(name => name !== true) + .join(" ")}, ` + + `known reexports: ${Array.from(info.reexportMap.keys()).join(" ")})`; + return `${Template.toNormalComment(problem)} undefined`; + } + case "external": { + const importedModule = info.module; + return getExternalImport( + importedModule, + info, + exportName, + asCall, + strictHarmonyModule + ); + } + } +}; + +const addScopeSymbols1 = (s, nameSet, scopeSet) => { + let scope = s; + while (scope) { + if (scopeSet.has(scope)) break; + scopeSet.add(scope); + for (const variable of scope.variables) { + nameSet.add(variable.name); + } + scope = scope.upper; + } +}; + +const addScopeSymbols2 = (s, nameSet, scopeSet1, scopeSet2) => { + let scope = s; + while (scope) { + if (scopeSet1.has(scope)) break; + if (scopeSet2.has(scope)) break; + scopeSet1.add(scope); + for (const variable of scope.variables) { + nameSet.add(variable.name); + } + scope = scope.upper; + } +}; + +const getAllReferences = variable => { + let set = variable.references; + // Look for inner scope variables too (like in class Foo { t() { Foo } }) + const identifiers = new Set(variable.identifiers); + for (const scope of variable.scope.childScopes) { + for (const innerVar of scope.variables) { + if (innerVar.identifiers.some(id => identifiers.has(id))) { + set = set.concat(innerVar.references); + break; + } + } + } + return set; +}; + +const getPathInAst = (ast, node) => { + if (ast === node) { + return []; + } + + const nr = node.range; + + const enterNode = n => { + if (!n) return undefined; + const r = n.range; + if (r) { + if (r[0] <= nr[0] && r[1] >= nr[1]) { + const path = getPathInAst(n, node); + if (path) { + path.push(n); + return path; + } + } + } + return undefined; + }; + + var i; + if (Array.isArray(ast)) { + for (i = 0; i < ast.length; i++) { + const enterResult = enterNode(ast[i]); + if (enterResult !== undefined) return enterResult; + } + } else if (ast && typeof ast === "object") { + const keys = Object.keys(ast); + for (i = 0; i < keys.length; i++) { + const value = ast[keys[i]]; + if (Array.isArray(value)) { + const pathResult = getPathInAst(value, node); + if (pathResult !== undefined) return pathResult; + } else if (value && typeof value === "object") { + const enterResult = enterNode(value); + if (enterResult !== undefined) return enterResult; + } + } + } +}; + +class ConcatenatedModule extends Module { + constructor(rootModule, modules, concatenationList) { + super("javascript/esm", null); + super.setChunks(rootModule._chunks); + + // Info from Factory + this.rootModule = rootModule; + this.factoryMeta = rootModule.factoryMeta; + + // Info from Compilation + this.index = rootModule.index; + this.index2 = rootModule.index2; + this.depth = rootModule.depth; + + // Info from Optimization + this.used = rootModule.used; + this.usedExports = rootModule.usedExports; + + // Info from Build + this.buildInfo = { + strict: true, + cacheable: modules.every(m => m.buildInfo.cacheable), + moduleArgument: rootModule.buildInfo.moduleArgument, + exportsArgument: rootModule.buildInfo.exportsArgument, + fileDependencies: new Set(), + contextDependencies: new Set(), + assets: undefined + }; + this.built = modules.some(m => m.built); + this.buildMeta = rootModule.buildMeta; + + // Caching + this._numberOfConcatenatedModules = modules.length; + + // Graph + const modulesSet = new Set(modules); + this.reasons = rootModule.reasons.filter( + reason => + !(reason.dependency instanceof HarmonyImportDependency) || + !modulesSet.has(reason.module) + ); + + this.dependencies = []; + + this.warnings = []; + this.errors = []; + this._orderedConcatenationList = + concatenationList || + ConcatenatedModule.createConcatenationList(rootModule, modulesSet, null); + for (const info of this._orderedConcatenationList) { + if (info.type === "concatenated") { + const m = info.module; + + // populate dependencies + for (const d of m.dependencies.filter( + dep => + !(dep instanceof HarmonyImportDependency) || + !modulesSet.has(dep._module) + )) { + this.dependencies.push(d); + } + // populate file dependencies + if (m.buildInfo.fileDependencies) { + for (const file of m.buildInfo.fileDependencies) { + this.buildInfo.fileDependencies.add(file); + } + } + // populate context dependencies + if (m.buildInfo.contextDependencies) { + for (const context of m.buildInfo.contextDependencies) { + this.buildInfo.contextDependencies.add(context); + } + } + // populate warnings + for (const warning of m.warnings) { + this.warnings.push(warning); + } + // populate errors + for (const error of m.errors) { + this.errors.push(error); + } + + if (m.buildInfo.assets) { + if (this.buildInfo.assets === undefined) { + this.buildInfo.assets = Object.create(null); + } + Object.assign(this.buildInfo.assets, m.buildInfo.assets); + } + } + } + this._identifier = this._createIdentifier(); + } + + get modules() { + return this._orderedConcatenationList + .filter(info => info.type === "concatenated") + .map(info => info.module); + } + + identifier() { + return this._identifier; + } + + readableIdentifier(requestShortener) { + return ( + this.rootModule.readableIdentifier(requestShortener) + + ` + ${this._numberOfConcatenatedModules - 1} modules` + ); + } + + libIdent(options) { + return this.rootModule.libIdent(options); + } + + nameForCondition() { + return this.rootModule.nameForCondition(); + } + + build(options, compilation, resolver, fs, callback) { + throw new Error("Cannot build this module. It should be already built."); + } + + size() { + // Guess size from embedded modules + return this._orderedConcatenationList.reduce((sum, info) => { + switch (info.type) { + case "concatenated": + return sum + info.module.size(); + case "external": + return sum + 5; + } + return sum; + }, 0); + } + + /** + * @param {Module} rootModule the root of the concatenation + * @param {Set} modulesSet a set of modules which should be concatenated + * @param {Compilation} compilation the compilation context + * @returns {ConcatenationEntry[]} concatenation list + */ + static createConcatenationList(rootModule, modulesSet, compilation) { + const list = []; + const set = new Set(); + + /** + * @param {Module} module a module + * @returns {(function(): Module)[]} imported modules in order + */ + const getConcatenatedImports = module => { + /** @type {WeakMap} */ + const map = new WeakMap(); + const references = module.dependencies + .filter(dep => dep instanceof HarmonyImportDependency) + .map(dep => { + const ref = compilation.getDependencyReference(module, dep); + if (ref) map.set(ref, dep); + return ref; + }) + .filter(ref => ref); + DependencyReference.sort(references); + // TODO webpack 5: remove this hack, see also DependencyReference + return references.map(ref => { + const dep = map.get(ref); + return () => compilation.getDependencyReference(module, dep).module; + }); + }; + + const enterModule = getModule => { + const module = getModule(); + if (!module) return; + if (set.has(module)) return; + set.add(module); + if (modulesSet.has(module)) { + const imports = getConcatenatedImports(module); + imports.forEach(enterModule); + list.push({ + type: "concatenated", + module + }); + } else { + list.push({ + type: "external", + get module() { + // We need to use a getter here, because the module in the dependency + // could be replaced by some other process (i. e. also replaced with a + // concatenated module) + return getModule(); + } + }); + } + }; + + enterModule(() => rootModule); + + return list; + } + + _createIdentifier() { + let orderedConcatenationListIdentifiers = ""; + for (let i = 0; i < this._orderedConcatenationList.length; i++) { + if (this._orderedConcatenationList[i].type === "concatenated") { + orderedConcatenationListIdentifiers += this._orderedConcatenationList[ + i + ].module.identifier(); + orderedConcatenationListIdentifiers += " "; + } + } + const hash = createHash("md4"); + hash.update(orderedConcatenationListIdentifiers); + return this.rootModule.identifier() + " " + hash.digest("hex"); + } + + source(dependencyTemplates, runtimeTemplate) { + const requestShortener = runtimeTemplate.requestShortener; + // Metainfo for each module + const modulesWithInfo = this._orderedConcatenationList.map((info, idx) => { + switch (info.type) { + case "concatenated": { + const exportMap = new Map(); + const reexportMap = new Map(); + for (const dep of info.module.dependencies) { + if (dep instanceof HarmonyExportSpecifierDependency) { + if (!exportMap.has(dep.name)) { + exportMap.set(dep.name, dep.id); + } + } else if (dep instanceof HarmonyExportExpressionDependency) { + if (!exportMap.has("default")) { + exportMap.set("default", "__WEBPACK_MODULE_DEFAULT_EXPORT__"); + } + } else if ( + dep instanceof HarmonyExportImportedSpecifierDependency + ) { + const exportName = dep.name; + const importName = dep.id; + const importedModule = dep._module; + if (exportName && importName) { + if (!reexportMap.has(exportName)) { + reexportMap.set(exportName, { + module: importedModule, + exportName: importName, + dependency: dep + }); + } + } else if (exportName) { + if (!reexportMap.has(exportName)) { + reexportMap.set(exportName, { + module: importedModule, + exportName: true, + dependency: dep + }); + } + } else if (importedModule) { + for (const name of importedModule.buildMeta.providedExports) { + if (dep.activeExports.has(name) || name === "default") { + continue; + } + if (!reexportMap.has(name)) { + reexportMap.set(name, { + module: importedModule, + exportName: name, + dependency: dep + }); + } + } + } + } + } + return { + type: "concatenated", + module: info.module, + index: idx, + ast: undefined, + internalSource: undefined, + source: undefined, + globalScope: undefined, + moduleScope: undefined, + internalNames: new Map(), + globalExports: new Set(), + exportMap: exportMap, + reexportMap: reexportMap, + hasNamespaceObject: false, + namespaceObjectSource: null + }; + } + case "external": + return { + type: "external", + module: info.module, + index: idx, + name: undefined, + interopNamespaceObjectUsed: false, + interopNamespaceObjectName: undefined, + interopDefaultAccessUsed: false, + interopDefaultAccessName: undefined + }; + default: + throw new Error(`Unsupported concatenation entry type ${info.type}`); + } + }); + + // Create mapping from module to info + const moduleToInfoMap = new Map(); + for (const m of modulesWithInfo) { + moduleToInfoMap.set(m.module, m); + } + + // Configure template decorators for dependencies + const innerDependencyTemplates = new Map(dependencyTemplates); + + innerDependencyTemplates.set( + HarmonyImportSpecifierDependency, + new HarmonyImportSpecifierDependencyConcatenatedTemplate( + dependencyTemplates.get(HarmonyImportSpecifierDependency), + moduleToInfoMap + ) + ); + innerDependencyTemplates.set( + HarmonyImportSideEffectDependency, + new HarmonyImportSideEffectDependencyConcatenatedTemplate( + dependencyTemplates.get(HarmonyImportSideEffectDependency), + moduleToInfoMap + ) + ); + innerDependencyTemplates.set( + HarmonyExportSpecifierDependency, + new HarmonyExportSpecifierDependencyConcatenatedTemplate( + dependencyTemplates.get(HarmonyExportSpecifierDependency), + this.rootModule + ) + ); + innerDependencyTemplates.set( + HarmonyExportExpressionDependency, + new HarmonyExportExpressionDependencyConcatenatedTemplate( + dependencyTemplates.get(HarmonyExportExpressionDependency), + this.rootModule + ) + ); + innerDependencyTemplates.set( + HarmonyExportImportedSpecifierDependency, + new HarmonyExportImportedSpecifierDependencyConcatenatedTemplate( + dependencyTemplates.get(HarmonyExportImportedSpecifierDependency), + this.rootModule, + moduleToInfoMap + ) + ); + innerDependencyTemplates.set( + HarmonyCompatibilityDependency, + new HarmonyCompatibilityDependencyConcatenatedTemplate( + dependencyTemplates.get(HarmonyCompatibilityDependency), + this.rootModule, + moduleToInfoMap + ) + ); + + // Must use full identifier in our cache here to ensure that the source + // is updated should our dependencies list change. + // TODO webpack 5 refactor + innerDependencyTemplates.set( + "hash", + innerDependencyTemplates.get("hash") + this.identifier() + ); + + // Generate source code and analyse scopes + // Prepare a ReplaceSource for the final source + for (const info of modulesWithInfo) { + if (info.type === "concatenated") { + const m = info.module; + const source = m.source(innerDependencyTemplates, runtimeTemplate); + const code = source.source(); + let ast; + try { + ast = Parser.parse(code, { + sourceType: "module" + }); + } catch (err) { + if ( + err.loc && + typeof err.loc === "object" && + typeof err.loc.line === "number" + ) { + const lineNumber = err.loc.line; + const lines = code.split("\n"); + err.message += + "\n| " + + lines + .slice(Math.max(0, lineNumber - 3), lineNumber + 2) + .join("\n| "); + } + throw err; + } + const scopeManager = eslintScope.analyze(ast, { + ecmaVersion: 6, + sourceType: "module", + optimistic: true, + ignoreEval: true, + impliedStrict: true + }); + const globalScope = scopeManager.acquire(ast); + const moduleScope = globalScope.childScopes[0]; + const resultSource = new ReplaceSource(source); + info.ast = ast; + info.internalSource = source; + info.source = resultSource; + info.globalScope = globalScope; + info.moduleScope = moduleScope; + } + } + + // List of all used names to avoid conflicts + const allUsedNames = new Set([ + "__WEBPACK_MODULE_DEFAULT_EXPORT__", // avoid using this internal name + + "abstract", + "arguments", + "async", + "await", + "boolean", + "break", + "byte", + "case", + "catch", + "char", + "class", + "const", + "continue", + "debugger", + "default", + "delete", + "do", + "double", + "else", + "enum", + "eval", + "export", + "extends", + "false", + "final", + "finally", + "float", + "for", + "function", + "goto", + "if", + "implements", + "import", + "in", + "instanceof", + "int", + "interface", + "let", + "long", + "native", + "new", + "null", + "package", + "private", + "protected", + "public", + "return", + "short", + "static", + "super", + "switch", + "synchronized", + "this", + "throw", + "throws", + "transient", + "true", + "try", + "typeof", + "var", + "void", + "volatile", + "while", + "with", + "yield", + + "module", + "__dirname", + "__filename", + "exports", + + "Array", + "Date", + "eval", + "function", + "hasOwnProperty", + "Infinity", + "isFinite", + "isNaN", + "isPrototypeOf", + "length", + "Math", + "NaN", + "name", + "Number", + "Object", + "prototype", + "String", + "toString", + "undefined", + "valueOf", + + "alert", + "all", + "anchor", + "anchors", + "area", + "assign", + "blur", + "button", + "checkbox", + "clearInterval", + "clearTimeout", + "clientInformation", + "close", + "closed", + "confirm", + "constructor", + "crypto", + "decodeURI", + "decodeURIComponent", + "defaultStatus", + "document", + "element", + "elements", + "embed", + "embeds", + "encodeURI", + "encodeURIComponent", + "escape", + "event", + "fileUpload", + "focus", + "form", + "forms", + "frame", + "innerHeight", + "innerWidth", + "layer", + "layers", + "link", + "location", + "mimeTypes", + "navigate", + "navigator", + "frames", + "frameRate", + "hidden", + "history", + "image", + "images", + "offscreenBuffering", + "open", + "opener", + "option", + "outerHeight", + "outerWidth", + "packages", + "pageXOffset", + "pageYOffset", + "parent", + "parseFloat", + "parseInt", + "password", + "pkcs11", + "plugin", + "prompt", + "propertyIsEnum", + "radio", + "reset", + "screenX", + "screenY", + "scroll", + "secure", + "select", + "self", + "setInterval", + "setTimeout", + "status", + "submit", + "taint", + "text", + "textarea", + "top", + "unescape", + "untaint", + "window", + + "onblur", + "onclick", + "onerror", + "onfocus", + "onkeydown", + "onkeypress", + "onkeyup", + "onmouseover", + "onload", + "onmouseup", + "onmousedown", + "onsubmit" + ]); + + // Set of already checked scopes + const alreadyCheckedScopes = new Set(); + + // get all global names + for (const info of modulesWithInfo) { + const superClassExpressions = []; + + // ignore symbols from moduleScope + if (info.moduleScope) { + alreadyCheckedScopes.add(info.moduleScope); + + // The super class expression in class scopes behaves weird + // We store ranges of all super class expressions to make + // renaming to work correctly + for (const childScope of info.moduleScope.childScopes) { + if (childScope.type !== "class") continue; + if (!childScope.block.superClass) continue; + superClassExpressions.push({ + range: childScope.block.superClass.range, + variables: childScope.variables + }); + } + } + + // add global symbols + if (info.globalScope) { + for (const reference of info.globalScope.through) { + const name = reference.identifier.name; + if ( + /^__WEBPACK_MODULE_REFERENCE__\d+_([\da-f]+|ns)(_call)?(_strict)?__$/.test( + name + ) + ) { + for (const expr of superClassExpressions) { + if ( + expr.range[0] <= reference.identifier.range[0] && + expr.range[1] >= reference.identifier.range[1] + ) { + for (const variable of expr.variables) { + allUsedNames.add(variable.name); + } + } + } + addScopeSymbols1( + reference.from, + allUsedNames, + alreadyCheckedScopes + ); + } else { + allUsedNames.add(name); + } + } + } + + // add exported globals + if (info.type === "concatenated") { + const variables = new Set(); + for (const variable of info.moduleScope.variables) { + variables.add(variable.name); + } + for (const [, variable] of info.exportMap) { + if (!variables.has(variable)) { + info.globalExports.add(variable); + } + } + } + } + + // generate names for symbols + for (const info of modulesWithInfo) { + switch (info.type) { + case "concatenated": { + const namespaceObjectName = this.findNewName( + "namespaceObject", + allUsedNames, + null, + info.module.readableIdentifier(requestShortener) + ); + allUsedNames.add(namespaceObjectName); + info.internalNames.set(namespaceObjectName, namespaceObjectName); + info.exportMap.set(true, namespaceObjectName); + for (const variable of info.moduleScope.variables) { + const name = variable.name; + if (allUsedNames.has(name)) { + const references = getAllReferences(variable); + const symbolsInReferences = new Set(); + const alreadyCheckedInnerScopes = new Set(); + for (const ref of references) { + addScopeSymbols2( + ref.from, + symbolsInReferences, + alreadyCheckedInnerScopes, + alreadyCheckedScopes + ); + } + const newName = this.findNewName( + name, + allUsedNames, + symbolsInReferences, + info.module.readableIdentifier(requestShortener) + ); + allUsedNames.add(newName); + info.internalNames.set(name, newName); + const source = info.source; + const allIdentifiers = new Set( + references.map(r => r.identifier).concat(variable.identifiers) + ); + for (const identifier of allIdentifiers) { + const r = identifier.range; + const path = getPathInAst(info.ast, identifier); + if ( + path && + path.length > 1 && + path[1].type === "Property" && + path[1].shorthand + ) { + source.insert(r[1], `: ${newName}`); + } else { + source.replace(r[0], r[1] - 1, newName); + } + } + } else { + allUsedNames.add(name); + info.internalNames.set(name, name); + } + } + break; + } + case "external": { + const externalName = this.findNewName( + "", + allUsedNames, + null, + info.module.readableIdentifier(requestShortener) + ); + allUsedNames.add(externalName); + info.name = externalName; + if ( + info.module.buildMeta.exportsType === "named" || + !info.module.buildMeta.exportsType + ) { + const externalNameInterop = this.findNewName( + "namespaceObject", + allUsedNames, + null, + info.module.readableIdentifier(requestShortener) + ); + allUsedNames.add(externalNameInterop); + info.interopNamespaceObjectName = externalNameInterop; + } + if (!info.module.buildMeta.exportsType) { + const externalNameInterop = this.findNewName( + "default", + allUsedNames, + null, + info.module.readableIdentifier(requestShortener) + ); + allUsedNames.add(externalNameInterop); + info.interopDefaultAccessName = externalNameInterop; + } + break; + } + } + } + + // Find and replace referenced to modules + for (const info of modulesWithInfo) { + if (info.type === "concatenated") { + for (const reference of info.globalScope.through) { + const name = reference.identifier.name; + const match = /^__WEBPACK_MODULE_REFERENCE__(\d+)_([\da-f]+|ns)(_call)?(_strict)?__$/.exec( + name + ); + if (match) { + const referencedModule = modulesWithInfo[+match[1]]; + let exportName; + if (match[2] === "ns") { + exportName = true; + } else { + const exportData = match[2]; + exportName = Buffer.from(exportData, "hex").toString("utf-8"); + } + const asCall = !!match[3]; + const strictHarmonyModule = !!match[4]; + const finalName = getFinalName( + referencedModule, + exportName, + moduleToInfoMap, + requestShortener, + asCall, + strictHarmonyModule + ); + const r = reference.identifier.range; + const source = info.source; + source.replace(r[0], r[1] - 1, finalName); + } + } + } + } + + const result = new ConcatSource(); + + // add harmony compatibility flag (must be first because of possible circular dependencies) + const usedExports = this.rootModule.usedExports; + if (usedExports === true) { + result.add( + runtimeTemplate.defineEsModuleFlagStatement({ + exportsArgument: this.exportsArgument + }) + ); + } + + // define required namespace objects (must be before evaluation modules) + for (const info of modulesWithInfo) { + if (info.namespaceObjectSource) { + result.add(info.namespaceObjectSource); + } + } + + // evaluate modules in order + for (const info of modulesWithInfo) { + switch (info.type) { + case "concatenated": + result.add( + `\n// CONCATENATED MODULE: ${info.module.readableIdentifier( + requestShortener + )}\n` + ); + result.add(info.source); + break; + case "external": + result.add( + `\n// EXTERNAL MODULE: ${info.module.readableIdentifier( + requestShortener + )}\n` + ); + result.add( + `var ${info.name} = __webpack_require__(${JSON.stringify( + info.module.id + )});\n` + ); + if (info.interopNamespaceObjectUsed) { + if (info.module.buildMeta.exportsType === "named") { + result.add( + `var ${ + info.interopNamespaceObjectName + } = /*#__PURE__*/__webpack_require__.t(${info.name}, 2);\n` + ); + } else if (!info.module.buildMeta.exportsType) { + result.add( + `var ${ + info.interopNamespaceObjectName + } = /*#__PURE__*/__webpack_require__.t(${info.name});\n` + ); + } + } + if (info.interopDefaultAccessUsed) { + result.add( + `var ${ + info.interopDefaultAccessName + } = /*#__PURE__*/__webpack_require__.n(${info.name});\n` + ); + } + break; + default: + throw new Error(`Unsupported concatenation entry type ${info.type}`); + } + } + + return result; + } + + findNewName(oldName, usedNamed1, usedNamed2, extraInfo) { + let name = oldName; + + if (name === "__WEBPACK_MODULE_DEFAULT_EXPORT__") name = ""; + + // Remove uncool stuff + extraInfo = extraInfo.replace( + /\.+\/|(\/index)?\.([a-zA-Z0-9]{1,4})($|\s|\?)|\s*\+\s*\d+\s*modules/g, + "" + ); + + const splittedInfo = extraInfo.split("/"); + while (splittedInfo.length) { + name = splittedInfo.pop() + (name ? "_" + name : ""); + const nameIdent = Template.toIdentifier(name); + if ( + !usedNamed1.has(nameIdent) && + (!usedNamed2 || !usedNamed2.has(nameIdent)) + ) + return nameIdent; + } + + let i = 0; + let nameWithNumber = Template.toIdentifier(`${name}_${i}`); + while ( + usedNamed1.has(nameWithNumber) || + (usedNamed2 && usedNamed2.has(nameWithNumber)) + ) { + i++; + nameWithNumber = Template.toIdentifier(`${name}_${i}`); + } + return nameWithNumber; + } + + /** + * @param {Hash} hash the hash used to track dependencies + * @returns {void} + */ + updateHash(hash) { + for (const info of this._orderedConcatenationList) { + switch (info.type) { + case "concatenated": + info.module.updateHash(hash); + break; + case "external": + hash.update(`${info.module.id}`); + break; + } + } + super.updateHash(hash); + } +} + +class HarmonyImportSpecifierDependencyConcatenatedTemplate { + constructor(originalTemplate, modulesMap) { + this.originalTemplate = originalTemplate; + this.modulesMap = modulesMap; + } + + getHarmonyInitOrder(dep) { + const module = dep._module; + const info = this.modulesMap.get(module); + if (!info) { + return this.originalTemplate.getHarmonyInitOrder(dep); + } + return NaN; + } + + harmonyInit(dep, source, runtimeTemplate, dependencyTemplates) { + const module = dep._module; + const info = this.modulesMap.get(module); + if (!info) { + this.originalTemplate.harmonyInit( + dep, + source, + runtimeTemplate, + dependencyTemplates + ); + return; + } + } + + apply(dep, source, runtime, dependencyTemplates) { + const module = dep._module; + const info = this.modulesMap.get(module); + if (!info) { + this.originalTemplate.apply(dep, source, runtime, dependencyTemplates); + return; + } + let content; + const callFlag = dep.call ? "_call" : ""; + const strictFlag = dep.originModule.buildMeta.strictHarmonyModule + ? "_strict" + : ""; + if (dep._id === null) { + content = `__WEBPACK_MODULE_REFERENCE__${info.index}_ns${strictFlag}__`; + } else if (dep.namespaceObjectAsContext) { + content = `__WEBPACK_MODULE_REFERENCE__${ + info.index + }_ns${strictFlag}__[${JSON.stringify(dep._id)}]`; + } else { + const exportData = Buffer.from(dep._id, "utf-8").toString("hex"); + content = `__WEBPACK_MODULE_REFERENCE__${ + info.index + }_${exportData}${callFlag}${strictFlag}__`; + } + if (dep.shorthand) { + content = dep.name + ": " + content; + } + source.replace(dep.range[0], dep.range[1] - 1, content); + } +} + +class HarmonyImportSideEffectDependencyConcatenatedTemplate { + constructor(originalTemplate, modulesMap) { + this.originalTemplate = originalTemplate; + this.modulesMap = modulesMap; + } + + getHarmonyInitOrder(dep) { + const module = dep._module; + const info = this.modulesMap.get(module); + if (!info) { + return this.originalTemplate.getHarmonyInitOrder(dep); + } + return NaN; + } + + harmonyInit(dep, source, runtime, dependencyTemplates) { + const module = dep._module; + const info = this.modulesMap.get(module); + if (!info) { + this.originalTemplate.harmonyInit( + dep, + source, + runtime, + dependencyTemplates + ); + return; + } + } + + apply(dep, source, runtime, dependencyTemplates) { + const module = dep._module; + const info = this.modulesMap.get(module); + if (!info) { + this.originalTemplate.apply(dep, source, runtime, dependencyTemplates); + return; + } + } +} + +class HarmonyExportSpecifierDependencyConcatenatedTemplate { + constructor(originalTemplate, rootModule) { + this.originalTemplate = originalTemplate; + this.rootModule = rootModule; + } + + getHarmonyInitOrder(dep) { + if (dep.originModule === this.rootModule) { + return this.originalTemplate.getHarmonyInitOrder(dep); + } + return NaN; + } + + harmonyInit(dep, source, runtime, dependencyTemplates) { + if (dep.originModule === this.rootModule) { + this.originalTemplate.harmonyInit( + dep, + source, + runtime, + dependencyTemplates + ); + return; + } + } + + apply(dep, source, runtime, dependencyTemplates) { + if (dep.originModule === this.rootModule) { + this.originalTemplate.apply(dep, source, runtime, dependencyTemplates); + } + } +} + +class HarmonyExportExpressionDependencyConcatenatedTemplate { + constructor(originalTemplate, rootModule) { + this.originalTemplate = originalTemplate; + this.rootModule = rootModule; + } + + apply(dep, source, runtime, dependencyTemplates) { + let content = + "/* harmony default export */ var __WEBPACK_MODULE_DEFAULT_EXPORT__ = "; + if (dep.originModule === this.rootModule) { + const used = dep.originModule.isUsed("default"); + const exportsName = dep.originModule.exportsArgument; + if (used) content += `${exportsName}[${JSON.stringify(used)}] = `; + } + + if (dep.range) { + source.replace(dep.rangeStatement[0], dep.range[0] - 1, content + "("); + source.replace(dep.range[1], dep.rangeStatement[1] - 1, ");"); + return; + } + + source.replace(dep.rangeStatement[0], dep.rangeStatement[1] - 1, content); + } +} + +class HarmonyExportImportedSpecifierDependencyConcatenatedTemplate { + constructor(originalTemplate, rootModule, modulesMap) { + this.originalTemplate = originalTemplate; + this.rootModule = rootModule; + this.modulesMap = modulesMap; + } + + getExports(dep) { + const importModule = dep._module; + if (dep.id) { + // export { named } from "module" + return [ + { + name: dep.name, + id: dep.id, + module: importModule + } + ]; + } + if (dep.name) { + // export * as abc from "module" + return [ + { + name: dep.name, + id: true, + module: importModule + } + ]; + } + // export * from "module" + return importModule.buildMeta.providedExports + .filter(exp => exp !== "default" && !dep.activeExports.has(exp)) + .map(exp => { + return { + name: exp, + id: exp, + module: importModule + }; + }); + } + + getHarmonyInitOrder(dep) { + const module = dep._module; + const info = this.modulesMap.get(module); + if (!info) { + return this.originalTemplate.getHarmonyInitOrder(dep); + } + return NaN; + } + + harmonyInit(dep, source, runtime, dependencyTemplates) { + const module = dep._module; + const info = this.modulesMap.get(module); + if (!info) { + this.originalTemplate.harmonyInit( + dep, + source, + runtime, + dependencyTemplates + ); + return; + } + } + + apply(dep, source, runtime, dependencyTemplates) { + if (dep.originModule === this.rootModule) { + if (this.modulesMap.get(dep._module)) { + const exportDefs = this.getExports(dep); + for (const def of exportDefs) { + const info = this.modulesMap.get(def.module); + const used = dep.originModule.isUsed(def.name); + if (!used) { + source.insert( + -1, + `/* unused concated harmony import ${def.name} */\n` + ); + continue; + } + let finalName; + const strictFlag = dep.originModule.buildMeta.strictHarmonyModule + ? "_strict" + : ""; + if (def.id === true) { + finalName = `__WEBPACK_MODULE_REFERENCE__${ + info.index + }_ns${strictFlag}__`; + } else { + const exportData = Buffer.from(def.id, "utf-8").toString("hex"); + finalName = `__WEBPACK_MODULE_REFERENCE__${ + info.index + }_${exportData}${strictFlag}__`; + } + const exportsName = this.rootModule.exportsArgument; + const content = + `/* concated harmony reexport ${def.name} */` + + `__webpack_require__.d(${exportsName}, ` + + `${JSON.stringify(used)}, ` + + `function() { return ${finalName}; });\n`; + source.insert(-1, content); + } + } else { + this.originalTemplate.apply(dep, source, runtime, dependencyTemplates); + } + } + } +} + +class HarmonyCompatibilityDependencyConcatenatedTemplate { + constructor(originalTemplate, rootModule, modulesMap) { + this.originalTemplate = originalTemplate; + this.rootModule = rootModule; + this.modulesMap = modulesMap; + } + + apply(dep, source, runtime, dependencyTemplates) { + // do nothing + } +} + +module.exports = ConcatenatedModule; diff --git a/node_modules/webpack/lib/optimize/DedupePlugin.js b/node_modules/webpack/lib/optimize/DedupePlugin.js deleted file mode 100644 index cffa43aaf..000000000 --- a/node_modules/webpack/lib/optimize/DedupePlugin.js +++ /dev/null @@ -1,15 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class DedupePlugin { - apply(compiler) { - compiler.plugin("compilation", (compilation) => { - compilation.warnings.push(new Error("DedupePlugin: This plugin was removed from webpack. Remove it from your configuration.")); - }); - } -} - -module.exports = DedupePlugin; diff --git a/node_modules/webpack/lib/optimize/EnsureChunkConditionsPlugin.js b/node_modules/webpack/lib/optimize/EnsureChunkConditionsPlugin.js index 2b291fdad..5d05ec834 100644 --- a/node_modules/webpack/lib/optimize/EnsureChunkConditionsPlugin.js +++ b/node_modules/webpack/lib/optimize/EnsureChunkConditionsPlugin.js @@ -1,40 +1,70 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class EnsureChunkConditionsPlugin { - - apply(compiler) { - compiler.plugin("compilation", (compilation) => { - const triesMap = new Map(); - compilation.plugin(["optimize-chunks-basic", "optimize-extracted-chunks-basic"], (chunks) => { - let changed = false; - chunks.forEach((chunk) => { - chunk.forEachModule((module) => { - if(!module.chunkCondition) return; - if(!module.chunkCondition(chunk)) { - let usedChunks = triesMap.get(module); - if(!usedChunks) triesMap.set(module, usedChunks = new Set()); - usedChunks.add(chunk); - const newChunks = []; - chunk.parents.forEach((parent) => { - if(!usedChunks.has(parent)) { - parent.addModule(module); - module.addChunk(parent); - newChunks.push(parent); - } - }); - module.rewriteChunkInReasons(chunk, newChunks); - chunk.removeModule(module); - changed = true; - } - }); - }); - if(changed) return true; - }); - }); - } -} -module.exports = EnsureChunkConditionsPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const GraphHelpers = require("../GraphHelpers"); + +class EnsureChunkConditionsPlugin { + apply(compiler) { + compiler.hooks.compilation.tap( + "EnsureChunkConditionsPlugin", + compilation => { + const handler = chunks => { + let changed = false; + for (const module of compilation.modules) { + if (!module.chunkCondition) continue; + const sourceChunks = new Set(); + const chunkGroups = new Set(); + for (const chunk of module.chunksIterable) { + if (!module.chunkCondition(chunk)) { + sourceChunks.add(chunk); + for (const group of chunk.groupsIterable) { + chunkGroups.add(group); + } + } + } + if (sourceChunks.size === 0) continue; + const targetChunks = new Set(); + chunkGroupLoop: for (const chunkGroup of chunkGroups) { + // Can module be placed in a chunk of this group? + for (const chunk of chunkGroup.chunks) { + if (module.chunkCondition(chunk)) { + targetChunks.add(chunk); + continue chunkGroupLoop; + } + } + // We reached the entrypoint: fail + if (chunkGroup.isInitial()) { + throw new Error( + "Cannot fullfil chunk condition of " + module.identifier() + ); + } + // Try placing in all parents + for (const group of chunkGroup.parentsIterable) { + chunkGroups.add(group); + } + } + for (const sourceChunk of sourceChunks) { + GraphHelpers.disconnectChunkAndModule(sourceChunk, module); + } + for (const targetChunk of targetChunks) { + GraphHelpers.connectChunkAndModule(targetChunk, module); + } + } + if (changed) return true; + }; + compilation.hooks.optimizeChunksBasic.tap( + "EnsureChunkConditionsPlugin", + handler + ); + compilation.hooks.optimizeExtractedChunksBasic.tap( + "EnsureChunkConditionsPlugin", + handler + ); + } + ); + } +} +module.exports = EnsureChunkConditionsPlugin; diff --git a/node_modules/webpack/lib/optimize/FlagIncludedChunksPlugin.js b/node_modules/webpack/lib/optimize/FlagIncludedChunksPlugin.js index 75277b5aa..1890f0581 100644 --- a/node_modules/webpack/lib/optimize/FlagIncludedChunksPlugin.js +++ b/node_modules/webpack/lib/optimize/FlagIncludedChunksPlugin.js @@ -1,35 +1,99 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class FlagIncludedChunksPlugin { - - apply(compiler) { - compiler.plugin("compilation", (compilation) => { - compilation.plugin("optimize-chunk-ids", (chunks) => { - chunks.forEach((chunkA) => { - chunks.forEach((chunkB) => { - // as we iterate the same iterables twice - // skip if we find ourselves - if(chunkA === chunkB) return; - - // instead of swapping A and B just bail - // as we loop twice the current A will be B and B then A - if(chunkA.getNumberOfModules() < chunkB.getNumberOfModules()) return; - - if(chunkB.getNumberOfModules() === 0) return; - - // is chunkB in chunkA? - for(const m of chunkB.modulesIterable) { - if(!chunkA.containsModule(m)) return; - } - chunkA.ids.push(chunkB.id); - }); - }); - }); - }); - } -} -module.exports = FlagIncludedChunksPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +class FlagIncludedChunksPlugin { + apply(compiler) { + compiler.hooks.compilation.tap("FlagIncludedChunksPlugin", compilation => { + compilation.hooks.optimizeChunkIds.tap( + "FlagIncludedChunksPlugin", + chunks => { + // prepare two bit integers for each module + // 2^31 is the max number represented as SMI in v8 + // we want the bits distributed this way: + // the bit 2^31 is pretty rar and only one module should get it + // so it has a probability of 1 / modulesCount + // the first bit (2^0) is the easiest and every module could get it + // if it doesn't get a better bit + // from bit 2^n to 2^(n+1) there is a probability of p + // so 1 / modulesCount == p^31 + // <=> p = sqrt31(1 / modulesCount) + // so we use a modulo of 1 / sqrt31(1 / modulesCount) + const moduleBits = new WeakMap(); + const modulesCount = compilation.modules.length; + + // precalculate the modulo values for each bit + const modulo = 1 / Math.pow(1 / modulesCount, 1 / 31); + const modulos = Array.from( + { length: 31 }, + (x, i) => Math.pow(modulo, i) | 0 + ); + + // iterate all modules to generate bit values + let i = 0; + for (const module of compilation.modules) { + let bit = 30; + while (i % modulos[bit] !== 0) { + bit--; + } + moduleBits.set(module, 1 << bit); + i++; + } + + // interate all chunks to generate bitmaps + const chunkModulesHash = new WeakMap(); + for (const chunk of chunks) { + let hash = 0; + for (const module of chunk.modulesIterable) { + hash |= moduleBits.get(module); + } + chunkModulesHash.set(chunk, hash); + } + + for (const chunkA of chunks) { + const chunkAHash = chunkModulesHash.get(chunkA); + const chunkAModulesCount = chunkA.getNumberOfModules(); + if (chunkAModulesCount === 0) continue; + let bestModule = undefined; + for (const module of chunkA.modulesIterable) { + if ( + bestModule === undefined || + bestModule.getNumberOfChunks() > module.getNumberOfChunks() + ) + bestModule = module; + } + loopB: for (const chunkB of bestModule.chunksIterable) { + // as we iterate the same iterables twice + // skip if we find ourselves + if (chunkA === chunkB) continue; + + const chunkBModulesCount = chunkB.getNumberOfModules(); + + // ids for empty chunks are not included + if (chunkBModulesCount === 0) continue; + + // instead of swapping A and B just bail + // as we loop twice the current A will be B and B then A + if (chunkAModulesCount > chunkBModulesCount) continue; + + // is chunkA in chunkB? + + // we do a cheap check for the hash value + const chunkBHash = chunkModulesHash.get(chunkB); + if ((chunkBHash & chunkAHash) !== chunkAHash) continue; + + // compare all modules + for (const m of chunkA.modulesIterable) { + if (!chunkB.containsModule(m)) continue loopB; + } + chunkB.ids.push(chunkA.id); + } + } + } + ); + }); + } +} +module.exports = FlagIncludedChunksPlugin; diff --git a/node_modules/webpack/lib/optimize/LimitChunkCountPlugin.js b/node_modules/webpack/lib/optimize/LimitChunkCountPlugin.js index c156338ff..f38b942b1 100644 --- a/node_modules/webpack/lib/optimize/LimitChunkCountPlugin.js +++ b/node_modules/webpack/lib/optimize/LimitChunkCountPlugin.js @@ -1,59 +1,66 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class LimitChunkCountPlugin { - constructor(options) { - if(options !== undefined && typeof options !== "object" || Array.isArray(options)) { - throw new Error("Argument should be an options object.\nFor more info on options, see https://webpack.js.org/plugins/"); - } - this.options = options || {}; - } - apply(compiler) { - const options = this.options; - compiler.plugin("compilation", (compilation) => { - compilation.plugin("optimize-chunks-advanced", (chunks) => { - const maxChunks = options.maxChunks; - if(!maxChunks) return; - if(maxChunks < 1) return; - if(chunks.length <= maxChunks) return; - - if(chunks.length > maxChunks) { - const sortedExtendedPairCombinations = chunks.reduce((combinations, a, idx) => { - // create combination pairs - for(let i = 0; i < idx; i++) { - const b = chunks[i]; - combinations.push([b, a]); - } - return combinations; - }, []).map((pair) => { - // extend combination pairs with size and integrated size - const a = pair[0].size(options); - const b = pair[1].size(options); - const ab = pair[0].integratedSize(pair[1], options); - return [a + b - ab, ab, pair[0], pair[1], a, b]; - }).filter((extendedPair) => { - // filter pairs that do not have an integratedSize - // meaning they can NOT be integrated! - return extendedPair[1] !== false; - }).sort((a, b) => { // sadly javascript does an inplace sort here - // sort them by size - const diff = b[0] - a[0]; - if(diff !== 0) return diff; - return a[1] - b[1]; - }); - - const pair = sortedExtendedPairCombinations[0]; - - if(pair && pair[2].integrate(pair[3], "limit")) { - chunks.splice(chunks.indexOf(pair[3]), 1); - return true; - } - } - }); - }); - } -} -module.exports = LimitChunkCountPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const validateOptions = require("schema-utils"); +const schema = require("../../schemas/plugins/optimize/LimitChunkCountPlugin.json"); + +class LimitChunkCountPlugin { + constructor(options) { + validateOptions(schema, options || {}, "Limit Chunk Count Plugin"); + this.options = options || {}; + } + apply(compiler) { + const options = this.options; + compiler.hooks.compilation.tap("LimitChunkCountPlugin", compilation => { + compilation.hooks.optimizeChunksAdvanced.tap( + "LimitChunkCountPlugin", + chunks => { + const maxChunks = options.maxChunks; + if (!maxChunks) return; + if (maxChunks < 1) return; + if (chunks.length <= maxChunks) return; + + const sortedExtendedPairCombinations = chunks + .reduce((combinations, a, idx) => { + // create combination pairs + for (let i = 0; i < idx; i++) { + const b = chunks[i]; + combinations.push([b, a]); + } + return combinations; + }, []) + .map(pair => { + // extend combination pairs with size and integrated size + const a = pair[0].size(options); + const b = pair[1].size(options); + const ab = pair[0].integratedSize(pair[1], options); + return [a + b - ab, ab, pair[0], pair[1], a, b]; + }) + .filter(extendedPair => { + // filter pairs that do not have an integratedSize + // meaning they can NOT be integrated! + return extendedPair[1] !== false; + }) + .sort((a, b) => { + // sadly javascript does an inplace sort here + // sort them by size + const diff = b[0] - a[0]; + if (diff !== 0) return diff; + return a[1] - b[1]; + }); + + const pair = sortedExtendedPairCombinations[0]; + + if (pair && pair[2].integrate(pair[3], "limit")) { + chunks.splice(chunks.indexOf(pair[3]), 1); + return true; + } + } + ); + }); + } +} +module.exports = LimitChunkCountPlugin; diff --git a/node_modules/webpack/lib/optimize/MergeDuplicateChunksPlugin.js b/node_modules/webpack/lib/optimize/MergeDuplicateChunksPlugin.js index 7b006fd17..1c3e23aa3 100644 --- a/node_modules/webpack/lib/optimize/MergeDuplicateChunksPlugin.js +++ b/node_modules/webpack/lib/optimize/MergeDuplicateChunksPlugin.js @@ -1,28 +1,78 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class MergeDuplicateChunksPlugin { - - apply(compiler) { - compiler.plugin("compilation", (compilation) => { - compilation.plugin("optimize-chunks-basic", (chunks) => { - const map = Object.create(null); - chunks.slice().forEach((chunk) => { - if(chunk.hasRuntime() || chunk.hasEntryModule()) return; - const ident = chunk.getModulesIdent(); - const otherChunk = map[ident]; - if(otherChunk) { - if(otherChunk.integrate(chunk, "duplicate")) - chunks.splice(chunks.indexOf(chunk), 1); - return; - } - map[ident] = chunk; - }); - }); - }); - } -} -module.exports = MergeDuplicateChunksPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +class MergeDuplicateChunksPlugin { + apply(compiler) { + compiler.hooks.compilation.tap( + "MergeDuplicateChunksPlugin", + compilation => { + compilation.hooks.optimizeChunksBasic.tap( + "MergeDuplicateChunksPlugin", + chunks => { + // remember already tested chunks for performance + const notDuplicates = new Set(); + + // for each chunk + for (const chunk of chunks) { + // track a Set of all chunk that could be duplicates + let possibleDuplicates; + for (const module of chunk.modulesIterable) { + if (possibleDuplicates === undefined) { + // when possibleDuplicates is not yet set, + // create a new Set from chunks of the current module + // including only chunks with the same number of modules + for (const dup of module.chunksIterable) { + if ( + dup !== chunk && + chunk.getNumberOfModules() === dup.getNumberOfModules() && + !notDuplicates.has(dup) + ) { + // delay allocating the new Set until here, reduce memory pressure + if (possibleDuplicates === undefined) { + possibleDuplicates = new Set(); + } + possibleDuplicates.add(dup); + } + } + // when no chunk is possible we can break here + if (possibleDuplicates === undefined) break; + } else { + // validate existing possible duplicates + for (const dup of possibleDuplicates) { + // remove possible duplicate when module is not contained + if (!dup.containsModule(module)) { + possibleDuplicates.delete(dup); + } + } + // when all chunks has been removed we can break here + if (possibleDuplicates.size === 0) break; + } + } + + // when we found duplicates + if ( + possibleDuplicates !== undefined && + possibleDuplicates.size > 0 + ) { + for (const otherChunk of possibleDuplicates) { + if (otherChunk.hasRuntime() !== chunk.hasRuntime()) continue; + // merge them + if (chunk.integrate(otherChunk, "duplicate")) { + chunks.splice(chunks.indexOf(otherChunk), 1); + } + } + } + + // don't check already processed chunks twice + notDuplicates.add(chunk); + } + } + ); + } + ); + } +} +module.exports = MergeDuplicateChunksPlugin; diff --git a/node_modules/webpack/lib/optimize/MinChunkSizePlugin.js b/node_modules/webpack/lib/optimize/MinChunkSizePlugin.js index 87a4c21af..0f3893910 100644 --- a/node_modules/webpack/lib/optimize/MinChunkSizePlugin.js +++ b/node_modules/webpack/lib/optimize/MinChunkSizePlugin.js @@ -1,65 +1,77 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class MinChunkSizePlugin { - constructor(options) { - if(typeof options !== "object" || Array.isArray(options)) { - throw new Error("Argument should be an options object.\nFor more info on options, see https://webpack.js.org/plugins/"); - } - this.options = options; - } - - apply(compiler) { - const options = this.options; - const minChunkSize = options.minChunkSize; - compiler.plugin("compilation", (compilation) => { - compilation.plugin("optimize-chunks-advanced", (chunks) => { - const equalOptions = { - chunkOverhead: 1, - entryChunkMultiplicator: 1 - }; - - const sortedSizeFilteredExtendedPairCombinations = chunks.reduce((combinations, a, idx) => { - // create combination pairs - for(let i = 0; i < idx; i++) { - const b = chunks[i]; - combinations.push([b, a]); - } - return combinations; - }, []).filter((pair) => { - // check if one of the chunks sizes is smaller than the minChunkSize - const p0SmallerThanMinChunkSize = pair[0].size(equalOptions) < minChunkSize; - const p1SmallerThanMinChunkSize = pair[1].size(equalOptions) < minChunkSize; - return p0SmallerThanMinChunkSize || p1SmallerThanMinChunkSize; - }).map((pair) => { - // extend combination pairs with size and integrated size - const a = pair[0].size(options); - const b = pair[1].size(options); - const ab = pair[0].integratedSize(pair[1], options); - return [a + b - ab, ab, pair[0], pair[1]]; - }).filter((pair) => { - // filter pairs that do not have an integratedSize - // meaning they can NOT be integrated! - return pair[1] !== false; - }).sort((a, b) => { // sadly javascript does an inplace sort here - // sort by size - const diff = b[0] - a[0]; - if(diff !== 0) return diff; - return a[1] - b[1]; - }); - - if(sortedSizeFilteredExtendedPairCombinations.length === 0) return; - - const pair = sortedSizeFilteredExtendedPairCombinations[0]; - - pair[2].integrate(pair[3], "min-size"); - chunks.splice(chunks.indexOf(pair[3]), 1); - return true; - }); - }); - } -} -module.exports = MinChunkSizePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const validateOptions = require("schema-utils"); +const schema = require("../../schemas/plugins/optimize/MinChunkSizePlugin.json"); + +class MinChunkSizePlugin { + constructor(options) { + validateOptions(schema, options, "Min Chunk Size Plugin"); + this.options = options; + } + + apply(compiler) { + const options = this.options; + const minChunkSize = options.minChunkSize; + compiler.hooks.compilation.tap("MinChunkSizePlugin", compilation => { + compilation.hooks.optimizeChunksAdvanced.tap( + "MinChunkSizePlugin", + chunks => { + const equalOptions = { + chunkOverhead: 1, + entryChunkMultiplicator: 1 + }; + + const sortedSizeFilteredExtendedPairCombinations = chunks + .reduce((combinations, a, idx) => { + // create combination pairs + for (let i = 0; i < idx; i++) { + const b = chunks[i]; + combinations.push([b, a]); + } + return combinations; + }, []) + .filter(pair => { + // check if one of the chunks sizes is smaller than the minChunkSize + const p0SmallerThanMinChunkSize = + pair[0].size(equalOptions) < minChunkSize; + const p1SmallerThanMinChunkSize = + pair[1].size(equalOptions) < minChunkSize; + return p0SmallerThanMinChunkSize || p1SmallerThanMinChunkSize; + }) + .map(pair => { + // extend combination pairs with size and integrated size + const a = pair[0].size(options); + const b = pair[1].size(options); + const ab = pair[0].integratedSize(pair[1], options); + return [a + b - ab, ab, pair[0], pair[1]]; + }) + .filter(pair => { + // filter pairs that do not have an integratedSize + // meaning they can NOT be integrated! + return pair[1] !== false; + }) + .sort((a, b) => { + // sadly javascript does an inplace sort here + // sort by size + const diff = b[0] - a[0]; + if (diff !== 0) return diff; + return a[1] - b[1]; + }); + + if (sortedSizeFilteredExtendedPairCombinations.length === 0) return; + + const pair = sortedSizeFilteredExtendedPairCombinations[0]; + + pair[2].integrate(pair[3], "min-size"); + chunks.splice(chunks.indexOf(pair[3]), 1); + return true; + } + ); + }); + } +} +module.exports = MinChunkSizePlugin; diff --git a/node_modules/webpack/lib/optimize/ModuleConcatenationPlugin.js b/node_modules/webpack/lib/optimize/ModuleConcatenationPlugin.js index 8a6a660cb..15b7d796a 100644 --- a/node_modules/webpack/lib/optimize/ModuleConcatenationPlugin.js +++ b/node_modules/webpack/lib/optimize/ModuleConcatenationPlugin.js @@ -1,308 +1,483 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency"); -const ModuleHotAcceptDependency = require("../dependencies/ModuleHotAcceptDependency"); -const ModuleHotDeclineDependency = require("../dependencies/ModuleHotDeclineDependency"); -const ConcatenatedModule = require("./ConcatenatedModule"); -const HarmonyExportImportedSpecifierDependency = require("../dependencies/HarmonyExportImportedSpecifierDependency"); -const HarmonyCompatibilityDependency = require("../dependencies/HarmonyCompatibilityDependency"); - -function formatBailoutReason(msg) { - return "ModuleConcatenation bailout: " + msg; -} - -class ModuleConcatenationPlugin { - constructor(options) { - if(typeof options !== "object") options = {}; - this.options = options; - } - - apply(compiler) { - compiler.plugin("compilation", (compilation, params) => { - params.normalModuleFactory.plugin("parser", (parser, parserOptions) => { - parser.plugin("call eval", () => { - parser.state.module.meta.hasEval = true; - }); - }); - const bailoutReasonMap = new Map(); - - function setBailoutReason(module, reason) { - bailoutReasonMap.set(module, reason); - module.optimizationBailout.push(typeof reason === "function" ? (rs) => formatBailoutReason(reason(rs)) : formatBailoutReason(reason)); - } - - function getBailoutReason(module, requestShortener) { - const reason = bailoutReasonMap.get(module); - if(typeof reason === "function") return reason(requestShortener); - return reason; - } - - compilation.plugin("optimize-chunk-modules", (chunks, modules) => { - const relevantModules = []; - const possibleInners = new Set(); - for(const module of modules) { - // Only harmony modules are valid for optimization - if(!module.meta || !module.meta.harmonyModule || !module.dependencies.some(d => d instanceof HarmonyCompatibilityDependency)) { - setBailoutReason(module, "Module is not an ECMAScript module"); - continue; - } - - // Because of variable renaming we can't use modules with eval - if(module.meta && module.meta.hasEval) { - setBailoutReason(module, "Module uses eval()"); - continue; - } - - // Exports must be known (and not dynamic) - if(!Array.isArray(module.providedExports)) { - setBailoutReason(module, "Module exports are unknown"); - continue; - } - - // Using dependency variables is not possible as this wraps the code in a function - if(module.variables.length > 0) { - setBailoutReason(module, `Module uses injected variables (${module.variables.map(v => v.name).join(", ")})`); - continue; - } - - // Hot Module Replacement need it's own module to work correctly - if(module.dependencies.some(dep => dep instanceof ModuleHotAcceptDependency || dep instanceof ModuleHotDeclineDependency)) { - setBailoutReason(module, "Module uses Hot Module Replacement"); - continue; - } - - relevantModules.push(module); - - // Module must not be the entry points - if(module.getChunks().some(chunk => chunk.entryModule === module)) { - setBailoutReason(module, "Module is an entry point"); - continue; - } - - // Module must only be used by Harmony Imports - const nonHarmonyReasons = module.reasons.filter(reason => !(reason.dependency instanceof HarmonyImportDependency)); - if(nonHarmonyReasons.length > 0) { - const importingModules = new Set(nonHarmonyReasons.map(r => r.module)); - const importingModuleTypes = new Map(Array.from(importingModules).map(m => [m, new Set(nonHarmonyReasons.filter(r => r.module === m).map(r => r.dependency.type).sort())])); - setBailoutReason(module, (requestShortener) => { - const names = Array.from(importingModules).map(m => `${m.readableIdentifier(requestShortener)} (referenced with ${Array.from(importingModuleTypes.get(m)).join(", ")})`).sort(); - return `Module is referenced from these modules with unsupported syntax: ${names.join(", ")}`; - }); - continue; - } - - possibleInners.add(module); - } - // sort by depth - // modules with lower depth are more likely suited as roots - // this improves performance, because modules already selected as inner are skipped - relevantModules.sort((a, b) => { - return a.depth - b.depth; - }); - const concatConfigurations = []; - const usedAsInner = new Set(); - for(const currentRoot of relevantModules) { - // when used by another configuration as inner: - // the other configuration is better and we can skip this one - if(usedAsInner.has(currentRoot)) - continue; - - // create a configuration with the root - const currentConfiguration = new ConcatConfiguration(currentRoot); - - // cache failures to add modules - const failureCache = new Map(); - - // try to add all imports - for(const imp of this.getImports(currentRoot)) { - const problem = this.tryToAdd(currentConfiguration, imp, possibleInners, failureCache); - if(problem) { - failureCache.set(imp, problem); - currentConfiguration.addWarning(imp, problem); - } - } - if(!currentConfiguration.isEmpty()) { - concatConfigurations.push(currentConfiguration); - for(const module of currentConfiguration.modules) { - if(module !== currentConfiguration.rootModule) - usedAsInner.add(module); - } - } - } - // HACK: Sort configurations by length and start with the longest one - // to get the biggers groups possible. Used modules are marked with usedModules - // TODO: Allow to reuse existing configuration while trying to add dependencies. - // This would improve performance. O(n^2) -> O(n) - concatConfigurations.sort((a, b) => { - return b.modules.size - a.modules.size; - }); - const usedModules = new Set(); - for(const concatConfiguration of concatConfigurations) { - if(usedModules.has(concatConfiguration.rootModule)) - continue; - const newModule = new ConcatenatedModule(concatConfiguration.rootModule, Array.from(concatConfiguration.modules)); - concatConfiguration.sortWarnings(); - for(const warning of concatConfiguration.warnings) { - newModule.optimizationBailout.push((requestShortener) => { - const reason = getBailoutReason(warning[0], requestShortener); - const reasonWithPrefix = reason ? ` (<- ${reason})` : ""; - if(warning[0] === warning[1]) - return formatBailoutReason(`Cannot concat with ${warning[0].readableIdentifier(requestShortener)}${reasonWithPrefix}`); - else - return formatBailoutReason(`Cannot concat with ${warning[0].readableIdentifier(requestShortener)} because of ${warning[1].readableIdentifier(requestShortener)}${reasonWithPrefix}`); - }); - } - const chunks = concatConfiguration.rootModule.getChunks(); - for(const m of concatConfiguration.modules) { - usedModules.add(m); - chunks.forEach(chunk => chunk.removeModule(m)); - } - chunks.forEach(chunk => { - chunk.addModule(newModule); - newModule.addChunk(chunk); - if(chunk.entryModule === concatConfiguration.rootModule) - chunk.entryModule = newModule; - }); - compilation.modules.push(newModule); - newModule.reasons.forEach(reason => reason.dependency.module = newModule); - newModule.dependencies.forEach(dep => { - if(dep.module) { - dep.module.reasons.forEach(reason => { - if(reason.dependency === dep) - reason.module = newModule; - }); - } - }); - } - compilation.modules = compilation.modules.filter(m => !usedModules.has(m)); - }); - }); - } - - getImports(module) { - return Array.from(new Set(module.dependencies - - // Only harmony Dependencies - .filter(dep => dep instanceof HarmonyImportDependency && dep.module) - - // Dependencies are simple enough to concat them - .filter(dep => { - return !module.dependencies.some(d => - d instanceof HarmonyExportImportedSpecifierDependency && - d.importDependency === dep && - !d.id && - !Array.isArray(dep.module.providedExports) - ); - }) - - // Take the imported module - .map(dep => dep.module) - )); - } - - tryToAdd(config, module, possibleModules, failureCache) { - const cacheEntry = failureCache.get(module); - if(cacheEntry) { - return cacheEntry; - } - - // Already added? - if(config.has(module)) { - return null; - } - - // Not possible to add? - if(!possibleModules.has(module)) { - failureCache.set(module, module); // cache failures for performance - return module; - } - - // module must be in the same chunks - if(!config.rootModule.hasEqualsChunks(module)) { - failureCache.set(module, module); // cache failures for performance - return module; - } - - // Clone config to make experimental changes - const testConfig = config.clone(); - - // Add the module - testConfig.add(module); - - // Every module which depends on the added module must be in the configuration too. - for(const reason of module.reasons) { - const problem = this.tryToAdd(testConfig, reason.module, possibleModules, failureCache); - if(problem) { - failureCache.set(module, problem); // cache failures for performance - return problem; - } - } - - // Eagerly try to add imports too if possible - for(const imp of this.getImports(module)) { - const problem = this.tryToAdd(testConfig, imp, possibleModules, failureCache); - if(problem) { - config.addWarning(module, problem); - } - } - - // Commit experimental changes - config.set(testConfig); - return null; - } -} - -class ConcatConfiguration { - constructor(rootModule) { - this.rootModule = rootModule; - this.modules = new Set([rootModule]); - this.warnings = new Map(); - } - - add(module) { - this.modules.add(module); - } - - has(module) { - return this.modules.has(module); - } - - isEmpty() { - return this.modules.size === 1; - } - - addWarning(module, problem) { - this.warnings.set(module, problem); - } - - sortWarnings() { - this.warnings = new Map(Array.from(this.warnings).sort((a, b) => { - const ai = a[0].identifier(); - const bi = b[0].identifier(); - if(ai < bi) return -1; - if(ai > bi) return 1; - return 0; - })); - } - - clone() { - const clone = new ConcatConfiguration(this.rootModule); - for(const module of this.modules) - clone.add(module); - for(const pair of this.warnings) - clone.addWarning(pair[0], pair[1]); - return clone; - } - - set(config) { - this.rootModule = config.rootModule; - this.modules = new Set(config.modules); - this.warnings = new Map(config.warnings); - } -} - -module.exports = ModuleConcatenationPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency"); +const ModuleHotAcceptDependency = require("../dependencies/ModuleHotAcceptDependency"); +const ModuleHotDeclineDependency = require("../dependencies/ModuleHotDeclineDependency"); +const ConcatenatedModule = require("./ConcatenatedModule"); +const HarmonyCompatibilityDependency = require("../dependencies/HarmonyCompatibilityDependency"); +const StackedSetMap = require("../util/StackedSetMap"); + +const formatBailoutReason = msg => { + return "ModuleConcatenation bailout: " + msg; +}; + +class ModuleConcatenationPlugin { + constructor(options) { + if (typeof options !== "object") options = {}; + this.options = options; + } + + apply(compiler) { + compiler.hooks.compilation.tap( + "ModuleConcatenationPlugin", + (compilation, { normalModuleFactory }) => { + const handler = (parser, parserOptions) => { + parser.hooks.call.for("eval").tap("ModuleConcatenationPlugin", () => { + // Because of variable renaming we can't use modules with eval. + parser.state.module.buildMeta.moduleConcatenationBailout = "eval()"; + }); + }; + + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("ModuleConcatenationPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/dynamic") + .tap("ModuleConcatenationPlugin", handler); + normalModuleFactory.hooks.parser + .for("javascript/esm") + .tap("ModuleConcatenationPlugin", handler); + + const bailoutReasonMap = new Map(); + + const setBailoutReason = (module, reason) => { + bailoutReasonMap.set(module, reason); + module.optimizationBailout.push( + typeof reason === "function" + ? rs => formatBailoutReason(reason(rs)) + : formatBailoutReason(reason) + ); + }; + + const getBailoutReason = (module, requestShortener) => { + const reason = bailoutReasonMap.get(module); + if (typeof reason === "function") return reason(requestShortener); + return reason; + }; + + compilation.hooks.optimizeChunkModules.tap( + "ModuleConcatenationPlugin", + (chunks, modules) => { + const relevantModules = []; + const possibleInners = new Set(); + for (const module of modules) { + // Only harmony modules are valid for optimization + if ( + !module.buildMeta || + module.buildMeta.exportsType !== "namespace" || + !module.dependencies.some( + d => d instanceof HarmonyCompatibilityDependency + ) + ) { + setBailoutReason(module, "Module is not an ECMAScript module"); + continue; + } + + // Some expressions are not compatible with module concatenation + // because they may produce unexpected results. The plugin bails out + // if some were detected upfront. + if ( + module.buildMeta && + module.buildMeta.moduleConcatenationBailout + ) { + setBailoutReason( + module, + `Module uses ${module.buildMeta.moduleConcatenationBailout}` + ); + continue; + } + + // Exports must be known (and not dynamic) + if (!Array.isArray(module.buildMeta.providedExports)) { + setBailoutReason(module, "Module exports are unknown"); + continue; + } + + // Using dependency variables is not possible as this wraps the code in a function + if (module.variables.length > 0) { + setBailoutReason( + module, + `Module uses injected variables (${module.variables + .map(v => v.name) + .join(", ")})` + ); + continue; + } + + // Hot Module Replacement need it's own module to work correctly + if ( + module.dependencies.some( + dep => + dep instanceof ModuleHotAcceptDependency || + dep instanceof ModuleHotDeclineDependency + ) + ) { + setBailoutReason(module, "Module uses Hot Module Replacement"); + continue; + } + + relevantModules.push(module); + + // Module must not be the entry points + if (module.isEntryModule()) { + setBailoutReason(module, "Module is an entry point"); + continue; + } + + // Module must be in any chunk (we don't want to do useless work) + if (module.getNumberOfChunks() === 0) { + setBailoutReason(module, "Module is not in any chunk"); + continue; + } + + // Module must only be used by Harmony Imports + const nonHarmonyReasons = module.reasons.filter( + reason => + !reason.dependency || + !(reason.dependency instanceof HarmonyImportDependency) + ); + if (nonHarmonyReasons.length > 0) { + const importingModules = new Set( + nonHarmonyReasons.map(r => r.module).filter(Boolean) + ); + const importingExplanations = new Set( + nonHarmonyReasons.map(r => r.explanation).filter(Boolean) + ); + const importingModuleTypes = new Map( + Array.from(importingModules).map( + m => /** @type {[string, Set]} */ ([ + m, + new Set( + nonHarmonyReasons + .filter(r => r.module === m) + .map(r => r.dependency.type) + .sort() + ) + ]) + ) + ); + setBailoutReason(module, requestShortener => { + const names = Array.from(importingModules) + .map( + m => + `${m.readableIdentifier( + requestShortener + )} (referenced with ${Array.from( + importingModuleTypes.get(m) + ).join(", ")})` + ) + .sort(); + const explanations = Array.from(importingExplanations).sort(); + if (names.length > 0 && explanations.length === 0) { + return `Module is referenced from these modules with unsupported syntax: ${names.join( + ", " + )}`; + } else if (names.length === 0 && explanations.length > 0) { + return `Module is referenced by: ${explanations.join( + ", " + )}`; + } else if (names.length > 0 && explanations.length > 0) { + return `Module is referenced from these modules with unsupported syntax: ${names.join( + ", " + )} and by: ${explanations.join(", ")}`; + } else { + return "Module is referenced in a unsupported way"; + } + }); + continue; + } + + possibleInners.add(module); + } + // sort by depth + // modules with lower depth are more likely suited as roots + // this improves performance, because modules already selected as inner are skipped + relevantModules.sort((a, b) => { + return a.depth - b.depth; + }); + const concatConfigurations = []; + const usedAsInner = new Set(); + for (const currentRoot of relevantModules) { + // when used by another configuration as inner: + // the other configuration is better and we can skip this one + if (usedAsInner.has(currentRoot)) continue; + + // create a configuration with the root + const currentConfiguration = new ConcatConfiguration(currentRoot); + + // cache failures to add modules + const failureCache = new Map(); + + // try to add all imports + for (const imp of this._getImports(compilation, currentRoot)) { + const problem = this._tryToAdd( + compilation, + currentConfiguration, + imp, + possibleInners, + failureCache + ); + if (problem) { + failureCache.set(imp, problem); + currentConfiguration.addWarning(imp, problem); + } + } + if (!currentConfiguration.isEmpty()) { + concatConfigurations.push(currentConfiguration); + for (const module of currentConfiguration.getModules()) { + if (module !== currentConfiguration.rootModule) { + usedAsInner.add(module); + } + } + } + } + // HACK: Sort configurations by length and start with the longest one + // to get the biggers groups possible. Used modules are marked with usedModules + // TODO: Allow to reuse existing configuration while trying to add dependencies. + // This would improve performance. O(n^2) -> O(n) + concatConfigurations.sort((a, b) => { + return b.modules.size - a.modules.size; + }); + const usedModules = new Set(); + for (const concatConfiguration of concatConfigurations) { + if (usedModules.has(concatConfiguration.rootModule)) continue; + const modules = concatConfiguration.getModules(); + const rootModule = concatConfiguration.rootModule; + const newModule = new ConcatenatedModule( + rootModule, + Array.from(modules), + ConcatenatedModule.createConcatenationList( + rootModule, + modules, + compilation + ) + ); + for (const warning of concatConfiguration.getWarningsSorted()) { + newModule.optimizationBailout.push(requestShortener => { + const reason = getBailoutReason(warning[0], requestShortener); + const reasonWithPrefix = reason ? ` (<- ${reason})` : ""; + if (warning[0] === warning[1]) { + return formatBailoutReason( + `Cannot concat with ${warning[0].readableIdentifier( + requestShortener + )}${reasonWithPrefix}` + ); + } else { + return formatBailoutReason( + `Cannot concat with ${warning[0].readableIdentifier( + requestShortener + )} because of ${warning[1].readableIdentifier( + requestShortener + )}${reasonWithPrefix}` + ); + } + }); + } + const chunks = concatConfiguration.rootModule.getChunks(); + for (const m of modules) { + usedModules.add(m); + for (const chunk of chunks) { + chunk.removeModule(m); + } + } + for (const chunk of chunks) { + chunk.addModule(newModule); + newModule.addChunk(chunk); + if (chunk.entryModule === concatConfiguration.rootModule) { + chunk.entryModule = newModule; + } + } + compilation.modules.push(newModule); + for (const reason of newModule.reasons) { + if (reason.dependency.module === concatConfiguration.rootModule) + reason.dependency.module = newModule; + if ( + reason.dependency.redirectedModule === + concatConfiguration.rootModule + ) + reason.dependency.redirectedModule = newModule; + } + // TODO: remove when LTS node version contains fixed v8 version + // @see https://github.com/webpack/webpack/pull/6613 + // Turbofan does not correctly inline for-of loops with polymorphic input arrays. + // Work around issue by using a standard for loop and assigning dep.module.reasons + for (let i = 0; i < newModule.dependencies.length; i++) { + let dep = newModule.dependencies[i]; + if (dep.module) { + let reasons = dep.module.reasons; + for (let j = 0; j < reasons.length; j++) { + let reason = reasons[j]; + if (reason.dependency === dep) { + reason.module = newModule; + } + } + } + } + } + compilation.modules = compilation.modules.filter( + m => !usedModules.has(m) + ); + } + ); + } + ); + } + + _getImports(compilation, module) { + return new Set( + module.dependencies + + // Get reference info only for harmony Dependencies + .map(dep => { + if (!(dep instanceof HarmonyImportDependency)) return null; + if (!compilation) return dep.getReference(); + return compilation.getDependencyReference(module, dep); + }) + + // Reference is valid and has a module + // Dependencies are simple enough to concat them + .filter( + ref => + ref && + ref.module && + (Array.isArray(ref.importedNames) || + Array.isArray(ref.module.buildMeta.providedExports)) + ) + + // Take the imported module + .map(ref => ref.module) + ); + } + + _tryToAdd(compilation, config, module, possibleModules, failureCache) { + const cacheEntry = failureCache.get(module); + if (cacheEntry) { + return cacheEntry; + } + + // Already added? + if (config.has(module)) { + return null; + } + + // Not possible to add? + if (!possibleModules.has(module)) { + failureCache.set(module, module); // cache failures for performance + return module; + } + + // module must be in the same chunks + if (!config.rootModule.hasEqualsChunks(module)) { + failureCache.set(module, module); // cache failures for performance + return module; + } + + // Clone config to make experimental changes + const testConfig = config.clone(); + + // Add the module + testConfig.add(module); + + // Every module which depends on the added module must be in the configuration too. + for (const reason of module.reasons) { + // Modules that are not used can be ignored + if ( + reason.module.factoryMeta.sideEffectFree && + reason.module.used === false + ) + continue; + + const problem = this._tryToAdd( + compilation, + testConfig, + reason.module, + possibleModules, + failureCache + ); + if (problem) { + failureCache.set(module, problem); // cache failures for performance + return problem; + } + } + + // Commit experimental changes + config.set(testConfig); + + // Eagerly try to add imports too if possible + for (const imp of this._getImports(compilation, module)) { + const problem = this._tryToAdd( + compilation, + config, + imp, + possibleModules, + failureCache + ); + if (problem) { + config.addWarning(imp, problem); + } + } + return null; + } +} + +class ConcatConfiguration { + constructor(rootModule, cloneFrom) { + this.rootModule = rootModule; + if (cloneFrom) { + this.modules = cloneFrom.modules.createChild(5); + this.warnings = cloneFrom.warnings.createChild(5); + } else { + this.modules = new StackedSetMap(); + this.modules.add(rootModule); + this.warnings = new StackedSetMap(); + } + } + + add(module) { + this.modules.add(module); + } + + has(module) { + return this.modules.has(module); + } + + isEmpty() { + return this.modules.size === 1; + } + + addWarning(module, problem) { + this.warnings.set(module, problem); + } + + getWarningsSorted() { + return new Map( + this.warnings.asPairArray().sort((a, b) => { + const ai = a[0].identifier(); + const bi = b[0].identifier(); + if (ai < bi) return -1; + if (ai > bi) return 1; + return 0; + }) + ); + } + + getModules() { + return this.modules.asSet(); + } + + clone() { + return new ConcatConfiguration(this.rootModule, this); + } + + set(config) { + this.rootModule = config.rootModule; + this.modules = config.modules; + this.warnings = config.warnings; + } +} + +module.exports = ModuleConcatenationPlugin; diff --git a/node_modules/webpack/lib/optimize/OccurrenceOrderPlugin.js b/node_modules/webpack/lib/optimize/OccurrenceOrderPlugin.js index 45ec34719..c73ec8e57 100644 --- a/node_modules/webpack/lib/optimize/OccurrenceOrderPlugin.js +++ b/node_modules/webpack/lib/optimize/OccurrenceOrderPlugin.js @@ -1,102 +1,135 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class OccurrenceOrderPlugin { - constructor(preferEntry) { - if(preferEntry !== undefined && typeof preferEntry !== "boolean") { - throw new Error("Argument should be a boolean.\nFor more info on this plugin, see https://webpack.js.org/plugins/"); - } - this.preferEntry = preferEntry; - } - apply(compiler) { - const preferEntry = this.preferEntry; - compiler.plugin("compilation", (compilation) => { - compilation.plugin("optimize-module-order", (modules) => { - const occursInInitialChunksMap = new Map(); - const occursInAllChunksMap = new Map(); - - const initialChunkChunkMap = new Map(); - const entryCountMap = new Map(); - modules.forEach(m => { - let initial = 0; - let entry = 0; - m.forEachChunk(c => { - if(c.isInitial()) initial++; - if(c.entryModule === m) entry++; - }); - initialChunkChunkMap.set(m, initial); - entryCountMap.set(m, entry); - }); - - const countOccursInEntry = (sum, r) => { - if(!r.module) return sum; - return sum + initialChunkChunkMap.get(r.module); - }; - const countOccurs = (sum, r) => { - if(!r.module) return sum; - return sum + r.module.getNumberOfChunks(); - }; - - if(preferEntry) { - modules.forEach(m => { - const result = m.reasons.reduce(countOccursInEntry, 0) + initialChunkChunkMap.get(m) + entryCountMap.get(m); - occursInInitialChunksMap.set(m, result); - }); - } - - modules.forEach(m => { - const result = m.reasons.reduce(countOccurs, 0) + m.getNumberOfChunks() + entryCountMap.get(m); - occursInAllChunksMap.set(m, result); - }); - - modules.sort((a, b) => { - if(preferEntry) { - const aEntryOccurs = occursInInitialChunksMap.get(a); - const bEntryOccurs = occursInInitialChunksMap.get(b); - if(aEntryOccurs > bEntryOccurs) return -1; - if(aEntryOccurs < bEntryOccurs) return 1; - } - const aOccurs = occursInAllChunksMap.get(a); - const bOccurs = occursInAllChunksMap.get(b); - if(aOccurs > bOccurs) return -1; - if(aOccurs < bOccurs) return 1; - if(a.index > b.index) return 1; - if(a.index < b.index) return -1; - return 0; - }); - }); - compilation.plugin("optimize-chunk-order", (chunks) => { - const occursInInitialChunksMap = new Map(); - - chunks.forEach(c => { - const result = c.parents.reduce((sum, p) => { - if(p.isInitial()) return sum + 1; - return sum; - }, 0); - return occursInInitialChunksMap.set(c, result); - }); - - function occurs(c) { - return c.blocks.length; - } - - chunks.sort((a, b) => { - const aEntryOccurs = occursInInitialChunksMap.get(a); - const bEntryOccurs = occursInInitialChunksMap.get(b); - if(aEntryOccurs > bEntryOccurs) return -1; - if(aEntryOccurs < bEntryOccurs) return 1; - const aOccurs = occurs(a); - const bOccurs = occurs(b); - if(aOccurs > bOccurs) return -1; - if(aOccurs < bOccurs) return 1; - return a.compareTo(b); - }); - }); - }); - } -} - -module.exports = OccurrenceOrderPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +// TODO webpack 5 remove this plugin +// It has been splitted into separate plugins for modules and chunks +class OccurrenceOrderPlugin { + constructor(preferEntry) { + if (preferEntry !== undefined && typeof preferEntry !== "boolean") { + throw new Error( + "Argument should be a boolean.\nFor more info on this plugin, see https://webpack.js.org/plugins/" + ); + } + this.preferEntry = preferEntry; + } + apply(compiler) { + const preferEntry = this.preferEntry; + compiler.hooks.compilation.tap("OccurrenceOrderPlugin", compilation => { + compilation.hooks.optimizeModuleOrder.tap( + "OccurrenceOrderPlugin", + modules => { + const occursInInitialChunksMap = new Map(); + const occursInAllChunksMap = new Map(); + + const initialChunkChunkMap = new Map(); + const entryCountMap = new Map(); + for (const m of modules) { + let initial = 0; + let entry = 0; + for (const c of m.chunksIterable) { + if (c.canBeInitial()) initial++; + if (c.entryModule === m) entry++; + } + initialChunkChunkMap.set(m, initial); + entryCountMap.set(m, entry); + } + + const countOccursInEntry = (sum, r) => { + if (!r.module) { + return sum; + } + return sum + initialChunkChunkMap.get(r.module); + }; + const countOccurs = (sum, r) => { + if (!r.module) { + return sum; + } + let factor = 1; + if (typeof r.dependency.getNumberOfIdOccurrences === "function") { + factor = r.dependency.getNumberOfIdOccurrences(); + } + if (factor === 0) { + return sum; + } + return sum + factor * r.module.getNumberOfChunks(); + }; + + if (preferEntry) { + for (const m of modules) { + const result = + m.reasons.reduce(countOccursInEntry, 0) + + initialChunkChunkMap.get(m) + + entryCountMap.get(m); + occursInInitialChunksMap.set(m, result); + } + } + + const originalOrder = new Map(); + let i = 0; + for (const m of modules) { + const result = + m.reasons.reduce(countOccurs, 0) + + m.getNumberOfChunks() + + entryCountMap.get(m); + occursInAllChunksMap.set(m, result); + originalOrder.set(m, i++); + } + + modules.sort((a, b) => { + if (preferEntry) { + const aEntryOccurs = occursInInitialChunksMap.get(a); + const bEntryOccurs = occursInInitialChunksMap.get(b); + if (aEntryOccurs > bEntryOccurs) return -1; + if (aEntryOccurs < bEntryOccurs) return 1; + } + const aOccurs = occursInAllChunksMap.get(a); + const bOccurs = occursInAllChunksMap.get(b); + if (aOccurs > bOccurs) return -1; + if (aOccurs < bOccurs) return 1; + const orgA = originalOrder.get(a); + const orgB = originalOrder.get(b); + return orgA - orgB; + }); + } + ); + compilation.hooks.optimizeChunkOrder.tap( + "OccurrenceOrderPlugin", + chunks => { + const occursInInitialChunksMap = new Map(); + const originalOrder = new Map(); + + let i = 0; + for (const c of chunks) { + let occurs = 0; + for (const chunkGroup of c.groupsIterable) { + for (const parent of chunkGroup.parentsIterable) { + if (parent.isInitial()) occurs++; + } + } + occursInInitialChunksMap.set(c, occurs); + originalOrder.set(c, i++); + } + + chunks.sort((a, b) => { + const aEntryOccurs = occursInInitialChunksMap.get(a); + const bEntryOccurs = occursInInitialChunksMap.get(b); + if (aEntryOccurs > bEntryOccurs) return -1; + if (aEntryOccurs < bEntryOccurs) return 1; + const aOccurs = a.getNumberOfGroups(); + const bOccurs = b.getNumberOfGroups(); + if (aOccurs > bOccurs) return -1; + if (aOccurs < bOccurs) return 1; + const orgA = originalOrder.get(a); + const orgB = originalOrder.get(b); + return orgA - orgB; + }); + } + ); + }); + } +} + +module.exports = OccurrenceOrderPlugin; diff --git a/node_modules/webpack/lib/optimize/RemoveEmptyChunksPlugin.js b/node_modules/webpack/lib/optimize/RemoveEmptyChunksPlugin.js index 4b75e4617..42ba24a15 100644 --- a/node_modules/webpack/lib/optimize/RemoveEmptyChunksPlugin.js +++ b/node_modules/webpack/lib/optimize/RemoveEmptyChunksPlugin.js @@ -1,21 +1,42 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class RemoveEmptyChunksPlugin { - - apply(compiler) { - compiler.plugin("compilation", (compilation) => { - compilation.plugin(["optimize-chunks-basic", "optimize-extracted-chunks-basic"], (chunks) => { - chunks.filter((chunk) => chunk.isEmpty() && !chunk.hasRuntime() && !chunk.hasEntryModule()) - .forEach((chunk) => { - chunk.remove("empty"); - chunks.splice(chunks.indexOf(chunk), 1); - }); - }); - }); - } -} -module.exports = RemoveEmptyChunksPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +class RemoveEmptyChunksPlugin { + apply(compiler) { + compiler.hooks.compilation.tap("RemoveEmptyChunksPlugin", compilation => { + const handler = chunks => { + for (let i = chunks.length - 1; i >= 0; i--) { + const chunk = chunks[i]; + if ( + chunk.isEmpty() && + !chunk.hasRuntime() && + !chunk.hasEntryModule() + ) { + chunk.remove("empty"); + chunks.splice(i, 1); + } + } + }; + compilation.hooks.optimizeChunksBasic.tap( + "RemoveEmptyChunksPlugin", + handler + ); + compilation.hooks.optimizeChunksAdvanced.tap( + "RemoveEmptyChunksPlugin", + handler + ); + compilation.hooks.optimizeExtractedChunksBasic.tap( + "RemoveEmptyChunksPlugin", + handler + ); + compilation.hooks.optimizeExtractedChunksAdvanced.tap( + "RemoveEmptyChunksPlugin", + handler + ); + }); + } +} +module.exports = RemoveEmptyChunksPlugin; diff --git a/node_modules/webpack/lib/optimize/RemoveParentModulesPlugin.js b/node_modules/webpack/lib/optimize/RemoveParentModulesPlugin.js index 43550819c..7fff59207 100644 --- a/node_modules/webpack/lib/optimize/RemoveParentModulesPlugin.js +++ b/node_modules/webpack/lib/optimize/RemoveParentModulesPlugin.js @@ -1,65 +1,127 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -function hasModule(chunk, module, checkedChunks) { - if(chunk.containsModule(module)) return [chunk]; - if(chunk.parents.length === 0) return false; - return allHaveModule(chunk.parents.filter((c) => { - return !checkedChunks.has(c); - }), module, checkedChunks); -} - -function allHaveModule(someChunks, module, checkedChunks) { - if(!checkedChunks) checkedChunks = new Set(); - var chunks = new Set(); - for(var i = 0; i < someChunks.length; i++) { - checkedChunks.add(someChunks[i]); - var subChunks = hasModule(someChunks[i], module, checkedChunks); - if(!subChunks) return false; - - for(var index = 0; index < subChunks.length; index++) { - var item = subChunks[index]; - - chunks.add(item); - } - } - return chunks; -} - -class RemoveParentModulesPlugin { - apply(compiler) { - compiler.plugin("compilation", (compilation) => { - compilation.plugin(["optimize-chunks-basic", "optimize-extracted-chunks-basic"], (chunks) => { - for(var index = 0; index < chunks.length; index++) { - var chunk = chunks[index]; - if(chunk.parents.length === 0) continue; - - // TODO consider Map when performance has improved https://gist.github.com/sokra/b36098368da7b8f6792fd7c85fca6311 - var cache = Object.create(null); - var modules = chunk.getModules(); - for(var i = 0; i < modules.length; i++) { - var module = modules[i]; - - var dId = module.getChunkIdsIdent(); - var parentChunksWithModule; - if(dId === null) { - parentChunksWithModule = allHaveModule(chunk.parents, module); - } else if(dId in cache) { - parentChunksWithModule = cache[dId]; - } else { - parentChunksWithModule = cache[dId] = allHaveModule(chunk.parents, module); - } - if(parentChunksWithModule) { - module.rewriteChunkInReasons(chunk, Array.from(parentChunksWithModule)); - chunk.removeModule(module); - } - } - } - }); - }); - } -} -module.exports = RemoveParentModulesPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const Queue = require("../util/Queue"); +const { intersect } = require("../util/SetHelpers"); + +const getParentChunksWithModule = (currentChunk, module) => { + const chunks = []; + const stack = new Set(currentChunk.parentsIterable); + + for (const chunk of stack) { + if (chunk.containsModule(module)) { + chunks.push(chunk); + } else { + for (const parent of chunk.parentsIterable) { + stack.add(parent); + } + } + } + + return chunks; +}; + +class RemoveParentModulesPlugin { + apply(compiler) { + compiler.hooks.compilation.tap("RemoveParentModulesPlugin", compilation => { + const handler = (chunks, chunkGroups) => { + const queue = new Queue(); + const availableModulesMap = new WeakMap(); + + for (const chunkGroup of compilation.entrypoints.values()) { + // initialize available modules for chunks without parents + availableModulesMap.set(chunkGroup, new Set()); + for (const child of chunkGroup.childrenIterable) { + queue.enqueue(child); + } + } + + while (queue.length > 0) { + const chunkGroup = queue.dequeue(); + let availableModules = availableModulesMap.get(chunkGroup); + let changed = false; + for (const parent of chunkGroup.parentsIterable) { + const availableModulesInParent = availableModulesMap.get(parent); + if (availableModulesInParent !== undefined) { + // If we know the available modules in parent: process these + if (availableModules === undefined) { + // if we have not own info yet: create new entry + availableModules = new Set(availableModulesInParent); + for (const chunk of parent.chunks) { + for (const m of chunk.modulesIterable) { + availableModules.add(m); + } + } + availableModulesMap.set(chunkGroup, availableModules); + changed = true; + } else { + for (const m of availableModules) { + if ( + !parent.containsModule(m) && + !availableModulesInParent.has(m) + ) { + availableModules.delete(m); + changed = true; + } + } + } + } + } + if (changed) { + // if something changed: enqueue our children + for (const child of chunkGroup.childrenIterable) { + queue.enqueue(child); + } + } + } + + // now we have available modules for every chunk + for (const chunk of chunks) { + const availableModulesSets = Array.from( + chunk.groupsIterable, + chunkGroup => availableModulesMap.get(chunkGroup) + ); + if (availableModulesSets.some(s => s === undefined)) continue; // No info about this chunk group + const availableModules = + availableModulesSets.length === 1 + ? availableModulesSets[0] + : intersect(availableModulesSets); + const numberOfModules = chunk.getNumberOfModules(); + const toRemove = new Set(); + if (numberOfModules < availableModules.size) { + for (const m of chunk.modulesIterable) { + if (availableModules.has(m)) { + toRemove.add(m); + } + } + } else { + for (const m of availableModules) { + if (chunk.containsModule(m)) { + toRemove.add(m); + } + } + } + for (const module of toRemove) { + module.rewriteChunkInReasons( + chunk, + getParentChunksWithModule(chunk, module) + ); + chunk.removeModule(module); + } + } + }; + compilation.hooks.optimizeChunksBasic.tap( + "RemoveParentModulesPlugin", + handler + ); + compilation.hooks.optimizeExtractedChunksBasic.tap( + "RemoveParentModulesPlugin", + handler + ); + }); + } +} +module.exports = RemoveParentModulesPlugin; diff --git a/node_modules/webpack/lib/optimize/UglifyJsPlugin.js b/node_modules/webpack/lib/optimize/UglifyJsPlugin.js deleted file mode 100644 index 1caa10817..000000000 --- a/node_modules/webpack/lib/optimize/UglifyJsPlugin.js +++ /dev/null @@ -1,9 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const UglifyJsPlugin = require("uglifyjs-webpack-plugin"); - -module.exports = UglifyJsPlugin; diff --git a/node_modules/webpack/lib/performance/AssetsOverSizeLimitWarning.js b/node_modules/webpack/lib/performance/AssetsOverSizeLimitWarning.js index 17a5112d8..aac8b65a9 100644 --- a/node_modules/webpack/lib/performance/AssetsOverSizeLimitWarning.js +++ b/node_modules/webpack/lib/performance/AssetsOverSizeLimitWarning.js @@ -1,23 +1,30 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Sean Larkin @thelarkinn -*/ -"use strict"; - -const WebpackError = require("../WebpackError"); -const SizeFormatHelpers = require("../SizeFormatHelpers"); - -module.exports = class AssetsOverSizeLimitWarning extends WebpackError { - constructor(assetsOverSizeLimit, assetLimit) { - super(); - - this.name = "AssetsOverSizeLimitWarning"; - this.assets = assetsOverSizeLimit; - const assetLists = this.assets.map(asset => `\n ${asset.name} (${SizeFormatHelpers.formatSize(asset.size)})`).join(""); - this.message = `asset size limit: The following asset(s) exceed the recommended size limit (${SizeFormatHelpers.formatSize(assetLimit)}). -This can impact web performance. -Assets: ${assetLists}`; - - Error.captureStackTrace(this, this.constructor); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Sean Larkin @thelarkinn +*/ +"use strict"; + +const WebpackError = require("../WebpackError"); +const SizeFormatHelpers = require("../SizeFormatHelpers"); + +module.exports = class AssetsOverSizeLimitWarning extends WebpackError { + constructor(assetsOverSizeLimit, assetLimit) { + const assetLists = assetsOverSizeLimit + .map( + asset => + `\n ${asset.name} (${SizeFormatHelpers.formatSize(asset.size)})` + ) + .join(""); + + super(`asset size limit: The following asset(s) exceed the recommended size limit (${SizeFormatHelpers.formatSize( + assetLimit + )}). +This can impact web performance. +Assets: ${assetLists}`); + + this.name = "AssetsOverSizeLimitWarning"; + this.assets = assetsOverSizeLimit; + + Error.captureStackTrace(this, this.constructor); + } +}; diff --git a/node_modules/webpack/lib/performance/EntrypointsOverSizeLimitWarning.js b/node_modules/webpack/lib/performance/EntrypointsOverSizeLimitWarning.js index 9fb2de104..3c29553d2 100644 --- a/node_modules/webpack/lib/performance/EntrypointsOverSizeLimitWarning.js +++ b/node_modules/webpack/lib/performance/EntrypointsOverSizeLimitWarning.js @@ -1,28 +1,30 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Sean Larkin @thelarkinn -*/ -"use strict"; - -const WebpackError = require("../WebpackError"); -const SizeFormatHelpers = require("../SizeFormatHelpers"); - -module.exports = class EntrypointsOverSizeLimitWarning extends WebpackError { - constructor(entrypoints, entrypointLimit) { - super(); - - this.name = "EntrypointsOverSizeLimitWarning"; - this.entrypoints = entrypoints; - const entrypointList = this.entrypoints.map(entrypoint => `\n ${ - entrypoint.name - } (${ - SizeFormatHelpers.formatSize(entrypoint.size) - })\n${ - entrypoint.files.map(asset => ` ${asset}`).join("\n") - }`).join(""); - this.message = `entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (${SizeFormatHelpers.formatSize(entrypointLimit)}). This can impact web performance. -Entrypoints:${entrypointList}\n`; - - Error.captureStackTrace(this, this.constructor); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Sean Larkin @thelarkinn +*/ +"use strict"; + +const WebpackError = require("../WebpackError"); +const SizeFormatHelpers = require("../SizeFormatHelpers"); + +module.exports = class EntrypointsOverSizeLimitWarning extends WebpackError { + constructor(entrypoints, entrypointLimit) { + const entrypointList = entrypoints + .map( + entrypoint => + `\n ${entrypoint.name} (${SizeFormatHelpers.formatSize( + entrypoint.size + )})\n${entrypoint.files.map(asset => ` ${asset}`).join("\n")}` + ) + .join(""); + super(`entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (${SizeFormatHelpers.formatSize( + entrypointLimit + )}). This can impact web performance. +Entrypoints:${entrypointList}\n`); + + this.name = "EntrypointsOverSizeLimitWarning"; + this.entrypoints = entrypoints; + + Error.captureStackTrace(this, this.constructor); + } +}; diff --git a/node_modules/webpack/lib/performance/NoAsyncChunksWarning.js b/node_modules/webpack/lib/performance/NoAsyncChunksWarning.js index 2ca7c35b9..c64475f97 100644 --- a/node_modules/webpack/lib/performance/NoAsyncChunksWarning.js +++ b/node_modules/webpack/lib/performance/NoAsyncChunksWarning.js @@ -1,20 +1,21 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Sean Larkin @thelarkinn -*/ -"use strict"; - -const WebpackError = require("../WebpackError"); - -module.exports = class NoAsyncChunksWarning extends WebpackError { - constructor() { - super(); - - this.name = "NoAsyncChunksWarning"; - this.message = "webpack performance recommendations: \n" + - "You can limit the size of your bundles by using import() or require.ensure to lazy load some parts of your application.\n" + - "For more info visit https://webpack.js.org/guides/code-splitting/"; - - Error.captureStackTrace(this, this.constructor); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Sean Larkin @thelarkinn +*/ +"use strict"; + +const WebpackError = require("../WebpackError"); + +module.exports = class NoAsyncChunksWarning extends WebpackError { + constructor() { + super( + "webpack performance recommendations: \n" + + "You can limit the size of your bundles by using import() or require.ensure to lazy load some parts of your application.\n" + + "For more info visit https://webpack.js.org/guides/code-splitting/" + ); + + this.name = "NoAsyncChunksWarning"; + + Error.captureStackTrace(this, this.constructor); + } +}; diff --git a/node_modules/webpack/lib/performance/SizeLimitsPlugin.js b/node_modules/webpack/lib/performance/SizeLimitsPlugin.js index e97b3b368..93b43651f 100644 --- a/node_modules/webpack/lib/performance/SizeLimitsPlugin.js +++ b/node_modules/webpack/lib/performance/SizeLimitsPlugin.js @@ -1,102 +1,105 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Sean Larkin @thelarkinn -*/ -"use strict"; -const EntrypointsOverSizeLimitWarning = require("./EntrypointsOverSizeLimitWarning"); -const AssetsOverSizeLimitWarning = require("./AssetsOverSizeLimitWarning"); -const NoAsyncChunksWarning = require("./NoAsyncChunksWarning"); - -module.exports = class SizeLimitsPlugin { - constructor(options) { - this.hints = options.hints; - this.maxAssetSize = options.maxAssetSize; - this.maxEntrypointSize = options.maxEntrypointSize; - this.assetFilter = options.assetFilter; - } - apply(compiler) { - const entrypointSizeLimit = this.maxEntrypointSize; - const assetSizeLimit = this.maxAssetSize; - const hints = this.hints; - const assetFilter = this.assetFilter || (asset => !(/\.map$/.test(asset))); - - compiler.plugin("after-emit", (compilation, callback) => { - const warnings = []; - - const getEntrypointSize = entrypoint => - entrypoint.getFiles() - .filter(assetFilter) - .map(file => compilation.assets[file]) - .filter(Boolean) - .map(asset => asset.size()) - .reduce((currentSize, nextSize) => currentSize + nextSize, 0); - - const assetsOverSizeLimit = []; - Object.keys(compilation.assets) - .filter(assetFilter) - .forEach(assetName => { - const asset = compilation.assets[assetName]; - const size = asset.size(); - - if(size > assetSizeLimit) { - assetsOverSizeLimit.push({ - name: assetName, - size: size, - }); - asset.isOverSizeLimit = true; - } - }); - - const entrypointsOverLimit = []; - Object.keys(compilation.entrypoints) - .forEach(key => { - const entry = compilation.entrypoints[key]; - const size = getEntrypointSize(entry, compilation); - - if(size > entrypointSizeLimit) { - entrypointsOverLimit.push({ - name: key, - size: size, - files: entry.getFiles().filter(assetFilter) - }); - entry.isOverSizeLimit = true; - } - }); - - if(hints) { - // 1. Individual Chunk: Size < 250kb - // 2. Collective Initial Chunks [entrypoint] (Each Set?): Size < 250kb - // 3. No Async Chunks - // if !1, then 2, if !2 return - if(assetsOverSizeLimit.length > 0) { - warnings.push( - new AssetsOverSizeLimitWarning( - assetsOverSizeLimit, - assetSizeLimit)); - } - if(entrypointsOverLimit.length > 0) { - warnings.push( - new EntrypointsOverSizeLimitWarning( - entrypointsOverLimit, - entrypointSizeLimit)); - } - - if(warnings.length > 0) { - const hasAsyncChunks = compilation.chunks.filter(chunk => !chunk.isInitial()).length > 0; - - if(!hasAsyncChunks) { - warnings.push(new NoAsyncChunksWarning()); - } - - if(hints === "error") { - Array.prototype.push.apply(compilation.errors, warnings); - } else { - Array.prototype.push.apply(compilation.warnings, warnings); - } - } - } - - callback(); - }); - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Sean Larkin @thelarkinn +*/ +"use strict"; +const EntrypointsOverSizeLimitWarning = require("./EntrypointsOverSizeLimitWarning"); +const AssetsOverSizeLimitWarning = require("./AssetsOverSizeLimitWarning"); +const NoAsyncChunksWarning = require("./NoAsyncChunksWarning"); + +module.exports = class SizeLimitsPlugin { + constructor(options) { + this.hints = options.hints; + this.maxAssetSize = options.maxAssetSize; + this.maxEntrypointSize = options.maxEntrypointSize; + this.assetFilter = options.assetFilter; + } + apply(compiler) { + const entrypointSizeLimit = this.maxEntrypointSize; + const assetSizeLimit = this.maxAssetSize; + const hints = this.hints; + const assetFilter = this.assetFilter || (asset => !asset.endsWith(".map")); + + compiler.hooks.afterEmit.tap("SizeLimitsPlugin", compilation => { + const warnings = []; + + const getEntrypointSize = entrypoint => + entrypoint.getFiles().reduce((currentSize, file) => { + if (assetFilter(file) && compilation.assets[file]) { + return currentSize + compilation.assets[file].size(); + } + + return currentSize; + }, 0); + + const assetsOverSizeLimit = []; + for (const assetName of Object.keys(compilation.assets)) { + if (!assetFilter(assetName)) { + continue; + } + + const asset = compilation.assets[assetName]; + const size = asset.size(); + if (size > assetSizeLimit) { + assetsOverSizeLimit.push({ + name: assetName, + size: size + }); + asset.isOverSizeLimit = true; + } + } + + const entrypointsOverLimit = []; + for (const pair of compilation.entrypoints) { + const name = pair[0]; + const entry = pair[1]; + const size = getEntrypointSize(entry); + + if (size > entrypointSizeLimit) { + entrypointsOverLimit.push({ + name: name, + size: size, + files: entry.getFiles().filter(assetFilter) + }); + entry.isOverSizeLimit = true; + } + } + + if (hints) { + // 1. Individual Chunk: Size < 250kb + // 2. Collective Initial Chunks [entrypoint] (Each Set?): Size < 250kb + // 3. No Async Chunks + // if !1, then 2, if !2 return + if (assetsOverSizeLimit.length > 0) { + warnings.push( + new AssetsOverSizeLimitWarning(assetsOverSizeLimit, assetSizeLimit) + ); + } + if (entrypointsOverLimit.length > 0) { + warnings.push( + new EntrypointsOverSizeLimitWarning( + entrypointsOverLimit, + entrypointSizeLimit + ) + ); + } + + if (warnings.length > 0) { + const hasAsyncChunks = + compilation.chunks.filter(chunk => !chunk.canBeInitial()).length > + 0; + + if (!hasAsyncChunks) { + warnings.push(new NoAsyncChunksWarning()); + } + + if (hints === "error") { + compilation.errors.push(...warnings); + } else { + compilation.warnings.push(...warnings); + } + } + } + }); + } +}; diff --git a/node_modules/webpack/lib/prepareOptions.js b/node_modules/webpack/lib/prepareOptions.js deleted file mode 100644 index 0b063a03b..000000000 --- a/node_modules/webpack/lib/prepareOptions.js +++ /dev/null @@ -1,29 +0,0 @@ -"use strict"; - -module.exports = function prepareOptions(options, argv) { - argv = argv || {}; - - options = handleExport(options); - - if(Array.isArray(options)) { - options = options.map(_options => handleFunction(_options, argv)); - } else { - options = handleFunction(options, argv); - } - return options; -}; - -function handleExport(options) { - const isES6DefaultExported = ( - typeof options === "object" && options !== null && typeof options.default !== "undefined" - ); - options = isES6DefaultExported ? options.default : options; - return options; -} - -function handleFunction(options, argv) { - if(typeof options === "function") { - options = options(argv.env, argv); - } - return options; -} diff --git a/node_modules/webpack/lib/removeAndDo.js b/node_modules/webpack/lib/removeAndDo.js deleted file mode 100644 index a857d8a32..000000000 --- a/node_modules/webpack/lib/removeAndDo.js +++ /dev/null @@ -1,15 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -module.exports = function removeAndDo(collection, thing, action) { - const idx = this[collection].indexOf(thing); - const hasThingInCollection = idx >= 0; - if(hasThingInCollection) { - this[collection].splice(idx, 1); - thing[action](this); - } - return hasThingInCollection; -}; diff --git a/node_modules/webpack/lib/util/Queue.js b/node_modules/webpack/lib/util/Queue.js index ef3ffdc80..6615e9f77 100644 --- a/node_modules/webpack/lib/util/Queue.js +++ b/node_modules/webpack/lib/util/Queue.js @@ -1,42 +1,46 @@ -"use strict"; - -module.exports = class Queue { - constructor(items) { - this.first = null; - this.last = null; - this.length = 0; - if(items) { - for(const item of items) { - this.enqueue(item); - } - } - } - - enqueue(item) { - const first = this.first; - const node = { - item, - next: null - }; - if(first === null) { - this.last = node; - } else { - first.next = node; - } - this.first = node; - this.length++; - } - - dequeue() { - const last = this.last; - if(last === null) - return undefined; - const next = last.next; - if(next === null) { - this.first = null; - } - this.last = next; - this.length--; - return last.item; - } -}; +"use strict"; + +/** + * @template T + */ +class Queue { + /** + * @param {Iterable=} items The initial elements. + */ + constructor(items) { + /** @private @type {Set} */ + this.set = new Set(items); + /** @private @type {Iterator} */ + this.iterator = this.set[Symbol.iterator](); + } + + /** + * Returns the number of elements in this queue. + * @returns {number} The number of elements in this queue. + */ + get length() { + return this.set.size; + } + + /** + * Appends the specified element to this queue. + * @param {T} item The element to add. + * @returns {void} + */ + enqueue(item) { + this.set.add(item); + } + + /** + * Retrieves and removes the head of this queue. + * @returns {T | undefined} The head of the queue of `undefined` if this queue is empty. + */ + dequeue() { + const result = this.iterator.next(); + if (result.done) return undefined; + this.set.delete(result.value); + return result.value; + } +} + +module.exports = Queue; diff --git a/node_modules/webpack/lib/util/Semaphore.js b/node_modules/webpack/lib/util/Semaphore.js index de9b69dde..d6c876651 100644 --- a/node_modules/webpack/lib/util/Semaphore.js +++ b/node_modules/webpack/lib/util/Semaphore.js @@ -1,32 +1,53 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class Semaphore { - constructor(available) { - this.available = available; - this.waiters = []; - } - - acquire(callback) { - if(this.available > 0) { - this.available--; - callback(); - } else { - this.waiters.push(callback); - } - } - - release() { - if(this.waiters.length > 0) { - const callback = this.waiters.pop(); - process.nextTick(callback); - } else { - this.available++; - } - } -} - -module.exports = Semaphore; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +class Semaphore { + /** + * Creates an instance of Semaphore. + * + * @param {number} available the amount available number of "tasks" + * in the Semaphore + */ + constructor(available) { + this.available = available; + /** @type {(function(): void)[]} */ + this.waiters = []; + /** @private */ + this._continue = this._continue.bind(this); + } + + /** + * @param {function(): void} callback function block to capture and run + * @returns {void} + */ + acquire(callback) { + if (this.available > 0) { + this.available--; + callback(); + } else { + this.waiters.push(callback); + } + } + + release() { + this.available++; + if (this.waiters.length > 0) { + process.nextTick(this._continue); + } + } + + _continue() { + if (this.available > 0) { + if (this.waiters.length > 0) { + this.available--; + const callback = this.waiters.pop(); + callback(); + } + } + } +} + +module.exports = Semaphore; diff --git a/node_modules/webpack/lib/util/SortableSet.js b/node_modules/webpack/lib/util/SortableSet.js index 15c7ecb87..44b692f37 100644 --- a/node_modules/webpack/lib/util/SortableSet.js +++ b/node_modules/webpack/lib/util/SortableSet.js @@ -1,45 +1,140 @@ -"use strict"; - -module.exports = class SortableSet extends Set { - - constructor(initialIterable, defaultSort) { - super(initialIterable); - this._sortFn = defaultSort; - this._lastActiveSortFn = null; - } - - /** - * @param {any} value - value to add to set - * @returns {SortableSet} - returns itself - */ - add(value) { - this._lastActiveSortFn = null; - super.add(value); - return this; - } - - /** - * @param {Function} sortFn - function to sort the set - * @returns {void} - */ - sortWith(sortFn) { - if(this.size === 0 || sortFn === this._lastActiveSortFn) { - // already sorted - nothing to do - return; - } - - const sortedArray = Array.from(this).sort(sortFn); - super.clear(); - for(let i = 0; i < sortedArray.length; i += 1) { - this.add(sortedArray[i]); - } - this._lastActiveSortFn = sortFn; - } - - /** - * @returns {void} - */ - sort() { - this.sortWith(this._sortFn); - } -}; +"use strict"; + +/** + * A subset of Set that offers sorting functionality + * @template T item type in set + * @extends {Set} + */ +class SortableSet extends Set { + /** + * Create a new sortable set + * @param {Iterable=} initialIterable The initial iterable value + * @typedef {function(T, T): number} SortFunction + * @param {SortFunction=} defaultSort Default sorting function + */ + constructor(initialIterable, defaultSort) { + super(initialIterable); + /** @private @type {function(T, T): number}} */ + this._sortFn = defaultSort; + /** @private @type {function(T, T): number} | null} */ + this._lastActiveSortFn = null; + /** @private @type {Map | undefined} */ + this._cache = undefined; + /** @private @type {Map | undefined} */ + this._cacheOrderIndependent = undefined; + } + + /** + * @param {T} value value to add to set + * @returns {this} returns itself + */ + add(value) { + this._lastActiveSortFn = null; + this._invalidateCache(); + this._invalidateOrderedCache(); + super.add(value); + return this; + } + + /** + * @param {T} value value to delete + * @returns {boolean} true if value existed in set, false otherwise + */ + delete(value) { + this._invalidateCache(); + this._invalidateOrderedCache(); + return super.delete(value); + } + + /** + * @returns {void} + */ + clear() { + this._invalidateCache(); + this._invalidateOrderedCache(); + return super.clear(); + } + + /** + * Sort with a comparer function + * @param {SortFunction} sortFn Sorting comparer function + * @returns {void} + */ + sortWith(sortFn) { + if (this.size <= 1 || sortFn === this._lastActiveSortFn) { + // already sorted - nothing to do + return; + } + + const sortedArray = Array.from(this).sort(sortFn); + super.clear(); + for (let i = 0; i < sortedArray.length; i += 1) { + super.add(sortedArray[i]); + } + this._lastActiveSortFn = sortFn; + this._invalidateCache(); + } + + sort() { + this.sortWith(this._sortFn); + } + + /** + * Get data from cache + * @param {function(SortableSet): T[]} fn function to calculate value + * @returns {T[]} returns result of fn(this), cached until set changes + */ + getFromCache(fn) { + if (this._cache === undefined) { + this._cache = new Map(); + } else { + const data = this._cache.get(fn); + if (data !== undefined) { + return data; + } + } + const newData = fn(this); + this._cache.set(fn, newData); + return newData; + } + + /** + * @param {function(SortableSet): string|number|T[]} fn function to calculate value + * @returns {any} returns result of fn(this), cached until set changes + */ + getFromUnorderedCache(fn) { + if (this._cacheOrderIndependent === undefined) { + this._cacheOrderIndependent = new Map(); + } else { + const data = this._cacheOrderIndependent.get(fn); + if (data !== undefined) { + return data; + } + } + const newData = fn(this); + this._cacheOrderIndependent.set(fn, newData); + return newData; + } + + /** + * @private + * @returns {void} + */ + _invalidateCache() { + if (this._cache !== undefined) { + this._cache.clear(); + } + } + + /** + * @private + * @returns {void} + */ + _invalidateOrderedCache() { + if (this._cacheOrderIndependent !== undefined) { + this._cacheOrderIndependent.clear(); + } + } +} + +module.exports = SortableSet; diff --git a/node_modules/webpack/lib/util/identifier.js b/node_modules/webpack/lib/util/identifier.js index 82e5b811f..186bc064e 100644 --- a/node_modules/webpack/lib/util/identifier.js +++ b/node_modules/webpack/lib/util/identifier.js @@ -1,38 +1,103 @@ -"use strict"; -const path = require("path"); - -const looksLikeAbsolutePath = (maybeAbsolutePath) => { - return /^(?:[a-z]:\\|\/)/i.test(maybeAbsolutePath); -}; - -const normalizePathSeparator = (p) => p.replace(/\\/g, "/"); - -const _makePathsRelative = (context, identifier) => { - return identifier - .split(/([|! ])/) - .map(str => looksLikeAbsolutePath(str) ? - normalizePathSeparator(path.relative(context, str)) : str) - .join(""); -}; - -exports.makePathsRelative = (context, identifier, cache) => { - if(!cache) return _makePathsRelative(context, identifier); - - const relativePaths = cache.relativePaths || (cache.relativePaths = new Map()); - - let cachedResult; - let contextCache = relativePaths.get(context); - if(typeof contextCache === "undefined") { - relativePaths.set(context, contextCache = new Map()); - } else { - cachedResult = contextCache.get(identifier); - } - - if(typeof cachedResult !== "undefined") { - return cachedResult; - } else { - const relativePath = _makePathsRelative(context, identifier); - contextCache.set(identifier, relativePath); - return relativePath; - } -}; +"use strict"; +const path = require("path"); + +/** + * @typedef {Object} MakeRelativePathsCache + * @property {Map>=} relativePaths + */ + +/** + * + * @param {string} maybeAbsolutePath path to check + * @returns {boolean} returns true if path is "Absolute Path"-like + */ +const looksLikeAbsolutePath = maybeAbsolutePath => { + if (/^\/.*\/$/.test(maybeAbsolutePath)) { + // this 'path' is actually a regexp generated by dynamic requires. + // Don't treat it as an absolute path. + return false; + } + return /^(?:[a-z]:\\|\/)/i.test(maybeAbsolutePath); +}; + +/** + * + * @param {string} p path to normalize + * @returns {string} normalized version of path + */ +const normalizePathSeparator = p => p.replace(/\\/g, "/"); + +/** + * + * @param {string} context context for relative path + * @param {string} identifier identifier for path + * @returns {string} a converted relative path + */ +const _makePathsRelative = (context, identifier) => { + return identifier + .split(/([|! ])/) + .map( + str => + looksLikeAbsolutePath(str) + ? normalizePathSeparator(path.relative(context, str)) + : str + ) + .join(""); +}; + +/** + * + * @param {string} context context used to create relative path + * @param {string} identifier identifier used to create relative path + * @param {MakeRelativePathsCache=} cache the cache object being set + * @returns {string} the returned relative path + */ +exports.makePathsRelative = (context, identifier, cache) => { + if (!cache) return _makePathsRelative(context, identifier); + + const relativePaths = + cache.relativePaths || (cache.relativePaths = new Map()); + + let cachedResult; + let contextCache = relativePaths.get(context); + if (contextCache === undefined) { + relativePaths.set(context, (contextCache = new Map())); + } else { + cachedResult = contextCache.get(identifier); + } + + if (cachedResult !== undefined) { + return cachedResult; + } else { + const relativePath = _makePathsRelative(context, identifier); + contextCache.set(identifier, relativePath); + return relativePath; + } +}; + +/** + * @param {string} context absolute context path + * @param {string} request any request string may containing absolute paths, query string, etc. + * @returns {string} a new request string avoiding absolute paths when possible + */ +exports.contextify = (context, request) => { + return request + .split("!") + .map(r => { + const splitPath = r.split("?", 2); + if (/^[a-zA-Z]:\\/.test(splitPath[0])) { + splitPath[0] = path.win32.relative(context, splitPath[0]); + if (!/^[a-zA-Z]:\\/.test(splitPath[0])) { + splitPath[0] = splitPath[0].replace(/\\/g, "/"); + } + } + if (/^\//.test(splitPath[0])) { + splitPath[0] = path.posix.relative(context, splitPath[0]); + } + if (!/^(\.\.\/|\/|[a-zA-Z]:\\)/.test(splitPath[0])) { + splitPath[0] = "./" + splitPath[0]; + } + return splitPath.join("?"); + }) + .join("!"); +}; diff --git a/node_modules/webpack/lib/validateSchema.js b/node_modules/webpack/lib/validateSchema.js index 8d415c170..b748c2c8f 100644 --- a/node_modules/webpack/lib/validateSchema.js +++ b/node_modules/webpack/lib/validateSchema.js @@ -1,66 +1,67 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Gajus Kuizinas @gajus -*/ -"use strict"; - -const Ajv = require("ajv"); -const ajv = new Ajv({ - errorDataPath: "configuration", - allErrors: true, - verbose: true -}); -require("ajv-keywords")(ajv, ["instanceof"]); -require("../schemas/ajv.absolutePath")(ajv); - -function validateSchema(schema, options) { - if(Array.isArray(options)) { - const errors = options.map((options) => validateObject(schema, options)); - errors.forEach((list, idx) => { - list.forEach(function applyPrefix(err) { - err.dataPath = `[${idx}]${err.dataPath}`; - if(err.children) { - err.children.forEach(applyPrefix); - } - }); - }); - return errors.reduce((arr, items) => { - return arr.concat(items); - }, []); - } else { - return validateObject(schema, options); - } -} - -function validateObject(schema, options) { - const validate = ajv.compile(schema); - const valid = validate(options); - return valid ? [] : filterErrors(validate.errors); -} - -function filterErrors(errors) { - let newErrors = []; - errors.forEach((err) => { - const dataPath = err.dataPath; - let children = []; - newErrors = newErrors.filter((oldError) => { - if(oldError.dataPath.includes(dataPath)) { - if(oldError.children) { - children = children.concat(oldError.children.slice(0)); - } - oldError.children = undefined; - children.push(oldError); - return false; - } - return true; - }); - if(children.length) { - err.children = children; - } - newErrors.push(err); - }); - - return newErrors; -} - -module.exports = validateSchema; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Gajus Kuizinas @gajus +*/ +"use strict"; + +const Ajv = require("ajv"); +const ajv = new Ajv({ + errorDataPath: "configuration", + allErrors: true, + verbose: true +}); +require("ajv-keywords")(ajv, ["instanceof"]); +require("../schemas/ajv.absolutePath")(ajv); + +const validateSchema = (schema, options) => { + if (Array.isArray(options)) { + const errors = options.map(options => validateObject(schema, options)); + errors.forEach((list, idx) => { + const applyPrefix = err => { + err.dataPath = `[${idx}]${err.dataPath}`; + if (err.children) { + err.children.forEach(applyPrefix); + } + }; + list.forEach(applyPrefix); + }); + return errors.reduce((arr, items) => { + return arr.concat(items); + }, []); + } else { + return validateObject(schema, options); + } +}; + +const validateObject = (schema, options) => { + const validate = ajv.compile(schema); + const valid = validate(options); + return valid ? [] : filterErrors(validate.errors); +}; + +const filterErrors = errors => { + let newErrors = []; + for (const err of errors) { + const dataPath = err.dataPath; + let children = []; + newErrors = newErrors.filter(oldError => { + if (oldError.dataPath.includes(dataPath)) { + if (oldError.children) { + children = children.concat(oldError.children.slice(0)); + } + oldError.children = undefined; + children.push(oldError); + return false; + } + return true; + }); + if (children.length) { + err.children = children; + } + newErrors.push(err); + } + + return newErrors; +}; + +module.exports = validateSchema; diff --git a/node_modules/webpack/lib/web/WebEnvironmentPlugin.js b/node_modules/webpack/lib/web/WebEnvironmentPlugin.js index 46e783bbb..9b0df5746 100644 --- a/node_modules/webpack/lib/web/WebEnvironmentPlugin.js +++ b/node_modules/webpack/lib/web/WebEnvironmentPlugin.js @@ -1,18 +1,18 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -class WebEnvironmentPlugin { - constructor(inputFileSystem, outputFileSystem) { - this.inputFileSystem = inputFileSystem; - this.outputFileSystem = outputFileSystem; - } - - apply(compiler) { - compiler.outputFileSystem = this.outputFileSystem; - } -} - -module.exports = WebEnvironmentPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +class WebEnvironmentPlugin { + constructor(inputFileSystem, outputFileSystem) { + this.inputFileSystem = inputFileSystem; + this.outputFileSystem = outputFileSystem; + } + + apply(compiler) { + compiler.outputFileSystem = this.outputFileSystem; + } +} + +module.exports = WebEnvironmentPlugin; diff --git a/node_modules/webpack/lib/webpack.js b/node_modules/webpack/lib/webpack.js index 81fc7d83f..61357818e 100644 --- a/node_modules/webpack/lib/webpack.js +++ b/node_modules/webpack/lib/webpack.js @@ -1,120 +1,191 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const Compiler = require("./Compiler"); -const MultiCompiler = require("./MultiCompiler"); -const NodeEnvironmentPlugin = require("./node/NodeEnvironmentPlugin"); -const WebpackOptionsApply = require("./WebpackOptionsApply"); -const WebpackOptionsDefaulter = require("./WebpackOptionsDefaulter"); -const validateSchema = require("./validateSchema"); -const WebpackOptionsValidationError = require("./WebpackOptionsValidationError"); -const webpackOptionsSchema = require("../schemas/webpackOptionsSchema.json"); - -function webpack(options, callback) { - const webpackOptionsValidationErrors = validateSchema(webpackOptionsSchema, options); - if(webpackOptionsValidationErrors.length) { - throw new WebpackOptionsValidationError(webpackOptionsValidationErrors); - } - let compiler; - if(Array.isArray(options)) { - compiler = new MultiCompiler(options.map(options => webpack(options))); - } else if(typeof options === "object") { - // TODO webpack 4: process returns options - new WebpackOptionsDefaulter().process(options); - - compiler = new Compiler(); - compiler.context = options.context; - compiler.options = options; - new NodeEnvironmentPlugin().apply(compiler); - if(options.plugins && Array.isArray(options.plugins)) { - compiler.apply.apply(compiler, options.plugins); - } - compiler.applyPlugins("environment"); - compiler.applyPlugins("after-environment"); - compiler.options = new WebpackOptionsApply().process(options, compiler); - } else { - throw new Error("Invalid argument: options"); - } - if(callback) { - if(typeof callback !== "function") throw new Error("Invalid argument: callback"); - if(options.watch === true || (Array.isArray(options) && options.some(o => o.watch))) { - const watchOptions = Array.isArray(options) ? options.map(o => o.watchOptions || {}) : (options.watchOptions || {}); - return compiler.watch(watchOptions, callback); - } - compiler.run(callback); - } - return compiler; -} -exports = module.exports = webpack; - -webpack.WebpackOptionsDefaulter = WebpackOptionsDefaulter; -webpack.WebpackOptionsApply = WebpackOptionsApply; -webpack.Compiler = Compiler; -webpack.MultiCompiler = MultiCompiler; -webpack.NodeEnvironmentPlugin = NodeEnvironmentPlugin; -webpack.validate = validateSchema.bind(this, webpackOptionsSchema); -webpack.validateSchema = validateSchema; -webpack.WebpackOptionsValidationError = WebpackOptionsValidationError; - -function exportPlugins(obj, mappings) { - Object.keys(mappings).forEach(name => { - Object.defineProperty(obj, name, { - configurable: false, - enumerable: true, - get: mappings[name] - }); - }); -} - -exportPlugins(exports, { - "DefinePlugin": () => require("./DefinePlugin"), - "NormalModuleReplacementPlugin": () => require("./NormalModuleReplacementPlugin"), - "ContextReplacementPlugin": () => require("./ContextReplacementPlugin"), - "ContextExclusionPlugin": () => require("./ContextExclusionPlugin"), - "IgnorePlugin": () => require("./IgnorePlugin"), - "WatchIgnorePlugin": () => require("./WatchIgnorePlugin"), - "BannerPlugin": () => require("./BannerPlugin"), - "PrefetchPlugin": () => require("./PrefetchPlugin"), - "AutomaticPrefetchPlugin": () => require("./AutomaticPrefetchPlugin"), - "ProvidePlugin": () => require("./ProvidePlugin"), - "HotModuleReplacementPlugin": () => require("./HotModuleReplacementPlugin"), - "SourceMapDevToolPlugin": () => require("./SourceMapDevToolPlugin"), - "EvalSourceMapDevToolPlugin": () => require("./EvalSourceMapDevToolPlugin"), - "EvalDevToolModulePlugin": () => require("./EvalDevToolModulePlugin"), - "CachePlugin": () => require("./CachePlugin"), - "ExtendedAPIPlugin": () => require("./ExtendedAPIPlugin"), - "ExternalsPlugin": () => require("./ExternalsPlugin"), - "JsonpTemplatePlugin": () => require("./JsonpTemplatePlugin"), - "LibraryTemplatePlugin": () => require("./LibraryTemplatePlugin"), - "LoaderTargetPlugin": () => require("./LoaderTargetPlugin"), - "MemoryOutputFileSystem": () => require("./MemoryOutputFileSystem"), - "ProgressPlugin": () => require("./ProgressPlugin"), - "SetVarMainTemplatePlugin": () => require("./SetVarMainTemplatePlugin"), - "UmdMainTemplatePlugin": () => require("./UmdMainTemplatePlugin"), - "NoErrorsPlugin": () => require("./NoErrorsPlugin"), - "NoEmitOnErrorsPlugin": () => require("./NoEmitOnErrorsPlugin"), - "NewWatchingPlugin": () => require("./NewWatchingPlugin"), - "EnvironmentPlugin": () => require("./EnvironmentPlugin"), - "DllPlugin": () => require("./DllPlugin"), - "DllReferencePlugin": () => require("./DllReferencePlugin"), - "LoaderOptionsPlugin": () => require("./LoaderOptionsPlugin"), - "NamedModulesPlugin": () => require("./NamedModulesPlugin"), - "NamedChunksPlugin": () => require("./NamedChunksPlugin"), - "HashedModuleIdsPlugin": () => require("./HashedModuleIdsPlugin"), - "ModuleFilenameHelpers": () => require("./ModuleFilenameHelpers") -}); -exportPlugins(exports.optimize = {}, { - "AggressiveMergingPlugin": () => require("./optimize/AggressiveMergingPlugin"), - "AggressiveSplittingPlugin": () => require("./optimize/AggressiveSplittingPlugin"), - "CommonsChunkPlugin": () => require("./optimize/CommonsChunkPlugin"), - "ChunkModuleIdRangePlugin": () => require("./optimize/ChunkModuleIdRangePlugin"), - "DedupePlugin": () => require("./optimize/DedupePlugin"), - "LimitChunkCountPlugin": () => require("./optimize/LimitChunkCountPlugin"), - "MinChunkSizePlugin": () => require("./optimize/MinChunkSizePlugin"), - "ModuleConcatenationPlugin": () => require("./optimize/ModuleConcatenationPlugin"), - "OccurrenceOrderPlugin": () => require("./optimize/OccurrenceOrderPlugin"), - "UglifyJsPlugin": () => require("./optimize/UglifyJsPlugin") -}); +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const Compiler = require("./Compiler"); +const MultiCompiler = require("./MultiCompiler"); +const NodeEnvironmentPlugin = require("./node/NodeEnvironmentPlugin"); +const WebpackOptionsApply = require("./WebpackOptionsApply"); +const WebpackOptionsDefaulter = require("./WebpackOptionsDefaulter"); +const validateSchema = require("./validateSchema"); +const WebpackOptionsValidationError = require("./WebpackOptionsValidationError"); +const webpackOptionsSchema = require("../schemas/WebpackOptions.json"); +const RemovedPluginError = require("./RemovedPluginError"); +const version = require("../package.json").version; + +const webpack = (options, callback) => { + const webpackOptionsValidationErrors = validateSchema( + webpackOptionsSchema, + options + ); + if (webpackOptionsValidationErrors.length) { + throw new WebpackOptionsValidationError(webpackOptionsValidationErrors); + } + let compiler; + if (Array.isArray(options)) { + compiler = new MultiCompiler(options.map(options => webpack(options))); + } else if (typeof options === "object") { + options = new WebpackOptionsDefaulter().process(options); + + compiler = new Compiler(options.context); + compiler.options = options; + new NodeEnvironmentPlugin().apply(compiler); + if (options.plugins && Array.isArray(options.plugins)) { + for (const plugin of options.plugins) { + plugin.apply(compiler); + } + } + compiler.hooks.environment.call(); + compiler.hooks.afterEnvironment.call(); + compiler.options = new WebpackOptionsApply().process(options, compiler); + } else { + throw new Error("Invalid argument: options"); + } + if (callback) { + if (typeof callback !== "function") { + throw new Error("Invalid argument: callback"); + } + if ( + options.watch === true || + (Array.isArray(options) && options.some(o => o.watch)) + ) { + const watchOptions = Array.isArray(options) + ? options.map(o => o.watchOptions || {}) + : options.watchOptions || {}; + return compiler.watch(watchOptions, callback); + } + compiler.run(callback); + } + return compiler; +}; + +exports = module.exports = webpack; +exports.version = version; + +webpack.WebpackOptionsDefaulter = WebpackOptionsDefaulter; +webpack.WebpackOptionsApply = WebpackOptionsApply; +webpack.Compiler = Compiler; +webpack.MultiCompiler = MultiCompiler; +webpack.NodeEnvironmentPlugin = NodeEnvironmentPlugin; +// @ts-ignore Global @this directive is not supported +webpack.validate = validateSchema.bind(this, webpackOptionsSchema); +webpack.validateSchema = validateSchema; +webpack.WebpackOptionsValidationError = WebpackOptionsValidationError; + +const exportPlugins = (obj, mappings) => { + for (const name of Object.keys(mappings)) { + Object.defineProperty(obj, name, { + configurable: false, + enumerable: true, + get: mappings[name] + }); + } +}; + +exportPlugins(exports, { + AutomaticPrefetchPlugin: () => require("./AutomaticPrefetchPlugin"), + BannerPlugin: () => require("./BannerPlugin"), + CachePlugin: () => require("./CachePlugin"), + ContextExclusionPlugin: () => require("./ContextExclusionPlugin"), + ContextReplacementPlugin: () => require("./ContextReplacementPlugin"), + DefinePlugin: () => require("./DefinePlugin"), + Dependency: () => require("./Dependency"), + DllPlugin: () => require("./DllPlugin"), + DllReferencePlugin: () => require("./DllReferencePlugin"), + EnvironmentPlugin: () => require("./EnvironmentPlugin"), + EvalDevToolModulePlugin: () => require("./EvalDevToolModulePlugin"), + EvalSourceMapDevToolPlugin: () => require("./EvalSourceMapDevToolPlugin"), + ExtendedAPIPlugin: () => require("./ExtendedAPIPlugin"), + ExternalsPlugin: () => require("./ExternalsPlugin"), + HashedModuleIdsPlugin: () => require("./HashedModuleIdsPlugin"), + HotModuleReplacementPlugin: () => require("./HotModuleReplacementPlugin"), + IgnorePlugin: () => require("./IgnorePlugin"), + LibraryTemplatePlugin: () => require("./LibraryTemplatePlugin"), + LoaderOptionsPlugin: () => require("./LoaderOptionsPlugin"), + LoaderTargetPlugin: () => require("./LoaderTargetPlugin"), + MemoryOutputFileSystem: () => require("./MemoryOutputFileSystem"), + Module: () => require("./Module"), + ModuleFilenameHelpers: () => require("./ModuleFilenameHelpers"), + NamedChunksPlugin: () => require("./NamedChunksPlugin"), + NamedModulesPlugin: () => require("./NamedModulesPlugin"), + NoEmitOnErrorsPlugin: () => require("./NoEmitOnErrorsPlugin"), + NormalModuleReplacementPlugin: () => + require("./NormalModuleReplacementPlugin"), + PrefetchPlugin: () => require("./PrefetchPlugin"), + ProgressPlugin: () => require("./ProgressPlugin"), + ProvidePlugin: () => require("./ProvidePlugin"), + SetVarMainTemplatePlugin: () => require("./SetVarMainTemplatePlugin"), + SingleEntryPlugin: () => require("./SingleEntryPlugin"), + SourceMapDevToolPlugin: () => require("./SourceMapDevToolPlugin"), + Stats: () => require("./Stats"), + Template: () => require("./Template"), + UmdMainTemplatePlugin: () => require("./UmdMainTemplatePlugin"), + WatchIgnorePlugin: () => require("./WatchIgnorePlugin") +}); +exportPlugins((exports.dependencies = {}), { + DependencyReference: () => require("./dependencies/DependencyReference") +}); +exportPlugins((exports.optimize = {}), { + AggressiveMergingPlugin: () => require("./optimize/AggressiveMergingPlugin"), + AggressiveSplittingPlugin: () => + require("./optimize/AggressiveSplittingPlugin"), + ChunkModuleIdRangePlugin: () => + require("./optimize/ChunkModuleIdRangePlugin"), + LimitChunkCountPlugin: () => require("./optimize/LimitChunkCountPlugin"), + MinChunkSizePlugin: () => require("./optimize/MinChunkSizePlugin"), + ModuleConcatenationPlugin: () => + require("./optimize/ModuleConcatenationPlugin"), + OccurrenceOrderPlugin: () => require("./optimize/OccurrenceOrderPlugin"), + OccurrenceModuleOrderPlugin: () => + require("./optimize/OccurrenceModuleOrderPlugin"), + OccurrenceChunkOrderPlugin: () => + require("./optimize/OccurrenceChunkOrderPlugin"), + RuntimeChunkPlugin: () => require("./optimize/RuntimeChunkPlugin"), + SideEffectsFlagPlugin: () => require("./optimize/SideEffectsFlagPlugin"), + SplitChunksPlugin: () => require("./optimize/SplitChunksPlugin") +}); +exportPlugins((exports.web = {}), { + FetchCompileWasmTemplatePlugin: () => + require("./web/FetchCompileWasmTemplatePlugin"), + JsonpTemplatePlugin: () => require("./web/JsonpTemplatePlugin") +}); +exportPlugins((exports.webworker = {}), { + WebWorkerTemplatePlugin: () => require("./webworker/WebWorkerTemplatePlugin") +}); +exportPlugins((exports.node = {}), { + NodeTemplatePlugin: () => require("./node/NodeTemplatePlugin"), + ReadFileCompileWasmTemplatePlugin: () => + require("./node/ReadFileCompileWasmTemplatePlugin") +}); +exportPlugins((exports.debug = {}), { + ProfilingPlugin: () => require("./debug/ProfilingPlugin") +}); +exportPlugins((exports.util = {}), { + createHash: () => require("./util/createHash") +}); + +const defineMissingPluginError = (namespace, pluginName, errorMessage) => { + Object.defineProperty(namespace, pluginName, { + configurable: false, + enumerable: true, + get() { + throw new RemovedPluginError(errorMessage); + } + }); +}; + +// TODO remove in webpack 5 +defineMissingPluginError( + exports.optimize, + "UglifyJsPlugin", + "webpack.optimize.UglifyJsPlugin has been removed, please use config.optimization.minimize instead." +); + +// TODO remove in webpack 5 +defineMissingPluginError( + exports.optimize, + "CommonsChunkPlugin", + "webpack.optimize.CommonsChunkPlugin has been removed, please use config.optimization.splitChunks instead." +); diff --git a/node_modules/webpack/lib/webpack.web.js b/node_modules/webpack/lib/webpack.web.js index 9747e11e5..1f60eab7f 100644 --- a/node_modules/webpack/lib/webpack.web.js +++ b/node_modules/webpack/lib/webpack.web.js @@ -1,29 +1,31 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const Compiler = require("./Compiler"); -const WebEnvironmentPlugin = require("./web/WebEnvironmentPlugin"); -const WebpackOptionsApply = require("./WebpackOptionsApply"); -const WebpackOptionsDefaulter = require("./WebpackOptionsDefaulter"); - -function webpack(options, callback) { - new WebpackOptionsDefaulter().process(options); - - const compiler = new Compiler(); - compiler.options = options; - compiler.options = new WebpackOptionsApply().process(options, compiler); - new WebEnvironmentPlugin(options.inputFileSystem, options.outputFileSystem).apply(compiler); - if(callback) { - compiler.run(callback); - } - return compiler; -} -module.exports = webpack; - -webpack.WebpackOptionsDefaulter = WebpackOptionsDefaulter; -webpack.WebpackOptionsApply = WebpackOptionsApply; -webpack.Compiler = Compiler; -webpack.WebEnvironmentPlugin = WebEnvironmentPlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const Compiler = require("./Compiler"); +const WebEnvironmentPlugin = require("./web/WebEnvironmentPlugin"); +const WebpackOptionsApply = require("./WebpackOptionsApply"); +const WebpackOptionsDefaulter = require("./WebpackOptionsDefaulter"); + +const webpack = (options, callback) => { + new WebpackOptionsDefaulter().process(options); + + const compiler = new Compiler(); + compiler.options = new WebpackOptionsApply().process(options, compiler); + new WebEnvironmentPlugin( + options.inputFileSystem, + options.outputFileSystem + ).apply(compiler); + if (callback) { + compiler.run(callback); + } + return compiler; +}; +module.exports = webpack; + +webpack.WebpackOptionsDefaulter = WebpackOptionsDefaulter; +webpack.WebpackOptionsApply = WebpackOptionsApply; +webpack.Compiler = Compiler; +webpack.WebEnvironmentPlugin = WebEnvironmentPlugin; diff --git a/node_modules/webpack/lib/webworker/WebWorkerChunkTemplatePlugin.js b/node_modules/webpack/lib/webworker/WebWorkerChunkTemplatePlugin.js index 3944f3cfc..f44ca26cd 100644 --- a/node_modules/webpack/lib/webworker/WebWorkerChunkTemplatePlugin.js +++ b/node_modules/webpack/lib/webworker/WebWorkerChunkTemplatePlugin.js @@ -1,29 +1,35 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const ConcatSource = require("webpack-sources").ConcatSource; -const Template = require("../Template"); - -class WebWorkerChunkTemplatePlugin { - - apply(chunkTemplate) { - chunkTemplate.plugin("render", function(modules, chunk) { - const chunkCallbackName = this.outputOptions.chunkCallbackName || Template.toIdentifier("webpackChunk" + (this.outputOptions.library || "")); - const source = new ConcatSource(); - source.add(`${chunkCallbackName}(${JSON.stringify(chunk.ids)},`); - source.add(modules); - source.add(")"); - return source; - }); - chunkTemplate.plugin("hash", function(hash) { - hash.update("webworker"); - hash.update("3"); - hash.update(`${this.outputOptions.chunkCallbackName}`); - hash.update(`${this.outputOptions.library}`); - }); - } -} -module.exports = WebWorkerChunkTemplatePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const { ConcatSource } = require("webpack-sources"); + +class WebWorkerChunkTemplatePlugin { + apply(chunkTemplate) { + chunkTemplate.hooks.render.tap( + "WebWorkerChunkTemplatePlugin", + (modules, chunk) => { + const chunkCallbackName = chunkTemplate.outputOptions.chunkCallbackName; + const globalObject = chunkTemplate.outputOptions.globalObject; + const source = new ConcatSource(); + source.add( + `${globalObject}[${JSON.stringify( + chunkCallbackName + )}](${JSON.stringify(chunk.ids)},` + ); + source.add(modules); + source.add(")"); + return source; + } + ); + chunkTemplate.hooks.hash.tap("WebWorkerChunkTemplatePlugin", hash => { + hash.update("webworker"); + hash.update("3"); + hash.update(`${chunkTemplate.outputOptions.chunkCallbackName}`); + hash.update(`${chunkTemplate.outputOptions.globalObject}`); + }); + } +} +module.exports = WebWorkerChunkTemplatePlugin; diff --git a/node_modules/webpack/lib/webworker/WebWorkerHotUpdateChunkTemplatePlugin.js b/node_modules/webpack/lib/webworker/WebWorkerHotUpdateChunkTemplatePlugin.js index c128be7c7..8b0261194 100644 --- a/node_modules/webpack/lib/webworker/WebWorkerHotUpdateChunkTemplatePlugin.js +++ b/node_modules/webpack/lib/webworker/WebWorkerHotUpdateChunkTemplatePlugin.js @@ -1,28 +1,40 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; -const ConcatSource = require("webpack-sources").ConcatSource; -const Template = require("../Template"); - -class WebWorkerHotUpdateChunkTemplatePlugin { - - apply(hotUpdateChunkTemplate) { - hotUpdateChunkTemplate.plugin("render", function(modulesSource, modules, removedModules, hash, id) { - const chunkCallbackName = this.outputOptions.hotUpdateFunction || Template.toIdentifier("webpackHotUpdate" + (this.outputOptions.library || "")); - const source = new ConcatSource(); - source.add(chunkCallbackName + "(" + JSON.stringify(id) + ","); - source.add(modulesSource); - source.add(")"); - return source; - }); - hotUpdateChunkTemplate.plugin("hash", function(hash) { - hash.update("WebWorkerHotUpdateChunkTemplatePlugin"); - hash.update("3"); - hash.update(this.outputOptions.hotUpdateFunction + ""); - hash.update(this.outputOptions.library + ""); - }); - } -} -module.exports = WebWorkerHotUpdateChunkTemplatePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; +const { ConcatSource } = require("webpack-sources"); + +class WebWorkerHotUpdateChunkTemplatePlugin { + apply(hotUpdateChunkTemplate) { + hotUpdateChunkTemplate.hooks.render.tap( + "WebWorkerHotUpdateChunkTemplatePlugin", + (modulesSource, modules, removedModules, hash, id) => { + const hotUpdateFunction = + hotUpdateChunkTemplate.outputOptions.hotUpdateFunction; + const globalObject = hotUpdateChunkTemplate.outputOptions.globalObject; + const source = new ConcatSource(); + source.add( + `${globalObject}[${JSON.stringify( + hotUpdateFunction + )}](${JSON.stringify(id)},` + ); + source.add(modulesSource); + source.add(")"); + return source; + } + ); + hotUpdateChunkTemplate.hooks.hash.tap( + "WebWorkerHotUpdateChunkTemplatePlugin", + hash => { + hash.update("WebWorkerHotUpdateChunkTemplatePlugin"); + hash.update("3"); + hash.update( + hotUpdateChunkTemplate.outputOptions.hotUpdateFunction + "" + ); + hash.update(hotUpdateChunkTemplate.outputOptions.globalObject + ""); + } + ); + } +} +module.exports = WebWorkerHotUpdateChunkTemplatePlugin; diff --git a/node_modules/webpack/lib/webworker/WebWorkerMainTemplate.runtime.js b/node_modules/webpack/lib/webworker/WebWorkerMainTemplate.runtime.js index 9b6c59fea..8c63f7729 100644 --- a/node_modules/webpack/lib/webworker/WebWorkerMainTemplate.runtime.js +++ b/node_modules/webpack/lib/webworker/WebWorkerMainTemplate.runtime.js @@ -1,58 +1,65 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -/*globals installedChunks hotAddUpdateChunk parentHotUpdateCallback importScripts XMLHttpRequest $require$ $hotChunkFilename$ $hotMainFilename$ */ -module.exports = function() { - function webpackHotUpdateCallback(chunkId, moreModules) { // eslint-disable-line no-unused-vars - hotAddUpdateChunk(chunkId, moreModules); - if(parentHotUpdateCallback) parentHotUpdateCallback(chunkId, moreModules); - } //$semicolon - - function hotDownloadUpdateChunk(chunkId) { // eslint-disable-line no-unused-vars - importScripts($require$.p + $hotChunkFilename$); - } - - function hotDownloadManifest(requestTimeout) { // eslint-disable-line no-unused-vars - requestTimeout = requestTimeout || 10000; - return new Promise(function(resolve, reject) { - if(typeof XMLHttpRequest === "undefined") - return reject(new Error("No browser support")); - try { - var request = new XMLHttpRequest(); - var requestPath = $require$.p + $hotMainFilename$; - request.open("GET", requestPath, true); - request.timeout = requestTimeout; - request.send(null); - } catch(err) { - return reject(err); - } - request.onreadystatechange = function() { - if(request.readyState !== 4) return; - if(request.status === 0) { - // timeout - reject(new Error("Manifest request to " + requestPath + " timed out.")); - } else if(request.status === 404) { - // no update available - resolve(); - } else if(request.status !== 200 && request.status !== 304) { - // other failure - reject(new Error("Manifest request to " + requestPath + " failed.")); - } else { - // success - try { - var update = JSON.parse(request.responseText); - } catch(e) { - reject(e); - return; - } - resolve(update); - } - }; - }); - } - - function hotDisposeChunk(chunkId) { //eslint-disable-line no-unused-vars - delete installedChunks[chunkId]; - } -}; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +/*globals installedChunks hotAddUpdateChunk parentHotUpdateCallback importScripts XMLHttpRequest $require$ $hotChunkFilename$ $hotMainFilename$ */ +module.exports = function() { + // eslint-disable-next-line no-unused-vars + function webpackHotUpdateCallback(chunkId, moreModules) { + hotAddUpdateChunk(chunkId, moreModules); + if (parentHotUpdateCallback) parentHotUpdateCallback(chunkId, moreModules); + } //$semicolon + + // eslint-disable-next-line no-unused-vars + function hotDownloadUpdateChunk(chunkId) { + importScripts($require$.p + $hotChunkFilename$); + } + + // eslint-disable-next-line no-unused-vars + function hotDownloadManifest(requestTimeout) { + requestTimeout = requestTimeout || 10000; + return new Promise(function(resolve, reject) { + if (typeof XMLHttpRequest === "undefined") { + return reject(new Error("No browser support")); + } + try { + var request = new XMLHttpRequest(); + var requestPath = $require$.p + $hotMainFilename$; + request.open("GET", requestPath, true); + request.timeout = requestTimeout; + request.send(null); + } catch (err) { + return reject(err); + } + request.onreadystatechange = function() { + if (request.readyState !== 4) return; + if (request.status === 0) { + // timeout + reject( + new Error("Manifest request to " + requestPath + " timed out.") + ); + } else if (request.status === 404) { + // no update available + resolve(); + } else if (request.status !== 200 && request.status !== 304) { + // other failure + reject(new Error("Manifest request to " + requestPath + " failed.")); + } else { + // success + try { + var update = JSON.parse(request.responseText); + } catch (e) { + reject(e); + return; + } + resolve(update); + } + }; + }); + } + + //eslint-disable-next-line no-unused-vars + function hotDisposeChunk(chunkId) { + delete installedChunks[chunkId]; + } +}; diff --git a/node_modules/webpack/lib/webworker/WebWorkerMainTemplatePlugin.js b/node_modules/webpack/lib/webworker/WebWorkerMainTemplatePlugin.js index ff2d6c2f5..39f7dabbd 100644 --- a/node_modules/webpack/lib/webworker/WebWorkerMainTemplatePlugin.js +++ b/node_modules/webpack/lib/webworker/WebWorkerMainTemplatePlugin.js @@ -1,105 +1,191 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const Template = require("../Template"); - -class WebWorkerMainTemplatePlugin { - apply(mainTemplate) { - mainTemplate.plugin("local-vars", function(source, chunk) { - if(chunk.chunks.length > 0) { - return this.asString([ - source, - "", - "// object to store loaded chunks", - "// \"1\" means \"already loaded\"", - "var installedChunks = {", - this.indent( - chunk.ids.map((id) => `${id}: 1`).join(",\n") - ), - "};" - ]); - } - return source; - }); - mainTemplate.plugin("require-ensure", function(_, chunk, hash) { - const chunkFilename = this.outputOptions.chunkFilename; - return this.asString([ - "return new Promise(function(resolve) {", - this.indent([ - "// \"1\" is the signal for \"already loaded\"", - "if(!installedChunks[chunkId]) {", - this.indent([ - "importScripts(" + - this.applyPluginsWaterfall("asset-path", JSON.stringify(chunkFilename), { - hash: `" + ${this.renderCurrentHashCode(hash)} + "`, - hashWithLength: (length) => `" + ${this.renderCurrentHashCode(hash, length)} + "`, - chunk: { - id: "\" + chunkId + \"" - } - }) + ");" - ]), - "}", - "resolve();" - ]), - "});" - ]); - }); - mainTemplate.plugin("bootstrap", function(source, chunk, hash) { - if(chunk.chunks.length > 0) { - const chunkCallbackName = this.outputOptions.chunkCallbackName || Template.toIdentifier("webpackChunk" + (this.outputOptions.library || "")); - return this.asString([ - source, - `this[${JSON.stringify(chunkCallbackName)}] = function webpackChunkCallback(chunkIds, moreModules) {`, - this.indent([ - "for(var moduleId in moreModules) {", - this.indent(this.renderAddModule(hash, chunk, "moduleId", "moreModules[moduleId]")), - "}", - "while(chunkIds.length)", - this.indent("installedChunks[chunkIds.pop()] = 1;") - ]), - "};" - ]); - } - return source; - }); - mainTemplate.plugin("hot-bootstrap", function(source, chunk, hash) { - const hotUpdateChunkFilename = this.outputOptions.hotUpdateChunkFilename; - const hotUpdateMainFilename = this.outputOptions.hotUpdateMainFilename; - const hotUpdateFunction = this.outputOptions.hotUpdateFunction || Template.toIdentifier("webpackHotUpdate" + (this.outputOptions.library || "")); - const currentHotUpdateChunkFilename = this.applyPluginsWaterfall("asset-path", JSON.stringify(hotUpdateChunkFilename), { - hash: `" + ${this.renderCurrentHashCode(hash)} + "`, - hashWithLength: (length) => `" + ${this.renderCurrentHashCode(hash, length)} + "`, - chunk: { - id: "\" + chunkId + \"" - } - }); - const currentHotUpdateMainFilename = this.applyPluginsWaterfall("asset-path", JSON.stringify(hotUpdateMainFilename), { - hash: `" + ${this.renderCurrentHashCode(hash)} + "`, - hashWithLength: (length) => `" + ${this.renderCurrentHashCode(hash, length)} + "`, - }); - - return source + "\n" + - `var parentHotUpdateCallback = self[${JSON.stringify(hotUpdateFunction)}];\n` + - `self[${JSON.stringify(hotUpdateFunction)}] = ` + - Template.getFunctionContent(require("./WebWorkerMainTemplate.runtime.js")) - .replace(/\/\/\$semicolon/g, ";") - .replace(/\$require\$/g, this.requireFn) - .replace(/\$hotMainFilename\$/g, currentHotUpdateMainFilename) - .replace(/\$hotChunkFilename\$/g, currentHotUpdateChunkFilename) - .replace(/\$hash\$/g, JSON.stringify(hash)); - }); - mainTemplate.plugin("hash", function(hash) { - hash.update("webworker"); - hash.update("3"); - hash.update(`${this.outputOptions.publicPath}`); - hash.update(`${this.outputOptions.filename}`); - hash.update(`${this.outputOptions.chunkFilename}`); - hash.update(`${this.outputOptions.chunkCallbackName}`); - hash.update(`${this.outputOptions.library}`); - }); - } -} -module.exports = WebWorkerMainTemplatePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const Template = require("../Template"); + +class WebWorkerMainTemplatePlugin { + apply(mainTemplate) { + const needChunkOnDemandLoadingCode = chunk => { + for (const chunkGroup of chunk.groupsIterable) { + if (chunkGroup.getNumberOfChildren() > 0) return true; + } + return false; + }; + mainTemplate.hooks.localVars.tap( + "WebWorkerMainTemplatePlugin", + (source, chunk) => { + if (needChunkOnDemandLoadingCode(chunk)) { + return Template.asString([ + source, + "", + "// object to store loaded chunks", + '// "1" means "already loaded"', + "var installedChunks = {", + Template.indent( + chunk.ids.map(id => `${JSON.stringify(id)}: 1`).join(",\n") + ), + "};" + ]); + } + return source; + } + ); + mainTemplate.hooks.requireEnsure.tap( + "WebWorkerMainTemplatePlugin", + (_, chunk, hash) => { + const chunkFilename = mainTemplate.outputOptions.chunkFilename; + const chunkMaps = chunk.getChunkMaps(); + return Template.asString([ + "promises.push(Promise.resolve().then(function() {", + Template.indent([ + '// "1" is the signal for "already loaded"', + "if(!installedChunks[chunkId]) {", + Template.indent([ + "importScripts(" + + mainTemplate.getAssetPath(JSON.stringify(chunkFilename), { + hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, + hashWithLength: length => + `" + ${mainTemplate.renderCurrentHashCode( + hash, + length + )} + "`, + chunk: { + id: '" + chunkId + "', + hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`, + hashWithLength(length) { + const shortChunkHashMap = Object.create(null); + for (const chunkId of Object.keys(chunkMaps.hash)) { + if (typeof chunkMaps.hash[chunkId] === "string") { + shortChunkHashMap[chunkId] = chunkMaps.hash[ + chunkId + ].substr(0, length); + } + } + return `" + ${JSON.stringify( + shortChunkHashMap + )}[chunkId] + "`; + }, + contentHash: { + javascript: `" + ${JSON.stringify( + chunkMaps.contentHash.javascript + )}[chunkId] + "` + }, + contentHashWithLength: { + javascript: length => { + const shortContentHashMap = {}; + const contentHash = chunkMaps.contentHash.javascript; + for (const chunkId of Object.keys(contentHash)) { + if (typeof contentHash[chunkId] === "string") { + shortContentHashMap[chunkId] = contentHash[ + chunkId + ].substr(0, length); + } + } + return `" + ${JSON.stringify( + shortContentHashMap + )}[chunkId] + "`; + } + }, + name: `" + (${JSON.stringify( + chunkMaps.name + )}[chunkId]||chunkId) + "` + }, + contentHashType: "javascript" + }) + + ");" + ]), + "}" + ]), + "}));" + ]); + } + ); + mainTemplate.hooks.bootstrap.tap( + "WebWorkerMainTemplatePlugin", + (source, chunk, hash) => { + if (needChunkOnDemandLoadingCode(chunk)) { + const chunkCallbackName = + mainTemplate.outputOptions.chunkCallbackName; + const globalObject = mainTemplate.outputOptions.globalObject; + return Template.asString([ + source, + `${globalObject}[${JSON.stringify( + chunkCallbackName + )}] = function webpackChunkCallback(chunkIds, moreModules) {`, + Template.indent([ + "for(var moduleId in moreModules) {", + Template.indent( + mainTemplate.renderAddModule( + hash, + chunk, + "moduleId", + "moreModules[moduleId]" + ) + ), + "}", + "while(chunkIds.length)", + Template.indent("installedChunks[chunkIds.pop()] = 1;") + ]), + "};" + ]); + } + return source; + } + ); + mainTemplate.hooks.hotBootstrap.tap( + "WebWorkerMainTemplatePlugin", + (source, chunk, hash) => { + const hotUpdateChunkFilename = + mainTemplate.outputOptions.hotUpdateChunkFilename; + const hotUpdateMainFilename = + mainTemplate.outputOptions.hotUpdateMainFilename; + const hotUpdateFunction = mainTemplate.outputOptions.hotUpdateFunction; + const globalObject = mainTemplate.outputOptions.globalObject; + const currentHotUpdateChunkFilename = mainTemplate.getAssetPath( + JSON.stringify(hotUpdateChunkFilename), + { + hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, + hashWithLength: length => + `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`, + chunk: { + id: '" + chunkId + "' + } + } + ); + const currentHotUpdateMainFilename = mainTemplate.getAssetPath( + JSON.stringify(hotUpdateMainFilename), + { + hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, + hashWithLength: length => + `" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "` + } + ); + + return ( + source + + "\n" + + `var parentHotUpdateCallback = ${globalObject}[${JSON.stringify( + hotUpdateFunction + )}];\n` + + `${globalObject}[${JSON.stringify(hotUpdateFunction)}] = ` + + Template.getFunctionContent( + require("./WebWorkerMainTemplate.runtime") + ) + .replace(/\/\/\$semicolon/g, ";") + .replace(/\$require\$/g, mainTemplate.requireFn) + .replace(/\$hotMainFilename\$/g, currentHotUpdateMainFilename) + .replace(/\$hotChunkFilename\$/g, currentHotUpdateChunkFilename) + .replace(/\$hash\$/g, JSON.stringify(hash)) + ); + } + ); + mainTemplate.hooks.hash.tap("WebWorkerMainTemplatePlugin", hash => { + hash.update("webworker"); + hash.update("4"); + }); + } +} +module.exports = WebWorkerMainTemplatePlugin; diff --git a/node_modules/webpack/lib/webworker/WebWorkerTemplatePlugin.js b/node_modules/webpack/lib/webworker/WebWorkerTemplatePlugin.js index 64f1e00f5..5ad89f37a 100644 --- a/node_modules/webpack/lib/webworker/WebWorkerTemplatePlugin.js +++ b/node_modules/webpack/lib/webworker/WebWorkerTemplatePlugin.js @@ -1,20 +1,25 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -"use strict"; - -const WebWorkerMainTemplatePlugin = require("./WebWorkerMainTemplatePlugin"); -const WebWorkerChunkTemplatePlugin = require("./WebWorkerChunkTemplatePlugin"); -const WebWorkerHotUpdateChunkTemplatePlugin = require("./WebWorkerHotUpdateChunkTemplatePlugin"); - -class WebWorkerTemplatePlugin { - apply(compiler) { - compiler.plugin("this-compilation", compilation => { - compilation.mainTemplate.apply(new WebWorkerMainTemplatePlugin()); - compilation.chunkTemplate.apply(new WebWorkerChunkTemplatePlugin()); - compilation.hotUpdateChunkTemplate.apply(new WebWorkerHotUpdateChunkTemplatePlugin()); - }); - } -} -module.exports = WebWorkerTemplatePlugin; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const WebWorkerMainTemplatePlugin = require("./WebWorkerMainTemplatePlugin"); +const WebWorkerChunkTemplatePlugin = require("./WebWorkerChunkTemplatePlugin"); +const WebWorkerHotUpdateChunkTemplatePlugin = require("./WebWorkerHotUpdateChunkTemplatePlugin"); + +class WebWorkerTemplatePlugin { + apply(compiler) { + compiler.hooks.thisCompilation.tap( + "WebWorkerTemplatePlugin", + compilation => { + new WebWorkerMainTemplatePlugin().apply(compilation.mainTemplate); + new WebWorkerChunkTemplatePlugin().apply(compilation.chunkTemplate); + new WebWorkerHotUpdateChunkTemplatePlugin().apply( + compilation.hotUpdateChunkTemplate + ); + } + ); + } +} +module.exports = WebWorkerTemplatePlugin; -- cgit v1.2.3