UNPKG

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