2016-12-03 18:36:10 +08:00
/ *
MIT License http : //www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @ sokra
* /
2018-07-30 23:08:51 +08:00
2017-01-12 01:58:05 +08:00
"use strict" ;
2016-12-03 18:36:10 +08:00
2020-06-10 19:31:01 +08:00
const AsyncDependenciesBlock = require ( "../AsyncDependenciesBlock" ) ;
2018-07-30 23:08:51 +08:00
const CommentCompilationWarning = require ( "../CommentCompilationWarning" ) ;
const UnsupportedFeatureWarning = require ( "../UnsupportedFeatureWarning" ) ;
2025-09-24 01:52:59 +08:00
const {
VariableInfo ,
getImportAttributes
} = require ( "../javascript/JavascriptParser" ) ;
2018-07-30 23:08:51 +08:00
const ContextDependencyHelpers = require ( "./ContextDependencyHelpers" ) ;
2017-10-16 18:52:04 +08:00
const ImportContextDependency = require ( "./ImportContextDependency" ) ;
2018-10-18 05:09:21 +08:00
const ImportDependency = require ( "./ImportDependency" ) ;
2017-05-05 00:37:25 +08:00
const ImportEagerDependency = require ( "./ImportEagerDependency" ) ;
2018-07-30 23:08:51 +08:00
const ImportWeakDependency = require ( "./ImportWeakDependency" ) ;
2016-12-03 18:36:10 +08:00
2022-03-09 15:27:02 +08:00
/** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
2019-06-14 17:44:54 +08:00
/** @typedef {import("../ChunkGroup").RawChunkGroupOptions} RawChunkGroupOptions */
/** @typedef {import("../ContextModule").ContextMode} ContextMode */
2023-06-17 03:44:20 +08:00
/** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */
2025-09-11 08:10:10 +08:00
/** @typedef {import("../Dependency").RawReferencedExports} RawReferencedExports */
2023-06-17 03:44:20 +08:00
/** @typedef {import("../Module").BuildMeta} BuildMeta */
2023-05-22 06:28:57 +08:00
/** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
2024-11-01 00:31:45 +08:00
/** @typedef {import("../javascript/JavascriptParser").ImportExpression} ImportExpression */
2023-06-17 03:44:20 +08:00
/** @typedef {import("../javascript/JavascriptParser").Range} Range */
2025-08-25 21:43:57 +08:00
/** @typedef {import("../javascript/JavascriptParser").ParserState} ParserState */
2025-09-11 08:10:10 +08:00
/** @typedef {import("../javascript/JavascriptParser").Members} Members */
/** @typedef {import("../javascript/JavascriptParser").MembersOptionals} MembersOptionals */
2025-09-18 20:46:16 +08:00
/** @typedef {import("../javascript/JavascriptParser").ArrowFunctionExpression} ArrowFunctionExpression */
/** @typedef {import("../javascript/JavascriptParser").FunctionExpression} FunctionExpression */
/** @typedef {import("../javascript/JavascriptParser").Identifier} Identifier */
/** @typedef {import("../javascript/JavascriptParser").ObjectPattern} ObjectPattern */
/** @typedef {import("../javascript/JavascriptParser").CallExpression} CallExpression */
2025-08-25 21:43:57 +08:00
2025-09-11 08:10:10 +08:00
/** @typedef {{ references: RawReferencedExports, expression: ImportExpression }} ImportSettings */
/** @typedef {WeakMap<ImportExpression, RawReferencedExports>} State */
2025-08-25 21:43:57 +08:00
/** @type {WeakMap<ParserState, State>} */
const parserStateMap = new WeakMap ( ) ;
const dynamicImportTag = Symbol ( "import()" ) ;
/ * *
* @ param { JavascriptParser } parser javascript parser
* @ returns { State } import parser plugin state
* /
function getState ( parser ) {
if ( ! parserStateMap . has ( parser . state ) ) {
parserStateMap . set ( parser . state , new WeakMap ( ) ) ;
}
return /** @type {State} */ ( parserStateMap . get ( parser . state ) ) ;
}
2019-06-14 17:44:54 +08:00
2025-09-18 20:46:16 +08:00
/ * *
* @ param { JavascriptParser } parser javascript parser
* @ param { ImportExpression } importCall import expression
* @ param { string } variableName variable name
* /
function tagDynamicImportReferenced ( parser , importCall , variableName ) {
const state = getState ( parser ) ;
/** @type {RawReferencedExports} */
const references = state . get ( importCall ) || [ ] ;
state . set ( importCall , references ) ;
parser . tagVariable (
variableName ,
dynamicImportTag ,
/** @type {ImportSettings} */ ( {
references ,
expression : importCall
} )
) ;
}
/ * *
* @ param { CallExpression } importThen import ( ) . then ( ) call
* @ returns { Identifier | ObjectPattern | undefined } the dynamic imported namespace obj
* /
function getFulfilledCallbackNamespaceObj ( importThen ) {
const fulfilledCallback = importThen . arguments [ 0 ] ;
if (
fulfilledCallback &&
( fulfilledCallback . type === "ArrowFunctionExpression" ||
fulfilledCallback . type === "FunctionExpression" ) &&
fulfilledCallback . params [ 0 ] &&
( fulfilledCallback . params [ 0 ] . type === "Identifier" ||
fulfilledCallback . params [ 0 ] . type === "ObjectPattern" )
) {
return fulfilledCallback . params [ 0 ] ;
}
}
/ * *
* @ param { JavascriptParser } parser javascript parser
* @ param { ImportExpression } importCall import expression
* @ param { ArrowFunctionExpression | FunctionExpression } fulfilledCallback the fulfilled callback
* @ param { Identifier | ObjectPattern } namespaceObjArg the argument of namespace object =
* /
function walkImportThenFulfilledCallback (
parser ,
importCall ,
fulfilledCallback ,
namespaceObjArg
) {
const arrow = fulfilledCallback . type === "ArrowFunctionExpression" ;
const wasTopLevel = parser . scope . topLevelScope ;
parser . scope . topLevelScope = arrow ? ( wasTopLevel ? "arrow" : false ) : false ;
const scopeParams = [ ... fulfilledCallback . params ] ;
// Add function name in scope for recursive calls
if ( ! arrow && fulfilledCallback . id ) {
scopeParams . push ( fulfilledCallback . id ) ;
}
parser . inFunctionScope ( ! arrow , scopeParams , ( ) => {
if ( namespaceObjArg . type === "Identifier" ) {
tagDynamicImportReferenced ( parser , importCall , namespaceObjArg . name ) ;
} else {
parser . enterDestructuringAssignment ( namespaceObjArg , importCall ) ;
const referencedPropertiesInDestructuring =
parser . destructuringAssignmentPropertiesFor ( importCall ) ;
if ( referencedPropertiesInDestructuring ) {
const state = getState ( parser ) ;
const references = /** @type {RawReferencedExports} */ (
state . get ( importCall )
) ;
for ( const ids of exportsFromEnumerable (
[ ... referencedPropertiesInDestructuring ] . map ( ( { id } ) => id )
) ) {
references . push ( ids ) ;
}
}
}
for ( const param of fulfilledCallback . params ) {
parser . walkPattern ( param ) ;
}
if ( fulfilledCallback . body . type === "BlockStatement" ) {
parser . detectMode ( fulfilledCallback . body . body ) ;
const prev = parser . prevStatement ;
parser . preWalkStatement ( fulfilledCallback . body ) ;
parser . prevStatement = prev ;
parser . walkStatement ( fulfilledCallback . body ) ;
} else {
parser . walkExpression ( fulfilledCallback . body ) ;
}
} ) ;
parser . scope . topLevelScope = wasTopLevel ;
}
/ * *
* @ template T
* @ param { Iterable < T > } enumerable enumerable
* @ returns { T [ ] [ ] } array of array
* /
const exportsFromEnumerable = ( enumerable ) =>
Array . from ( enumerable , ( e ) => [ e ] ) ;
2025-05-22 22:54:59 +08:00
const PLUGIN _NAME = "ImportParserPlugin" ;
2017-01-12 01:58:05 +08:00
class ImportParserPlugin {
2022-03-09 15:27:02 +08:00
/ * *
* @ param { JavascriptParserOptions } options options
* /
2017-01-12 01:58:05 +08:00
constructor ( options ) {
this . options = options ;
}
2016-12-03 18:36:10 +08:00
2023-05-22 06:28:57 +08:00
/ * *
* @ param { JavascriptParser } parser the parser
* @ returns { void }
* /
2017-01-12 01:58:05 +08:00
apply ( parser ) {
2025-08-25 21:43:57 +08:00
/ * *
2025-09-11 08:10:10 +08:00
* @ param { Members } members members
* @ param { MembersOptionals } membersOptionals members Optionals
2025-08-25 21:43:57 +08:00
* @ returns { string [ ] } a non optional part
* /
function getNonOptionalPart ( members , membersOptionals ) {
let i = 0 ;
while ( i < members . length && membersOptionals [ i ] === false ) i ++ ;
return i !== members . length ? members . slice ( 0 , i ) : members ;
}
2025-08-17 23:10:08 +08:00
parser . hooks . collectDestructuringAssignmentProperties . tap (
PLUGIN _NAME ,
( expr ) => {
if ( expr . type === "ImportExpression" ) return true ;
2025-09-24 01:52:59 +08:00
const nameInfo = parser . getNameForExpression ( expr ) ;
if (
nameInfo &&
nameInfo . rootInfo instanceof VariableInfo &&
nameInfo . rootInfo . name &&
parser . getTagData ( nameInfo . rootInfo . name , dynamicImportTag )
) {
return true ;
}
2025-08-17 23:10:08 +08:00
}
) ;
2025-08-25 21:43:57 +08:00
parser . hooks . preDeclarator . tap ( PLUGIN _NAME , ( decl ) => {
if (
decl . init &&
decl . init . type === "AwaitExpression" &&
decl . init . argument . type === "ImportExpression" &&
decl . id . type === "Identifier"
) {
2025-09-26 20:17:26 +08:00
parser . defineVariable ( decl . id . name ) ;
2025-09-18 20:46:16 +08:00
tagDynamicImportReferenced ( parser , decl . init . argument , decl . id . name ) ;
2025-08-25 21:43:57 +08:00
}
} ) ;
2025-09-24 01:52:59 +08:00
parser . hooks . expression . for ( dynamicImportTag ) . tap ( PLUGIN _NAME , ( expr ) => {
2025-08-25 21:43:57 +08:00
const settings = /** @type {ImportSettings} */ ( parser . currentTagData ) ;
2025-09-24 01:52:59 +08:00
const referencedPropertiesInDestructuring =
parser . destructuringAssignmentPropertiesFor ( expr ) ;
if ( referencedPropertiesInDestructuring ) {
for ( const ids of exportsFromEnumerable (
[ ... referencedPropertiesInDestructuring ] . map ( ( { id } ) => id )
) ) {
settings . references . push ( ids ) ;
}
} else {
settings . references . push ( [ ] ) ;
}
2025-08-25 21:43:57 +08:00
return true ;
} ) ;
parser . hooks . expressionMemberChain
. for ( dynamicImportTag )
. tap ( PLUGIN _NAME , ( _expression , members , membersOptionals ) => {
const settings = /** @type {ImportSettings} */ ( parser . currentTagData ) ;
const ids = getNonOptionalPart ( members , membersOptionals ) ;
settings . references . push ( ids ) ;
return true ;
} ) ;
parser . hooks . callMemberChain
. for ( dynamicImportTag )
2025-09-18 20:46:16 +08:00
. tap ( PLUGIN _NAME , ( expression , members , membersOptionals ) => {
const { arguments : args } = expression ;
2025-08-25 21:43:57 +08:00
const settings = /** @type {ImportSettings} */ ( parser . currentTagData ) ;
let ids = getNonOptionalPart ( members , membersOptionals ) ;
const directImport = members . length === 0 ;
if (
! directImport &&
( this . options . strictThisContextOnImports || ids . length > 1 )
) {
ids = ids . slice ( 0 , - 1 ) ;
}
settings . references . push ( ids ) ;
2025-09-18 20:46:16 +08:00
if ( args ) parser . walkExpressions ( args ) ;
2025-08-25 21:43:57 +08:00
return true ;
} ) ;
2025-09-18 20:46:16 +08:00
parser . hooks . importCall . tap ( PLUGIN _NAME , ( expr , importThen ) => {
2019-08-14 20:42:07 +08:00
const param = parser . evaluateExpression ( expr . source ) ;
2017-04-10 17:35:32 +08:00
2017-03-26 17:07:52 +08:00
let chunkName = null ;
2023-06-17 03:44:20 +08:00
let mode = /** @type {ContextMode} */ ( this . options . dynamicImportMode ) ;
2017-10-14 05:31:15 +08:00
let include = null ;
2017-10-13 05:35:23 +08:00
let exclude = null ;
2025-09-11 08:10:10 +08:00
/** @type {RawReferencedExports | null} */
2020-05-28 02:34:55 +08:00
let exports = null ;
2019-06-14 17:44:54 +08:00
/** @type {RawChunkGroupOptions} */
2018-04-16 16:27:22 +08:00
const groupOptions = { } ;
2017-03-26 17:07:52 +08:00
2023-04-15 06:30:42 +08:00
const {
dynamicImportPreload ,
dynamicImportPrefetch ,
dynamicImportFetchPriority
} = this . options ;
2025-07-02 20:10:54 +08:00
if (
dynamicImportPreload !== undefined &&
dynamicImportPreload !== false
) {
2022-03-15 21:42:52 +08:00
groupOptions . preloadOrder =
dynamicImportPreload === true ? 0 : dynamicImportPreload ;
2025-07-02 20:10:54 +08:00
}
2023-04-23 04:42:55 +08:00
if (
dynamicImportPrefetch !== undefined &&
dynamicImportPrefetch !== false
2025-07-02 20:10:54 +08:00
) {
2023-04-23 04:42:55 +08:00
groupOptions . prefetchOrder =
dynamicImportPrefetch === true ? 0 : dynamicImportPrefetch ;
2025-07-02 20:10:54 +08:00
}
2023-04-15 06:30:42 +08:00
if (
dynamicImportFetchPriority !== undefined &&
dynamicImportFetchPriority !== false
2025-07-02 20:10:54 +08:00
) {
2023-05-24 09:13:01 +08:00
groupOptions . fetchPriority = dynamicImportFetchPriority ;
2025-07-02 20:10:54 +08:00
}
2022-03-09 15:27:02 +08:00
2021-05-11 15:31:46 +08:00
const { options : importOptions , errors : commentErrors } =
2023-06-17 03:44:20 +08:00
parser . parseCommentOptions ( /** @type {Range} */ ( expr . range ) ) ;
2018-05-29 19:17:36 +08:00
if ( commentErrors ) {
2022-11-22 12:03:27 +08:00
for ( const e of commentErrors ) {
const { comment } = e ;
2019-11-08 19:43:05 +08:00
parser . state . module . addWarning (
2018-05-30 09:24:36 +08:00
new CommentCompilationWarning (
2019-06-09 17:23:42 +08:00
` Compilation error while processing magic comment(-s): /* ${ comment . value } */: ${ e . message } ` ,
2024-10-16 22:42:26 +08:00
/** @type {DependencyLocation} */ ( comment . loc )
2018-05-29 19:17:36 +08:00
)
) ;
}
2018-05-29 15:29:23 +08:00
}
2025-07-02 20:02:03 +08:00
let phase = expr . phase ;
if ( ! phase && importOptions && importOptions . webpackDefer !== undefined ) {
if ( typeof importOptions . webpackDefer !== "boolean" ) {
parser . state . module . addWarning (
new UnsupportedFeatureWarning (
` \` webpackDefer \` expected a boolean, but received: ${ importOptions . webpackDefer } . ` ,
/** @type {DependencyLocation} */ ( expr . loc )
)
) ;
} else if ( importOptions . webpackDefer ) {
phase = "defer" ;
}
}
if ( phase === "defer" ) {
parser . state . module . addWarning (
new UnsupportedFeatureWarning (
"import.defer() is not implemented yet." ,
/** @type {DependencyLocation} */ ( expr . loc )
)
) ;
}
2018-02-25 09:00:20 +08:00
if ( importOptions ) {
2018-08-21 08:26:50 +08:00
if ( importOptions . webpackIgnore !== undefined ) {
2018-04-12 23:33:22 +08:00
if ( typeof importOptions . webpackIgnore !== "boolean" ) {
2019-11-08 19:43:05 +08:00
parser . state . module . addWarning (
2018-04-12 23:33:22 +08:00
new UnsupportedFeatureWarning (
2019-06-09 17:23:42 +08:00
` \` webpackIgnore \` expected a boolean, but received: ${ importOptions . webpackIgnore } . ` ,
2023-06-17 03:44:20 +08:00
/** @type {DependencyLocation} */ ( expr . loc )
2018-04-12 23:33:22 +08:00
)
) ;
2024-07-31 04:54:55 +08:00
} else if ( importOptions . webpackIgnore ) {
2018-09-22 05:24:18 +08:00
// Do not instrument `import()` if `webpackIgnore` is `true`
2024-07-31 04:54:55 +08:00
return false ;
2018-04-12 23:33:22 +08:00
}
}
2018-08-21 08:26:50 +08:00
if ( importOptions . webpackChunkName !== undefined ) {
2018-04-12 23:33:22 +08:00
if ( typeof importOptions . webpackChunkName !== "string" ) {
2019-11-08 19:43:05 +08:00
parser . state . module . addWarning (
2018-02-25 09:00:20 +08:00
new UnsupportedFeatureWarning (
2019-06-09 17:23:42 +08:00
` \` webpackChunkName \` expected a string, but received: ${ importOptions . webpackChunkName } . ` ,
2023-06-17 03:44:20 +08:00
/** @type {DependencyLocation} */ ( expr . loc )
2018-02-25 09:00:20 +08:00
)
) ;
2018-04-12 23:33:22 +08:00
} else {
chunkName = importOptions . webpackChunkName ;
}
2017-05-05 00:37:25 +08:00
}
2018-08-21 08:26:50 +08:00
if ( importOptions . webpackMode !== undefined ) {
2018-04-12 23:33:22 +08:00
if ( typeof importOptions . webpackMode !== "string" ) {
2019-11-08 19:43:05 +08:00
parser . state . module . addWarning (
2018-02-25 09:00:20 +08:00
new UnsupportedFeatureWarning (
2019-06-09 17:23:42 +08:00
` \` webpackMode \` expected a string, but received: ${ importOptions . webpackMode } . ` ,
2023-06-17 03:44:20 +08:00
/** @type {DependencyLocation} */ ( expr . loc )
2018-02-25 09:00:20 +08:00
)
) ;
2018-04-12 23:33:22 +08:00
} else {
2024-10-01 03:05:27 +08:00
mode = /** @type {ContextMode} */ ( importOptions . webpackMode ) ;
2018-04-12 23:33:22 +08:00
}
2017-03-26 17:07:52 +08:00
}
2018-08-21 08:26:50 +08:00
if ( importOptions . webpackPrefetch !== undefined ) {
2018-04-16 23:43:13 +08:00
if ( importOptions . webpackPrefetch === true ) {
2018-04-17 00:00:34 +08:00
groupOptions . prefetchOrder = 0 ;
2018-04-16 23:43:13 +08:00
} else if ( typeof importOptions . webpackPrefetch === "number" ) {
2018-04-17 00:00:34 +08:00
groupOptions . prefetchOrder = importOptions . webpackPrefetch ;
2018-04-16 23:43:13 +08:00
} else {
2019-11-08 19:43:05 +08:00
parser . state . module . addWarning (
2018-04-16 16:27:22 +08:00
new UnsupportedFeatureWarning (
2019-06-09 17:23:42 +08:00
` \` webpackPrefetch \` expected true or a number, but received: ${ importOptions . webpackPrefetch } . ` ,
2023-06-17 03:44:20 +08:00
/** @type {DependencyLocation} */ ( expr . loc )
2018-04-16 16:27:22 +08:00
)
) ;
}
}
2018-08-21 08:26:50 +08:00
if ( importOptions . webpackPreload !== undefined ) {
2018-04-16 23:43:13 +08:00
if ( importOptions . webpackPreload === true ) {
2018-04-17 00:00:34 +08:00
groupOptions . preloadOrder = 0 ;
2018-04-16 23:43:13 +08:00
} else if ( typeof importOptions . webpackPreload === "number" ) {
2018-04-17 00:00:34 +08:00
groupOptions . preloadOrder = importOptions . webpackPreload ;
2018-04-16 23:43:13 +08:00
} else {
2019-11-08 19:43:05 +08:00
parser . state . module . addWarning (
2018-04-16 16:27:22 +08:00
new UnsupportedFeatureWarning (
2019-06-09 17:23:42 +08:00
` \` webpackPreload \` expected true or a number, but received: ${ importOptions . webpackPreload } . ` ,
2023-06-17 03:44:20 +08:00
/** @type {DependencyLocation} */ ( expr . loc )
2018-04-16 16:27:22 +08:00
)
) ;
}
2017-03-26 17:07:52 +08:00
}
2023-04-15 06:30:42 +08:00
if ( importOptions . webpackFetchPriority !== undefined ) {
2023-05-24 09:13:01 +08:00
if (
2023-04-23 05:32:14 +08:00
typeof importOptions . webpackFetchPriority === "string" &&
[ "high" , "low" , "auto" ] . includes ( importOptions . webpackFetchPriority )
2023-04-15 06:30:42 +08:00
) {
2024-10-01 03:05:27 +08:00
groupOptions . fetchPriority =
/** @type {"low" | "high" | "auto"} */
( importOptions . webpackFetchPriority ) ;
2023-04-23 05:32:14 +08:00
} else {
2023-04-15 06:30:42 +08:00
parser . state . module . addWarning (
new UnsupportedFeatureWarning (
2023-04-23 05:32:14 +08:00
` \` webpackFetchPriority \` expected true or "low", "high" or "auto", but received: ${ importOptions . webpackFetchPriority } . ` ,
2023-06-17 03:44:20 +08:00
/** @type {DependencyLocation} */ ( expr . loc )
2023-04-15 06:30:42 +08:00
)
) ;
}
}
2018-08-21 08:26:50 +08:00
if ( importOptions . webpackInclude !== undefined ) {
2018-02-25 09:00:20 +08:00
if (
! importOptions . webpackInclude ||
2022-11-22 11:37:16 +08:00
! ( importOptions . webpackInclude instanceof RegExp )
2018-02-25 09:00:20 +08:00
) {
2019-11-08 19:43:05 +08:00
parser . state . module . addWarning (
2018-02-25 09:00:20 +08:00
new UnsupportedFeatureWarning (
2019-06-09 17:23:42 +08:00
` \` webpackInclude \` expected a regular expression, but received: ${ importOptions . webpackInclude } . ` ,
2023-06-17 03:44:20 +08:00
/** @type {DependencyLocation} */ ( expr . loc )
2018-02-25 09:00:20 +08:00
)
) ;
2017-10-12 05:30:54 +08:00
} else {
2022-11-22 11:37:16 +08:00
include = importOptions . webpackInclude ;
2017-10-12 05:30:54 +08:00
}
}
2018-08-21 08:26:50 +08:00
if ( importOptions . webpackExclude !== undefined ) {
2018-02-25 09:00:20 +08:00
if (
! importOptions . webpackExclude ||
2022-11-22 11:37:16 +08:00
! ( importOptions . webpackExclude instanceof RegExp )
2018-02-25 09:00:20 +08:00
) {
2019-11-08 19:43:05 +08:00
parser . state . module . addWarning (
2018-02-25 09:00:20 +08:00
new UnsupportedFeatureWarning (
2019-06-09 17:23:42 +08:00
` \` webpackExclude \` expected a regular expression, but received: ${ importOptions . webpackExclude } . ` ,
2023-06-17 03:44:20 +08:00
/** @type {DependencyLocation} */ ( expr . loc )
2018-02-25 09:00:20 +08:00
)
) ;
2017-10-13 05:35:23 +08:00
} else {
2022-11-22 11:37:16 +08:00
exclude = importOptions . webpackExclude ;
2017-10-13 05:35:23 +08:00
}
}
2020-05-28 02:34:55 +08:00
if ( importOptions . webpackExports !== undefined ) {
if (
! (
typeof importOptions . webpackExports === "string" ||
( Array . isArray ( importOptions . webpackExports ) &&
2025-09-11 08:10:10 +08:00
importOptions . webpackExports . every (
2025-07-17 00:13:14 +08:00
( item ) => typeof item === "string"
2020-05-28 02:34:55 +08:00
) )
)
) {
parser . state . module . addWarning (
new UnsupportedFeatureWarning (
` \` webpackExports \` expected a string or an array of strings, but received: ${ importOptions . webpackExports } . ` ,
2023-06-17 03:44:20 +08:00
/** @type {DependencyLocation} */ ( expr . loc )
2020-05-28 02:34:55 +08:00
)
) ;
2024-07-31 04:54:55 +08:00
} else if ( typeof importOptions . webpackExports === "string" ) {
exports = [ [ importOptions . webpackExports ] ] ;
2020-05-28 02:34:55 +08:00
} else {
2024-07-31 04:54:55 +08:00
exports = exportsFromEnumerable ( importOptions . webpackExports ) ;
2020-05-28 02:34:55 +08:00
}
}
2017-03-26 17:07:52 +08:00
}
2022-03-15 23:34:05 +08:00
if (
mode !== "lazy" &&
mode !== "lazy-once" &&
mode !== "eager" &&
mode !== "weak"
) {
parser . state . module . addWarning (
new UnsupportedFeatureWarning (
` \` webpackMode \` expected 'lazy', 'lazy-once', 'eager' or 'weak', but received: ${ mode } . ` ,
2023-06-17 03:44:20 +08:00
/** @type {DependencyLocation} */ ( expr . loc )
2022-03-15 23:34:05 +08:00
)
) ;
mode = "lazy" ;
}
2017-05-05 00:37:25 +08:00
2023-04-13 22:16:32 +08:00
const referencedPropertiesInDestructuring =
parser . destructuringAssignmentPropertiesFor ( expr ) ;
2025-08-25 21:43:57 +08:00
const state = getState ( parser ) ;
const referencedPropertiesInMember = state . get ( expr ) ;
2025-09-18 20:46:16 +08:00
const fulfilledNamespaceObj =
importThen && getFulfilledCallbackNamespaceObj ( importThen ) ;
if (
referencedPropertiesInDestructuring ||
referencedPropertiesInMember ||
fulfilledNamespaceObj
) {
2023-04-13 22:16:32 +08:00
if ( exports ) {
parser . state . module . addWarning (
new UnsupportedFeatureWarning (
2025-08-25 21:43:57 +08:00
"You don't need `webpackExports` if the usage of dynamic import is statically analyse-able. You can safely remove the `webpackExports` magic comment." ,
2023-06-17 03:44:20 +08:00
/** @type {DependencyLocation} */ ( expr . loc )
2023-04-13 22:16:32 +08:00
)
) ;
}
2025-07-02 20:10:54 +08:00
2025-08-25 21:43:57 +08:00
if ( referencedPropertiesInDestructuring ) {
exports = exportsFromEnumerable (
[ ... referencedPropertiesInDestructuring ] . map ( ( { id } ) => id )
) ;
} else if ( referencedPropertiesInMember ) {
exports = referencedPropertiesInMember ;
2025-09-18 20:46:16 +08:00
} else {
/** @type {RawReferencedExports} */
const references = [ ] ;
state . set ( expr , references ) ;
exports = references ;
2025-08-25 21:43:57 +08:00
}
2023-04-13 22:16:32 +08:00
}
2022-03-15 23:34:05 +08:00
if ( param . isString ( ) ) {
2024-10-31 22:43:31 +08:00
const attributes = getImportAttributes ( expr ) ;
2024-03-15 22:24:33 +08:00
2018-02-25 09:00:20 +08:00
if ( mode === "eager" ) {
2020-05-28 02:34:55 +08:00
const dep = new ImportEagerDependency (
2023-06-17 03:44:20 +08:00
/** @type {string} */ ( param . string ) ,
/** @type {Range} */ ( expr . range ) ,
2024-03-15 22:24:33 +08:00
exports ,
2024-03-15 23:11:02 +08:00
attributes
2020-05-28 02:34:55 +08:00
) ;
2017-05-05 00:37:25 +08:00
parser . state . current . addDependency ( dep ) ;
2018-02-25 09:00:20 +08:00
} else if ( mode === "weak" ) {
2020-05-28 02:34:55 +08:00
const dep = new ImportWeakDependency (
2023-06-17 03:44:20 +08:00
/** @type {string} */ ( param . string ) ,
/** @type {Range} */ ( expr . range ) ,
2024-03-15 22:24:33 +08:00
exports ,
2024-03-15 23:11:02 +08:00
attributes
2020-05-28 02:34:55 +08:00
) ;
2017-07-26 20:49:37 +08:00
parser . state . current . addDependency ( dep ) ;
2017-05-05 00:37:25 +08:00
} else {
2020-06-10 19:31:01 +08:00
const depBlock = new AsyncDependenciesBlock (
2019-06-19 19:16:05 +08:00
{
... groupOptions ,
2018-04-16 16:27:22 +08:00
name : chunkName
2019-06-19 19:16:05 +08:00
} ,
2023-06-17 03:44:20 +08:00
/** @type {DependencyLocation} */ ( expr . loc ) ,
2020-06-10 19:31:01 +08:00
param . string
2018-02-25 09:00:20 +08:00
) ;
2023-06-17 03:44:20 +08:00
const dep = new ImportDependency (
/** @type {string} */ ( param . string ) ,
/** @type {Range} */ ( expr . range ) ,
2024-03-15 22:24:33 +08:00
exports ,
2024-03-15 23:11:02 +08:00
attributes
2023-06-17 03:44:20 +08:00
) ;
dep . loc = /** @type {DependencyLocation} */ ( expr . loc ) ;
2024-07-31 11:11:11 +08:00
dep . optional = Boolean ( parser . scope . inTry ) ;
2018-10-18 05:09:21 +08:00
depBlock . addDependency ( dep ) ;
2017-05-05 00:37:25 +08:00
parser . state . current . addBlock ( depBlock ) ;
}
2025-09-18 20:46:16 +08:00
} else {
if ( mode === "weak" ) {
mode = "async-weak" ;
}
const dep = ContextDependencyHelpers . create (
ImportContextDependency ,
/** @type {Range} */ ( expr . range ) ,
param ,
expr ,
this . options ,
{
chunkName ,
groupOptions ,
include ,
exclude ,
mode ,
namespaceObject :
/** @type {BuildMeta} */
( parser . state . module . buildMeta ) . strictHarmonyModule
? "strict"
: true ,
typePrefix : "import()" ,
category : "esm" ,
referencedExports : exports ,
attributes : getImportAttributes ( expr )
} ,
parser
) ;
if ( ! dep ) return ;
dep . loc = /** @type {DependencyLocation} */ ( expr . loc ) ;
dep . optional = Boolean ( parser . scope . inTry ) ;
parser . state . current . addDependency ( dep ) ;
2017-01-12 01:58:05 +08:00
}
2025-09-18 20:46:16 +08:00
if ( fulfilledNamespaceObj ) {
walkImportThenFulfilledCallback (
parser ,
expr ,
/** @type {ArrowFunctionExpression | FunctionExpression} */
( importThen . arguments [ 0 ] ) ,
fulfilledNamespaceObj
) ;
parser . walkExpressions ( importThen . arguments . slice ( 1 ) ) ;
2025-09-25 20:22:37 +08:00
} else if ( importThen ) {
parser . walkExpressions ( importThen . arguments ) ;
2024-07-31 04:21:27 +08:00
}
2025-09-18 20:46:16 +08:00
2024-07-31 04:21:27 +08:00
return true ;
2018-01-16 04:26:47 +08:00
} ) ;
2017-01-12 01:58:05 +08:00
}
}
2018-05-29 15:29:23 +08:00
2017-01-12 01:58:05 +08:00
module . exports = ImportParserPlugin ;