NodeStuffPlugin.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const path = require("path");
  7. const ParserHelpers = require("./ParserHelpers");
  8. const ConstDependency = require("./dependencies/ConstDependency");
  9. const NullFactory = require("./NullFactory");
  10. class NodeStuffPlugin {
  11. constructor(options) {
  12. this.options = options;
  13. }
  14. apply(compiler) {
  15. const options = this.options;
  16. compiler.hooks.compilation.tap(
  17. "NodeStuffPlugin",
  18. (compilation, { normalModuleFactory }) => {
  19. compilation.dependencyFactories.set(ConstDependency, new NullFactory());
  20. compilation.dependencyTemplates.set(
  21. ConstDependency,
  22. new ConstDependency.Template()
  23. );
  24. const handler = (parser, parserOptions) => {
  25. if (parserOptions.node === false) return;
  26. let localOptions = options;
  27. if (parserOptions.node) {
  28. localOptions = Object.assign({}, localOptions, parserOptions.node);
  29. }
  30. const setConstant = (expressionName, value) => {
  31. parser.hooks.expression
  32. .for(expressionName)
  33. .tap("NodeStuffPlugin", () => {
  34. parser.state.current.addVariable(
  35. expressionName,
  36. JSON.stringify(value)
  37. );
  38. return true;
  39. });
  40. };
  41. const setModuleConstant = (expressionName, fn) => {
  42. parser.hooks.expression
  43. .for(expressionName)
  44. .tap("NodeStuffPlugin", () => {
  45. parser.state.current.addVariable(
  46. expressionName,
  47. JSON.stringify(fn(parser.state.module))
  48. );
  49. return true;
  50. });
  51. };
  52. const context = compiler.context;
  53. if (localOptions.__filename === "mock") {
  54. setConstant("__filename", "/index.js");
  55. } else if (localOptions.__filename) {
  56. setModuleConstant("__filename", module =>
  57. path.relative(context, module.resource)
  58. );
  59. }
  60. parser.hooks.evaluateIdentifier
  61. .for("__filename")
  62. .tap("NodeStuffPlugin", expr => {
  63. if (!parser.state.module) return;
  64. const resource = parser.state.module.resource;
  65. const i = resource.indexOf("?");
  66. return ParserHelpers.evaluateToString(
  67. i < 0 ? resource : resource.substr(0, i)
  68. )(expr);
  69. });
  70. if (localOptions.__dirname === "mock") {
  71. setConstant("__dirname", "/");
  72. } else if (localOptions.__dirname) {
  73. setModuleConstant("__dirname", module =>
  74. path.relative(context, module.context)
  75. );
  76. }
  77. parser.hooks.evaluateIdentifier
  78. .for("__dirname")
  79. .tap("NodeStuffPlugin", expr => {
  80. if (!parser.state.module) return;
  81. return ParserHelpers.evaluateToString(
  82. parser.state.module.context
  83. )(expr);
  84. });
  85. parser.hooks.expression
  86. .for("require.main")
  87. .tap(
  88. "NodeStuffPlugin",
  89. ParserHelpers.toConstantDependencyWithWebpackRequire(
  90. parser,
  91. "__webpack_require__.c[__webpack_require__.s]"
  92. )
  93. );
  94. parser.hooks.expression
  95. .for("require.extensions")
  96. .tap(
  97. "NodeStuffPlugin",
  98. ParserHelpers.expressionIsUnsupported(
  99. parser,
  100. "require.extensions is not supported by webpack. Use a loader instead."
  101. )
  102. );
  103. parser.hooks.expression
  104. .for("require.main.require")
  105. .tap(
  106. "NodeStuffPlugin",
  107. ParserHelpers.expressionIsUnsupported(
  108. parser,
  109. "require.main.require is not supported by webpack."
  110. )
  111. );
  112. parser.hooks.expression
  113. .for("module.parent.require")
  114. .tap(
  115. "NodeStuffPlugin",
  116. ParserHelpers.expressionIsUnsupported(
  117. parser,
  118. "module.parent.require is not supported by webpack."
  119. )
  120. );
  121. parser.hooks.expression
  122. .for("module.loaded")
  123. .tap("NodeStuffPlugin", expr => {
  124. parser.state.module.buildMeta.moduleConcatenationBailout =
  125. "module.loaded";
  126. return ParserHelpers.toConstantDependency(parser, "module.l")(
  127. expr
  128. );
  129. });
  130. parser.hooks.expression
  131. .for("module.id")
  132. .tap("NodeStuffPlugin", expr => {
  133. parser.state.module.buildMeta.moduleConcatenationBailout =
  134. "module.id";
  135. return ParserHelpers.toConstantDependency(parser, "module.i")(
  136. expr
  137. );
  138. });
  139. parser.hooks.expression
  140. .for("module.exports")
  141. .tap("NodeStuffPlugin", () => {
  142. const module = parser.state.module;
  143. const isHarmony =
  144. module.buildMeta && module.buildMeta.exportsType;
  145. if (!isHarmony) return true;
  146. });
  147. parser.hooks.evaluateIdentifier
  148. .for("module.hot")
  149. .tap(
  150. "NodeStuffPlugin",
  151. ParserHelpers.evaluateToIdentifier("module.hot", false)
  152. );
  153. parser.hooks.expression.for("module").tap("NodeStuffPlugin", () => {
  154. const module = parser.state.module;
  155. const isHarmony = module.buildMeta && module.buildMeta.exportsType;
  156. let moduleJsPath = path.join(
  157. __dirname,
  158. "..",
  159. "buildin",
  160. isHarmony ? "harmony-module.js" : "module.js"
  161. );
  162. if (module.context) {
  163. moduleJsPath = path.relative(
  164. parser.state.module.context,
  165. moduleJsPath
  166. );
  167. if (!/^[A-Z]:/i.test(moduleJsPath)) {
  168. moduleJsPath = `./${moduleJsPath.replace(/\\/g, "/")}`;
  169. }
  170. }
  171. return ParserHelpers.addParsedVariableToModule(
  172. parser,
  173. "module",
  174. `require(${JSON.stringify(moduleJsPath)})(module)`
  175. );
  176. });
  177. };
  178. normalModuleFactory.hooks.parser
  179. .for("javascript/auto")
  180. .tap("NodeStuffPlugin", handler);
  181. normalModuleFactory.hooks.parser
  182. .for("javascript/dynamic")
  183. .tap("NodeStuffPlugin", handler);
  184. }
  185. );
  186. }
  187. }
  188. module.exports = NodeStuffPlugin;