ImportPhase.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Haijie Xie @hai-x
  4. */
  5. "use strict";
  6. const memoize = require("../util/memoize");
  7. const getCommentCompilationWarning = memoize(() =>
  8. require("../CommentCompilationWarning")
  9. );
  10. /** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
  11. /** @typedef {import("../javascript/JavascriptParser").ExportAllDeclaration} ExportAllDeclaration */
  12. /** @typedef {import("../javascript/JavascriptParser").ExportNamedDeclaration} ExportNamedDeclaration */
  13. /** @typedef {import("../javascript/JavascriptParser").ImportDeclaration} ImportDeclaration */
  14. /** @typedef {import("../javascript/JavascriptParser").ImportExpression} ImportExpression */
  15. /** @typedef {typeof ImportPhase.Evaluation | typeof ImportPhase.Defer | typeof ImportPhase.Source} ImportPhaseType */
  16. const ImportPhase = Object.freeze({
  17. Evaluation: 0b00,
  18. Defer: 0b01,
  19. Source: 0b10
  20. });
  21. /**
  22. * @typedef {object} ImportPhaseUtils
  23. * @property {(phase: ImportPhaseType) => boolean} isEvaluation true if phase is evaluation
  24. * @property {(phase: ImportPhaseType) => boolean} isDefer true if phase is defer
  25. * @property {(phase: ImportPhaseType) => boolean} isSource true if phase is source
  26. */
  27. /** @type {ImportPhaseUtils} */
  28. const ImportPhaseUtils = {
  29. isEvaluation(phase) {
  30. return phase === ImportPhase.Evaluation;
  31. },
  32. isDefer(phase) {
  33. return phase === ImportPhase.Defer;
  34. },
  35. isSource(phase) {
  36. return phase === ImportPhase.Source;
  37. }
  38. };
  39. /**
  40. * @typedef {() => Record<string, EXPECTED_ANY> | null} GetCommentOptions
  41. */
  42. /**
  43. * @callback GetImportPhase
  44. * @param {JavascriptParser} parser parser
  45. * @param {ExportNamedDeclaration | ExportAllDeclaration | ImportDeclaration | ImportExpression} node node
  46. * @param {GetCommentOptions=} getCommentOptions optional function that returns the comment options object.
  47. * @returns {ImportPhaseType} import phase
  48. */
  49. /**
  50. * @param {boolean=} enableImportPhase enable import phase detection
  51. * @returns {GetImportPhase} evaluates the import phase for ast node
  52. */
  53. function createGetImportPhase(enableImportPhase) {
  54. return (parser, node, getCommentOptions) => {
  55. if (!enableImportPhase) return ImportPhase.Evaluation;
  56. // We now only support `defer import`
  57. const phaseBySyntax =
  58. "phase" in node && node.phase === "defer"
  59. ? ImportPhase.Defer
  60. : ImportPhase.Evaluation;
  61. if (!node.range) {
  62. return phaseBySyntax;
  63. }
  64. getCommentOptions =
  65. getCommentOptions ||
  66. (() => {
  67. if (!node.range) return null;
  68. const { options, errors } = parser.parseCommentOptions(node.range);
  69. if (errors) {
  70. for (const e of errors) {
  71. const { comment } = e;
  72. if (!comment.loc) continue;
  73. const CommentCompilationWarning = getCommentCompilationWarning();
  74. parser.state.module.addWarning(
  75. new CommentCompilationWarning(
  76. `Compilation error while processing magic comment(-s): /*${comment.value}*/: ${e.message}`,
  77. comment.loc
  78. )
  79. );
  80. }
  81. }
  82. return options;
  83. });
  84. const options = getCommentOptions();
  85. if (!options || !options.webpackDefer) return phaseBySyntax;
  86. const { webpackDefer } = options;
  87. if (typeof webpackDefer === "boolean") {
  88. return webpackDefer ? ImportPhase.Defer : phaseBySyntax;
  89. } else if (node.loc) {
  90. const CommentCompilationWarning = getCommentCompilationWarning();
  91. parser.state.module.addWarning(
  92. new CommentCompilationWarning(
  93. "webpackDefer magic comment expected a boolean value.",
  94. node.loc
  95. )
  96. );
  97. }
  98. return phaseBySyntax;
  99. };
  100. }
  101. module.exports = {
  102. ImportPhase,
  103. ImportPhaseUtils,
  104. createGetImportPhase
  105. };