|
|
- /*
- 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;
- };
-
- const isUnboundFunctionExpression = expr => {
- if (expr.type === "FunctionExpression") return true;
- if (expr.type === "ArrowFunctionExpression") return true;
- return false;
- };
-
- const isCallable = expr => {
- if (isUnboundFunctionExpression(expr)) return true;
- if (isBoundFunctionExpression(expr)) return true;
- return false;
- };
-
- class AMDDefineDependencyParserPlugin {
- constructor(options) {
- this.options = options;
- }
-
- apply(parser) {
- parser.hooks.call
- .for("define")
- .tap(
- "AMDDefineDependencyParserPlugin",
- this.processCallDefine.bind(this, parser)
- );
- }
-
- processArray(parser, 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 = this.processItem(parser, expr, param, namedModule);
- if (result === undefined) {
- this.processContext(parser, 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
- ))
- ) {
- dep = new LocalModuleDependency(localModule, undefined, false);
- dep.loc = expr.loc;
- parser.state.current.addDependency(dep);
- } else {
- dep = this.newRequireItemDependency(request);
- dep.loc = expr.loc;
- dep.optional = !!parser.scope.inTry;
- parser.state.current.addDependency(dep);
- }
- deps.push(dep);
- });
- const dep = this.newRequireArrayDependency(deps, param.range);
- dep.loc = expr.loc;
- dep.optional = !!parser.scope.inTry;
- parser.state.current.addDependency(dep);
- return true;
- }
- }
- processItem(parser, expr, param, namedModule) {
- if (param.isConditional()) {
- param.options.forEach(param => {
- const result = this.processItem(parser, expr, param);
- if (result === undefined) {
- this.processContext(parser, 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
- ))
- ) {
- dep = new LocalModuleDependency(localModule, param.range, false);
- } else {
- dep = this.newRequireItemDependency(param.string, param.range);
- }
- dep.loc = expr.loc;
- dep.optional = !!parser.scope.inTry;
- parser.state.current.addDependency(dep);
- return true;
- }
- }
- processContext(parser, expr, param) {
- const dep = ContextDependencyHelpers.create(
- AMDRequireContextDependency,
- param.range,
- param,
- expr,
- this.options,
- {},
- parser
- );
- if (!dep) return;
- dep.loc = expr.loc;
- dep.optional = !!parser.scope.inTry;
- parser.state.current.addDependency(dep);
- return true;
- }
-
- processCallDefine(parser, 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();
- if (array) {
- const identifiers = {};
- const param = parser.evaluateExpression(array);
- const result = this.processArray(
- parser,
- 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 {
- const 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;
- }
-
- newDefineDependency(
- range,
- arrayRange,
- functionRange,
- objectRange,
- namedModule
- ) {
- return new AMDDefineDependency(
- range,
- arrayRange,
- functionRange,
- objectRange,
- namedModule
- );
- }
- newRequireArrayDependency(depsArray, range) {
- return new AMDRequireArrayDependency(depsArray, range);
- }
- newRequireItemDependency(request, range) {
- return new AMDRequireItemDependency(request, range);
- }
- }
- module.exports = AMDDefineDependencyParserPlugin;
|