| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | 	Author Tobias Koppers @sokra | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-09 03:56:32 +08:00
										 |  |  | const { | 
					
						
							|  |  |  | 	harmonySpecifierTag | 
					
						
							|  |  |  | } = require("../dependencies/HarmonyImportDependencyParserPlugin"); | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | const PureExpressionDependency = require("../dependencies/PureExpressionDependency"); | 
					
						
							| 
									
										
										
										
											2020-01-21 22:25:40 +08:00
										 |  |  | const InnerGraph = require("./InnerGraph"); | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-09 21:53:59 +08:00
										 |  |  | /** @typedef {import("estree").ClassDeclaration} ClassDeclarationNode */ | 
					
						
							|  |  |  | /** @typedef {import("estree").ClassExpression} ClassExpressionNode */ | 
					
						
							| 
									
										
										
										
											2020-04-09 03:40:13 +08:00
										 |  |  | /** @typedef {import("estree").Node} Node */ | 
					
						
							| 
									
										
										
										
											2020-04-09 21:53:59 +08:00
										 |  |  | /** @typedef {import("estree").VariableDeclarator} VariableDeclaratorNode */ | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | /** @typedef {import("../Compiler")} Compiler */ | 
					
						
							| 
									
										
										
										
											2019-09-04 15:27:19 +08:00
										 |  |  | /** @typedef {import("../Dependency")} Dependency */ | 
					
						
							| 
									
										
										
										
											2020-01-21 22:25:40 +08:00
										 |  |  | /** @typedef {import("../dependencies/HarmonyImportSpecifierDependency")} HarmonyImportSpecifierDependency */ | 
					
						
							| 
									
										
										
										
											2019-10-11 21:46:57 +08:00
										 |  |  | /** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */ | 
					
						
							| 
									
										
										
										
											2020-01-21 22:25:40 +08:00
										 |  |  | /** @typedef {import("./InnerGraph").InnerGraph} InnerGraph */ | 
					
						
							|  |  |  | /** @typedef {import("./InnerGraph").TopLevelSymbol} TopLevelSymbol */ | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-23 20:59:27 +08:00
										 |  |  | const { topLevelSymbolTag } = InnerGraph; | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-09 03:56:32 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @param {any} expr an expression | 
					
						
							|  |  |  |  * @param {JavascriptParser} parser the parser | 
					
						
							| 
									
										
										
										
											2020-01-16 02:24:52 +08:00
										 |  |  |  * @param {number} commentsStartPos source position from which annotation comments are checked | 
					
						
							| 
									
										
										
										
											2019-09-09 03:56:32 +08:00
										 |  |  |  * @returns {boolean} true, when the expression is pure | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-01-16 02:24:52 +08:00
										 |  |  | const isPure = (expr, parser, commentsStartPos) => { | 
					
						
							| 
									
										
										
										
											2019-09-05 17:47:18 +08:00
										 |  |  | 	switch (expr.type) { | 
					
						
							|  |  |  | 		case "Identifier": | 
					
						
							| 
									
										
										
										
											2019-09-09 03:56:32 +08:00
										 |  |  | 			return ( | 
					
						
							|  |  |  | 				parser.isVariableDefined(expr.name) || | 
					
						
							|  |  |  | 				parser.getTagData(expr.name, harmonySpecifierTag) | 
					
						
							|  |  |  | 			); | 
					
						
							| 
									
										
										
										
											2020-01-16 02:24:52 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-09 03:40:13 +08:00
										 |  |  | 		case "ClassDeclaration": | 
					
						
							| 
									
										
										
										
											2020-01-16 02:24:52 +08:00
										 |  |  | 		case "ClassExpression": | 
					
						
							|  |  |  | 			if (expr.body.type !== "ClassBody") return false; | 
					
						
							|  |  |  | 			if (expr.superClass && !isPure(expr.superClass, parser, expr.range[0])) { | 
					
						
							|  |  |  | 				return false; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return expr.body.body.every(item => { | 
					
						
							|  |  |  | 				switch (item.type) { | 
					
						
							|  |  |  | 					case "ClassProperty": | 
					
						
							|  |  |  | 						// TODO add test case once acorn supports it
 | 
					
						
							|  |  |  | 						// Currently this is not parsable
 | 
					
						
							|  |  |  | 						if (item.static) return isPure(item.value, parser, item.range[0]); | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				return true; | 
					
						
							|  |  |  | 			}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-09 03:40:13 +08:00
										 |  |  | 		case "FunctionDeclaration": | 
					
						
							| 
									
										
										
										
											2020-01-16 02:24:52 +08:00
										 |  |  | 		case "FunctionExpression": | 
					
						
							|  |  |  | 		case "ArrowFunctionExpression": | 
					
						
							| 
									
										
										
										
											2019-09-05 17:47:18 +08:00
										 |  |  | 		case "Literal": | 
					
						
							|  |  |  | 			return true; | 
					
						
							| 
									
										
										
										
											2020-01-16 02:24:52 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-05 17:47:18 +08:00
										 |  |  | 		case "ConditionalExpression": | 
					
						
							|  |  |  | 			return ( | 
					
						
							| 
									
										
										
										
											2020-01-16 02:24:52 +08:00
										 |  |  | 				isPure(expr.test, parser, commentsStartPos) && | 
					
						
							|  |  |  | 				isPure(expr.consequent, parser, expr.test.range[1]) && | 
					
						
							|  |  |  | 				isPure(expr.alternate, parser, expr.consequent.range[1]) | 
					
						
							| 
									
										
										
										
											2019-09-05 17:47:18 +08:00
										 |  |  | 			); | 
					
						
							| 
									
										
										
										
											2020-01-16 02:24:52 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case "SequenceExpression": | 
					
						
							|  |  |  | 			return expr.expressions.every(expr => { | 
					
						
							|  |  |  | 				const pureFlag = isPure(expr, parser, commentsStartPos); | 
					
						
							|  |  |  | 				commentsStartPos = expr.range[1]; | 
					
						
							|  |  |  | 				return pureFlag; | 
					
						
							|  |  |  | 			}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case "CallExpression": { | 
					
						
							|  |  |  | 			const pureFlag = | 
					
						
							|  |  |  | 				expr.range[0] - commentsStartPos > 12 && | 
					
						
							|  |  |  | 				parser | 
					
						
							|  |  |  | 					.getComments([commentsStartPos, expr.range[0]]) | 
					
						
							|  |  |  | 					.some( | 
					
						
							|  |  |  | 						comment => | 
					
						
							|  |  |  | 							comment.type === "Block" && | 
					
						
							|  |  |  | 							/^\s*(#|@)__PURE__\s*$/.test(comment.value) | 
					
						
							|  |  |  | 					); | 
					
						
							|  |  |  | 			if (!pureFlag) return false; | 
					
						
							|  |  |  | 			commentsStartPos = expr.callee.range[1]; | 
					
						
							|  |  |  | 			return expr.arguments.every(arg => { | 
					
						
							|  |  |  | 				if (arg.type === "SpreadElement") return false; | 
					
						
							|  |  |  | 				const pureFlag = isPure(arg, parser, commentsStartPos); | 
					
						
							|  |  |  | 				commentsStartPos = arg.range[1]; | 
					
						
							|  |  |  | 				return pureFlag; | 
					
						
							|  |  |  | 			}); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-09-05 17:47:18 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return false; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | class InnerGraphPlugin { | 
					
						
							|  |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2020-04-23 16:48:36 +08:00
										 |  |  | 	 * Apply the plugin | 
					
						
							|  |  |  | 	 * @param {Compiler} compiler the compiler instance | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 	 * @returns {void} | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	apply(compiler) { | 
					
						
							|  |  |  | 		compiler.hooks.compilation.tap( | 
					
						
							|  |  |  | 			"InnerGraphPlugin", | 
					
						
							|  |  |  | 			(compilation, { normalModuleFactory }) => { | 
					
						
							| 
									
										
										
										
											2020-01-30 18:34:33 +08:00
										 |  |  | 				const logger = compilation.getLogger("webpack.InnerGraphPlugin"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 				compilation.dependencyTemplates.set( | 
					
						
							|  |  |  | 					PureExpressionDependency, | 
					
						
							|  |  |  | 					new PureExpressionDependency.Template() | 
					
						
							|  |  |  | 				); | 
					
						
							| 
									
										
										
										
											2020-04-09 15:28:46 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 				/** | 
					
						
							|  |  |  | 				 * @param {JavascriptParser} parser the parser | 
					
						
							|  |  |  | 				 * @param {Object} parserOptions options | 
					
						
							|  |  |  | 				 * @returns {void} | 
					
						
							|  |  |  | 				 */ | 
					
						
							|  |  |  | 				const handler = (parser, parserOptions) => { | 
					
						
							| 
									
										
										
										
											2020-04-09 15:28:46 +08:00
										 |  |  | 					const onUsageSuper = sup => { | 
					
						
							|  |  |  | 						InnerGraph.onUsage(parser.state, usedByExports => { | 
					
						
							|  |  |  | 							switch (usedByExports) { | 
					
						
							|  |  |  | 								case undefined: | 
					
						
							|  |  |  | 								case true: | 
					
						
							|  |  |  | 									return; | 
					
						
							|  |  |  | 								default: { | 
					
						
							|  |  |  | 									const dep = new PureExpressionDependency(sup.range); | 
					
						
							|  |  |  | 									dep.loc = sup.loc; | 
					
						
							|  |  |  | 									dep.usedByExports = usedByExports; | 
					
						
							|  |  |  | 									parser.state.module.addDependency(dep); | 
					
						
							|  |  |  | 									break; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						}); | 
					
						
							|  |  |  | 					}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 					parser.hooks.program.tap("InnerGraphPlugin", () => { | 
					
						
							| 
									
										
										
										
											2020-01-21 22:25:40 +08:00
										 |  |  | 						InnerGraph.enable(parser.state); | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 					}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-05 17:47:18 +08:00
										 |  |  | 					parser.hooks.finish.tap("InnerGraphPlugin", () => { | 
					
						
							| 
									
										
										
										
											2020-01-23 20:59:27 +08:00
										 |  |  | 						if (!InnerGraph.isEnabled(parser.state)) return; | 
					
						
							| 
									
										
										
										
											2020-01-21 22:25:40 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-30 18:34:33 +08:00
										 |  |  | 						logger.time("infer dependency usage"); | 
					
						
							| 
									
										
										
										
											2020-01-30 09:34:30 +08:00
										 |  |  | 						InnerGraph.inferDependencyUsage(parser.state); | 
					
						
							| 
									
										
										
										
											2020-01-30 18:34:33 +08:00
										 |  |  | 						logger.timeAggregate("infer dependency usage"); | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 					}); | 
					
						
							| 
									
										
										
										
											2020-04-09 21:53:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					// During prewalking the following datastructures are filled with
 | 
					
						
							|  |  |  | 					// nodes that have a TopLevelSymbol assigned and
 | 
					
						
							|  |  |  | 					// variables are tagged with the assigned TopLevelSymbol
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// We differ 3 types of nodes:
 | 
					
						
							|  |  |  | 					// 1. full statements (export default, function declaration)
 | 
					
						
							|  |  |  | 					// 2. classes (class declaration, class expression)
 | 
					
						
							|  |  |  | 					// 3. variable declarators (const x = ...)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-09 03:40:13 +08:00
										 |  |  | 					/** @type {WeakMap<Node, TopLevelSymbol>} */ | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 					const statementWithTopLevelSymbol = new WeakMap(); | 
					
						
							| 
									
										
										
										
											2020-04-09 03:40:13 +08:00
										 |  |  | 					/** @type {WeakMap<Node, Node>} */ | 
					
						
							|  |  |  | 					const statementPurePart = new WeakMap(); | 
					
						
							| 
									
										
										
										
											2020-04-04 04:52:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-09 21:53:59 +08:00
										 |  |  | 					/** @type {WeakMap<ClassExpressionNode | ClassDeclarationNode, TopLevelSymbol>} */ | 
					
						
							|  |  |  | 					const classWithTopLevelSymbol = new WeakMap(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/** @type {WeakMap<VariableDeclaratorNode, TopLevelSymbol>} */ | 
					
						
							|  |  |  | 					const declWithTopLevelSymbol = new WeakMap(); | 
					
						
							|  |  |  | 					/** @type {WeakSet<VariableDeclaratorNode>} */ | 
					
						
							|  |  |  | 					const pureDeclarators = new WeakSet(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// The following hooks are used during prewalking:
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 					parser.hooks.preStatement.tap("InnerGraphPlugin", statement => { | 
					
						
							| 
									
										
										
										
											2020-01-23 20:59:27 +08:00
										 |  |  | 						if (!InnerGraph.isEnabled(parser.state)) return; | 
					
						
							| 
									
										
										
										
											2020-01-21 22:25:40 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 						if (parser.scope.topLevelScope === true) { | 
					
						
							|  |  |  | 							if (statement.type === "FunctionDeclaration") { | 
					
						
							|  |  |  | 								const name = statement.id ? statement.id.name : "*default*"; | 
					
						
							| 
									
										
										
										
											2020-01-27 23:46:23 +08:00
										 |  |  | 								const fn = InnerGraph.tagTopLevelSymbol(parser, name); | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 								statementWithTopLevelSymbol.set(statement, fn); | 
					
						
							|  |  |  | 								return true; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					}); | 
					
						
							| 
									
										
										
										
											2020-04-09 21:53:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 					parser.hooks.blockPreStatement.tap("InnerGraphPlugin", statement => { | 
					
						
							| 
									
										
										
										
											2020-01-23 20:59:27 +08:00
										 |  |  | 						if (!InnerGraph.isEnabled(parser.state)) return; | 
					
						
							| 
									
										
										
										
											2020-01-21 22:25:40 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 						if (parser.scope.topLevelScope === true) { | 
					
						
							|  |  |  | 							if (statement.type === "ClassDeclaration") { | 
					
						
							|  |  |  | 								const name = statement.id ? statement.id.name : "*default*"; | 
					
						
							| 
									
										
										
										
											2020-01-27 23:46:23 +08:00
										 |  |  | 								const fn = InnerGraph.tagTopLevelSymbol(parser, name); | 
					
						
							| 
									
										
										
										
											2020-04-09 21:53:59 +08:00
										 |  |  | 								classWithTopLevelSymbol.set(statement, fn); | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 								return true; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							if (statement.type === "ExportDefaultDeclaration") { | 
					
						
							| 
									
										
										
										
											2020-04-09 21:53:59 +08:00
										 |  |  | 								const name = "*default*"; | 
					
						
							|  |  |  | 								const fn = InnerGraph.tagTopLevelSymbol(parser, name); | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 								const decl = statement.declaration; | 
					
						
							| 
									
										
										
										
											2020-04-09 21:53:59 +08:00
										 |  |  | 								if ( | 
					
						
							|  |  |  | 									decl.type === "ClassExpression" || | 
					
						
							|  |  |  | 									decl.type === "ClassDeclaration" | 
					
						
							|  |  |  | 								) { | 
					
						
							|  |  |  | 									classWithTopLevelSymbol.set(decl, fn); | 
					
						
							|  |  |  | 								} else if (isPure(decl, parser, decl.range[1])) { | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 									statementWithTopLevelSymbol.set(statement, fn); | 
					
						
							| 
									
										
										
										
											2020-04-09 03:40:13 +08:00
										 |  |  | 									if ( | 
					
						
							|  |  |  | 										!decl.type.endsWith("FunctionExpression") && | 
					
						
							|  |  |  | 										!decl.type.endsWith("Declaration") && | 
					
						
							|  |  |  | 										decl.type !== "Literal" | 
					
						
							|  |  |  | 									) { | 
					
						
							|  |  |  | 										statementPurePart.set(statement, decl); | 
					
						
							| 
									
										
										
										
											2020-04-04 04:52:49 +08:00
										 |  |  | 									} | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					}); | 
					
						
							| 
									
										
										
										
											2020-04-04 04:52:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 					parser.hooks.preDeclarator.tap( | 
					
						
							|  |  |  | 						"InnerGraphPlugin", | 
					
						
							|  |  |  | 						(decl, statement) => { | 
					
						
							| 
									
										
										
										
											2020-01-23 20:59:27 +08:00
										 |  |  | 							if (!InnerGraph.isEnabled(parser.state)) return; | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 							if ( | 
					
						
							|  |  |  | 								parser.scope.topLevelScope === true && | 
					
						
							|  |  |  | 								decl.init && | 
					
						
							|  |  |  | 								decl.id.type === "Identifier" | 
					
						
							|  |  |  | 							) { | 
					
						
							| 
									
										
										
										
											2020-04-09 21:53:59 +08:00
										 |  |  | 								const name = decl.id.name; | 
					
						
							|  |  |  | 								if (decl.init.type === "ClassExpression") { | 
					
						
							|  |  |  | 									const fn = InnerGraph.tagTopLevelSymbol(parser, name); | 
					
						
							|  |  |  | 									classWithTopLevelSymbol.set(decl.init, fn); | 
					
						
							|  |  |  | 								} else if (isPure(decl.init, parser, decl.id.range[1])) { | 
					
						
							| 
									
										
										
										
											2020-01-27 23:46:23 +08:00
										 |  |  | 									const fn = InnerGraph.tagTopLevelSymbol(parser, name); | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 									declWithTopLevelSymbol.set(decl, fn); | 
					
						
							| 
									
										
										
										
											2020-04-09 03:40:13 +08:00
										 |  |  | 									if ( | 
					
						
							|  |  |  | 										!decl.init.type.endsWith("FunctionExpression") && | 
					
						
							|  |  |  | 										decl.init.type !== "Literal" | 
					
						
							|  |  |  | 									) { | 
					
						
							|  |  |  | 										pureDeclarators.add(decl); | 
					
						
							|  |  |  | 									} | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 									return true; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					); | 
					
						
							| 
									
										
										
										
											2020-04-09 21:53:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					// During real walking we set the TopLevelSymbol state to the assigned
 | 
					
						
							|  |  |  | 					// TopLevelSymbol by using the fill datastructures.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// In addition to tracking TopLevelSymbols, we sometimes need to
 | 
					
						
							|  |  |  | 					// add a PureExpressionDependency. This is needed to skip execution
 | 
					
						
							|  |  |  | 					// of pure expressions, even when they are not dropped due to
 | 
					
						
							|  |  |  | 					// minimizing. Otherwise symbols used there might not exist anymore
 | 
					
						
							|  |  |  | 					// as they are removed as unused by this optimization
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// When we find a reference to a TopLevelSymbol, we register a
 | 
					
						
							|  |  |  | 					// TopLevelSymbol dependency from TopLevelSymbol in state to the
 | 
					
						
							|  |  |  | 					// referenced TopLevelSymbol. This way we get a graph of all
 | 
					
						
							|  |  |  | 					// TopLevelSymbols.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// The following hooks are called during walking:
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 					parser.hooks.statement.tap("InnerGraphPlugin", statement => { | 
					
						
							| 
									
										
										
										
											2020-01-23 20:59:27 +08:00
										 |  |  | 						if (!InnerGraph.isEnabled(parser.state)) return; | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 						if (parser.scope.topLevelScope === true) { | 
					
						
							| 
									
										
										
										
											2020-01-23 20:59:27 +08:00
										 |  |  | 							InnerGraph.setTopLevelSymbol(parser.state, undefined); | 
					
						
							| 
									
										
										
										
											2020-04-09 00:22:40 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-09 21:53:59 +08:00
										 |  |  | 							const fn = statementWithTopLevelSymbol.get(statement); | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 							if (fn) { | 
					
						
							| 
									
										
										
										
											2020-01-23 20:59:27 +08:00
										 |  |  | 								InnerGraph.setTopLevelSymbol(parser.state, fn); | 
					
						
							| 
									
										
										
										
											2020-04-09 03:40:13 +08:00
										 |  |  | 								const purePart = statementPurePart.get(statement); | 
					
						
							|  |  |  | 								if (purePart) { | 
					
						
							| 
									
										
										
										
											2020-04-04 04:52:49 +08:00
										 |  |  | 									InnerGraph.onUsage(parser.state, usedByExports => { | 
					
						
							|  |  |  | 										switch (usedByExports) { | 
					
						
							|  |  |  | 											case undefined: | 
					
						
							|  |  |  | 											case true: | 
					
						
							|  |  |  | 												return; | 
					
						
							|  |  |  | 											default: { | 
					
						
							| 
									
										
										
										
											2020-04-09 03:40:13 +08:00
										 |  |  | 												const dep = new PureExpressionDependency( | 
					
						
							|  |  |  | 													purePart.range | 
					
						
							|  |  |  | 												); | 
					
						
							| 
									
										
										
										
											2020-04-04 17:30:37 +08:00
										 |  |  | 												dep.loc = statement.loc; | 
					
						
							| 
									
										
										
										
											2020-04-04 04:52:49 +08:00
										 |  |  | 												dep.usedByExports = usedByExports; | 
					
						
							| 
									
										
										
										
											2020-04-06 05:59:01 +08:00
										 |  |  | 												parser.state.module.addDependency(dep); | 
					
						
							|  |  |  | 												break; | 
					
						
							|  |  |  | 											} | 
					
						
							|  |  |  | 										} | 
					
						
							|  |  |  | 									}); | 
					
						
							|  |  |  | 								} | 
					
						
							| 
									
										
										
										
											2020-04-09 21:53:59 +08:00
										 |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					parser.hooks.classExtendsExpression.tap( | 
					
						
							|  |  |  | 						"InnerGraphPlugin", | 
					
						
							|  |  |  | 						(expr, statement) => { | 
					
						
							|  |  |  | 							if (!InnerGraph.isEnabled(parser.state)) return; | 
					
						
							|  |  |  | 							if (parser.scope.topLevelScope === true) { | 
					
						
							|  |  |  | 								const fn = classWithTopLevelSymbol.get(statement); | 
					
						
							| 
									
										
										
										
											2020-04-06 05:59:01 +08:00
										 |  |  | 								if ( | 
					
						
							| 
									
										
										
										
											2020-04-09 21:53:59 +08:00
										 |  |  | 									fn && | 
					
						
							|  |  |  | 									isPure( | 
					
						
							|  |  |  | 										expr, | 
					
						
							|  |  |  | 										parser, | 
					
						
							|  |  |  | 										statement.id ? statement.id.range[1] : statement.range[0] | 
					
						
							|  |  |  | 									) | 
					
						
							| 
									
										
										
										
											2020-04-06 05:59:01 +08:00
										 |  |  | 								) { | 
					
						
							| 
									
										
										
										
											2020-04-09 21:53:59 +08:00
										 |  |  | 									InnerGraph.setTopLevelSymbol(parser.state, fn); | 
					
						
							|  |  |  | 									onUsageSuper(expr); | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					parser.hooks.classBodyElement.tap( | 
					
						
							|  |  |  | 						"InnerGraphPlugin", | 
					
						
							|  |  |  | 						(element, statement) => { | 
					
						
							|  |  |  | 							if (!InnerGraph.isEnabled(parser.state)) return; | 
					
						
							|  |  |  | 							if (parser.scope.topLevelScope === true) { | 
					
						
							|  |  |  | 								const fn = classWithTopLevelSymbol.get(statement); | 
					
						
							|  |  |  | 								if (fn) { | 
					
						
							|  |  |  | 									if (element.type === "MethodDefinition") { | 
					
						
							|  |  |  | 										InnerGraph.setTopLevelSymbol(parser.state, fn); | 
					
						
							|  |  |  | 									} else if ( | 
					
						
							|  |  |  | 										element.type === "ClassProperty" && | 
					
						
							|  |  |  | 										!element.static | 
					
						
							|  |  |  | 									) { | 
					
						
							|  |  |  | 										// TODO add test case once acorn supports it
 | 
					
						
							|  |  |  | 										// Currently this is not parsable
 | 
					
						
							|  |  |  | 										InnerGraph.setTopLevelSymbol(parser.state, fn); | 
					
						
							| 
									
										
										
										
											2020-04-09 00:22:40 +08:00
										 |  |  | 									} else { | 
					
						
							|  |  |  | 										InnerGraph.setTopLevelSymbol(parser.state, undefined); | 
					
						
							|  |  |  | 									} | 
					
						
							| 
									
										
										
										
											2020-04-04 04:52:49 +08:00
										 |  |  | 								} | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2020-04-09 21:53:59 +08:00
										 |  |  | 					); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 					parser.hooks.declarator.tap("InnerGraphPlugin", (decl, statement) => { | 
					
						
							| 
									
										
										
										
											2020-01-23 20:59:27 +08:00
										 |  |  | 						if (!InnerGraph.isEnabled(parser.state)) return; | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 						const fn = declWithTopLevelSymbol.get(decl); | 
					
						
							| 
									
										
										
										
											2020-04-04 04:52:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 						if (fn) { | 
					
						
							| 
									
										
										
										
											2020-02-05 18:06:27 +08:00
										 |  |  | 							InnerGraph.setTopLevelSymbol(parser.state, fn); | 
					
						
							| 
									
										
										
										
											2019-09-08 21:21:00 +08:00
										 |  |  | 							if (pureDeclarators.has(decl)) { | 
					
						
							| 
									
										
										
										
											2020-04-09 15:28:46 +08:00
										 |  |  | 								if (decl.init.type === "ClassExpression") { | 
					
						
							|  |  |  | 									if (decl.init.superClass) { | 
					
						
							|  |  |  | 										onUsageSuper(decl.init.superClass); | 
					
						
							| 
									
										
										
										
											2020-02-05 18:06:27 +08:00
										 |  |  | 									} | 
					
						
							| 
									
										
										
										
											2020-04-09 15:28:46 +08:00
										 |  |  | 								} else { | 
					
						
							|  |  |  | 									InnerGraph.onUsage(parser.state, usedByExports => { | 
					
						
							|  |  |  | 										switch (usedByExports) { | 
					
						
							|  |  |  | 											case undefined: | 
					
						
							|  |  |  | 											case true: | 
					
						
							|  |  |  | 												return; | 
					
						
							|  |  |  | 											default: { | 
					
						
							|  |  |  | 												const dep = new PureExpressionDependency( | 
					
						
							|  |  |  | 													decl.init.range | 
					
						
							|  |  |  | 												); | 
					
						
							|  |  |  | 												dep.loc = decl.loc; | 
					
						
							|  |  |  | 												dep.usedByExports = usedByExports; | 
					
						
							|  |  |  | 												parser.state.module.addDependency(dep); | 
					
						
							|  |  |  | 												break; | 
					
						
							|  |  |  | 											} | 
					
						
							|  |  |  | 										} | 
					
						
							|  |  |  | 									}); | 
					
						
							|  |  |  | 								} | 
					
						
							| 
									
										
										
										
											2019-09-08 21:21:00 +08:00
										 |  |  | 							} | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 							parser.walkExpression(decl.init); | 
					
						
							| 
									
										
										
										
											2020-01-23 20:59:27 +08:00
										 |  |  | 							InnerGraph.setTopLevelSymbol(parser.state, undefined); | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 							return true; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					}); | 
					
						
							| 
									
										
										
										
											2020-04-09 21:53:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 					parser.hooks.expression | 
					
						
							|  |  |  | 						.for(topLevelSymbolTag) | 
					
						
							| 
									
										
										
										
											2020-01-23 20:59:27 +08:00
										 |  |  | 						.tap("InnerGraphPlugin", () => { | 
					
						
							| 
									
										
										
										
											2020-03-29 06:10:15 +08:00
										 |  |  | 							const topLevelSymbol = /** @type {TopLevelSymbol} */ (parser.currentTagData); | 
					
						
							| 
									
										
										
										
											2020-01-23 20:59:27 +08:00
										 |  |  | 							const currentTopLevelSymbol = InnerGraph.getTopLevelSymbol( | 
					
						
							|  |  |  | 								parser.state | 
					
						
							|  |  |  | 							); | 
					
						
							| 
									
										
										
										
											2020-01-29 21:24:55 +08:00
										 |  |  | 							InnerGraph.addUsage( | 
					
						
							|  |  |  | 								parser.state, | 
					
						
							|  |  |  | 								topLevelSymbol, | 
					
						
							|  |  |  | 								currentTopLevelSymbol || true | 
					
						
							|  |  |  | 							); | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 						}); | 
					
						
							|  |  |  | 					parser.hooks.assign | 
					
						
							|  |  |  | 						.for(topLevelSymbolTag) | 
					
						
							|  |  |  | 						.tap("InnerGraphPlugin", expr => { | 
					
						
							| 
									
										
										
										
											2020-01-21 22:25:40 +08:00
										 |  |  | 							if (!InnerGraph.isEnabled(parser.state)) return; | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 							if (expr.operator === "=") return true; | 
					
						
							|  |  |  | 						}); | 
					
						
							|  |  |  | 				}; | 
					
						
							|  |  |  | 				normalModuleFactory.hooks.parser | 
					
						
							|  |  |  | 					.for("javascript/auto") | 
					
						
							| 
									
										
										
										
											2019-10-30 04:37:59 +08:00
										 |  |  | 					.tap("InnerGraphPlugin", handler); | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 				normalModuleFactory.hooks.parser | 
					
						
							|  |  |  | 					.for("javascript/esm") | 
					
						
							| 
									
										
										
										
											2019-10-30 04:37:59 +08:00
										 |  |  | 					.tap("InnerGraphPlugin", handler); | 
					
						
							| 
									
										
										
										
											2020-01-30 18:34:33 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				compilation.hooks.finishModules.tap("InnerGraphPlugin", () => { | 
					
						
							|  |  |  | 					logger.timeAggregateEnd("infer dependency usage"); | 
					
						
							|  |  |  | 				}); | 
					
						
							| 
									
										
										
										
											2019-09-03 20:11:50 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports = InnerGraphPlugin; |