RequireEnsureDependenciesBlockParserPlugin.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const RequireEnsureDependenciesBlock = require("./RequireEnsureDependenciesBlock");
  7. const RequireEnsureItemDependency = require("./RequireEnsureItemDependency");
  8. const getFunctionExpression = require("./getFunctionExpression");
  9. module.exports = class RequireEnsureDependenciesBlockParserPlugin {
  10. apply(parser) {
  11. parser.hooks.call
  12. .for("require.ensure")
  13. .tap("RequireEnsureDependenciesBlockParserPlugin", expr => {
  14. let chunkName = null;
  15. let chunkNameRange = null;
  16. let errorExpressionArg = null;
  17. let errorExpression = null;
  18. switch (expr.arguments.length) {
  19. case 4: {
  20. const chunkNameExpr = parser.evaluateExpression(expr.arguments[3]);
  21. if (!chunkNameExpr.isString()) return;
  22. chunkNameRange = chunkNameExpr.range;
  23. chunkName = chunkNameExpr.string;
  24. }
  25. // falls through
  26. case 3: {
  27. errorExpressionArg = expr.arguments[2];
  28. errorExpression = getFunctionExpression(errorExpressionArg);
  29. if (!errorExpression && !chunkName) {
  30. const chunkNameExpr = parser.evaluateExpression(
  31. expr.arguments[2]
  32. );
  33. if (!chunkNameExpr.isString()) return;
  34. chunkNameRange = chunkNameExpr.range;
  35. chunkName = chunkNameExpr.string;
  36. }
  37. }
  38. // falls through
  39. case 2: {
  40. const dependenciesExpr = parser.evaluateExpression(
  41. expr.arguments[0]
  42. );
  43. const dependenciesItems = dependenciesExpr.isArray()
  44. ? dependenciesExpr.items
  45. : [dependenciesExpr];
  46. const successExpressionArg = expr.arguments[1];
  47. const successExpression = getFunctionExpression(
  48. successExpressionArg
  49. );
  50. if (successExpression) {
  51. parser.walkExpressions(successExpression.expressions);
  52. }
  53. if (errorExpression) {
  54. parser.walkExpressions(errorExpression.expressions);
  55. }
  56. const dep = new RequireEnsureDependenciesBlock(
  57. expr,
  58. successExpression ? successExpression.fn : successExpressionArg,
  59. errorExpression ? errorExpression.fn : errorExpressionArg,
  60. chunkName,
  61. chunkNameRange,
  62. parser.state.module,
  63. expr.loc
  64. );
  65. const old = parser.state.current;
  66. parser.state.current = dep;
  67. try {
  68. let failed = false;
  69. parser.inScope([], () => {
  70. for (const ee of dependenciesItems) {
  71. if (ee.isString()) {
  72. const edep = new RequireEnsureItemDependency(ee.string);
  73. edep.loc = dep.loc;
  74. dep.addDependency(edep);
  75. } else {
  76. failed = true;
  77. }
  78. }
  79. });
  80. if (failed) {
  81. return;
  82. }
  83. if (successExpression) {
  84. if (successExpression.fn.body.type === "BlockStatement") {
  85. parser.walkStatement(successExpression.fn.body);
  86. } else {
  87. parser.walkExpression(successExpression.fn.body);
  88. }
  89. }
  90. old.addBlock(dep);
  91. } finally {
  92. parser.state.current = old;
  93. }
  94. if (!successExpression) {
  95. parser.walkExpression(successExpressionArg);
  96. }
  97. if (errorExpression) {
  98. if (errorExpression.fn.body.type === "BlockStatement") {
  99. parser.walkStatement(errorExpression.fn.body);
  100. } else {
  101. parser.walkExpression(errorExpression.fn.body);
  102. }
  103. } else if (errorExpressionArg) {
  104. parser.walkExpression(errorExpressionArg);
  105. }
  106. return true;
  107. }
  108. }
  109. });
  110. }
  111. };