123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 |
- "use strict";
- const { UsageState } = require("../ExportsInfo");
- const parserStateMap = new WeakMap();
- const topLevelSymbolTag = Symbol("top level symbol");
- function getState(parserState) {
- return parserStateMap.get(parserState);
- }
- exports.bailout = parserState => {
- parserStateMap.set(parserState, false);
- };
- exports.enable = parserState => {
- const state = parserStateMap.get(parserState);
- if (state === false) {
- return;
- }
- parserStateMap.set(parserState, {
- innerGraph: new Map(),
- currentTopLevelSymbol: undefined,
- usageCallbackMap: new Map()
- });
- };
- exports.isEnabled = parserState => {
- const state = parserStateMap.get(parserState);
- return !!state;
- };
- 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);
- }
- }
- };
- exports.addVariableUsage = (parser, name, usage) => {
- const symbol =
- (
- parser.getTagData(name, topLevelSymbolTag)
- ) || exports.tagTopLevelSymbol(parser, name);
- if (symbol) {
- exports.addUsage(parser.state, symbol, usage);
- }
- };
- exports.inferDependencyUsage = state => {
- const innerGraphState = getState(state);
- if (!innerGraphState) {
- return;
- }
- const { innerGraph, usageCallbackMap } = innerGraphState;
- const processed = new Map();
-
- const nonTerminal = new Set(innerGraph.keys());
- while (nonTerminal.size > 0) {
- for (const key of nonTerminal) {
-
- 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);
-
- 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);
- }
- }
- }
- }
- }
- }
- }
- }
-
- for (const [symbol, callbacks] of usageCallbackMap) {
- const usage = (
- innerGraph.get(symbol)
- );
- for (const callback of callbacks) {
- callback(usage === undefined ? false : usage);
- }
- }
- };
- 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);
- }
- };
- exports.setTopLevelSymbol = (state, symbol) => {
- const innerGraphState = getState(state);
- if (innerGraphState) {
- innerGraphState.currentTopLevelSymbol = symbol;
- }
- };
- exports.getTopLevelSymbol = state => {
- const innerGraphState = getState(state);
- if (innerGraphState) {
- return innerGraphState.currentTopLevelSymbol;
- }
- };
- exports.tagTopLevelSymbol = (parser, name) => {
- const innerGraphState = getState(parser.state);
- if (!innerGraphState) return;
- parser.defineVariable(name);
- const existingTag = (
- parser.getTagData(name, topLevelSymbolTag)
- );
- if (existingTag) {
- return existingTag;
- }
- const fn = new TopLevelSymbol(name);
- parser.tagVariable(name, topLevelSymbolTag, fn);
- return fn;
- };
- exports.isDependencyUsedByExports = (
- dependency,
- usedByExports,
- moduleGraph,
- runtime
- ) => {
- if (usedByExports === false) return false;
- if (usedByExports !== true && usedByExports !== undefined) {
- const selfModule =
-
- (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;
- };
- exports.getDependencyUsedByExportsCondition = (
- dependency,
- usedByExports,
- moduleGraph
- ) => {
- if (usedByExports === false) return false;
- if (usedByExports !== true && usedByExports !== undefined) {
- const selfModule =
-
- (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 {
-
- constructor(name) {
- this.name = name;
- }
- }
- exports.TopLevelSymbol = TopLevelSymbol;
- exports.topLevelSymbolTag = topLevelSymbolTag;
|