HarmonyImportDependencyParserPlugin.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const HarmonyImportDependency = require("./HarmonyImportDependency");
  7. const HarmonyImportSpecifierDependency = require("./HarmonyImportSpecifierDependency");
  8. const HarmonyAcceptImportDependency = require("./HarmonyAcceptImportDependency");
  9. const HarmonyAcceptDependency = require("./HarmonyAcceptDependency");
  10. const HarmonyModulesHelpers = require("./HarmonyModulesHelpers");
  11. module.exports = class HarmonyImportDependencyParserPlugin {
  12. constructor(moduleOptions) {
  13. this.strictExportPresence = moduleOptions.strictExportPresence;
  14. this.strictThisContextOnImports = moduleOptions.strictThisContextOnImports;
  15. }
  16. apply(parser) {
  17. parser.plugin("import", (statement, source) => {
  18. const dep = new HarmonyImportDependency(source, HarmonyModulesHelpers.getNewModuleVar(parser.state, source), statement.range);
  19. dep.loc = statement.loc;
  20. parser.state.current.addDependency(dep);
  21. parser.state.lastHarmonyImport = dep;
  22. return true;
  23. });
  24. parser.plugin("import specifier", (statement, source, id, name) => {
  25. parser.scope.definitions.length--;
  26. parser.scope.renames[`$${name}`] = "imported var";
  27. if(!parser.state.harmonySpecifier) parser.state.harmonySpecifier = {};
  28. parser.state.harmonySpecifier[`$${name}`] = [parser.state.lastHarmonyImport, HarmonyModulesHelpers.getModuleVar(parser.state, source), id];
  29. return true;
  30. });
  31. parser.plugin("expression imported var", (expr) => {
  32. const name = expr.name;
  33. const settings = parser.state.harmonySpecifier[`$${name}`];
  34. const dep = new HarmonyImportSpecifierDependency(settings[0], settings[1], settings[2], name, expr.range, this.strictExportPresence);
  35. dep.shorthand = parser.scope.inShorthand;
  36. dep.directImport = true;
  37. dep.loc = expr.loc;
  38. parser.state.current.addDependency(dep);
  39. return true;
  40. });
  41. parser.plugin("expression imported var.*", (expr) => {
  42. const name = expr.object.name;
  43. const settings = parser.state.harmonySpecifier[`$${name}`];
  44. if(settings[2] !== null)
  45. return false;
  46. const dep = new HarmonyImportSpecifierDependency(settings[0], settings[1], expr.property.name || expr.property.value, name, expr.range, this.strictExportPresence);
  47. dep.shorthand = parser.scope.inShorthand;
  48. dep.directImport = false;
  49. dep.loc = expr.loc;
  50. parser.state.current.addDependency(dep);
  51. return true;
  52. });
  53. if(this.strictThisContextOnImports) {
  54. // only in case when we strictly follow the spec we need a special case here
  55. parser.plugin("call imported var.*", (expr) => {
  56. const name = expr.callee.object.name;
  57. const settings = parser.state.harmonySpecifier[`$${name}`];
  58. if(settings[2] !== null)
  59. return false;
  60. const dep = new HarmonyImportSpecifierDependency(settings[0], settings[1], expr.callee.property.name || expr.callee.property.value, name, expr.callee.range, this.strictExportPresence);
  61. dep.shorthand = parser.scope.inShorthand;
  62. dep.directImport = false;
  63. dep.namespaceObjectAsContext = true;
  64. dep.loc = expr.callee.loc;
  65. parser.state.current.addDependency(dep);
  66. if(expr.arguments)
  67. parser.walkExpressions(expr.arguments);
  68. return true;
  69. });
  70. }
  71. parser.plugin("call imported var", (expr) => {
  72. const args = expr.arguments;
  73. const fullExpr = expr;
  74. expr = expr.callee;
  75. const name = expr.name;
  76. const settings = parser.state.harmonySpecifier[`$${name}`];
  77. const dep = new HarmonyImportSpecifierDependency(settings[0], settings[1], settings[2], name, expr.range, this.strictExportPresence);
  78. dep.directImport = true;
  79. dep.callArgs = args;
  80. dep.call = fullExpr;
  81. dep.loc = expr.loc;
  82. parser.state.current.addDependency(dep);
  83. if(args)
  84. parser.walkExpressions(args);
  85. return true;
  86. });
  87. parser.plugin("hot accept callback", (expr, requests) => {
  88. const dependencies = requests
  89. .filter(request => HarmonyModulesHelpers.checkModuleVar(parser.state, request))
  90. .map(request => {
  91. const dep = new HarmonyAcceptImportDependency(request, HarmonyModulesHelpers.getModuleVar(parser.state, request), expr.range);
  92. dep.loc = expr.loc;
  93. parser.state.current.addDependency(dep);
  94. return dep;
  95. });
  96. if(dependencies.length > 0) {
  97. const dep = new HarmonyAcceptDependency(expr.range, dependencies, true);
  98. dep.loc = expr.loc;
  99. parser.state.current.addDependency(dep);
  100. }
  101. });
  102. parser.plugin("hot accept without callback", (expr, requests) => {
  103. const dependencies = requests
  104. .filter(request => HarmonyModulesHelpers.checkModuleVar(parser.state, request))
  105. .map(request => {
  106. const dep = new HarmonyAcceptImportDependency(request, HarmonyModulesHelpers.getModuleVar(parser.state, request), expr.range);
  107. dep.loc = expr.loc;
  108. parser.state.current.addDependency(dep);
  109. return dep;
  110. });
  111. if(dependencies.length > 0) {
  112. const dep = new HarmonyAcceptDependency(expr.range, dependencies, false);
  113. dep.loc = expr.loc;
  114. parser.state.current.addDependency(dep);
  115. }
  116. });
  117. }
  118. };