| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 | /*	MIT License http://www.opensource.org/licenses/mit-license.php	Author Sergey Melyukov @smelukov*/"use strict";const { UsageState } = require("../ExportsInfo");/** @typedef {import("estree").Node} AnyNode *//** @typedef {import("../Dependency")} Dependency *//** @typedef {import("../Module")} Module *//** @typedef {import("../ModuleGraph")} ModuleGraph *//** @typedef {import("../ModuleGraphConnection")} ModuleGraphConnection *//** @typedef {import("../ModuleGraphConnection").ConnectionState} ConnectionState *//** @typedef {import("../Parser").ParserState} ParserState *//** @typedef {import("../javascript/JavascriptParser")} JavascriptParser *//** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec *//** @typedef {Map<TopLevelSymbol | null, Set<string | TopLevelSymbol> | true | undefined>} InnerGraph *//** @typedef {function(boolean | Set<string> | undefined): void} UsageCallback *//** * @typedef {object} StateObject * @property {InnerGraph} innerGraph * @property {TopLevelSymbol=} currentTopLevelSymbol * @property {Map<TopLevelSymbol, Set<UsageCallback>>} usageCallbackMap *//** @typedef {false|StateObject} State *//** @type {WeakMap<ParserState, State>} */const parserStateMap = new WeakMap();const topLevelSymbolTag = Symbol("top level symbol");/** * @param {ParserState} parserState parser state * @returns {State | undefined} state */function getState(parserState) {	return parserStateMap.get(parserState);}/** * @param {ParserState} parserState parser state * @returns {void} */exports.bailout = parserState => {	parserStateMap.set(parserState, false);};/** * @param {ParserState} parserState parser state * @returns {void} */exports.enable = parserState => {	const state = parserStateMap.get(parserState);	if (state === false) {		return;	}	parserStateMap.set(parserState, {		innerGraph: new Map(),		currentTopLevelSymbol: undefined,		usageCallbackMap: new Map()	});};/** * @param {ParserState} parserState parser state * @returns {boolean} true, when enabled */exports.isEnabled = parserState => {	const state = parserStateMap.get(parserState);	return !!state;};/** * @param {ParserState} state parser state * @param {TopLevelSymbol | null} symbol the symbol, or null for all symbols * @param {string | TopLevelSymbol | true} usage usage data * @returns {void} */exports.addUsage = (state, symbol, usage) => {	const innerGraphState = getState(state);	if (innerGraphState) {		const { innerGraph } = innerGraphState;		const info = innerGraph.get(symbol);		if (usage === true) {			innerGraph.set(symbol, true);		} else if (info === undefined) {			innerGraph.set(symbol, new Set([usage]));		} else if (info !== true) {			info.add(usage);		}	}};/** * @param {JavascriptParser} parser the parser * @param {string} name name of variable * @param {string | TopLevelSymbol | true} usage usage data * @returns {void} */exports.addVariableUsage = (parser, name, usage) => {	const symbol =		/** @type {TopLevelSymbol} */ (			parser.getTagData(name, topLevelSymbolTag)		) || exports.tagTopLevelSymbol(parser, name);	if (symbol) {		exports.addUsage(parser.state, symbol, usage);	}};/** * @param {ParserState} state parser state * @returns {void} */exports.inferDependencyUsage = state => {	const innerGraphState = getState(state);	if (!innerGraphState) {		return;	}	const { innerGraph, usageCallbackMap } = innerGraphState;	const processed = new Map();	// flatten graph to terminal nodes (string, undefined or true)	const nonTerminal = new Set(innerGraph.keys());	while (nonTerminal.size > 0) {		for (const key of nonTerminal) {			/** @type {Set<string|TopLevelSymbol> | true} */			let newSet = new Set();			let isTerminal = true;			const value = innerGraph.get(key);			let alreadyProcessed = processed.get(key);			if (alreadyProcessed === undefined) {				alreadyProcessed = new Set();				processed.set(key, alreadyProcessed);			}			if (value !== true && value !== undefined) {				for (const item of value) {					alreadyProcessed.add(item);				}				for (const item of value) {					if (typeof item === "string") {						newSet.add(item);					} else {						const itemValue = innerGraph.get(item);						if (itemValue === true) {							newSet = true;							break;						}						if (itemValue !== undefined) {							for (const i of itemValue) {								if (i === key) continue;								if (alreadyProcessed.has(i)) continue;								newSet.add(i);								if (typeof i !== "string") {									isTerminal = false;								}							}						}					}				}				if (newSet === true) {					innerGraph.set(key, true);				} else if (newSet.size === 0) {					innerGraph.set(key, undefined);				} else {					innerGraph.set(key, newSet);				}			}			if (isTerminal) {				nonTerminal.delete(key);				// For the global key, merge with all other keys				if (key === null) {					const globalValue = innerGraph.get(null);					if (globalValue) {						for (const [key, value] of innerGraph) {							if (key !== null && value !== true) {								if (globalValue === true) {									innerGraph.set(key, true);								} else {									const newSet = new Set(value);									for (const item of globalValue) {										newSet.add(item);									}									innerGraph.set(key, newSet);								}							}						}					}				}			}		}	}	/** @type {Map<Dependency, true | Set<string>>} */	for (const [symbol, callbacks] of usageCallbackMap) {		const usage = /** @type {true | Set<string> | undefined} */ (			innerGraph.get(symbol)		);		for (const callback of callbacks) {			callback(usage === undefined ? false : usage);		}	}};/** * @param {ParserState} state parser state * @param {UsageCallback} onUsageCallback on usage callback */exports.onUsage = (state, onUsageCallback) => {	const innerGraphState = getState(state);	if (innerGraphState) {		const { usageCallbackMap, currentTopLevelSymbol } = innerGraphState;		if (currentTopLevelSymbol) {			let callbacks = usageCallbackMap.get(currentTopLevelSymbol);			if (callbacks === undefined) {				callbacks = new Set();				usageCallbackMap.set(currentTopLevelSymbol, callbacks);			}			callbacks.add(onUsageCallback);		} else {			onUsageCallback(true);		}	} else {		onUsageCallback(undefined);	}};/** * @param {ParserState} state parser state * @param {TopLevelSymbol | undefined} symbol the symbol */exports.setTopLevelSymbol = (state, symbol) => {	const innerGraphState = getState(state);	if (innerGraphState) {		innerGraphState.currentTopLevelSymbol = symbol;	}};/** * @param {ParserState} state parser state * @returns {TopLevelSymbol|void} usage data */exports.getTopLevelSymbol = state => {	const innerGraphState = getState(state);	if (innerGraphState) {		return innerGraphState.currentTopLevelSymbol;	}};/** * @param {JavascriptParser} parser parser * @param {string} name name of variable * @returns {TopLevelSymbol | undefined} symbol */exports.tagTopLevelSymbol = (parser, name) => {	const innerGraphState = getState(parser.state);	if (!innerGraphState) return;	parser.defineVariable(name);	const existingTag = /** @type {TopLevelSymbol} */ (		parser.getTagData(name, topLevelSymbolTag)	);	if (existingTag) {		return existingTag;	}	const fn = new TopLevelSymbol(name);	parser.tagVariable(name, topLevelSymbolTag, fn);	return fn;};/** * @param {Dependency} dependency the dependency * @param {Set<string> | boolean} usedByExports usedByExports info * @param {ModuleGraph} moduleGraph moduleGraph * @param {RuntimeSpec} runtime runtime * @returns {boolean} false, when unused. Otherwise true */exports.isDependencyUsedByExports = (	dependency,	usedByExports,	moduleGraph,	runtime) => {	if (usedByExports === false) return false;	if (usedByExports !== true && usedByExports !== undefined) {		const selfModule =			/** @type {Module} */			(moduleGraph.getParentModule(dependency));		const exportsInfo = moduleGraph.getExportsInfo(selfModule);		let used = false;		for (const exportName of usedByExports) {			if (exportsInfo.getUsed(exportName, runtime) !== UsageState.Unused)				used = true;		}		if (!used) return false;	}	return true;};/** * @param {Dependency} dependency the dependency * @param {Set<string> | boolean | undefined} usedByExports usedByExports info * @param {ModuleGraph} moduleGraph moduleGraph * @returns {null | false | function(ModuleGraphConnection, RuntimeSpec): ConnectionState} function to determine if the connection is active */exports.getDependencyUsedByExportsCondition = (	dependency,	usedByExports,	moduleGraph) => {	if (usedByExports === false) return false;	if (usedByExports !== true && usedByExports !== undefined) {		const selfModule =			/** @type {Module} */			(moduleGraph.getParentModule(dependency));		const exportsInfo = moduleGraph.getExportsInfo(selfModule);		return (connections, runtime) => {			for (const exportName of usedByExports) {				if (exportsInfo.getUsed(exportName, runtime) !== UsageState.Unused)					return true;			}			return false;		};	}	return null;};class TopLevelSymbol {	/**	 * @param {string} name name of the variable	 */	constructor(name) {		this.name = name;	}}exports.TopLevelSymbol = TopLevelSymbol;exports.topLevelSymbolTag = topLevelSymbolTag;
 |