/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; const AliasPlugin = require("enhanced-resolve/lib/AliasPlugin"); const ParserHelpers = require("../ParserHelpers"); const nodeLibsBrowser = require("node-libs-browser"); module.exports = class NodeSourcePlugin { constructor(options) { this.options = options; } apply(compiler) { const options = this.options; if(options === false) // allow single kill switch to turn off this plugin return; const getPathToModule = (module, type) => { if(type === true || (type === undefined && nodeLibsBrowser[module])) { if(!nodeLibsBrowser[module]) throw new Error(`No browser version for node.js core module ${module} available`); return nodeLibsBrowser[module]; } else if(type === "mock") { return require.resolve(`node-libs-browser/mock/${module}`); } else if(type === "empty") { return require.resolve("node-libs-browser/mock/empty"); } else return module; }; const addExpression = (parser, name, module, type, suffix) => { suffix = suffix || ""; parser.hooks.expression.for(name).tap("NodeSourcePlugin", () => { if(parser.state.module && parser.state.module.resource === getPathToModule(module, type)) return; const mockModule = ParserHelpers.requireFileAsExpression(parser.state.module.context, getPathToModule(module, type)); return ParserHelpers.addParsedVariableToModule(parser, name, mockModule + suffix); }); }; compiler.hooks.compilation.tap("NodeSourcePlugin", (compilation, { normalModuleFactory }) => { const handler = (parser, parserOptions) => { if(parserOptions.node === false) return; let localOptions = options; if(parserOptions.node) localOptions = Object.assign({}, localOptions, parserOptions.node); if(localOptions.global) { parser.hooks.expression.for("global").tap("NodeSourcePlugin", () => { const retrieveGlobalModule = ParserHelpers.requireFileAsExpression(parser.state.module.context, require.resolve("../../buildin/global.js")); return ParserHelpers.addParsedVariableToModule(parser, "global", retrieveGlobalModule); }); } if(localOptions.process) { const processType = localOptions.process; addExpression(parser, "process", "process", processType); } if(localOptions.console) { const consoleType = localOptions.console; addExpression(parser, "console", "console", consoleType); } const bufferType = localOptions.Buffer; if(bufferType) { addExpression(parser, "Buffer", "buffer", bufferType, ".Buffer"); } if(localOptions.setImmediate) { const setImmediateType = localOptions.setImmediate; addExpression(parser, "setImmediate", "timers", setImmediateType, ".setImmediate"); addExpression(parser, "clearImmediate", "timers", setImmediateType, ".clearImmediate"); } }; normalModuleFactory.hooks.parser.for("javascript/auto").tap("NodeSourcePlugin", handler); normalModuleFactory.hooks.parser.for("javascript/dynamic").tap("NodeSourcePlugin", handler); normalModuleFactory.hooks.parser.for("javascript/esm").tap("NodeSourcePlugin", handler); }); compiler.hooks.afterResolvers.tap("NodeSourcePlugin", (compiler) => { Object.keys(nodeLibsBrowser).forEach((lib) => { if(options[lib] !== false) { compiler.resolverFactory.hooks.resolver.for("normal").tap("NodeSourcePlugin", resolver => { new AliasPlugin("described-resolve", { name: lib, onlyModule: true, alias: getPathToModule(lib, options[lib]) }, "resolve").apply(resolver); }); } }); }); } };