You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

248 lines
7.0 KiB

4 years ago
  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): /*${comment.value}*/: ${e.message}`,
  40. parser.state.module,
  41. comment.loc
  42. )
  43. );
  44. }
  45. }
  46. if (importOptions) {
  47. if (importOptions.webpackIgnore !== undefined) {
  48. if (typeof importOptions.webpackIgnore !== "boolean") {
  49. parser.state.module.warnings.push(
  50. new UnsupportedFeatureWarning(
  51. parser.state.module,
  52. `\`webpackIgnore\` expected a boolean, but received: ${importOptions.webpackIgnore}.`,
  53. expr.loc
  54. )
  55. );
  56. } else {
  57. // Do not instrument `import()` if `webpackIgnore` is `true`
  58. if (importOptions.webpackIgnore) {
  59. return false;
  60. }
  61. }
  62. }
  63. if (importOptions.webpackChunkName !== undefined) {
  64. if (typeof importOptions.webpackChunkName !== "string") {
  65. parser.state.module.warnings.push(
  66. new UnsupportedFeatureWarning(
  67. parser.state.module,
  68. `\`webpackChunkName\` expected a string, but received: ${importOptions.webpackChunkName}.`,
  69. expr.loc
  70. )
  71. );
  72. } else {
  73. chunkName = importOptions.webpackChunkName;
  74. }
  75. }
  76. if (importOptions.webpackMode !== undefined) {
  77. if (typeof importOptions.webpackMode !== "string") {
  78. parser.state.module.warnings.push(
  79. new UnsupportedFeatureWarning(
  80. parser.state.module,
  81. `\`webpackMode\` expected a string, but received: ${importOptions.webpackMode}.`,
  82. expr.loc
  83. )
  84. );
  85. } else {
  86. mode = importOptions.webpackMode;
  87. }
  88. }
  89. if (importOptions.webpackPrefetch !== undefined) {
  90. if (importOptions.webpackPrefetch === true) {
  91. groupOptions.prefetchOrder = 0;
  92. } else if (typeof importOptions.webpackPrefetch === "number") {
  93. groupOptions.prefetchOrder = importOptions.webpackPrefetch;
  94. } else {
  95. parser.state.module.warnings.push(
  96. new UnsupportedFeatureWarning(
  97. parser.state.module,
  98. `\`webpackPrefetch\` expected true or a number, but received: ${importOptions.webpackPrefetch}.`,
  99. expr.loc
  100. )
  101. );
  102. }
  103. }
  104. if (importOptions.webpackPreload !== undefined) {
  105. if (importOptions.webpackPreload === true) {
  106. groupOptions.preloadOrder = 0;
  107. } else if (typeof importOptions.webpackPreload === "number") {
  108. groupOptions.preloadOrder = importOptions.webpackPreload;
  109. } else {
  110. parser.state.module.warnings.push(
  111. new UnsupportedFeatureWarning(
  112. parser.state.module,
  113. `\`webpackPreload\` expected true or a number, but received: ${importOptions.webpackPreload}.`,
  114. expr.loc
  115. )
  116. );
  117. }
  118. }
  119. if (importOptions.webpackInclude !== undefined) {
  120. if (
  121. !importOptions.webpackInclude ||
  122. importOptions.webpackInclude.constructor.name !== "RegExp"
  123. ) {
  124. parser.state.module.warnings.push(
  125. new UnsupportedFeatureWarning(
  126. parser.state.module,
  127. `\`webpackInclude\` expected a regular expression, but received: ${importOptions.webpackInclude}.`,
  128. expr.loc
  129. )
  130. );
  131. } else {
  132. include = new RegExp(importOptions.webpackInclude);
  133. }
  134. }
  135. if (importOptions.webpackExclude !== undefined) {
  136. if (
  137. !importOptions.webpackExclude ||
  138. importOptions.webpackExclude.constructor.name !== "RegExp"
  139. ) {
  140. parser.state.module.warnings.push(
  141. new UnsupportedFeatureWarning(
  142. parser.state.module,
  143. `\`webpackExclude\` expected a regular expression, but received: ${importOptions.webpackExclude}.`,
  144. expr.loc
  145. )
  146. );
  147. } else {
  148. exclude = new RegExp(importOptions.webpackExclude);
  149. }
  150. }
  151. }
  152. if (param.isString()) {
  153. if (mode !== "lazy" && mode !== "eager" && mode !== "weak") {
  154. parser.state.module.warnings.push(
  155. new UnsupportedFeatureWarning(
  156. parser.state.module,
  157. `\`webpackMode\` expected 'lazy', 'eager' or 'weak', but received: ${mode}.`,
  158. expr.loc
  159. )
  160. );
  161. }
  162. if (mode === "eager") {
  163. const dep = new ImportEagerDependency(
  164. param.string,
  165. parser.state.module,
  166. expr.range
  167. );
  168. parser.state.current.addDependency(dep);
  169. } else if (mode === "weak") {
  170. const dep = new ImportWeakDependency(
  171. param.string,
  172. parser.state.module,
  173. expr.range
  174. );
  175. parser.state.current.addDependency(dep);
  176. } else {
  177. const depBlock = new ImportDependenciesBlock(
  178. param.string,
  179. expr.range,
  180. Object.assign(groupOptions, {
  181. name: chunkName
  182. }),
  183. parser.state.module,
  184. expr.loc,
  185. parser.state.module
  186. );
  187. parser.state.current.addBlock(depBlock);
  188. }
  189. return true;
  190. } else {
  191. if (
  192. mode !== "lazy" &&
  193. mode !== "lazy-once" &&
  194. mode !== "eager" &&
  195. mode !== "weak"
  196. ) {
  197. parser.state.module.warnings.push(
  198. new UnsupportedFeatureWarning(
  199. parser.state.module,
  200. `\`webpackMode\` expected 'lazy', 'lazy-once', 'eager' or 'weak', but received: ${mode}.`,
  201. expr.loc
  202. )
  203. );
  204. mode = "lazy";
  205. }
  206. if (mode === "weak") {
  207. mode = "async-weak";
  208. }
  209. const dep = ContextDependencyHelpers.create(
  210. ImportContextDependency,
  211. expr.range,
  212. param,
  213. expr,
  214. this.options,
  215. {
  216. chunkName,
  217. groupOptions,
  218. include,
  219. exclude,
  220. mode,
  221. namespaceObject: parser.state.module.buildMeta.strictHarmonyModule
  222. ? "strict"
  223. : true
  224. },
  225. parser
  226. );
  227. if (!dep) return;
  228. dep.loc = expr.loc;
  229. dep.optional = !!parser.scope.inTry;
  230. parser.state.current.addDependency(dep);
  231. return true;
  232. }
  233. });
  234. }
  235. }
  236. module.exports = ImportParserPlugin;