2013-01-31 01:49:25 +08:00
/ *
MIT License http : //www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @ sokra
* /
2017-01-10 22:52:19 +08:00
"use strict" ;
2013-01-31 01:49:25 +08:00
2017-01-10 22:52:19 +08:00
const AMDRequireItemDependency = require ( "./AMDRequireItemDependency" ) ;
const AMDRequireArrayDependency = require ( "./AMDRequireArrayDependency" ) ;
const AMDRequireContextDependency = require ( "./AMDRequireContextDependency" ) ;
const AMDRequireDependenciesBlock = require ( "./AMDRequireDependenciesBlock" ) ;
const UnsupportedDependency = require ( "./UnsupportedDependency" ) ;
const LocalModuleDependency = require ( "./LocalModuleDependency" ) ;
const ContextDependencyHelpers = require ( "./ContextDependencyHelpers" ) ;
const LocalModulesHelpers = require ( "./LocalModulesHelpers" ) ;
const ConstDependency = require ( "./ConstDependency" ) ;
const getFunctionExpression = require ( "./getFunctionExpression" ) ;
const UnsupportedFeatureWarning = require ( "../UnsupportedFeatureWarning" ) ;
2014-03-11 23:08:22 +08:00
2017-01-10 22:52:19 +08:00
class AMDRequireDependenciesBlockParserPlugin {
constructor ( options ) {
this . options = options ;
}
2014-03-11 23:08:22 +08:00
2017-01-10 22:52:19 +08:00
processFunctionArgument ( parser , expression ) {
let bindThis = true ;
const fnData = getFunctionExpression ( expression ) ;
if ( fnData ) {
parser . inScope ( fnData . fn . params . filter ( ( i ) => {
return [ "require" , "module" , "exports" ] . indexOf ( i . name ) < 0 ;
} ) , ( ) => {
if ( fnData . fn . body . type === "BlockStatement" )
parser . walkStatement ( fnData . fn . body ) ;
else
parser . walkExpression ( fnData . fn . body ) ;
} ) ;
parser . walkExpressions ( fnData . expressions ) ;
if ( fnData . needThis === false ) {
bindThis = false ;
}
} else {
parser . walkExpression ( expression ) ;
2016-08-27 05:15:49 +08:00
}
2017-01-10 22:52:19 +08:00
return bindThis ;
2016-08-27 05:15:49 +08:00
}
2017-01-10 22:52:19 +08:00
apply ( parser ) {
const options = this . options ;
parser . plugin ( "call require" , ( expr ) => {
let param ;
let dep ;
let result ;
2016-08-27 05:15:49 +08:00
2017-02-05 08:34:16 +08:00
const old = parser . state . current ;
2016-08-27 05:15:49 +08:00
2017-01-10 22:52:19 +08:00
if ( expr . arguments . length >= 1 ) {
param = parser . evaluateExpression ( expr . arguments [ 0 ] ) ;
dep = new AMDRequireDependenciesBlock (
expr ,
param . range ,
( expr . arguments . length > 1 ) ? expr . arguments [ 1 ] . range : null ,
( expr . arguments . length > 2 ) ? expr . arguments [ 2 ] . range : null ,
parser . state . module ,
expr . loc
) ;
parser . state . current = dep ;
}
2016-08-27 05:15:49 +08:00
2017-01-10 22:52:19 +08:00
if ( expr . arguments . length === 1 ) {
parser . inScope ( [ ] , ( ) => {
result = parser . applyPluginsBailResult ( "call require:amd:array" , expr , param ) ;
} ) ;
parser . state . current = old ;
if ( ! result ) return ;
parser . state . current . addBlock ( dep ) ;
return true ;
}
2016-08-27 05:15:49 +08:00
2017-01-10 22:52:19 +08:00
if ( expr . arguments . length === 2 || expr . arguments . length === 3 ) {
try {
parser . inScope ( [ ] , ( ) => {
result = parser . applyPluginsBailResult ( "call require:amd:array" , expr , param ) ;
} ) ;
if ( ! result ) {
dep = new UnsupportedDependency ( "unsupported" , expr . range ) ;
old . addDependency ( dep ) ;
if ( parser . state . module )
parser . state . module . errors . push ( new UnsupportedFeatureWarning ( parser . state . module , "Cannot statically analyse 'require(..., ...)' in line " + expr . loc . start . line ) ) ;
dep = null ;
return true ;
}
dep . functionBindThis = this . processFunctionArgument ( parser , expr . arguments [ 1 ] ) ;
if ( expr . arguments . length === 3 ) {
dep . errorCallbackBindThis = this . processFunctionArgument ( parser , expr . arguments [ 2 ] ) ;
}
} finally {
parser . state . current = old ;
if ( dep )
parser . state . current . addBlock ( dep ) ;
2016-08-27 05:15:49 +08:00
}
2017-01-10 22:52:19 +08:00
return true ;
2016-08-27 05:15:49 +08:00
}
2017-01-10 22:52:19 +08:00
} ) ;
parser . plugin ( "call require:amd:array" , ( expr , param ) => {
if ( param . isArray ( ) ) {
param . items . forEach ( ( param ) => {
const result = parser . applyPluginsBailResult ( "call require:amd:item" , expr , param ) ;
if ( result === undefined ) {
parser . applyPluginsBailResult ( "call require:amd:context" , expr , param ) ;
}
} ) ;
return true ;
} else if ( param . isConstArray ( ) ) {
const deps = [ ] ;
param . array . forEach ( ( request ) => {
let dep , localModule ;
if ( request === "require" ) {
dep = "__webpack_require__" ;
} else if ( [ "exports" , "module" ] . indexOf ( request ) >= 0 ) {
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 ;
}
} ) ;
parser . plugin ( "call require:amd:item" , ( expr , param ) => {
if ( param . isConditional ( ) ) {
param . options . forEach ( ( param ) => {
const result = parser . applyPluginsBailResult ( "call require:amd:item" , expr , param ) ;
if ( result === undefined ) {
parser . applyPluginsBailResult ( "call require:amd:context" , expr , param ) ;
}
} ) ;
return true ;
} else if ( param . isString ( ) ) {
let dep , localModule ;
if ( param . string === "require" ) {
dep = new ConstDependency ( "__webpack_require__" , param . string ) ;
2017-01-26 07:01:45 +08:00
} else if ( param . string === "module" ) {
2017-11-12 01:48:29 +08:00
dep = new ConstDependency ( parser . state . module . moduleArgument , param . range ) ;
2017-01-26 07:01:45 +08:00
} else if ( param . string === "exports" ) {
2017-11-12 01:48:29 +08:00
dep = new ConstDependency ( parser . state . module . exportsArgument , param . range ) ;
2017-01-10 22:52:19 +08:00
} else if ( localModule = LocalModulesHelpers . getLocalModule ( parser . state , param . string ) ) { // eslint-disable-line no-cond-assign
dep = new LocalModuleDependency ( localModule , param . range ) ;
2013-12-08 21:59:52 +08:00
} else {
2017-01-10 22:52:19 +08:00
dep = new AMDRequireItemDependency ( param . string , param . range ) ;
2013-01-31 01:49:25 +08:00
}
2017-01-10 22:52:19 +08:00
dep . loc = expr . loc ;
dep . optional = ! ! parser . scope . inTry ;
parser . state . current . addDependency ( dep ) ;
return true ;
2013-01-31 01:49:25 +08:00
}
2017-01-10 22:52:19 +08:00
} ) ;
parser . plugin ( "call require:amd:context" , ( expr , param ) => {
const dep = ContextDependencyHelpers . create ( AMDRequireContextDependency , param . range , param , expr , options ) ;
if ( ! dep ) return ;
2013-01-31 01:49:25 +08:00
dep . loc = expr . loc ;
2017-01-10 22:52:19 +08:00
dep . optional = ! ! parser . scope . inTry ;
parser . state . current . addDependency ( dep ) ;
2013-01-31 01:49:25 +08:00
return true ;
2017-01-10 22:52:19 +08:00
} ) ;
}
}
module . exports = AMDRequireDependenciesBlockParserPlugin ;