ImportParserPlugin.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const AsyncDependenciesBlock = require("../AsyncDependenciesBlock");
  7. const CommentCompilationWarning = require("../CommentCompilationWarning");
  8. const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning");
  9. const {
  10. VariableInfo,
  11. getImportAttributes
  12. } = require("../javascript/JavascriptParser");
  13. const traverseDestructuringAssignmentProperties = require("../util/traverseDestructuringAssignmentProperties");
  14. const ContextDependencyHelpers = require("./ContextDependencyHelpers");
  15. const { getNonOptionalPart } = require("./HarmonyImportDependency");
  16. const ImportContextDependency = require("./ImportContextDependency");
  17. const ImportDependency = require("./ImportDependency");
  18. const ImportEagerDependency = require("./ImportEagerDependency");
  19. const { createGetImportPhase } = require("./ImportPhase");
  20. const ImportWeakDependency = require("./ImportWeakDependency");
  21. /** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
  22. /** @typedef {import("../ChunkGroup").RawChunkGroupOptions} RawChunkGroupOptions */
  23. /** @typedef {import("../ContextModule").ContextMode} ContextMode */
  24. /** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */
  25. /** @typedef {import("../Dependency").RawReferencedExports} RawReferencedExports */
  26. /** @typedef {import("../Module").BuildMeta} BuildMeta */
  27. /** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
  28. /** @typedef {import("../javascript/JavascriptParser").ImportExpression} ImportExpression */
  29. /** @typedef {import("../javascript/JavascriptParser").Range} Range */
  30. /** @typedef {import("../javascript/JavascriptParser").JavascriptParserState} JavascriptParserState */
  31. /** @typedef {import("../javascript/JavascriptParser").Members} Members */
  32. /** @typedef {import("../javascript/JavascriptParser").MembersOptionals} MembersOptionals */
  33. /** @typedef {import("../javascript/JavascriptParser").ArrowFunctionExpression} ArrowFunctionExpression */
  34. /** @typedef {import("../javascript/JavascriptParser").FunctionExpression} FunctionExpression */
  35. /** @typedef {import("../javascript/JavascriptParser").Identifier} Identifier */
  36. /** @typedef {import("../javascript/JavascriptParser").ObjectPattern} ObjectPattern */
  37. /** @typedef {import("../javascript/JavascriptParser").CallExpression} CallExpression */
  38. /** @typedef {{ references: RawReferencedExports, expression: ImportExpression }} ImportSettings */
  39. /** @typedef {WeakMap<ImportExpression, RawReferencedExports>} State */
  40. /** @type {WeakMap<JavascriptParserState, State>} */
  41. const parserStateMap = new WeakMap();
  42. const dynamicImportTag = Symbol("import()");
  43. /**
  44. * Returns import parser plugin state.
  45. * @param {JavascriptParser} parser javascript parser
  46. * @returns {State} import parser plugin state
  47. */
  48. function getState(parser) {
  49. if (!parserStateMap.has(parser.state)) {
  50. parserStateMap.set(parser.state, new WeakMap());
  51. }
  52. return /** @type {State} */ (parserStateMap.get(parser.state));
  53. }
  54. /**
  55. * Tag dynamic import referenced.
  56. * @param {JavascriptParser} parser javascript parser
  57. * @param {ImportExpression} importCall import expression
  58. * @param {string} variableName variable name
  59. */
  60. function tagDynamicImportReferenced(parser, importCall, variableName) {
  61. const state = getState(parser);
  62. /** @type {RawReferencedExports} */
  63. const references = state.get(importCall) || [];
  64. state.set(importCall, references);
  65. parser.tagVariable(
  66. variableName,
  67. dynamicImportTag,
  68. /** @type {ImportSettings} */ ({
  69. references,
  70. expression: importCall
  71. })
  72. );
  73. }
  74. /**
  75. * Gets fulfilled callback namespace obj.
  76. * @param {CallExpression} importThen import().then() call
  77. * @returns {Identifier | ObjectPattern | undefined} the dynamic imported namespace obj
  78. */
  79. function getFulfilledCallbackNamespaceObj(importThen) {
  80. const fulfilledCallback = importThen.arguments[0];
  81. if (
  82. fulfilledCallback &&
  83. (fulfilledCallback.type === "ArrowFunctionExpression" ||
  84. fulfilledCallback.type === "FunctionExpression") &&
  85. fulfilledCallback.params[0] &&
  86. (fulfilledCallback.params[0].type === "Identifier" ||
  87. fulfilledCallback.params[0].type === "ObjectPattern")
  88. ) {
  89. return fulfilledCallback.params[0];
  90. }
  91. }
  92. /**
  93. * Walk import then fulfilled callback.
  94. * @param {JavascriptParser} parser javascript parser
  95. * @param {ImportExpression} importCall import expression
  96. * @param {ArrowFunctionExpression | FunctionExpression} fulfilledCallback the fulfilled callback
  97. * @param {Identifier | ObjectPattern} namespaceObjArg the argument of namespace object=
  98. */
  99. function walkImportThenFulfilledCallback(
  100. parser,
  101. importCall,
  102. fulfilledCallback,
  103. namespaceObjArg
  104. ) {
  105. const arrow = fulfilledCallback.type === "ArrowFunctionExpression";
  106. const wasTopLevel = parser.scope.topLevelScope;
  107. parser.scope.topLevelScope = arrow ? (wasTopLevel ? "arrow" : false) : false;
  108. const scopeParams = [...fulfilledCallback.params];
  109. // Add function name in scope for recursive calls
  110. if (!arrow && fulfilledCallback.id) {
  111. scopeParams.push(fulfilledCallback.id);
  112. }
  113. parser.inFunctionScope(!arrow, scopeParams, () => {
  114. if (namespaceObjArg.type === "Identifier") {
  115. tagDynamicImportReferenced(parser, importCall, namespaceObjArg.name);
  116. } else {
  117. parser.enterDestructuringAssignment(namespaceObjArg, importCall);
  118. const referencedPropertiesInDestructuring =
  119. parser.destructuringAssignmentPropertiesFor(importCall);
  120. if (referencedPropertiesInDestructuring) {
  121. const state = getState(parser);
  122. const references = /** @type {RawReferencedExports} */ (
  123. state.get(importCall)
  124. );
  125. /** @type {RawReferencedExports} */
  126. const refsInDestructuring = [];
  127. traverseDestructuringAssignmentProperties(
  128. referencedPropertiesInDestructuring,
  129. (stack) => refsInDestructuring.push(stack.map((p) => p.id))
  130. );
  131. for (const ids of refsInDestructuring) {
  132. references.push(ids);
  133. }
  134. }
  135. }
  136. for (const param of fulfilledCallback.params) {
  137. parser.walkPattern(param);
  138. }
  139. if (fulfilledCallback.body.type === "BlockStatement") {
  140. parser.detectMode(fulfilledCallback.body.body);
  141. const prev = parser.prevStatement;
  142. parser.preWalkStatement(fulfilledCallback.body);
  143. parser.prevStatement = prev;
  144. parser.walkStatement(fulfilledCallback.body);
  145. } else {
  146. parser.walkExpression(fulfilledCallback.body);
  147. }
  148. });
  149. parser.scope.topLevelScope = wasTopLevel;
  150. }
  151. /**
  152. * Exports from enumerable.
  153. * @template T
  154. * @param {Iterable<T>} enumerable enumerable
  155. * @returns {T[][]} array of array
  156. */
  157. const exportsFromEnumerable = (enumerable) =>
  158. Array.from(enumerable, (e) => [e]);
  159. const PLUGIN_NAME = "ImportParserPlugin";
  160. class ImportParserPlugin {
  161. /**
  162. * Creates an instance of ImportParserPlugin.
  163. * @param {JavascriptParserOptions} options options
  164. */
  165. constructor(options) {
  166. this.options = options;
  167. }
  168. /**
  169. * Applies the plugin by registering its hooks on the compiler.
  170. * @param {JavascriptParser} parser the parser
  171. * @returns {void}
  172. */
  173. apply(parser) {
  174. parser.hooks.collectDestructuringAssignmentProperties.tap(
  175. PLUGIN_NAME,
  176. (expr) => {
  177. if (expr.type === "ImportExpression") return true;
  178. const nameInfo = parser.getNameForExpression(expr);
  179. if (
  180. nameInfo &&
  181. nameInfo.rootInfo instanceof VariableInfo &&
  182. nameInfo.rootInfo.name &&
  183. parser.getTagData(nameInfo.rootInfo.name, dynamicImportTag)
  184. ) {
  185. return true;
  186. }
  187. }
  188. );
  189. parser.hooks.preDeclarator.tap(PLUGIN_NAME, (decl) => {
  190. if (
  191. decl.init &&
  192. decl.init.type === "AwaitExpression" &&
  193. decl.init.argument.type === "ImportExpression" &&
  194. decl.id.type === "Identifier"
  195. ) {
  196. parser.defineVariable(decl.id.name);
  197. tagDynamicImportReferenced(parser, decl.init.argument, decl.id.name);
  198. }
  199. });
  200. parser.hooks.expression.for(dynamicImportTag).tap(PLUGIN_NAME, (expr) => {
  201. const settings = /** @type {ImportSettings} */ (parser.currentTagData);
  202. const referencedPropertiesInDestructuring =
  203. parser.destructuringAssignmentPropertiesFor(expr);
  204. if (referencedPropertiesInDestructuring) {
  205. /** @type {RawReferencedExports} */
  206. const refsInDestructuring = [];
  207. traverseDestructuringAssignmentProperties(
  208. referencedPropertiesInDestructuring,
  209. (stack) => refsInDestructuring.push(stack.map((p) => p.id))
  210. );
  211. for (const ids of refsInDestructuring) {
  212. settings.references.push(ids);
  213. }
  214. } else {
  215. settings.references.push([]);
  216. }
  217. return true;
  218. });
  219. parser.hooks.expressionMemberChain
  220. .for(dynamicImportTag)
  221. .tap(PLUGIN_NAME, (_expression, members, membersOptionals) => {
  222. const settings = /** @type {ImportSettings} */ (parser.currentTagData);
  223. const ids = getNonOptionalPart(members, membersOptionals);
  224. settings.references.push(ids);
  225. return true;
  226. });
  227. parser.hooks.callMemberChain
  228. .for(dynamicImportTag)
  229. .tap(PLUGIN_NAME, (expression, members, membersOptionals) => {
  230. const { arguments: args } = expression;
  231. const settings = /** @type {ImportSettings} */ (parser.currentTagData);
  232. let ids = getNonOptionalPart(members, membersOptionals);
  233. const directImport = members.length === 0;
  234. if (
  235. !directImport &&
  236. (this.options.strictThisContextOnImports || ids.length > 1)
  237. ) {
  238. ids = ids.slice(0, -1);
  239. }
  240. settings.references.push(ids);
  241. if (args) parser.walkExpressions(args);
  242. return true;
  243. });
  244. parser.hooks.importCall.tap(PLUGIN_NAME, (expr, importThen) => {
  245. const param = parser.evaluateExpression(expr.source);
  246. /** @type {null | string} */
  247. let chunkName = null;
  248. let mode = /** @type {ContextMode} */ (this.options.dynamicImportMode);
  249. /** @type {null | RegExp} */
  250. let include = null;
  251. /** @type {null | RegExp} */
  252. let exclude = null;
  253. /** @type {null | RawReferencedExports} */
  254. let exports = null;
  255. /** @type {RawChunkGroupOptions} */
  256. const groupOptions = {};
  257. const {
  258. dynamicImportPreload,
  259. dynamicImportPrefetch,
  260. dynamicImportFetchPriority
  261. } = this.options;
  262. if (
  263. dynamicImportPreload !== undefined &&
  264. dynamicImportPreload !== false
  265. ) {
  266. groupOptions.preloadOrder =
  267. dynamicImportPreload === true ? 0 : dynamicImportPreload;
  268. }
  269. if (
  270. dynamicImportPrefetch !== undefined &&
  271. dynamicImportPrefetch !== false
  272. ) {
  273. groupOptions.prefetchOrder =
  274. dynamicImportPrefetch === true ? 0 : dynamicImportPrefetch;
  275. }
  276. if (
  277. dynamicImportFetchPriority !== undefined &&
  278. dynamicImportFetchPriority !== false
  279. ) {
  280. groupOptions.fetchPriority = dynamicImportFetchPriority;
  281. }
  282. const { options: importOptions, errors: commentErrors } =
  283. parser.parseCommentOptions(/** @type {Range} */ (expr.range));
  284. if (commentErrors) {
  285. for (const e of commentErrors) {
  286. const { comment } = e;
  287. parser.state.module.addWarning(
  288. new CommentCompilationWarning(
  289. `Compilation error while processing magic comment(-s): /*${comment.value}*/: ${e.message}`,
  290. /** @type {DependencyLocation} */ (comment.loc)
  291. )
  292. );
  293. }
  294. }
  295. const phase = createGetImportPhase(
  296. this.options.deferImport,
  297. this.options.sourceImport
  298. )(parser, expr, () => importOptions);
  299. if (importOptions) {
  300. if (importOptions.webpackIgnore !== undefined) {
  301. if (typeof importOptions.webpackIgnore !== "boolean") {
  302. parser.state.module.addWarning(
  303. new UnsupportedFeatureWarning(
  304. `\`webpackIgnore\` expected a boolean, but received: ${importOptions.webpackIgnore}.`,
  305. /** @type {DependencyLocation} */ (expr.loc)
  306. )
  307. );
  308. } else if (importOptions.webpackIgnore) {
  309. // Do not instrument `import()` if `webpackIgnore` is `true`
  310. return false;
  311. }
  312. }
  313. if (importOptions.webpackChunkName !== undefined) {
  314. if (typeof importOptions.webpackChunkName !== "string") {
  315. parser.state.module.addWarning(
  316. new UnsupportedFeatureWarning(
  317. `\`webpackChunkName\` expected a string, but received: ${importOptions.webpackChunkName}.`,
  318. /** @type {DependencyLocation} */ (expr.loc)
  319. )
  320. );
  321. } else {
  322. chunkName = importOptions.webpackChunkName;
  323. }
  324. }
  325. if (importOptions.webpackMode !== undefined) {
  326. if (typeof importOptions.webpackMode !== "string") {
  327. parser.state.module.addWarning(
  328. new UnsupportedFeatureWarning(
  329. `\`webpackMode\` expected a string, but received: ${importOptions.webpackMode}.`,
  330. /** @type {DependencyLocation} */ (expr.loc)
  331. )
  332. );
  333. } else {
  334. mode = /** @type {ContextMode} */ (importOptions.webpackMode);
  335. }
  336. }
  337. if (importOptions.webpackPrefetch !== undefined) {
  338. if (importOptions.webpackPrefetch === true) {
  339. groupOptions.prefetchOrder = 0;
  340. } else if (typeof importOptions.webpackPrefetch === "number") {
  341. groupOptions.prefetchOrder = importOptions.webpackPrefetch;
  342. } else {
  343. parser.state.module.addWarning(
  344. new UnsupportedFeatureWarning(
  345. `\`webpackPrefetch\` expected true or a number, but received: ${importOptions.webpackPrefetch}.`,
  346. /** @type {DependencyLocation} */ (expr.loc)
  347. )
  348. );
  349. }
  350. }
  351. if (importOptions.webpackPreload !== undefined) {
  352. if (importOptions.webpackPreload === true) {
  353. groupOptions.preloadOrder = 0;
  354. } else if (typeof importOptions.webpackPreload === "number") {
  355. groupOptions.preloadOrder = importOptions.webpackPreload;
  356. } else {
  357. parser.state.module.addWarning(
  358. new UnsupportedFeatureWarning(
  359. `\`webpackPreload\` expected true or a number, but received: ${importOptions.webpackPreload}.`,
  360. /** @type {DependencyLocation} */ (expr.loc)
  361. )
  362. );
  363. }
  364. }
  365. if (importOptions.webpackFetchPriority !== undefined) {
  366. if (
  367. typeof importOptions.webpackFetchPriority === "string" &&
  368. ["high", "low", "auto"].includes(importOptions.webpackFetchPriority)
  369. ) {
  370. groupOptions.fetchPriority =
  371. /** @type {"low" | "high" | "auto"} */
  372. (importOptions.webpackFetchPriority);
  373. } else {
  374. parser.state.module.addWarning(
  375. new UnsupportedFeatureWarning(
  376. `\`webpackFetchPriority\` expected true or "low", "high" or "auto", but received: ${importOptions.webpackFetchPriority}.`,
  377. /** @type {DependencyLocation} */ (expr.loc)
  378. )
  379. );
  380. }
  381. }
  382. if (importOptions.webpackInclude !== undefined) {
  383. if (
  384. !importOptions.webpackInclude ||
  385. !(importOptions.webpackInclude instanceof RegExp)
  386. ) {
  387. parser.state.module.addWarning(
  388. new UnsupportedFeatureWarning(
  389. `\`webpackInclude\` expected a regular expression, but received: ${importOptions.webpackInclude}.`,
  390. /** @type {DependencyLocation} */ (expr.loc)
  391. )
  392. );
  393. } else {
  394. include = importOptions.webpackInclude;
  395. }
  396. }
  397. if (importOptions.webpackExclude !== undefined) {
  398. if (
  399. !importOptions.webpackExclude ||
  400. !(importOptions.webpackExclude instanceof RegExp)
  401. ) {
  402. parser.state.module.addWarning(
  403. new UnsupportedFeatureWarning(
  404. `\`webpackExclude\` expected a regular expression, but received: ${importOptions.webpackExclude}.`,
  405. /** @type {DependencyLocation} */ (expr.loc)
  406. )
  407. );
  408. } else {
  409. exclude = importOptions.webpackExclude;
  410. }
  411. }
  412. if (importOptions.webpackExports !== undefined) {
  413. if (
  414. !(
  415. typeof importOptions.webpackExports === "string" ||
  416. (Array.isArray(importOptions.webpackExports) &&
  417. importOptions.webpackExports.every(
  418. (item) => typeof item === "string"
  419. ))
  420. )
  421. ) {
  422. parser.state.module.addWarning(
  423. new UnsupportedFeatureWarning(
  424. `\`webpackExports\` expected a string or an array of strings, but received: ${importOptions.webpackExports}.`,
  425. /** @type {DependencyLocation} */ (expr.loc)
  426. )
  427. );
  428. } else if (typeof importOptions.webpackExports === "string") {
  429. exports = [[importOptions.webpackExports]];
  430. } else {
  431. exports = exportsFromEnumerable(importOptions.webpackExports);
  432. }
  433. }
  434. }
  435. if (
  436. mode !== "lazy" &&
  437. mode !== "lazy-once" &&
  438. mode !== "eager" &&
  439. mode !== "weak"
  440. ) {
  441. parser.state.module.addWarning(
  442. new UnsupportedFeatureWarning(
  443. `\`webpackMode\` expected 'lazy', 'lazy-once', 'eager' or 'weak', but received: ${mode}.`,
  444. /** @type {DependencyLocation} */ (expr.loc)
  445. )
  446. );
  447. mode = "lazy";
  448. }
  449. const referencedPropertiesInDestructuring =
  450. parser.destructuringAssignmentPropertiesFor(expr);
  451. const state = getState(parser);
  452. const referencedPropertiesInMember = state.get(expr);
  453. const fulfilledNamespaceObj =
  454. importThen && getFulfilledCallbackNamespaceObj(importThen);
  455. if (
  456. referencedPropertiesInDestructuring ||
  457. referencedPropertiesInMember ||
  458. fulfilledNamespaceObj
  459. ) {
  460. if (exports) {
  461. parser.state.module.addWarning(
  462. new UnsupportedFeatureWarning(
  463. "You don't need `webpackExports` if the usage of dynamic import is statically analyse-able. You can safely remove the `webpackExports` magic comment.",
  464. /** @type {DependencyLocation} */ (expr.loc)
  465. )
  466. );
  467. }
  468. if (referencedPropertiesInDestructuring) {
  469. /** @type {RawReferencedExports} */
  470. const refsInDestructuring = [];
  471. traverseDestructuringAssignmentProperties(
  472. referencedPropertiesInDestructuring,
  473. (stack) => refsInDestructuring.push(stack.map((p) => p.id))
  474. );
  475. exports = refsInDestructuring;
  476. } else if (referencedPropertiesInMember) {
  477. exports = referencedPropertiesInMember;
  478. } else {
  479. /** @type {RawReferencedExports} */
  480. const references = [];
  481. state.set(expr, references);
  482. exports = references;
  483. }
  484. }
  485. if (param.isString()) {
  486. const attributes = getImportAttributes(expr);
  487. if (mode === "eager") {
  488. const dep = new ImportEagerDependency(
  489. /** @type {string} */ (param.string),
  490. /** @type {Range} */ (expr.range),
  491. exports,
  492. phase,
  493. attributes
  494. );
  495. parser.state.current.addDependency(dep);
  496. } else if (mode === "weak") {
  497. const dep = new ImportWeakDependency(
  498. /** @type {string} */ (param.string),
  499. /** @type {Range} */ (expr.range),
  500. exports,
  501. phase,
  502. attributes
  503. );
  504. parser.state.current.addDependency(dep);
  505. } else {
  506. const depBlock = new AsyncDependenciesBlock(
  507. {
  508. ...groupOptions,
  509. name: chunkName
  510. },
  511. /** @type {DependencyLocation} */ (expr.loc),
  512. param.string
  513. );
  514. const dep = new ImportDependency(
  515. /** @type {string} */ (param.string),
  516. /** @type {Range} */ (expr.range),
  517. exports,
  518. phase,
  519. attributes
  520. );
  521. dep.loc = /** @type {DependencyLocation} */ (expr.loc);
  522. dep.optional = Boolean(parser.scope.inTry);
  523. depBlock.addDependency(dep);
  524. parser.state.current.addBlock(depBlock);
  525. }
  526. } else {
  527. if (mode === "weak") {
  528. mode = "async-weak";
  529. }
  530. const dep = ContextDependencyHelpers.create(
  531. ImportContextDependency,
  532. /** @type {Range} */ (expr.range),
  533. param,
  534. expr,
  535. this.options,
  536. {
  537. chunkName,
  538. groupOptions,
  539. include,
  540. exclude,
  541. mode,
  542. namespaceObject:
  543. /** @type {BuildMeta} */
  544. (parser.state.module.buildMeta).strictHarmonyModule
  545. ? "strict"
  546. : true,
  547. typePrefix: "import()",
  548. category: "esm",
  549. referencedExports: exports,
  550. attributes: getImportAttributes(expr),
  551. phase
  552. },
  553. parser
  554. );
  555. if (!dep) return;
  556. dep.loc = /** @type {DependencyLocation} */ (expr.loc);
  557. dep.optional = Boolean(parser.scope.inTry);
  558. parser.state.current.addDependency(dep);
  559. }
  560. if (fulfilledNamespaceObj) {
  561. walkImportThenFulfilledCallback(
  562. parser,
  563. expr,
  564. /** @type {ArrowFunctionExpression | FunctionExpression} */
  565. (importThen.arguments[0]),
  566. fulfilledNamespaceObj
  567. );
  568. parser.walkExpressions(importThen.arguments.slice(1));
  569. } else if (importThen) {
  570. parser.walkExpressions(importThen.arguments);
  571. }
  572. return true;
  573. });
  574. }
  575. }
  576. module.exports = ImportParserPlugin;