text: /*
  	MIT License http://www.opensource.org/licenses/mit-license.php
  	Author Tobias Koppers @sokra
  */
  "use strict";
  
  const AMDRequireItemDependency = require("./AMDRequireItemDependency");
  const AMDRequireContextDependency = require("./AMDRequireContextDependency");
  const ConstDependency = require("./ConstDependency");
  const AMDDefineDependency = require("./AMDDefineDependency");
  const AMDRequireArrayDependency = require("./AMDRequireArrayDependency");
  const LocalModuleDependency = require("./LocalModuleDependency");
  const ContextDependencyHelpers = require("./ContextDependencyHelpers");
  const LocalModulesHelpers = require("./LocalModulesHelpers");
  
  const isBoundFunctionExpression = expr => {
  	if (expr.type !== "CallExpression") return false;
  	if (expr.callee.type !== "MemberExpression") return false;
  	if (expr.callee.computed) return false;
  	if (expr.callee.object.type !== "FunctionExpression") return false;
  	if (expr.callee.property.type !== "Identifier") return false;
  	if (expr.callee.property.name !== "bind") return false;
  	return true;
  };
  
  function isUnboundFunctionExpression(expr) {
  	if (expr.type === "FunctionExpression") return true;
  	if (expr.type === "ArrowFunctionExpression") return true;
  	return false;
  }
  
  function isCallable(expr) {
  	if (isUnboundFunctionExpression(expr)) return true;
  	if (isBoundFunctionExpression(expr)) return true;
  	return false;
  }
  
  class AMDDefineDependencyParserPlugin {
  	constructor(options) {
  		this.options = options;
  	}
  
  	newDefineDependency(
  		range,
  		arrayRange,
  		functionRange,
  		objectRange,
  		namedModule
  	) {
  		return new AMDDefineDependency(
  			range,
  			arrayRange,
  			functionRange,
  			objectRange,
  			namedModule
  		);
  	}
  
  	apply(parser) {
  		const options = this.options;
  
  		const processArray = (expr, param, identifiers, namedModule) => {
  			if (param.isArray()) {
  				param.items.forEach((param, idx) => {
  					if (
  						param.isString() &&
  						["require", "module", "exports"].includes(param.string)
  					)
  						identifiers[idx] = param.string;
  					const result = processItem(expr, param, namedModule);
  					if (result === undefined) {
  						processContext(expr, param);
  					}
  				});
  				return true;
  			} else if (param.isConstArray()) {
  				const deps = [];
  				param.array.forEach((request, idx) => {
  					let dep;
  					let localModule;
  					if (request === "require") {
  						identifiers[idx] = request;
  						dep = "__webpack_require__";
  					} else if (["exports", "module"].includes(request)) {
  						identifiers[idx] = request;
  						dep = request;
  					} else if (
  						(localModule = LocalModulesHelpers.getLocalModule(
  							parser.state,
  							request
  						))
  					) {
  						// eslint-disable-line no-cond-assign
  						dep = new LocalModuleDependency(localModule);
  						dep.loc = expr.loc;
  						parser.state.current.addDependency(dep);
  					} else {
  						dep = new AMDRequireItemDependency(request);
  						dep.loc = expr.loc;
  						dep.optional = !!parser.scope.inTry;
  						parser.state.current.addDependency(dep);
  					}
  					deps.push(dep);
  				});
  				const dep = new AMDRequireArrayDependency(deps, param.range);
  				dep.loc = expr.loc;
  				dep.optional = !!parser.scope.inTry;
  				parser.state.current.addDependency(dep);
  				return true;
  			}
  		};
  		const processItem = (expr, param, namedModule) => {
  			if (param.isConditional()) {
  				param.options.forEach(param => {
  					const result = processItem(expr, param);
  					if (result === undefined) {
  						processContext(expr, param);
  					}
  				});
  				return true;
  			} else if (param.isString()) {
  				let dep, localModule;
  				if (param.string === "require") {
  					dep = new ConstDependency("__webpack_require__", param.range);
  				} else if (["require", "exports", "module"].includes(param.string)) {
  					dep = new ConstDependency(param.string, param.range);
  				} else if (
  					(localModule = LocalModulesHelpers.getLocalModule(
  						parser.state,
  						param.string,
  						namedModule
  					))
  				) {
  					// eslint-disable-line no-cond-assign
  					dep = new LocalModuleDependency(localModule, param.range);
  				} else {
  					dep = new AMDRequireItemDependency(param.string, param.range);
  				}
  				dep.loc = expr.loc;
  				dep.optional = !!parser.scope.inTry;
  				parser.state.current.addDependency(dep);
  				return true;
  			}
  		};
  		const processContext = (expr, param) => {
  			const dep = ContextDependencyHelpers.create(
  				AMDRequireContextDependency,
  				param.range,
  				param,
  				expr,
  				options
  			);
  			if (!dep) return;
  			dep.loc = expr.loc;
  			dep.optional = !!parser.scope.inTry;
  			parser.state.current.addDependency(dep);
  			return true;
  		};
  
  		parser.hooks.call
  			.for("define")
  			.tap("AMDDefineDependencyParserPlugin", expr => {
  				let array, fn, obj, namedModule;
  				switch (expr.arguments.length) {
  					case 1:
  						if (isCallable(expr.arguments[0])) {
  							// define(f() {...})
  							fn = expr.arguments[0];
  						} else if (expr.arguments[0].type === "ObjectExpression") {
  							// define({...})
  							obj = expr.arguments[0];
  						} else {
  							// define(expr)
  							// unclear if function or object
  							obj = fn = expr.arguments[0];
  						}
  						break;
  					case 2:
  						if (expr.arguments[0].type === "Literal") {
  							namedModule = expr.arguments[0].value;
  							// define("...", ...)
  							if (isCallable(expr.arguments[1])) {
  								// define("...", f() {...})
  								fn = expr.arguments[1];
  							} else if (expr.arguments[1].type === "ObjectExpression") {
  								// define("...", {...})
  								obj = expr.arguments[1];
  							} else {
  								// define("...", expr)
  								// unclear if function or object
  								obj = fn = expr.arguments[1];
  							}
  						} else {
  							array = expr.arguments[0];
  							if (isCallable(expr.arguments[1])) {
  								// define([...], f() {})
  								fn = expr.arguments[1];
  							} else if (expr.arguments[1].type === "ObjectExpression") {
  								// define([...], {...})
  								obj = expr.arguments[1];
  							} else {
  								// define([...], expr)
  								// unclear if function or object
  								obj = fn = expr.arguments[1];
  							}
  						}
  						break;
  					case 3:
  						// define("...", [...], f() {...})
  						namedModule = expr.arguments[0].value;
  						array = expr.arguments[1];
  						if (isCallable(expr.arguments[2])) {
  							// define("...", [...], f() {})
  							fn = expr.arguments[2];
  						} else if (expr.arguments[2].type === "ObjectExpression") {
  							// define("...", [...], {...})
  							obj = expr.arguments[2];
  						} else {
  							// define("...", [...], expr)
  							// unclear if function or object
  							obj = fn = expr.arguments[2];
  						}
  						break;
  					default:
  						return;
  				}
  				let fnParams = null;
  				let fnParamsOffset = 0;
  				if (fn) {
  					if (isUnboundFunctionExpression(fn)) fnParams = fn.params;
  					else if (isBoundFunctionExpression(fn)) {
  						fnParams = fn.callee.object.params;
  						fnParamsOffset = fn.arguments.length - 1;
  						if (fnParamsOffset < 0) fnParamsOffset = 0;
  					}
  				}
  				let fnRenames = parser.scope.renames.createChild();
  				let identifiers;
  				if (array) {
  					identifiers = {};
  					const param = parser.evaluateExpression(array);
  					const result = processArray(expr, param, identifiers, namedModule);
  					if (!result) return;
  					if (fnParams)
  						fnParams = fnParams.slice(fnParamsOffset).filter((param, idx) => {
  							if (identifiers[idx]) {
  								fnRenames.set(param.name, identifiers[idx]);
  								return false;
  							}
  							return true;
  						});
  				} else {
  					identifiers = ["require", "exports", "module"];
  					if (fnParams)
  						fnParams = fnParams.slice(fnParamsOffset).filter((param, idx) => {
  							if (identifiers[idx]) {
  								fnRenames.set(param.name, identifiers[idx]);
  								return false;
  							}
  							return true;
  						});
  				}
  				let inTry;
  				if (fn && isUnboundFunctionExpression(fn)) {
  					inTry = parser.scope.inTry;
  					parser.inScope(fnParams, () => {
  						parser.scope.renames = fnRenames;
  						parser.scope.inTry = inTry;
  						if (fn.body.type === "BlockStatement")
  							parser.walkStatement(fn.body);
  						else parser.walkExpression(fn.body);
  					});
  				} else if (fn && isBoundFunctionExpression(fn)) {
  					inTry = parser.scope.inTry;
  					parser.inScope(
  						fn.callee.object.params.filter(
  							i => !["require", "module", "exports"].includes(i.name)
  						),
  						() => {
  							parser.scope.renames = fnRenames;
  							parser.scope.inTry = inTry;
  							if (fn.callee.object.body.type === "BlockStatement")
  								parser.walkStatement(fn.callee.object.body);
  							else parser.walkExpression(fn.callee.object.body);
  						}
  					);
  					if (fn.arguments) parser.walkExpressions(fn.arguments);
  				} else if (fn || obj) {
  					parser.walkExpression(fn || obj);
  				}
  
  				const dep = this.newDefineDependency(
  					expr.range,
  					array ? array.range : null,
  					fn ? fn.range : null,
  					obj ? obj.range : null,
  					namedModule ? namedModule : null
  				);
  				dep.loc = expr.loc;
  				if (namedModule) {
  					dep.localModule = LocalModulesHelpers.addLocalModule(
  						parser.state,
  						namedModule
  					);
  				}
  				parser.state.current.addDependency(dep);
  				return true;
  			});
  	}
  }
  module.exports = AMDDefineDependencyParserPlugin;
  