diff options
Diffstat (limited to 'node_modules/webpack/lib/asset')
| -rw-r--r-- | node_modules/webpack/lib/asset/AssetGenerator.js | 586 | ||||
| -rw-r--r-- | node_modules/webpack/lib/asset/AssetModulesPlugin.js | 244 | ||||
| -rw-r--r-- | node_modules/webpack/lib/asset/AssetParser.js | 65 | ||||
| -rw-r--r-- | node_modules/webpack/lib/asset/AssetSourceGenerator.js | 91 | ||||
| -rw-r--r-- | node_modules/webpack/lib/asset/AssetSourceParser.js | 37 | ||||
| -rw-r--r-- | node_modules/webpack/lib/asset/RawDataUrlModule.js | 162 |
6 files changed, 1185 insertions, 0 deletions
diff --git a/node_modules/webpack/lib/asset/AssetGenerator.js b/node_modules/webpack/lib/asset/AssetGenerator.js new file mode 100644 index 00000000..f5727490 --- /dev/null +++ b/node_modules/webpack/lib/asset/AssetGenerator.js @@ -0,0 +1,586 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Sergey Melyukov @smelukov +*/ + +"use strict"; + +const mimeTypes = require("mime-types"); +const path = require("path"); +const { RawSource } = require("webpack-sources"); +const ConcatenationScope = require("../ConcatenationScope"); +const Generator = require("../Generator"); +const { ASSET_MODULE_TYPE } = require("../ModuleTypeConstants"); +const RuntimeGlobals = require("../RuntimeGlobals"); +const CssUrlDependency = require("../dependencies/CssUrlDependency"); +const createHash = require("../util/createHash"); +const { makePathsRelative } = require("../util/identifier"); +const nonNumericOnlyHash = require("../util/nonNumericOnlyHash"); + +/** @typedef {import("webpack-sources").Source} Source */ +/** @typedef {import("../../declarations/WebpackOptions").AssetGeneratorDataUrlOptions} AssetGeneratorDataUrlOptions */ +/** @typedef {import("../../declarations/WebpackOptions").AssetGeneratorOptions} AssetGeneratorOptions */ +/** @typedef {import("../../declarations/WebpackOptions").AssetModuleFilename} AssetModuleFilename */ +/** @typedef {import("../../declarations/WebpackOptions").AssetModuleOutputPath} AssetModuleOutputPath */ +/** @typedef {import("../../declarations/WebpackOptions").RawPublicPath} RawPublicPath */ +/** @typedef {import("../Compilation")} Compilation */ +/** @typedef {import("../Compiler")} Compiler */ +/** @typedef {import("../Generator").GenerateContext} GenerateContext */ +/** @typedef {import("../Generator").UpdateHashContext} UpdateHashContext */ +/** @typedef {import("../Module")} Module */ +/** @typedef {import("../Module").BuildInfo} BuildInfo */ +/** @typedef {import("../Module").ConcatenationBailoutReasonContext} ConcatenationBailoutReasonContext */ +/** @typedef {import("../NormalModule")} NormalModule */ +/** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */ +/** @typedef {import("../TemplatedPathPlugin").TemplatePath} TemplatePath */ +/** @typedef {import("../util/Hash")} Hash */ +/** @typedef {import("../util/createHash").Algorithm} Algorithm */ + +/** + * @template T + * @template U + * @param {Array<T> | Set<T>} a a + * @param {Array<U> | Set<U>} b b + * @returns {Array<T> & Array<U>} array + */ +const mergeMaybeArrays = (a, b) => { + const set = new Set(); + if (Array.isArray(a)) for (const item of a) set.add(item); + else set.add(a); + if (Array.isArray(b)) for (const item of b) set.add(item); + else set.add(b); + return Array.from(set); +}; + +/** + * @template {object} T + * @template {object} U + * @param {TODO} a a + * @param {TODO} b b + * @returns {T & U} object + */ +const mergeAssetInfo = (a, b) => { + const result = { ...a, ...b }; + for (const key of Object.keys(a)) { + if (key in b) { + if (a[key] === b[key]) continue; + switch (key) { + case "fullhash": + case "chunkhash": + case "modulehash": + case "contenthash": + result[key] = mergeMaybeArrays(a[key], b[key]); + break; + case "immutable": + case "development": + case "hotModuleReplacement": + case "javascriptModule": + result[key] = a[key] || b[key]; + break; + case "related": + result[key] = mergeRelatedInfo(a[key], b[key]); + break; + default: + throw new Error(`Can't handle conflicting asset info for ${key}`); + } + } + } + return result; +}; + +/** + * @template {object} T + * @template {object} U + * @param {TODO} a a + * @param {TODO} b b + * @returns {T & U} object + */ +const mergeRelatedInfo = (a, b) => { + const result = { ...a, ...b }; + for (const key of Object.keys(a)) { + if (key in b) { + if (a[key] === b[key]) continue; + result[key] = mergeMaybeArrays(a[key], b[key]); + } + } + return result; +}; + +/** + * @param {"base64" | false} encoding encoding + * @param {Source} source source + * @returns {string} encoded data + */ +const encodeDataUri = (encoding, source) => { + /** @type {string | undefined} */ + let encodedContent; + + switch (encoding) { + case "base64": { + encodedContent = source.buffer().toString("base64"); + break; + } + case false: { + const content = source.source(); + + if (typeof content !== "string") { + encodedContent = content.toString("utf-8"); + } + + encodedContent = encodeURIComponent( + /** @type {string} */ + (encodedContent) + ).replace( + /[!'()*]/g, + character => + `%${/** @type {number} */ (character.codePointAt(0)).toString(16)}` + ); + break; + } + default: + throw new Error(`Unsupported encoding '${encoding}'`); + } + + return encodedContent; +}; + +/** + * @param {string} encoding encoding + * @param {string} content content + * @returns {Buffer} decoded content + */ +const decodeDataUriContent = (encoding, content) => { + const isBase64 = encoding === "base64"; + + if (isBase64) { + return Buffer.from(content, "base64"); + } + + // If we can't decode return the original body + try { + return Buffer.from(decodeURIComponent(content), "ascii"); + } catch (_) { + return Buffer.from(content, "ascii"); + } +}; + +const JS_TYPES = new Set(["javascript"]); +const JS_AND_ASSET_TYPES = new Set(["javascript", ASSET_MODULE_TYPE]); +const DEFAULT_ENCODING = "base64"; + +class AssetGenerator extends Generator { + /** + * @param {AssetGeneratorOptions["dataUrl"]=} dataUrlOptions the options for the data url + * @param {AssetModuleFilename=} filename override for output.assetModuleFilename + * @param {RawPublicPath=} publicPath override for output.assetModulePublicPath + * @param {AssetModuleOutputPath=} outputPath the output path for the emitted file which is not included in the runtime import + * @param {boolean=} emit generate output asset + */ + constructor(dataUrlOptions, filename, publicPath, outputPath, emit) { + super(); + this.dataUrlOptions = dataUrlOptions; + this.filename = filename; + this.publicPath = publicPath; + this.outputPath = outputPath; + this.emit = emit; + } + + /** + * @param {NormalModule} module module + * @param {RuntimeTemplate} runtimeTemplate runtime template + * @returns {string} source file name + */ + getSourceFileName(module, runtimeTemplate) { + return makePathsRelative( + runtimeTemplate.compilation.compiler.context, + module.matchResource || module.resource, + runtimeTemplate.compilation.compiler.root + ).replace(/^\.\//, ""); + } + + /** + * @param {NormalModule} module module for which the bailout reason should be determined + * @param {ConcatenationBailoutReasonContext} context context + * @returns {string | undefined} reason why this module can't be concatenated, undefined when it can be concatenated + */ + getConcatenationBailoutReason(module, context) { + return undefined; + } + + /** + * @param {NormalModule} module module + * @returns {string} mime type + */ + getMimeType(module) { + if (typeof this.dataUrlOptions === "function") { + throw new Error( + "This method must not be called when dataUrlOptions is a function" + ); + } + + /** @type {string | boolean | undefined} */ + let mimeType = + /** @type {AssetGeneratorDataUrlOptions} */ + (this.dataUrlOptions).mimetype; + if (mimeType === undefined) { + const ext = path.extname( + /** @type {string} */ + (module.nameForCondition()) + ); + if ( + module.resourceResolveData && + module.resourceResolveData.mimetype !== undefined + ) { + mimeType = + module.resourceResolveData.mimetype + + module.resourceResolveData.parameters; + } else if (ext) { + mimeType = mimeTypes.lookup(ext); + + if (typeof mimeType !== "string") { + throw new Error( + "DataUrl can't be generated automatically, " + + `because there is no mimetype for "${ext}" in mimetype database. ` + + 'Either pass a mimetype via "generator.mimetype" or ' + + 'use type: "asset/resource" to create a resource file instead of a DataUrl' + ); + } + } + } + + if (typeof mimeType !== "string") { + throw new Error( + "DataUrl can't be generated automatically. " + + 'Either pass a mimetype via "generator.mimetype" or ' + + 'use type: "asset/resource" to create a resource file instead of a DataUrl' + ); + } + + return /** @type {string} */ (mimeType); + } + + /** + * @param {NormalModule} module module for which the code should be generated + * @param {GenerateContext} generateContext context for generate + * @returns {Source} generated code + */ + generate( + module, + { + runtime, + concatenationScope, + chunkGraph, + runtimeTemplate, + runtimeRequirements, + type, + getData + } + ) { + switch (type) { + case ASSET_MODULE_TYPE: + return /** @type {Source} */ (module.originalSource()); + default: { + let content; + const originalSource = /** @type {Source} */ (module.originalSource()); + if ( + /** @type {BuildInfo} */ + (module.buildInfo).dataUrl + ) { + let encodedSource; + if (typeof this.dataUrlOptions === "function") { + encodedSource = this.dataUrlOptions.call( + null, + originalSource.source(), + { + filename: module.matchResource || module.resource, + module + } + ); + } else { + /** @type {"base64" | false | undefined} */ + let encoding = + /** @type {AssetGeneratorDataUrlOptions} */ + (this.dataUrlOptions).encoding; + if ( + encoding === undefined && + module.resourceResolveData && + module.resourceResolveData.encoding !== undefined + ) { + encoding = module.resourceResolveData.encoding; + } + if (encoding === undefined) { + encoding = DEFAULT_ENCODING; + } + const mimeType = this.getMimeType(module); + + let encodedContent; + + if ( + module.resourceResolveData && + module.resourceResolveData.encoding === encoding && + decodeDataUriContent( + module.resourceResolveData.encoding, + module.resourceResolveData.encodedContent + ).equals(originalSource.buffer()) + ) { + encodedContent = module.resourceResolveData.encodedContent; + } else { + encodedContent = encodeDataUri(encoding, originalSource); + } + + encodedSource = `data:${mimeType}${ + encoding ? `;${encoding}` : "" + },${encodedContent}`; + } + const data = + /** @type {NonNullable<GenerateContext["getData"]>} */ + (getData)(); + data.set("url", Buffer.from(encodedSource)); + content = JSON.stringify(encodedSource); + } else { + const assetModuleFilename = + this.filename || + /** @type {AssetModuleFilename} */ + (runtimeTemplate.outputOptions.assetModuleFilename); + const hash = createHash( + /** @type {Algorithm} */ + (runtimeTemplate.outputOptions.hashFunction) + ); + if (runtimeTemplate.outputOptions.hashSalt) { + hash.update(runtimeTemplate.outputOptions.hashSalt); + } + hash.update(originalSource.buffer()); + const fullHash = /** @type {string} */ ( + hash.digest(runtimeTemplate.outputOptions.hashDigest) + ); + const contentHash = nonNumericOnlyHash( + fullHash, + /** @type {number} */ + (runtimeTemplate.outputOptions.hashDigestLength) + ); + /** @type {BuildInfo} */ + (module.buildInfo).fullContentHash = fullHash; + const sourceFilename = this.getSourceFileName( + module, + runtimeTemplate + ); + let { path: filename, info: assetInfo } = + runtimeTemplate.compilation.getAssetPathWithInfo( + assetModuleFilename, + { + module, + runtime, + filename: sourceFilename, + chunkGraph, + contentHash + } + ); + let assetPath; + let assetPathForCss; + if (this.publicPath !== undefined) { + const { path, info } = + runtimeTemplate.compilation.getAssetPathWithInfo( + this.publicPath, + { + module, + runtime, + filename: sourceFilename, + chunkGraph, + contentHash + } + ); + assetInfo = mergeAssetInfo(assetInfo, info); + assetPath = JSON.stringify(path + filename); + assetPathForCss = path + filename; + } else { + runtimeRequirements.add(RuntimeGlobals.publicPath); // add __webpack_require__.p + assetPath = runtimeTemplate.concatenation( + { expr: RuntimeGlobals.publicPath }, + filename + ); + const compilation = runtimeTemplate.compilation; + const path = + compilation.outputOptions.publicPath === "auto" + ? CssUrlDependency.PUBLIC_PATH_AUTO + : compilation.getAssetPath( + /** @type {TemplatePath} */ + (compilation.outputOptions.publicPath), + { + hash: compilation.hash + } + ); + assetPathForCss = path + filename; + } + assetInfo = { + sourceFilename, + ...assetInfo + }; + if (this.outputPath) { + const { path: outputPath, info } = + runtimeTemplate.compilation.getAssetPathWithInfo( + this.outputPath, + { + module, + runtime, + filename: sourceFilename, + chunkGraph, + contentHash + } + ); + assetInfo = mergeAssetInfo(assetInfo, info); + filename = path.posix.join(outputPath, filename); + } + /** @type {BuildInfo} */ + (module.buildInfo).filename = filename; + /** @type {BuildInfo} */ + (module.buildInfo).assetInfo = assetInfo; + if (getData) { + // Due to code generation caching module.buildInfo.XXX can't used to store such information + // It need to be stored in the code generation results instead, where it's cached too + // TODO webpack 6 For back-compat reasons we also store in on module.buildInfo + const data = getData(); + data.set("fullContentHash", fullHash); + data.set("filename", filename); + data.set("assetInfo", assetInfo); + data.set("assetPathForCss", assetPathForCss); + } + content = assetPath; + } + + if (concatenationScope) { + concatenationScope.registerNamespaceExport( + ConcatenationScope.NAMESPACE_OBJECT_EXPORT + ); + return new RawSource( + `${runtimeTemplate.supportsConst() ? "const" : "var"} ${ + ConcatenationScope.NAMESPACE_OBJECT_EXPORT + } = ${content};` + ); + } + runtimeRequirements.add(RuntimeGlobals.module); + return new RawSource(`${RuntimeGlobals.module}.exports = ${content};`); + } + } + } + + /** + * @param {NormalModule} module fresh module + * @returns {Set<string>} available types (do not mutate) + */ + getTypes(module) { + if ((module.buildInfo && module.buildInfo.dataUrl) || this.emit === false) { + return JS_TYPES; + } + return JS_AND_ASSET_TYPES; + } + + /** + * @param {NormalModule} module the module + * @param {string=} type source type + * @returns {number} estimate size of the module + */ + getSize(module, type) { + switch (type) { + case ASSET_MODULE_TYPE: { + const originalSource = module.originalSource(); + + if (!originalSource) { + return 0; + } + + return originalSource.size(); + } + default: + if (module.buildInfo && module.buildInfo.dataUrl) { + const originalSource = module.originalSource(); + + if (!originalSource) { + return 0; + } + + // roughly for data url + // Example: m.exports="data:image/png;base64,ag82/f+2==" + // 4/3 = base64 encoding + // 34 = ~ data url header + footer + rounding + return originalSource.size() * 1.34 + 36; + } + // it's only estimated so this number is probably fine + // Example: m.exports=r.p+"0123456789012345678901.ext" + return 42; + } + } + + /** + * @param {Hash} hash hash that will be modified + * @param {UpdateHashContext} updateHashContext context for updating hash + */ + updateHash(hash, updateHashContext) { + const { module } = updateHashContext; + if ( + /** @type {BuildInfo} */ + (module.buildInfo).dataUrl + ) { + hash.update("data-url"); + // this.dataUrlOptions as function should be pure and only depend on input source and filename + // therefore it doesn't need to be hashed + if (typeof this.dataUrlOptions === "function") { + const ident = /** @type {{ ident?: string }} */ (this.dataUrlOptions) + .ident; + if (ident) hash.update(ident); + } else { + const dataUrlOptions = + /** @type {AssetGeneratorDataUrlOptions} */ + (this.dataUrlOptions); + if ( + dataUrlOptions.encoding && + dataUrlOptions.encoding !== DEFAULT_ENCODING + ) { + hash.update(dataUrlOptions.encoding); + } + if (dataUrlOptions.mimetype) hash.update(dataUrlOptions.mimetype); + // computed mimetype depends only on module filename which is already part of the hash + } + } else { + hash.update("resource"); + + const { module, chunkGraph, runtime } = updateHashContext; + const runtimeTemplate = + /** @type {NonNullable<UpdateHashContext["runtimeTemplate"]>} */ + (updateHashContext.runtimeTemplate); + + const pathData = { + module, + runtime, + filename: this.getSourceFileName(module, runtimeTemplate), + chunkGraph, + contentHash: runtimeTemplate.contentHashReplacement + }; + + if (typeof this.publicPath === "function") { + hash.update("path"); + const assetInfo = {}; + hash.update(this.publicPath(pathData, assetInfo)); + hash.update(JSON.stringify(assetInfo)); + } else if (this.publicPath) { + hash.update("path"); + hash.update(this.publicPath); + } else { + hash.update("no-path"); + } + + const assetModuleFilename = + this.filename || + /** @type {AssetModuleFilename} */ + (runtimeTemplate.outputOptions.assetModuleFilename); + const { path: filename, info } = + runtimeTemplate.compilation.getAssetPathWithInfo( + assetModuleFilename, + pathData + ); + hash.update(filename); + hash.update(JSON.stringify(info)); + } + } +} + +module.exports = AssetGenerator; diff --git a/node_modules/webpack/lib/asset/AssetModulesPlugin.js b/node_modules/webpack/lib/asset/AssetModulesPlugin.js new file mode 100644 index 00000000..490969b2 --- /dev/null +++ b/node_modules/webpack/lib/asset/AssetModulesPlugin.js @@ -0,0 +1,244 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Yuta Hiroto @hiroppy +*/ + +"use strict"; + +const { + ASSET_MODULE_TYPE_RESOURCE, + ASSET_MODULE_TYPE_INLINE, + ASSET_MODULE_TYPE, + ASSET_MODULE_TYPE_SOURCE +} = require("../ModuleTypeConstants"); +const { cleverMerge } = require("../util/cleverMerge"); +const { compareModulesByIdentifier } = require("../util/comparators"); +const createSchemaValidation = require("../util/create-schema-validation"); +const memoize = require("../util/memoize"); + +/** @typedef {import("webpack-sources").Source} Source */ +/** @typedef {import("../../declarations/WebpackOptions").AssetParserOptions} AssetParserOptions */ +/** @typedef {import("../Chunk")} Chunk */ +/** @typedef {import("../Compiler")} Compiler */ +/** @typedef {import("../Module")} Module */ +/** @typedef {import("../Module").BuildInfo} BuildInfo */ +/** @typedef {import("../Module").CodeGenerationResult} CodeGenerationResult */ + +/** + * @param {string} name name of definitions + * @returns {TODO} definition + */ +const getSchema = name => { + const { definitions } = require("../../schemas/WebpackOptions.json"); + return { + definitions, + oneOf: [{ $ref: `#/definitions/${name}` }] + }; +}; + +const generatorValidationOptions = { + name: "Asset Modules Plugin", + baseDataPath: "generator" +}; +const validateGeneratorOptions = { + asset: createSchemaValidation( + require("../../schemas/plugins/asset/AssetGeneratorOptions.check.js"), + () => getSchema("AssetGeneratorOptions"), + generatorValidationOptions + ), + "asset/resource": createSchemaValidation( + require("../../schemas/plugins/asset/AssetResourceGeneratorOptions.check.js"), + () => getSchema("AssetResourceGeneratorOptions"), + generatorValidationOptions + ), + "asset/inline": createSchemaValidation( + require("../../schemas/plugins/asset/AssetInlineGeneratorOptions.check.js"), + () => getSchema("AssetInlineGeneratorOptions"), + generatorValidationOptions + ) +}; + +const validateParserOptions = createSchemaValidation( + require("../../schemas/plugins/asset/AssetParserOptions.check.js"), + () => getSchema("AssetParserOptions"), + { + name: "Asset Modules Plugin", + baseDataPath: "parser" + } +); + +const getAssetGenerator = memoize(() => require("./AssetGenerator")); +const getAssetParser = memoize(() => require("./AssetParser")); +const getAssetSourceParser = memoize(() => require("./AssetSourceParser")); +const getAssetSourceGenerator = memoize(() => + require("./AssetSourceGenerator") +); + +const type = ASSET_MODULE_TYPE; +const plugin = "AssetModulesPlugin"; + +class AssetModulesPlugin { + /** + * Apply the plugin + * @param {Compiler} compiler the compiler instance + * @returns {void} + */ + apply(compiler) { + compiler.hooks.compilation.tap( + plugin, + (compilation, { normalModuleFactory }) => { + normalModuleFactory.hooks.createParser + .for(ASSET_MODULE_TYPE) + .tap(plugin, parserOptions => { + validateParserOptions(parserOptions); + parserOptions = cleverMerge( + /** @type {AssetParserOptions} */ + (compiler.options.module.parser.asset), + parserOptions + ); + + let dataUrlCondition = parserOptions.dataUrlCondition; + if (!dataUrlCondition || typeof dataUrlCondition === "object") { + dataUrlCondition = { + maxSize: 8096, + ...dataUrlCondition + }; + } + + const AssetParser = getAssetParser(); + + return new AssetParser(dataUrlCondition); + }); + normalModuleFactory.hooks.createParser + .for(ASSET_MODULE_TYPE_INLINE) + .tap(plugin, _parserOptions => { + const AssetParser = getAssetParser(); + + return new AssetParser(true); + }); + normalModuleFactory.hooks.createParser + .for(ASSET_MODULE_TYPE_RESOURCE) + .tap(plugin, _parserOptions => { + const AssetParser = getAssetParser(); + + return new AssetParser(false); + }); + normalModuleFactory.hooks.createParser + .for(ASSET_MODULE_TYPE_SOURCE) + .tap(plugin, _parserOptions => { + const AssetSourceParser = getAssetSourceParser(); + + return new AssetSourceParser(); + }); + + for (const type of [ + ASSET_MODULE_TYPE, + ASSET_MODULE_TYPE_INLINE, + ASSET_MODULE_TYPE_RESOURCE + ]) { + normalModuleFactory.hooks.createGenerator + .for(type) + .tap(plugin, generatorOptions => { + validateGeneratorOptions[type](generatorOptions); + + let dataUrl; + if (type !== ASSET_MODULE_TYPE_RESOURCE) { + dataUrl = generatorOptions.dataUrl; + if (!dataUrl || typeof dataUrl === "object") { + dataUrl = { + encoding: undefined, + mimetype: undefined, + ...dataUrl + }; + } + } + + let filename; + let publicPath; + let outputPath; + if (type !== ASSET_MODULE_TYPE_INLINE) { + filename = generatorOptions.filename; + publicPath = generatorOptions.publicPath; + outputPath = generatorOptions.outputPath; + } + + const AssetGenerator = getAssetGenerator(); + + return new AssetGenerator( + dataUrl, + filename, + publicPath, + outputPath, + generatorOptions.emit !== false + ); + }); + } + normalModuleFactory.hooks.createGenerator + .for(ASSET_MODULE_TYPE_SOURCE) + .tap(plugin, () => { + const AssetSourceGenerator = getAssetSourceGenerator(); + + return new AssetSourceGenerator(); + }); + + compilation.hooks.renderManifest.tap(plugin, (result, options) => { + const { chunkGraph } = compilation; + const { chunk, codeGenerationResults } = options; + + const modules = chunkGraph.getOrderedChunkModulesIterableBySourceType( + chunk, + ASSET_MODULE_TYPE, + compareModulesByIdentifier + ); + if (modules) { + for (const module of modules) { + try { + const codeGenResult = codeGenerationResults.get( + module, + chunk.runtime + ); + const buildInfo = /** @type {BuildInfo} */ (module.buildInfo); + const data = + /** @type {NonNullable<CodeGenerationResult["data"]>} */ + (codeGenResult.data); + result.push({ + render: () => + /** @type {Source} */ (codeGenResult.sources.get(type)), + filename: buildInfo.filename || data.get("filename"), + info: buildInfo.assetInfo || data.get("assetInfo"), + auxiliary: true, + identifier: `assetModule${chunkGraph.getModuleId(module)}`, + hash: buildInfo.fullContentHash || data.get("fullContentHash") + }); + } catch (err) { + /** @type {Error} */ (err).message += + `\nduring rendering of asset ${module.identifier()}`; + throw err; + } + } + } + + return result; + }); + + compilation.hooks.prepareModuleExecution.tap( + "AssetModulesPlugin", + (options, context) => { + const { codeGenerationResult } = options; + const source = codeGenerationResult.sources.get(ASSET_MODULE_TYPE); + if (source === undefined) return; + const data = + /** @type {NonNullable<CodeGenerationResult["data"]>} */ + (codeGenerationResult.data); + context.assets.set(data.get("filename"), { + source, + info: data.get("assetInfo") + }); + } + ); + } + ); + } +} + +module.exports = AssetModulesPlugin; diff --git a/node_modules/webpack/lib/asset/AssetParser.js b/node_modules/webpack/lib/asset/AssetParser.js new file mode 100644 index 00000000..b4f1d534 --- /dev/null +++ b/node_modules/webpack/lib/asset/AssetParser.js @@ -0,0 +1,65 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Yuta Hiroto @hiroppy +*/ + +"use strict"; + +const Parser = require("../Parser"); + +/** @typedef {import("../../declarations/WebpackOptions").AssetParserDataUrlOptions} AssetParserDataUrlOptions */ +/** @typedef {import("../../declarations/WebpackOptions").AssetParserOptions} AssetParserOptions */ +/** @typedef {import("../Module").BuildInfo} BuildInfo */ +/** @typedef {import("../Module").BuildMeta} BuildMeta */ +/** @typedef {import("../Parser").ParserState} ParserState */ +/** @typedef {import("../Parser").PreparsedAst} PreparsedAst */ + +class AssetParser extends Parser { + /** + * @param {AssetParserOptions["dataUrlCondition"] | boolean} dataUrlCondition condition for inlining as DataUrl + */ + constructor(dataUrlCondition) { + super(); + this.dataUrlCondition = dataUrlCondition; + } + + /** + * @param {string | Buffer | PreparsedAst} source the source to parse + * @param {ParserState} state the parser state + * @returns {ParserState} the parser state + */ + parse(source, state) { + if (typeof source === "object" && !Buffer.isBuffer(source)) { + throw new Error("AssetParser doesn't accept preparsed AST"); + } + + const buildInfo = /** @type {BuildInfo} */ (state.module.buildInfo); + buildInfo.strict = true; + const buildMeta = /** @type {BuildMeta} */ (state.module.buildMeta); + buildMeta.exportsType = "default"; + buildMeta.defaultObject = false; + + if (typeof this.dataUrlCondition === "function") { + buildInfo.dataUrl = this.dataUrlCondition(source, { + filename: state.module.matchResource || state.module.resource, + module: state.module + }); + } else if (typeof this.dataUrlCondition === "boolean") { + buildInfo.dataUrl = this.dataUrlCondition; + } else if ( + this.dataUrlCondition && + typeof this.dataUrlCondition === "object" + ) { + buildInfo.dataUrl = + Buffer.byteLength(source) <= + /** @type {NonNullable<AssetParserDataUrlOptions["maxSize"]>} */ + (this.dataUrlCondition.maxSize); + } else { + throw new Error("Unexpected dataUrlCondition type"); + } + + return state; + } +} + +module.exports = AssetParser; diff --git a/node_modules/webpack/lib/asset/AssetSourceGenerator.js b/node_modules/webpack/lib/asset/AssetSourceGenerator.js new file mode 100644 index 00000000..6149a779 --- /dev/null +++ b/node_modules/webpack/lib/asset/AssetSourceGenerator.js @@ -0,0 +1,91 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Sergey Melyukov @smelukov +*/ + +"use strict"; + +const { RawSource } = require("webpack-sources"); +const ConcatenationScope = require("../ConcatenationScope"); +const Generator = require("../Generator"); +const RuntimeGlobals = require("../RuntimeGlobals"); + +/** @typedef {import("webpack-sources").Source} Source */ +/** @typedef {import("../Generator").GenerateContext} GenerateContext */ +/** @typedef {import("../Module").ConcatenationBailoutReasonContext} ConcatenationBailoutReasonContext */ +/** @typedef {import("../NormalModule")} NormalModule */ + +const TYPES = new Set(["javascript"]); + +class AssetSourceGenerator extends Generator { + /** + * @param {NormalModule} module module for which the code should be generated + * @param {GenerateContext} generateContext context for generate + * @returns {Source} generated code + */ + generate( + module, + { concatenationScope, chunkGraph, runtimeTemplate, runtimeRequirements } + ) { + const originalSource = module.originalSource(); + + if (!originalSource) { + return new RawSource(""); + } + + const content = originalSource.source(); + const encodedSource = + typeof content === "string" ? content : content.toString("utf-8"); + + let sourceContent; + if (concatenationScope) { + concatenationScope.registerNamespaceExport( + ConcatenationScope.NAMESPACE_OBJECT_EXPORT + ); + sourceContent = `${runtimeTemplate.supportsConst() ? "const" : "var"} ${ + ConcatenationScope.NAMESPACE_OBJECT_EXPORT + } = ${JSON.stringify(encodedSource)};`; + } else { + runtimeRequirements.add(RuntimeGlobals.module); + sourceContent = `${RuntimeGlobals.module}.exports = ${JSON.stringify( + encodedSource + )};`; + } + return new RawSource(sourceContent); + } + + /** + * @param {NormalModule} module module for which the bailout reason should be determined + * @param {ConcatenationBailoutReasonContext} context context + * @returns {string | undefined} reason why this module can't be concatenated, undefined when it can be concatenated + */ + getConcatenationBailoutReason(module, context) { + return undefined; + } + + /** + * @param {NormalModule} module fresh module + * @returns {Set<string>} available types (do not mutate) + */ + getTypes(module) { + return TYPES; + } + + /** + * @param {NormalModule} module the module + * @param {string=} type source type + * @returns {number} estimate size of the module + */ + getSize(module, type) { + const originalSource = module.originalSource(); + + if (!originalSource) { + return 0; + } + + // Example: m.exports="abcd" + return originalSource.size() + 12; + } +} + +module.exports = AssetSourceGenerator; diff --git a/node_modules/webpack/lib/asset/AssetSourceParser.js b/node_modules/webpack/lib/asset/AssetSourceParser.js new file mode 100644 index 00000000..c122f0ea --- /dev/null +++ b/node_modules/webpack/lib/asset/AssetSourceParser.js @@ -0,0 +1,37 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Yuta Hiroto @hiroppy +*/ + +"use strict"; + +const Parser = require("../Parser"); + +/** @typedef {import("../Module").BuildInfo} BuildInfo */ +/** @typedef {import("../Module").BuildMeta} BuildMeta */ +/** @typedef {import("../Parser").ParserState} ParserState */ +/** @typedef {import("../Parser").PreparsedAst} PreparsedAst */ + +class AssetSourceParser extends Parser { + /** + * @param {string | Buffer | PreparsedAst} source the source to parse + * @param {ParserState} state the parser state + * @returns {ParserState} the parser state + */ + parse(source, state) { + if (typeof source === "object" && !Buffer.isBuffer(source)) { + throw new Error("AssetSourceParser doesn't accept preparsed AST"); + } + const { module } = state; + /** @type {BuildInfo} */ + (module.buildInfo).strict = true; + /** @type {BuildMeta} */ + (module.buildMeta).exportsType = "default"; + /** @type {BuildMeta} */ + (state.module.buildMeta).defaultObject = false; + + return state; + } +} + +module.exports = AssetSourceParser; diff --git a/node_modules/webpack/lib/asset/RawDataUrlModule.js b/node_modules/webpack/lib/asset/RawDataUrlModule.js new file mode 100644 index 00000000..3098b9c2 --- /dev/null +++ b/node_modules/webpack/lib/asset/RawDataUrlModule.js @@ -0,0 +1,162 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ + +"use strict"; + +const { RawSource } = require("webpack-sources"); +const Module = require("../Module"); +const { ASSET_MODULE_TYPE_RAW_DATA_URL } = require("../ModuleTypeConstants"); +const RuntimeGlobals = require("../RuntimeGlobals"); +const makeSerializable = require("../util/makeSerializable"); + +/** @typedef {import("../../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */ +/** @typedef {import("../Compilation")} Compilation */ +/** @typedef {import("../Dependency").UpdateHashContext} UpdateHashContext */ +/** @typedef {import("../Module").CodeGenerationContext} CodeGenerationContext */ +/** @typedef {import("../Module").CodeGenerationResult} CodeGenerationResult */ +/** @typedef {import("../Module").NeedBuildContext} NeedBuildContext */ +/** @typedef {import("../Module").SourceTypes} SourceTypes */ +/** @typedef {import("../RequestShortener")} RequestShortener */ +/** @typedef {import("../ResolverFactory").ResolverWithOptions} ResolverWithOptions */ +/** @typedef {import("../WebpackError")} WebpackError */ +/** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */ +/** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */ +/** @typedef {import("../util/Hash")} Hash */ +/** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */ + +const TYPES = new Set(["javascript"]); + +class RawDataUrlModule extends Module { + /** + * @param {string} url raw url + * @param {string} identifier unique identifier + * @param {string=} readableIdentifier readable identifier + */ + constructor(url, identifier, readableIdentifier) { + super(ASSET_MODULE_TYPE_RAW_DATA_URL, null); + this.url = url; + this.urlBuffer = url ? Buffer.from(url) : undefined; + this.identifierStr = identifier || this.url; + this.readableIdentifierStr = readableIdentifier || this.identifierStr; + } + + /** + * @returns {SourceTypes} types available (do not mutate) + */ + getSourceTypes() { + return TYPES; + } + + /** + * @returns {string} a unique identifier of the module + */ + identifier() { + return this.identifierStr; + } + + /** + * @param {string=} type the source type for which the size should be estimated + * @returns {number} the estimated size of the module (must be non-zero) + */ + size(type) { + if (this.url === undefined) + this.url = /** @type {Buffer} */ (this.urlBuffer).toString(); + return Math.max(1, this.url.length); + } + + /** + * @param {RequestShortener} requestShortener the request shortener + * @returns {string} a user readable identifier of the module + */ + readableIdentifier(requestShortener) { + return /** @type {string} */ ( + requestShortener.shorten(this.readableIdentifierStr) + ); + } + + /** + * @param {NeedBuildContext} context context info + * @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild + * @returns {void} + */ + needBuild(context, callback) { + return callback(null, !this.buildMeta); + } + + /** + * @param {WebpackOptions} options webpack options + * @param {Compilation} compilation the compilation + * @param {ResolverWithOptions} resolver the resolver + * @param {InputFileSystem} fs the file system + * @param {function(WebpackError=): void} callback callback function + * @returns {void} + */ + build(options, compilation, resolver, fs, callback) { + this.buildMeta = {}; + this.buildInfo = { + cacheable: true + }; + callback(); + } + + /** + * @param {CodeGenerationContext} context context for code generation + * @returns {CodeGenerationResult} result + */ + codeGeneration(context) { + if (this.url === undefined) + this.url = /** @type {Buffer} */ (this.urlBuffer).toString(); + const sources = new Map(); + sources.set( + "javascript", + new RawSource(`module.exports = ${JSON.stringify(this.url)};`) + ); + const data = new Map(); + data.set("url", this.urlBuffer); + const runtimeRequirements = new Set(); + runtimeRequirements.add(RuntimeGlobals.module); + return { sources, runtimeRequirements, data }; + } + + /** + * @param {Hash} hash the hash used to track dependencies + * @param {UpdateHashContext} context context + * @returns {void} + */ + updateHash(hash, context) { + hash.update(/** @type {Buffer} */ (this.urlBuffer)); + super.updateHash(hash, context); + } + + /** + * @param {ObjectSerializerContext} context context + */ + serialize(context) { + const { write } = context; + + write(this.urlBuffer); + write(this.identifierStr); + write(this.readableIdentifierStr); + + super.serialize(context); + } + + /** + * @param {ObjectDeserializerContext} context context + */ + deserialize(context) { + const { read } = context; + + this.urlBuffer = read(); + this.identifierStr = read(); + this.readableIdentifierStr = read(); + + super.deserialize(context); + } +} + +makeSerializable(RawDataUrlModule, "webpack/lib/asset/RawDataUrlModule"); + +module.exports = RawDataUrlModule; |
