UNPKG

4.02 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const RuntimeGlobals = require("./RuntimeGlobals");
9const CachedConstDependency = require("./dependencies/CachedConstDependency");
10const ConstDependency = require("./dependencies/ConstDependency");
11const {
12 evaluateToString,
13 expressionIsUnsupported
14} = require("./javascript/JavascriptParserHelpers");
15const { relative } = require("./util/fs");
16const { parseResource } = require("./util/identifier");
17
18/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
19/** @typedef {import("./Compiler")} Compiler */
20/** @typedef {import("./Dependency")} Dependency */
21/** @typedef {import("./DependencyTemplates")} DependencyTemplates */
22/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
23
24class NodeStuffPlugin {
25 constructor(options) {
26 this.options = options;
27 }
28
29 /**
30 * Apply the plugin
31 * @param {Compiler} compiler the compiler instance
32 * @returns {void}
33 */
34 apply(compiler) {
35 const options = this.options;
36 compiler.hooks.compilation.tap(
37 "NodeStuffPlugin",
38 (compilation, { normalModuleFactory }) => {
39 const handler = (parser, parserOptions) => {
40 if (parserOptions.node === false) return;
41
42 let localOptions = options;
43 if (parserOptions.node) {
44 localOptions = { ...localOptions, ...parserOptions.node };
45 }
46
47 if (localOptions.global) {
48 parser.hooks.expression
49 .for("global")
50 .tap("NodeStuffPlugin", expr => {
51 const dep = new ConstDependency(
52 RuntimeGlobals.global,
53 expr.range,
54 [RuntimeGlobals.global]
55 );
56 dep.loc = expr.loc;
57 parser.state.module.addPresentationalDependency(dep);
58 });
59 }
60
61 const setModuleConstant = (expressionName, fn) => {
62 parser.hooks.expression
63 .for(expressionName)
64 .tap("NodeStuffPlugin", expr => {
65 const dep = new CachedConstDependency(
66 JSON.stringify(fn(parser.state.module)),
67 expr.range,
68 expressionName
69 );
70 dep.loc = expr.loc;
71 parser.state.module.addPresentationalDependency(dep);
72 return true;
73 });
74 };
75
76 const setConstant = (expressionName, value) =>
77 setModuleConstant(expressionName, () => value);
78
79 const context = compiler.context;
80 if (localOptions.__filename) {
81 if (localOptions.__filename === "mock") {
82 setConstant("__filename", "/index.js");
83 } else if (localOptions.__filename === true) {
84 setModuleConstant("__filename", module =>
85 relative(compiler.inputFileSystem, context, module.resource)
86 );
87 }
88 parser.hooks.evaluateIdentifier
89 .for("__filename")
90 .tap("NodeStuffPlugin", expr => {
91 if (!parser.state.module) return;
92 const resource = parseResource(parser.state.module.resource);
93 return evaluateToString(resource.path)(expr);
94 });
95 }
96 if (localOptions.__dirname) {
97 if (localOptions.__dirname === "mock") {
98 setConstant("__dirname", "/");
99 } else if (localOptions.__dirname === true) {
100 setModuleConstant("__dirname", module =>
101 relative(compiler.inputFileSystem, context, module.context)
102 );
103 }
104 parser.hooks.evaluateIdentifier
105 .for("__dirname")
106 .tap("NodeStuffPlugin", expr => {
107 if (!parser.state.module) return;
108 return evaluateToString(parser.state.module.context)(expr);
109 });
110 }
111 parser.hooks.expression
112 .for("require.extensions")
113 .tap(
114 "NodeStuffPlugin",
115 expressionIsUnsupported(
116 parser,
117 "require.extensions is not supported by webpack. Use a loader instead."
118 )
119 );
120 };
121
122 normalModuleFactory.hooks.parser
123 .for("javascript/auto")
124 .tap("NodeStuffPlugin", handler);
125 normalModuleFactory.hooks.parser
126 .for("javascript/dynamic")
127 .tap("NodeStuffPlugin", handler);
128 }
129 );
130 }
131}
132
133module.exports = NodeStuffPlugin;