ImportParserPlugin.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const ImportContextDependency = require("./ImportContextDependency");
  7. const ImportWeakDependency = require("./ImportWeakDependency");
  8. const ImportDependenciesBlock = require("./ImportDependenciesBlock");
  9. const ImportEagerDependency = require("./ImportEagerDependency");
  10. const ContextDependencyHelpers = require("./ContextDependencyHelpers");
  11. const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning");
  12. const CommentCompilationWarning = require("../CommentCompilationWarning");
  13. class ImportParserPlugin {
  14. constructor(options) {
  15. this.options = options;
  16. }
  17. apply(parser) {
  18. parser.hooks.importCall.tap("ImportParserPlugin", expr => {
  19. if (expr.arguments.length !== 1) {
  20. throw new Error(
  21. "Incorrect number of arguments provided to 'import(module: string) -> Promise'."
  22. );
  23. }
  24. const param = parser.evaluateExpression(expr.arguments[0]);
  25. let chunkName = null;
  26. let mode = "lazy";
  27. let include = null;
  28. let exclude = null;
  29. const groupOptions = {};
  30. const {
  31. options: importOptions,
  32. errors: commentErrors
  33. } = parser.parseCommentOptions(expr.range);
  34. if (commentErrors) {
  35. for (const e of commentErrors) {
  36. const { comment } = e;
  37. parser.state.module.warnings.push(
  38. new CommentCompilationWarning(
  39. `Compilation error while processing magic comment(-s): /*${
  40. comment.value
  41. }*/: ${e.message}`,
  42. parser.state.module,
  43. comment.loc
  44. )
  45. );
  46. }
  47. }
  48. if (importOptions) {
  49. if (importOptions.webpackIgnore !== undefined) {
  50. if (typeof importOptions.webpackIgnore !== "boolean") {
  51. parser.state.module.warnings.push(
  52. new UnsupportedFeatureWarning(
  53. parser.state.module,
  54. `\`webpackIgnore\` expected a boolean, but received: ${
  55. importOptions.webpackIgnore
  56. }.`,
  57. expr.loc
  58. )
  59. );
  60. } else {
  61. // Do not instrument `import()` if `webpackIgnore` is `true`
  62. if (importOptions.webpackIgnore) {
  63. return false;
  64. }
  65. }
  66. }
  67. if (importOptions.webpackChunkName !== undefined) {
  68. if (typeof importOptions.webpackChunkName !== "string") {
  69. parser.state.module.warnings.push(
  70. new UnsupportedFeatureWarning(
  71. parser.state.module,
  72. `\`webpackChunkName\` expected a string, but received: ${
  73. importOptions.webpackChunkName
  74. }.`,
  75. expr.loc
  76. )
  77. );
  78. } else {
  79. chunkName = importOptions.webpackChunkName;
  80. }
  81. }
  82. if (importOptions.webpackMode !== undefined) {
  83. if (typeof importOptions.webpackMode !== "string") {
  84. parser.state.module.warnings.push(
  85. new UnsupportedFeatureWarning(
  86. parser.state.module,
  87. `\`webpackMode\` expected a string, but received: ${
  88. importOptions.webpackMode
  89. }.`,
  90. expr.loc
  91. )
  92. );
  93. } else {
  94. mode = importOptions.webpackMode;
  95. }
  96. }
  97. if (importOptions.webpackPrefetch !== undefined) {
  98. if (importOptions.webpackPrefetch === true) {
  99. groupOptions.prefetchOrder = 0;
  100. } else if (typeof importOptions.webpackPrefetch === "number") {
  101. groupOptions.prefetchOrder = importOptions.webpackPrefetch;
  102. } else {
  103. parser.state.module.warnings.push(
  104. new UnsupportedFeatureWarning(
  105. parser.state.module,
  106. `\`webpackPrefetch\` expected true or a number, but received: ${
  107. importOptions.webpackPrefetch
  108. }.`,
  109. expr.loc
  110. )
  111. );
  112. }
  113. }
  114. if (importOptions.webpackPreload !== undefined) {
  115. if (importOptions.webpackPreload === true) {
  116. groupOptions.preloadOrder = 0;
  117. } else if (typeof importOptions.webpackPreload === "number") {
  118. groupOptions.preloadOrder = importOptions.webpackPreload;
  119. } else {
  120. parser.state.module.warnings.push(
  121. new UnsupportedFeatureWarning(
  122. parser.state.module,
  123. `\`webpackPreload\` expected true or a number, but received: ${
  124. importOptions.webpackPreload
  125. }.`,
  126. expr.loc
  127. )
  128. );
  129. }
  130. }
  131. if (importOptions.webpackInclude !== undefined) {
  132. if (
  133. !importOptions.webpackInclude ||
  134. importOptions.webpackInclude.constructor.name !== "RegExp"
  135. ) {
  136. parser.state.module.warnings.push(
  137. new UnsupportedFeatureWarning(
  138. parser.state.module,
  139. `\`webpackInclude\` expected a regular expression, but received: ${
  140. importOptions.webpackInclude
  141. }.`,
  142. expr.loc
  143. )
  144. );
  145. } else {
  146. include = new RegExp(importOptions.webpackInclude);
  147. }
  148. }
  149. if (importOptions.webpackExclude !== undefined) {
  150. if (
  151. !importOptions.webpackExclude ||
  152. importOptions.webpackExclude.constructor.name !== "RegExp"
  153. ) {
  154. parser.state.module.warnings.push(
  155. new UnsupportedFeatureWarning(
  156. parser.state.module,
  157. `\`webpackExclude\` expected a regular expression, but received: ${
  158. importOptions.webpackExclude
  159. }.`,
  160. expr.loc
  161. )
  162. );
  163. } else {
  164. exclude = new RegExp(importOptions.webpackExclude);
  165. }
  166. }
  167. }
  168. if (param.isString()) {
  169. if (mode !== "lazy" && mode !== "eager" && mode !== "weak") {
  170. parser.state.module.warnings.push(
  171. new UnsupportedFeatureWarning(
  172. parser.state.module,
  173. `\`webpackMode\` expected 'lazy', 'eager' or 'weak', but received: ${mode}.`,
  174. expr.loc
  175. )
  176. );
  177. }
  178. if (mode === "eager") {
  179. const dep = new ImportEagerDependency(
  180. param.string,
  181. parser.state.module,
  182. expr.range
  183. );
  184. parser.state.current.addDependency(dep);
  185. } else if (mode === "weak") {
  186. const dep = new ImportWeakDependency(
  187. param.string,
  188. parser.state.module,
  189. expr.range
  190. );
  191. parser.state.current.addDependency(dep);
  192. } else {
  193. const depBlock = new ImportDependenciesBlock(
  194. param.string,
  195. expr.range,
  196. Object.assign(groupOptions, {
  197. name: chunkName
  198. }),
  199. parser.state.module,
  200. expr.loc,
  201. parser.state.module
  202. );
  203. parser.state.current.addBlock(depBlock);
  204. }
  205. return true;
  206. } else {
  207. if (
  208. mode !== "lazy" &&
  209. mode !== "lazy-once" &&
  210. mode !== "eager" &&
  211. mode !== "weak"
  212. ) {
  213. parser.state.module.warnings.push(
  214. new UnsupportedFeatureWarning(
  215. parser.state.module,
  216. `\`webpackMode\` expected 'lazy', 'lazy-once', 'eager' or 'weak', but received: ${mode}.`,
  217. expr.loc
  218. )
  219. );
  220. mode = "lazy";
  221. }
  222. if (mode === "weak") {
  223. mode = "async-weak";
  224. }
  225. const dep = ContextDependencyHelpers.create(
  226. ImportContextDependency,
  227. expr.range,
  228. param,
  229. expr,
  230. this.options,
  231. {
  232. chunkName,
  233. groupOptions,
  234. include,
  235. exclude,
  236. mode,
  237. namespaceObject: parser.state.module.buildMeta.strictHarmonyModule
  238. ? "strict"
  239. : true
  240. },
  241. parser
  242. );
  243. if (!dep) return;
  244. dep.loc = expr.loc;
  245. dep.optional = !!parser.scope.inTry;
  246. parser.state.current.addDependency(dep);
  247. return true;
  248. }
  249. });
  250. }
  251. }
  252. module.exports = ImportParserPlugin;