aboutsummaryrefslogtreecommitdiff
path: root/node_modules/webpack/lib/DefinePlugin.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/webpack/lib/DefinePlugin.js')
-rw-r--r--node_modules/webpack/lib/DefinePlugin.js406
1 files changed, 283 insertions, 123 deletions
diff --git a/node_modules/webpack/lib/DefinePlugin.js b/node_modules/webpack/lib/DefinePlugin.js
index 6318124f5..805b055ef 100644
--- a/node_modules/webpack/lib/DefinePlugin.js
+++ b/node_modules/webpack/lib/DefinePlugin.js
@@ -1,123 +1,283 @@
-/*
- MIT License http://www.opensource.org/licenses/mit-license.php
- Author Tobias Koppers @sokra
-*/
-"use strict";
-
-const ConstDependency = require("./dependencies/ConstDependency");
-const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
-const ParserHelpers = require("./ParserHelpers");
-const NullFactory = require("./NullFactory");
-
-class DefinePlugin {
- constructor(definitions) {
- this.definitions = definitions;
- }
-
- apply(compiler) {
- const definitions = this.definitions;
- compiler.plugin("compilation", (compilation, params) => {
- compilation.dependencyFactories.set(ConstDependency, new NullFactory());
- compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template());
-
- params.normalModuleFactory.plugin("parser", (parser) => {
- (function walkDefinitions(definitions, prefix) {
- Object.keys(definitions).forEach((key) => {
- const code = definitions[key];
- if(code && typeof code === "object" && !(code instanceof RegExp)) {
- walkDefinitions(code, prefix + key + ".");
- applyObjectDefine(prefix + key, code);
- return;
- }
- applyDefineKey(prefix, key);
- applyDefine(prefix + key, code);
- });
- }(definitions, ""));
-
- function stringifyObj(obj) {
- return "Object({" + Object.keys(obj).map((key) => {
- const code = obj[key];
- return JSON.stringify(key) + ":" + toCode(code);
- }).join(",") + "})";
- }
-
- function toCode(code) {
- if(code === null) return "null";
- else if(code === undefined) return "undefined";
- else if(code instanceof RegExp && code.toString) return code.toString();
- else if(typeof code === "function" && code.toString) return "(" + code.toString() + ")";
- else if(typeof code === "object") return stringifyObj(code);
- else return code + "";
- }
-
- function applyDefineKey(prefix, key) {
- const splittedKey = key.split(".");
- splittedKey.slice(1).forEach((_, i) => {
- const fullKey = prefix + splittedKey.slice(0, i + 1).join(".");
- parser.plugin("can-rename " + fullKey, ParserHelpers.approve);
- });
- }
-
- function applyDefine(key, code) {
- const isTypeof = /^typeof\s+/.test(key);
- if(isTypeof) key = key.replace(/^typeof\s+/, "");
- let recurse = false;
- let recurseTypeof = false;
- code = toCode(code);
- if(!isTypeof) {
- parser.plugin("can-rename " + key, ParserHelpers.approve);
- parser.plugin("evaluate Identifier " + key, (expr) => {
- /**
- * this is needed in case there is a recursion in the DefinePlugin
- * to prevent an endless recursion
- * e.g.: new DefinePlugin({
- * "a": "b",
- * "b": "a"
- * });
- */
- if(recurse) return;
- recurse = true;
- const res = parser.evaluate(code);
- recurse = false;
- res.setRange(expr.range);
- return res;
- });
- parser.plugin("expression " + key, ParserHelpers.toConstantDependency(code));
- }
- const typeofCode = isTypeof ? code : "typeof (" + code + ")";
- parser.plugin("evaluate typeof " + key, (expr) => {
- /**
- * this is needed in case there is a recursion in the DefinePlugin
- * to prevent an endless recursion
- * e.g.: new DefinePlugin({
- * "typeof a": "tyepof b",
- * "typeof b": "typeof a"
- * });
- */
- if(recurseTypeof) return;
- recurseTypeof = true;
- const res = parser.evaluate(typeofCode);
- recurseTypeof = false;
- res.setRange(expr.range);
- return res;
- });
- parser.plugin("typeof " + key, (expr) => {
- const res = parser.evaluate(typeofCode);
- if(!res.isString()) return;
- return ParserHelpers.toConstantDependency(JSON.stringify(res.string)).bind(parser)(expr);
- });
- }
-
- function applyObjectDefine(key, obj) {
- const code = stringifyObj(obj);
- parser.plugin("can-rename " + key, ParserHelpers.approve);
- parser.plugin("evaluate Identifier " + key, (expr) => new BasicEvaluatedExpression().setTruthy().setRange(expr.range));
- parser.plugin("evaluate typeof " + key, ParserHelpers.evaluateToString("object"));
- parser.plugin("expression " + key, ParserHelpers.toConstantDependency(code));
- parser.plugin("typeof " + key, ParserHelpers.toConstantDependency(JSON.stringify("object")));
- }
- });
- });
- }
-}
-module.exports = DefinePlugin;
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+"use strict";
+
+const ConstDependency = require("./dependencies/ConstDependency");
+const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
+const ParserHelpers = require("./ParserHelpers");
+const NullFactory = require("./NullFactory");
+
+/** @typedef {import("./Compiler")} Compiler */
+/** @typedef {import("./Parser")} Parser */
+/** @typedef {null|undefined|RegExp|Function|string|number} CodeValuePrimitive */
+/** @typedef {CodeValuePrimitive|Record<string, CodeValuePrimitive>|RuntimeValue} CodeValue */
+
+class RuntimeValue {
+ constructor(fn, fileDependencies) {
+ this.fn = fn;
+ this.fileDependencies = fileDependencies || [];
+ }
+
+ exec(parser) {
+ for (const fileDependency of this.fileDependencies) {
+ parser.state.module.buildInfo.fileDependencies.add(fileDependency);
+ }
+
+ return this.fn();
+ }
+}
+
+const stringifyObj = (obj, parser) => {
+ return (
+ "Object({" +
+ Object.keys(obj)
+ .map(key => {
+ const code = obj[key];
+ return JSON.stringify(key) + ":" + toCode(code, parser);
+ })
+ .join(",") +
+ "})"
+ );
+};
+
+/**
+ * Convert code to a string that evaluates
+ * @param {CodeValue} code Code to evaluate
+ * @param {Parser} parser Parser
+ * @returns {string} code converted to string that evaluates
+ */
+const toCode = (code, parser) => {
+ if (code === null) {
+ return "null";
+ }
+ if (code === undefined) {
+ return "undefined";
+ }
+ if (code instanceof RuntimeValue) {
+ return toCode(code.exec(parser), parser);
+ }
+ if (code instanceof RegExp && code.toString) {
+ return code.toString();
+ }
+ if (typeof code === "function" && code.toString) {
+ return "(" + code.toString() + ")";
+ }
+ if (typeof code === "object") {
+ return stringifyObj(code, parser);
+ }
+ return code + "";
+};
+
+class DefinePlugin {
+ /**
+ * Create a new define plugin
+ * @param {Record<string, CodeValue>} definitions A map of global object definitions
+ */
+ constructor(definitions) {
+ this.definitions = definitions;
+ }
+
+ static runtimeValue(fn, fileDependencies) {
+ return new RuntimeValue(fn, fileDependencies);
+ }
+
+ /**
+ * Apply the plugin
+ * @param {Compiler} compiler Webpack compiler
+ * @returns {void}
+ */
+ apply(compiler) {
+ const definitions = this.definitions;
+ compiler.hooks.compilation.tap(
+ "DefinePlugin",
+ (compilation, { normalModuleFactory }) => {
+ compilation.dependencyFactories.set(ConstDependency, new NullFactory());
+ compilation.dependencyTemplates.set(
+ ConstDependency,
+ new ConstDependency.Template()
+ );
+
+ /**
+ * Handler
+ * @param {Parser} parser Parser
+ * @returns {void}
+ */
+ const handler = parser => {
+ /**
+ * Walk definitions
+ * @param {Object} definitions Definitions map
+ * @param {string} prefix Prefix string
+ * @returns {void}
+ */
+ const walkDefinitions = (definitions, prefix) => {
+ Object.keys(definitions).forEach(key => {
+ const code = definitions[key];
+ if (
+ code &&
+ typeof code === "object" &&
+ !(code instanceof RuntimeValue) &&
+ !(code instanceof RegExp)
+ ) {
+ walkDefinitions(code, prefix + key + ".");
+ applyObjectDefine(prefix + key, code);
+ return;
+ }
+ applyDefineKey(prefix, key);
+ applyDefine(prefix + key, code);
+ });
+ };
+
+ /**
+ * Apply define key
+ * @param {string} prefix Prefix
+ * @param {string} key Key
+ * @returns {void}
+ */
+ const applyDefineKey = (prefix, key) => {
+ const splittedKey = key.split(".");
+ splittedKey.slice(1).forEach((_, i) => {
+ const fullKey = prefix + splittedKey.slice(0, i + 1).join(".");
+ parser.hooks.canRename
+ .for(fullKey)
+ .tap("DefinePlugin", ParserHelpers.approve);
+ });
+ };
+
+ /**
+ * Apply Code
+ * @param {string} key Key
+ * @param {CodeValue} code Code
+ * @returns {void}
+ */
+ const applyDefine = (key, code) => {
+ const isTypeof = /^typeof\s+/.test(key);
+ if (isTypeof) key = key.replace(/^typeof\s+/, "");
+ let recurse = false;
+ let recurseTypeof = false;
+ if (!isTypeof) {
+ parser.hooks.canRename
+ .for(key)
+ .tap("DefinePlugin", ParserHelpers.approve);
+ parser.hooks.evaluateIdentifier
+ .for(key)
+ .tap("DefinePlugin", expr => {
+ /**
+ * this is needed in case there is a recursion in the DefinePlugin
+ * to prevent an endless recursion
+ * e.g.: new DefinePlugin({
+ * "a": "b",
+ * "b": "a"
+ * });
+ */
+ if (recurse) return;
+ recurse = true;
+ const res = parser.evaluate(toCode(code, parser));
+ recurse = false;
+ res.setRange(expr.range);
+ return res;
+ });
+ parser.hooks.expression.for(key).tap("DefinePlugin", expr => {
+ const strCode = toCode(code, parser);
+ if (/__webpack_require__/.test(strCode)) {
+ return ParserHelpers.toConstantDependencyWithWebpackRequire(
+ parser,
+ strCode
+ )(expr);
+ } else {
+ return ParserHelpers.toConstantDependency(parser, strCode)(
+ expr
+ );
+ }
+ });
+ }
+ parser.hooks.evaluateTypeof.for(key).tap("DefinePlugin", expr => {
+ /**
+ * this is needed in case there is a recursion in the DefinePlugin
+ * to prevent an endless recursion
+ * e.g.: new DefinePlugin({
+ * "typeof a": "typeof b",
+ * "typeof b": "typeof a"
+ * });
+ */
+ if (recurseTypeof) return;
+ recurseTypeof = true;
+ const typeofCode = isTypeof
+ ? toCode(code, parser)
+ : "typeof (" + toCode(code, parser) + ")";
+ const res = parser.evaluate(typeofCode);
+ recurseTypeof = false;
+ res.setRange(expr.range);
+ return res;
+ });
+ parser.hooks.typeof.for(key).tap("DefinePlugin", expr => {
+ const typeofCode = isTypeof
+ ? toCode(code, parser)
+ : "typeof (" + toCode(code, parser) + ")";
+ const res = parser.evaluate(typeofCode);
+ if (!res.isString()) return;
+ return ParserHelpers.toConstantDependency(
+ parser,
+ JSON.stringify(res.string)
+ ).bind(parser)(expr);
+ });
+ };
+
+ /**
+ * Apply Object
+ * @param {string} key Key
+ * @param {Object} obj Object
+ * @returns {void}
+ */
+ const applyObjectDefine = (key, obj) => {
+ parser.hooks.canRename
+ .for(key)
+ .tap("DefinePlugin", ParserHelpers.approve);
+ parser.hooks.evaluateIdentifier
+ .for(key)
+ .tap("DefinePlugin", expr =>
+ new BasicEvaluatedExpression().setTruthy().setRange(expr.range)
+ );
+ parser.hooks.evaluateTypeof.for(key).tap("DefinePlugin", expr => {
+ return ParserHelpers.evaluateToString("object")(expr);
+ });
+ parser.hooks.expression.for(key).tap("DefinePlugin", expr => {
+ const strCode = stringifyObj(obj, parser);
+
+ if (/__webpack_require__/.test(strCode)) {
+ return ParserHelpers.toConstantDependencyWithWebpackRequire(
+ parser,
+ strCode
+ )(expr);
+ } else {
+ return ParserHelpers.toConstantDependency(parser, strCode)(
+ expr
+ );
+ }
+ });
+ parser.hooks.typeof.for(key).tap("DefinePlugin", expr => {
+ return ParserHelpers.toConstantDependency(
+ parser,
+ JSON.stringify("object")
+ )(expr);
+ });
+ };
+
+ walkDefinitions(definitions, "");
+ };
+
+ normalModuleFactory.hooks.parser
+ .for("javascript/auto")
+ .tap("DefinePlugin", handler);
+ normalModuleFactory.hooks.parser
+ .for("javascript/dynamic")
+ .tap("DefinePlugin", handler);
+ normalModuleFactory.hooks.parser
+ .for("javascript/esm")
+ .tap("DefinePlugin", handler);
+ }
+ );
+ }
+}
+module.exports = DefinePlugin;