diff options
| author | littleblack111 <littleblack11111@gmail.com> | 2023-11-05 17:16:09 +0800 |
|---|---|---|
| committer | littleblack111 <littleblack11111@gmail.com> | 2023-11-05 17:16:09 +0800 |
| commit | d1d9f00b1bd660842addf5e6b1d1b64c852a9eea (patch) | |
| tree | 60fb37ae73a1109d95301de5ec9b61b5726a4b61 /node_modules/webpack/lib/dependencies/WorkerPlugin.js | |
| parent | 7c85166c4cbdd862fc4252007d2df5befcbc2a58 (diff) | |
added hover prefixer
Diffstat (limited to 'node_modules/webpack/lib/dependencies/WorkerPlugin.js')
| -rw-r--r-- | node_modules/webpack/lib/dependencies/WorkerPlugin.js | 491 |
1 files changed, 491 insertions, 0 deletions
diff --git a/node_modules/webpack/lib/dependencies/WorkerPlugin.js b/node_modules/webpack/lib/dependencies/WorkerPlugin.js new file mode 100644 index 00000000..cdbea3e5 --- /dev/null +++ b/node_modules/webpack/lib/dependencies/WorkerPlugin.js @@ -0,0 +1,491 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ + +"use strict"; + +const { pathToFileURL } = require("url"); +const AsyncDependenciesBlock = require("../AsyncDependenciesBlock"); +const CommentCompilationWarning = require("../CommentCompilationWarning"); +const { + JAVASCRIPT_MODULE_TYPE_AUTO, + JAVASCRIPT_MODULE_TYPE_ESM +} = require("../ModuleTypeConstants"); +const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning"); +const EnableChunkLoadingPlugin = require("../javascript/EnableChunkLoadingPlugin"); +const { equals } = require("../util/ArrayHelpers"); +const createHash = require("../util/createHash"); +const { contextify } = require("../util/identifier"); +const EnableWasmLoadingPlugin = require("../wasm/EnableWasmLoadingPlugin"); +const ConstDependency = require("./ConstDependency"); +const CreateScriptUrlDependency = require("./CreateScriptUrlDependency"); +const { + harmonySpecifierTag +} = require("./HarmonyImportDependencyParserPlugin"); +const WorkerDependency = require("./WorkerDependency"); + +/** @typedef {import("estree").CallExpression} CallExpression */ +/** @typedef {import("estree").Expression} Expression */ +/** @typedef {import("estree").ObjectExpression} ObjectExpression */ +/** @typedef {import("estree").Pattern} Pattern */ +/** @typedef {import("estree").Property} Property */ +/** @typedef {import("estree").SpreadElement} SpreadElement */ +/** @typedef {import("../../declarations/WebpackOptions").ChunkLoading} ChunkLoading */ +/** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */ +/** @typedef {import("../../declarations/WebpackOptions").OutputModule} OutputModule */ +/** @typedef {import("../../declarations/WebpackOptions").WasmLoading} WasmLoading */ +/** @typedef {import("../../declarations/WebpackOptions").WorkerPublicPath} WorkerPublicPath */ +/** @typedef {import("../Compiler")} Compiler */ +/** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */ +/** @typedef {import("../Entrypoint").EntryOptions} EntryOptions */ +/** @typedef {import("../NormalModule")} NormalModule */ +/** @typedef {import("../Parser").ParserState} ParserState */ +/** @typedef {import("../javascript/BasicEvaluatedExpression")} BasicEvaluatedExpression */ +/** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */ +/** @typedef {import("../javascript/JavascriptParser")} Parser */ +/** @typedef {import("../javascript/JavascriptParser").Range} Range */ +/** @typedef {import("./HarmonyImportDependencyParserPlugin").HarmonySettings} HarmonySettings */ + +/** + * @param {NormalModule} module module + * @returns {string} url + */ +const getUrl = module => { + return pathToFileURL(module.resource).toString(); +}; + +const WorkerSpecifierTag = Symbol("worker specifier tag"); + +const DEFAULT_SYNTAX = [ + "Worker", + "SharedWorker", + "navigator.serviceWorker.register()", + "Worker from worker_threads" +]; + +/** @type {WeakMap<ParserState, number>} */ +const workerIndexMap = new WeakMap(); + +const PLUGIN_NAME = "WorkerPlugin"; + +class WorkerPlugin { + /** + * @param {ChunkLoading} chunkLoading chunk loading + * @param {WasmLoading} wasmLoading wasm loading + * @param {OutputModule} module output module + * @param {WorkerPublicPath} workerPublicPath worker public path + */ + constructor(chunkLoading, wasmLoading, module, workerPublicPath) { + this._chunkLoading = chunkLoading; + this._wasmLoading = wasmLoading; + this._module = module; + this._workerPublicPath = workerPublicPath; + } + /** + * Apply the plugin + * @param {Compiler} compiler the compiler instance + * @returns {void} + */ + apply(compiler) { + if (this._chunkLoading) { + new EnableChunkLoadingPlugin(this._chunkLoading).apply(compiler); + } + if (this._wasmLoading) { + new EnableWasmLoadingPlugin(this._wasmLoading).apply(compiler); + } + const cachedContextify = contextify.bindContextCache( + compiler.context, + compiler.root + ); + compiler.hooks.thisCompilation.tap( + PLUGIN_NAME, + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set( + WorkerDependency, + normalModuleFactory + ); + compilation.dependencyTemplates.set( + WorkerDependency, + new WorkerDependency.Template() + ); + compilation.dependencyTemplates.set( + CreateScriptUrlDependency, + new CreateScriptUrlDependency.Template() + ); + + /** + * @param {JavascriptParser} parser the parser + * @param {Expression} expr expression + * @returns {[BasicEvaluatedExpression, [number, number]] | void} parsed + */ + const parseModuleUrl = (parser, expr) => { + if ( + expr.type !== "NewExpression" || + expr.callee.type === "Super" || + expr.arguments.length !== 2 + ) + return; + const [arg1, arg2] = expr.arguments; + if (arg1.type === "SpreadElement") return; + if (arg2.type === "SpreadElement") return; + const callee = parser.evaluateExpression(expr.callee); + if (!callee.isIdentifier() || callee.identifier !== "URL") return; + const arg2Value = parser.evaluateExpression(arg2); + if ( + !arg2Value.isString() || + !(/** @type {string} */ (arg2Value.string).startsWith("file://")) || + arg2Value.string !== getUrl(parser.state.module) + ) { + return; + } + const arg1Value = parser.evaluateExpression(arg1); + return [ + arg1Value, + [ + /** @type {Range} */ (arg1.range)[0], + /** @type {Range} */ (arg2.range)[1] + ] + ]; + }; + + /** + * @param {JavascriptParser} parser the parser + * @param {ObjectExpression} expr expression + * @returns {{ expressions: Record<string, Expression | Pattern>, otherElements: (Property | SpreadElement)[], values: Record<string, any>, spread: boolean, insertType: "comma" | "single", insertLocation: number }} parsed object + */ + const parseObjectExpression = (parser, expr) => { + /** @type {Record<string, any>} */ + const values = {}; + /** @type {Record<string, Expression | Pattern>} */ + const expressions = {}; + /** @type {(Property | SpreadElement)[]} */ + const otherElements = []; + let spread = false; + for (const prop of expr.properties) { + if (prop.type === "SpreadElement") { + spread = true; + } else if ( + prop.type === "Property" && + !prop.method && + !prop.computed && + prop.key.type === "Identifier" + ) { + expressions[prop.key.name] = prop.value; + if (!prop.shorthand && !prop.value.type.endsWith("Pattern")) { + const value = parser.evaluateExpression( + /** @type {Expression} */ (prop.value) + ); + if (value.isCompileTimeValue()) + values[prop.key.name] = value.asCompileTimeValue(); + } + } else { + otherElements.push(prop); + } + } + const insertType = expr.properties.length > 0 ? "comma" : "single"; + const insertLocation = + expr.properties[expr.properties.length - 1].range[1]; + return { + expressions, + otherElements, + values, + spread, + insertType, + insertLocation + }; + }; + + /** + * @param {Parser} parser parser parser + * @param {JavascriptParserOptions} parserOptions parserOptions + * @returns {void} + */ + const parserPlugin = (parser, parserOptions) => { + if (parserOptions.worker === false) return; + const options = !Array.isArray(parserOptions.worker) + ? ["..."] + : parserOptions.worker; + /** + * @param {CallExpression} expr expression + * @returns {boolean | void} true when handled + */ + const handleNewWorker = expr => { + if (expr.arguments.length === 0 || expr.arguments.length > 2) + return; + const [arg1, arg2] = expr.arguments; + if (arg1.type === "SpreadElement") return; + if (arg2 && arg2.type === "SpreadElement") return; + const parsedUrl = parseModuleUrl(parser, arg1); + if (!parsedUrl) return; + const [url, range] = parsedUrl; + if (!url.isString()) return; + const { + expressions, + otherElements, + values: options, + spread: hasSpreadInOptions, + insertType, + insertLocation + } = arg2 && arg2.type === "ObjectExpression" + ? parseObjectExpression(parser, arg2) + : { + /** @type {Record<string, Expression | Pattern>} */ + expressions: {}, + otherElements: [], + /** @type {Record<string, any>} */ + values: {}, + spread: false, + insertType: arg2 ? "spread" : "argument", + insertLocation: arg2 + ? /** @type {Range} */ (arg2.range) + : /** @type {Range} */ (arg1.range)[1] + }; + const { options: importOptions, errors: commentErrors } = + parser.parseCommentOptions(/** @type {Range} */ (expr.range)); + + if (commentErrors) { + for (const e of commentErrors) { + const { comment } = e; + parser.state.module.addWarning( + new CommentCompilationWarning( + `Compilation error while processing magic comment(-s): /*${comment.value}*/: ${e.message}`, + comment.loc + ) + ); + } + } + + /** @type {EntryOptions} */ + let entryOptions = {}; + + if (importOptions) { + if (importOptions.webpackIgnore !== undefined) { + if (typeof importOptions.webpackIgnore !== "boolean") { + parser.state.module.addWarning( + new UnsupportedFeatureWarning( + `\`webpackIgnore\` expected a boolean, but received: ${importOptions.webpackIgnore}.`, + /** @type {DependencyLocation} */ (expr.loc) + ) + ); + } else { + if (importOptions.webpackIgnore) { + return false; + } + } + } + if (importOptions.webpackEntryOptions !== undefined) { + if ( + typeof importOptions.webpackEntryOptions !== "object" || + importOptions.webpackEntryOptions === null + ) { + parser.state.module.addWarning( + new UnsupportedFeatureWarning( + `\`webpackEntryOptions\` expected a object, but received: ${importOptions.webpackEntryOptions}.`, + /** @type {DependencyLocation} */ (expr.loc) + ) + ); + } else { + Object.assign( + entryOptions, + importOptions.webpackEntryOptions + ); + } + } + if (importOptions.webpackChunkName !== undefined) { + if (typeof importOptions.webpackChunkName !== "string") { + parser.state.module.addWarning( + new UnsupportedFeatureWarning( + `\`webpackChunkName\` expected a string, but received: ${importOptions.webpackChunkName}.`, + /** @type {DependencyLocation} */ (expr.loc) + ) + ); + } else { + entryOptions.name = importOptions.webpackChunkName; + } + } + } + + if ( + !Object.prototype.hasOwnProperty.call(entryOptions, "name") && + options && + typeof options.name === "string" + ) { + entryOptions.name = options.name; + } + + if (entryOptions.runtime === undefined) { + let i = workerIndexMap.get(parser.state) || 0; + workerIndexMap.set(parser.state, i + 1); + let name = `${cachedContextify( + parser.state.module.identifier() + )}|${i}`; + const hash = createHash(compilation.outputOptions.hashFunction); + hash.update(name); + const digest = /** @type {string} */ ( + hash.digest(compilation.outputOptions.hashDigest) + ); + entryOptions.runtime = digest.slice( + 0, + compilation.outputOptions.hashDigestLength + ); + } + + const block = new AsyncDependenciesBlock({ + name: entryOptions.name, + entryOptions: { + chunkLoading: this._chunkLoading, + wasmLoading: this._wasmLoading, + ...entryOptions + } + }); + block.loc = expr.loc; + const dep = new WorkerDependency( + /** @type {string} */ (url.string), + range, + { + publicPath: this._workerPublicPath + } + ); + dep.loc = /** @type {DependencyLocation} */ (expr.loc); + block.addDependency(dep); + parser.state.module.addBlock(block); + + if (compilation.outputOptions.trustedTypes) { + const dep = new CreateScriptUrlDependency( + /** @type {Range} */ (expr.arguments[0].range) + ); + dep.loc = /** @type {DependencyLocation} */ (expr.loc); + parser.state.module.addDependency(dep); + } + + if (expressions.type) { + const expr = expressions.type; + if (options.type !== false) { + const dep = new ConstDependency( + this._module ? '"module"' : "undefined", + /** @type {Range} */ (expr.range) + ); + dep.loc = /** @type {DependencyLocation} */ (expr.loc); + parser.state.module.addPresentationalDependency(dep); + expressions.type = undefined; + } + } else if (insertType === "comma") { + if (this._module || hasSpreadInOptions) { + const dep = new ConstDependency( + `, type: ${this._module ? '"module"' : "undefined"}`, + insertLocation + ); + dep.loc = /** @type {DependencyLocation} */ (expr.loc); + parser.state.module.addPresentationalDependency(dep); + } + } else if (insertType === "spread") { + const dep1 = new ConstDependency( + "Object.assign({}, ", + /** @type {Range} */ (insertLocation)[0] + ); + const dep2 = new ConstDependency( + `, { type: ${this._module ? '"module"' : "undefined"} })`, + /** @type {Range} */ (insertLocation)[1] + ); + dep1.loc = /** @type {DependencyLocation} */ (expr.loc); + dep2.loc = /** @type {DependencyLocation} */ (expr.loc); + parser.state.module.addPresentationalDependency(dep1); + parser.state.module.addPresentationalDependency(dep2); + } else if (insertType === "argument") { + if (this._module) { + const dep = new ConstDependency( + ', { type: "module" }', + insertLocation + ); + dep.loc = /** @type {DependencyLocation} */ (expr.loc); + parser.state.module.addPresentationalDependency(dep); + } + } + + parser.walkExpression(expr.callee); + for (const key of Object.keys(expressions)) { + if (expressions[key]) parser.walkExpression(expressions[key]); + } + for (const prop of otherElements) { + parser.walkProperty(prop); + } + if (insertType === "spread") { + parser.walkExpression(arg2); + } + + return true; + }; + /** + * @param {string} item item + */ + const processItem = item => { + if ( + item.startsWith("*") && + item.includes(".") && + item.endsWith("()") + ) { + const firstDot = item.indexOf("."); + const pattern = item.slice(1, firstDot); + const itemMembers = item.slice(firstDot + 1, -2); + + parser.hooks.pattern.for(pattern).tap(PLUGIN_NAME, pattern => { + parser.tagVariable(pattern.name, WorkerSpecifierTag); + return true; + }); + parser.hooks.callMemberChain + .for(WorkerSpecifierTag) + .tap(PLUGIN_NAME, (expression, members) => { + if (itemMembers !== members.join(".")) { + return; + } + + return handleNewWorker(expression); + }); + } else if (item.endsWith("()")) { + parser.hooks.call + .for(item.slice(0, -2)) + .tap(PLUGIN_NAME, handleNewWorker); + } else { + const match = /^(.+?)(\(\))?\s+from\s+(.+)$/.exec(item); + if (match) { + const ids = match[1].split("."); + const call = match[2]; + const source = match[3]; + (call ? parser.hooks.call : parser.hooks.new) + .for(harmonySpecifierTag) + .tap(PLUGIN_NAME, expr => { + const settings = /** @type {HarmonySettings} */ ( + parser.currentTagData + ); + if ( + !settings || + settings.source !== source || + !equals(settings.ids, ids) + ) { + return; + } + return handleNewWorker(expr); + }); + } else { + parser.hooks.new.for(item).tap(PLUGIN_NAME, handleNewWorker); + } + } + }; + for (const item of options) { + if (item === "...") { + DEFAULT_SYNTAX.forEach(processItem); + } else processItem(item); + } + }; + normalModuleFactory.hooks.parser + .for(JAVASCRIPT_MODULE_TYPE_AUTO) + .tap(PLUGIN_NAME, parserPlugin); + normalModuleFactory.hooks.parser + .for(JAVASCRIPT_MODULE_TYPE_ESM) + .tap(PLUGIN_NAME, parserPlugin); + } + ); + } +} +module.exports = WorkerPlugin; |
