Repository: webpack/webpack
Pull request #7640 (2018-07-03 08:28:33)

Rename parser and its helpers
⚠️ Best reviewed with whitespaces ignored

- Rename `Parser` into `JavascriptParser`
- Rename `ParserHelpers` into `JavascriptParserHelpers`
- Destructure helpers for _better_ readability

**What kind of change does this PR introduce?**

refactoring

**Did you add tests for your changes?**

already tested

**Does this PR introduce a breaking change?**

yes

**What needs to be documented once your changes are merged?**

`Parser` is now `JavascriptParser`.


webpack-bot: <!-- identifier: admin-actions -->

*For maintainers only:*

* [ ] <!-- document --> This need to be documented (issue in webpack/webpack.js.org will be filed when merged)

Patch:
diff --git a/lib/APIPlugin.js b/lib/APIPlugin.js
index 6cd80646d..6e2dac455 100644
--- a/lib/APIPlugin.js
+++ b/lib/APIPlugin.js
@@ -5,7 +5,11 @@
 "use strict";
 
 const ConstDependency = require("./dependencies/ConstDependency");
-const ParserHelpers = require("./ParserHelpers");
+const {
+	toConstantDependency,
+	toConstantDependencyWithWebpackRequire,
+	evaluateToString
+} = require("./JavascriptParserHelpers");
 
 const NullFactory = require("./NullFactory");
 
@@ -49,21 +53,15 @@ class APIPlugin {
 							.tap(
 								"APIPlugin",
 								NO_WEBPACK_REQUIRE[key]
-									? ParserHelpers.toConstantDependency(
-											parser,
-											REPLACEMENTS[key]
-									  )
-									: ParserHelpers.toConstantDependencyWithWebpackRequire(
+									? toConstantDependency(parser, REPLACEMENTS[key])
+									: toConstantDependencyWithWebpackRequire(
 											parser,
 											REPLACEMENTS[key]
 									  )
 							);
 						parser.hooks.evaluateTypeof
 							.for(key)
-							.tap(
-								"APIPlugin",
-								ParserHelpers.evaluateToString(REPLACEMENT_TYPES[key])
-							);
+							.tap("APIPlugin", evaluateToString(REPLACEMENT_TYPES[key]));
 					});
 				};
 
diff --git a/lib/ConstPlugin.js b/lib/ConstPlugin.js
index 03b279b64..07240b439 100644
--- a/lib/ConstPlugin.js
+++ b/lib/ConstPlugin.js
@@ -3,9 +3,10 @@
 	Author Tobias Koppers @sokra
 */
 "use strict";
+
 const ConstDependency = require("./dependencies/ConstDependency");
 const NullFactory = require("./NullFactory");
-const ParserHelpers = require("./ParserHelpers");
+const { evaluateToString } = require("./JavascriptParserHelpers");
 
 const getQuery = request => {
 	const i = request.indexOf("?");
@@ -225,9 +226,9 @@ class ConstPlugin {
 						.for("__resourceQuery")
 						.tap("ConstPlugin", expr => {
 							if (!parser.state.module) return;
-							return ParserHelpers.evaluateToString(
-								getQuery(parser.state.module.resource)
-							)(expr);
+							return evaluateToString(getQuery(parser.state.module.resource))(
+								expr
+							);
 						});
 					parser.hooks.expression
 						.for("__resourceQuery")
diff --git a/lib/DefinePlugin.js b/lib/DefinePlugin.js
index 4d485a9eb..849cda7da 100644
--- a/lib/DefinePlugin.js
+++ b/lib/DefinePlugin.js
@@ -6,7 +6,12 @@
 
 const ConstDependency = require("./dependencies/ConstDependency");
 const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
-const ParserHelpers = require("./ParserHelpers");
+const {
+	approve,
+	evaluateToString,
+	toConstantDependency,
+	toConstantDependencyWithWebpackRequire
+} = require("./JavascriptParserHelpers");
 const NullFactory = require("./NullFactory");
 
 const stringifyObj = obj => {
@@ -79,9 +84,7 @@ class DefinePlugin {
 						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);
+							parser.hooks.canRename.for(fullKey).tap("DefinePlugin", approve);
 						});
 					};
 
@@ -92,9 +95,7 @@ class DefinePlugin {
 						let recurseTypeof = false;
 						code = toCode(code);
 						if (!isTypeof) {
-							parser.hooks.canRename
-								.for(key)
-								.tap("DefinePlugin", ParserHelpers.approve);
+							parser.hooks.canRename.for(key).tap("DefinePlugin", approve);
 							parser.hooks.evaluateIdentifier
 								.for(key)
 								.tap("DefinePlugin", expr => {
@@ -118,11 +119,8 @@ class DefinePlugin {
 								.tap(
 									"DefinePlugin",
 									/__webpack_require__/.test(code)
-										? ParserHelpers.toConstantDependencyWithWebpackRequire(
-												parser,
-												code
-										  )
-										: ParserHelpers.toConstantDependency(parser, code)
+										? toConstantDependencyWithWebpackRequire(parser, code)
+										: toConstantDependency(parser, code)
 								);
 						}
 						const typeofCode = isTypeof ? code : "typeof (" + code + ")";
@@ -145,7 +143,7 @@ class DefinePlugin {
 						parser.hooks.typeof.for(key).tap("DefinePlugin", expr => {
 							const res = parser.evaluate(typeofCode);
 							if (!res.isString()) return;
-							return ParserHelpers.toConstantDependency(
+							return toConstantDependency(
 								parser,
 								JSON.stringify(res.string)
 							).bind(parser)(expr);
@@ -154,9 +152,7 @@ class DefinePlugin {
 
 					const applyObjectDefine = (key, obj) => {
 						const code = stringifyObj(obj);
-						parser.hooks.canRename
-							.for(key)
-							.tap("DefinePlugin", ParserHelpers.approve);
+						parser.hooks.canRename.for(key).tap("DefinePlugin", approve);
 						parser.hooks.evaluateIdentifier
 							.for(key)
 							.tap("DefinePlugin", expr =>
@@ -164,26 +160,20 @@ class DefinePlugin {
 							);
 						parser.hooks.evaluateTypeof
 							.for(key)
-							.tap("DefinePlugin", ParserHelpers.evaluateToString("object"));
+							.tap("DefinePlugin", evaluateToString("object"));
 						parser.hooks.expression
 							.for(key)
 							.tap(
 								"DefinePlugin",
 								/__webpack_require__/.test(code)
-									? ParserHelpers.toConstantDependencyWithWebpackRequire(
-											parser,
-											code
-									  )
-									: ParserHelpers.toConstantDependency(parser, code)
+									? toConstantDependencyWithWebpackRequire(parser, code)
+									: toConstantDependency(parser, code)
 							);
 						parser.hooks.typeof
 							.for(key)
 							.tap(
 								"DefinePlugin",
-								ParserHelpers.toConstantDependency(
-									parser,
-									JSON.stringify("object")
-								)
+								toConstantDependency(parser, JSON.stringify("object"))
 							);
 					};
 
diff --git a/lib/ExtendedAPIPlugin.js b/lib/ExtendedAPIPlugin.js
index a894a9faf..0d98bed1e 100644
--- a/lib/ExtendedAPIPlugin.js
+++ b/lib/ExtendedAPIPlugin.js
@@ -6,7 +6,10 @@
 
 const Template = require("./Template");
 const ConstDependency = require("./dependencies/ConstDependency");
-const ParserHelpers = require("./ParserHelpers");
+const {
+	evaluateToString,
+	toConstantDependencyWithWebpackRequire
+} = require("./JavascriptParserHelpers");
 const NullFactory = require("./NullFactory");
 
 const REPLACEMENTS = {
@@ -53,7 +56,7 @@ class ExtendedAPIPlugin {
 							.for(key)
 							.tap(
 								"ExtendedAPIPlugin",
-								ParserHelpers.toConstantDependencyWithWebpackRequire(
+								toConstantDependencyWithWebpackRequire(
 									parser,
 									REPLACEMENTS[key]
 								)
@@ -62,7 +65,7 @@ class ExtendedAPIPlugin {
 							.for(key)
 							.tap(
 								"ExtendedAPIPlugin",
-								ParserHelpers.evaluateToString(REPLACEMENT_TYPES[key])
+								evaluateToString(REPLACEMENT_TYPES[key])
 							);
 					});
 				};
diff --git a/lib/HotModuleReplacementPlugin.js b/lib/HotModuleReplacementPlugin.js
index 4b0edac72..bfe9a4058 100644
--- a/lib/HotModuleReplacementPlugin.js
+++ b/lib/HotModuleReplacementPlugin.js
@@ -11,7 +11,12 @@ const ModuleHotAcceptDependency = require("./dependencies/ModuleHotAcceptDepende
 const ModuleHotDeclineDependency = require("./dependencies/ModuleHotDeclineDependency");
 const ConstDependency = require("./dependencies/ConstDependency");
 const NullFactory = require("./NullFactory");
-const ParserHelpers = require("./ParserHelpers");
+const {
+	evaluateToIdentifier,
+	evaluateToString,
+	skipTraversal,
+	toConstantDependencyWithWebpackRequire
+} = require("./JavascriptParserHelpers");
 
 module.exports = class HotModuleReplacementPlugin {
 	constructor(options) {
@@ -280,24 +285,21 @@ module.exports = class HotModuleReplacementPlugin {
 						.for("__webpack_hash__")
 						.tap(
 							"HotModuleReplacementPlugin",
-							ParserHelpers.toConstantDependencyWithWebpackRequire(
+							toConstantDependencyWithWebpackRequire(
 								parser,
 								"__webpack_require__.h()"
 							)
 						);
 					parser.hooks.evaluateTypeof
 						.for("__webpack_hash__")
-						.tap(
-							"HotModuleReplacementPlugin",
-							ParserHelpers.evaluateToString("string")
-						);
+						.tap("HotModuleReplacementPlugin", evaluateToString("string"));
 					parser.hooks.evaluateIdentifier.for("module.hot").tap(
 						{
 							name: "HotModuleReplacementPlugin",
 							before: "NodeStuffPlugin"
 						},
 						expr => {
-							return ParserHelpers.evaluateToIdentifier(
+							return evaluateToIdentifier(
 								"module.hot",
 								!!parser.state.compilation.hotUpdateChunkTemplate
 							)(expr);
@@ -386,7 +388,7 @@ module.exports = class HotModuleReplacementPlugin {
 						});
 					parser.hooks.expression
 						.for("module.hot")
-						.tap("HotModuleReplacementPlugin", ParserHelpers.skipTraversal);
+						.tap("HotModuleReplacementPlugin", skipTraversal);
 				};
 
 				// TODO add HMR support for javascript/esm
diff --git a/lib/JavascriptModulesPlugin.js b/lib/JavascriptModulesPlugin.js
index 6361f6187..39b666a09 100644
--- a/lib/JavascriptModulesPlugin.js
+++ b/lib/JavascriptModulesPlugin.js
@@ -4,7 +4,7 @@
 */
 "use strict";
 
-const Parser = require("./Parser");
+const JavascriptParser = require("./JavascriptParser");
 const Template = require("./Template");
 const { ConcatSource } = require("webpack-sources");
 const JavascriptGenerator = require("./JavascriptGenerator");
@@ -18,17 +18,17 @@ class JavascriptModulesPlugin {
 				normalModuleFactory.hooks.createParser
 					.for("javascript/auto")
 					.tap("JavascriptModulesPlugin", options => {
-						return new Parser(options, "auto");
+						return new JavascriptParser(options, "auto");
 					});
 				normalModuleFactory.hooks.createParser
 					.for("javascript/dynamic")
 					.tap("JavascriptModulesPlugin", options => {
-						return new Parser(options, "script");
+						return new JavascriptParser(options, "script");
 					});
 				normalModuleFactory.hooks.createParser
 					.for("javascript/esm")
 					.tap("JavascriptModulesPlugin", options => {
-						return new Parser(options, "module");
+						return new JavascriptParser(options, "module");
 					});
 				normalModuleFactory.hooks.createGenerator
 					.for("javascript/auto")
diff --git a/lib/Parser.js b/lib/JavascriptParser.js
similarity index 82%
rename from lib/Parser.js
rename to lib/JavascriptParser.js
index 2b563bb4b..57ddee6fd 100644
--- a/lib/Parser.js
+++ b/lib/JavascriptParser.js
@@ -40,7 +40,7 @@ const EMPTY_COMMENT_OPTIONS = {
 	errors: null
 };
 
-class Parser {
+class JavascriptParser {
 	constructor(options, sourceType = "auto") {
 		this.hooks = {
 			evaluateTypeof: new HookMap(() => new SyncBailHook(["expression"])),
@@ -106,7 +106,7 @@ class Parser {
 	}
 
 	initializeEvaluating() {
-		this.hooks.evaluate.for("Literal").tap("Parser", expr => {
+		this.hooks.evaluate.for("Literal").tap("JavascriptParser", expr => {
 			switch (typeof expr.value) {
 				case "number":
 					return new BasicEvaluatedExpression()
@@ -130,224 +130,228 @@ class Parser {
 					.setRange(expr.range);
 			}
 		});
-		this.hooks.evaluate.for("LogicalExpression").tap("Parser", expr => {
-			let left;
-			let leftAsBool;
-			let right;
-			if (expr.operator === "&&") {
-				left = this.evaluateExpression(expr.left);
-				leftAsBool = left && left.asBool();
-				if (leftAsBool === false) return left.setRange(expr.range);
-				if (leftAsBool !== true) return;
-				right = this.evaluateExpression(expr.right);
-				return right.setRange(expr.range);
-			} else if (expr.operator === "||") {
-				left = this.evaluateExpression(expr.left);
-				leftAsBool = left && left.asBool();
-				if (leftAsBool === true) return left.setRange(expr.range);
-				if (leftAsBool !== false) return;
-				right = this.evaluateExpression(expr.right);
-				return right.setRange(expr.range);
-			}
-		});
-		this.hooks.evaluate.for("BinaryExpression").tap("Parser", expr => {
-			let left;
-			let right;
-			let res;
-			if (expr.operator === "+") {
-				left = this.evaluateExpression(expr.left);
-				right = this.evaluateExpression(expr.right);
-				if (!left || !right) return;
-				res = new BasicEvaluatedExpression();
-				if (left.isString()) {
-					if (right.isString()) {
-						res.setString(left.string + right.string);
-					} else if (right.isNumber()) {
-						res.setString(left.string + right.number);
-					} else if (
-						right.isWrapped() &&
-						right.prefix &&
-						right.prefix.isString()
-					) {
-						res.setWrapped(
-							new BasicEvaluatedExpression()
-								.setString(left.string + right.prefix.string)
-								.setRange(joinRanges(left.range, right.prefix.range)),
-							right.postfix
-						);
-					} else if (right.isWrapped()) {
-						res.setWrapped(
-							new BasicEvaluatedExpression()
-								.setString(left.string)
-								.setRange(left.range),
-							right.postfix
-						);
+		this.hooks.evaluate
+			.for("LogicalExpression")
+			.tap("JavascriptParser", expr => {
+				let left;
+				let leftAsBool;
+				let right;
+				if (expr.operator === "&&") {
+					left = this.evaluateExpression(expr.left);
+					leftAsBool = left && left.asBool();
+					if (leftAsBool === false) return left.setRange(expr.range);
+					if (leftAsBool !== true) return;
+					right = this.evaluateExpression(expr.right);
+					return right.setRange(expr.range);
+				} else if (expr.operator === "||") {
+					left = this.evaluateExpression(expr.left);
+					leftAsBool = left && left.asBool();
+					if (leftAsBool === true) return left.setRange(expr.range);
+					if (leftAsBool !== false) return;
+					right = this.evaluateExpression(expr.right);
+					return right.setRange(expr.range);
+				}
+			});
+		this.hooks.evaluate
+			.for("BinaryExpression")
+			.tap("JavascriptParser", expr => {
+				let left;
+				let right;
+				let res;
+				if (expr.operator === "+") {
+					left = this.evaluateExpression(expr.left);
+					right = this.evaluateExpression(expr.right);
+					if (!left || !right) return;
+					res = new BasicEvaluatedExpression();
+					if (left.isString()) {
+						if (right.isString()) {
+							res.setString(left.string + right.string);
+						} else if (right.isNumber()) {
+							res.setString(left.string + right.number);
+						} else if (
+							right.isWrapped() &&
+							right.prefix &&
+							right.prefix.isString()
+						) {
+							res.setWrapped(
+								new BasicEvaluatedExpression()
+									.setString(left.string + right.prefix.string)
+									.setRange(joinRanges(left.range, right.prefix.range)),
+								right.postfix
+							);
+						} else if (right.isWrapped()) {
+							res.setWrapped(
+								new BasicEvaluatedExpression()
+									.setString(left.string)
+									.setRange(left.range),
+								right.postfix
+							);
+						} else {
+							res.setWrapped(left, null);
+						}
+					} else if (left.isNumber()) {
+						if (right.isString()) {
+							res.setString(left.number + right.string);
+						} else if (right.isNumber()) {
+							res.setNumber(left.number + right.number);
+						}
+					} else if (left.isWrapped()) {
+						if (left.postfix && left.postfix.isString() && right.isString()) {
+							res.setWrapped(
+								left.prefix,
+								new BasicEvaluatedExpression()
+									.setString(left.postfix.string + right.string)
+									.setRange(joinRanges(left.postfix.range, right.range))
+							);
+						} else if (
+							left.postfix &&
+							left.postfix.isString() &&
+							right.isNumber()
+						) {
+							res.setWrapped(
+								left.prefix,
+								new BasicEvaluatedExpression()
+									.setString(left.postfix.string + right.number)
+									.setRange(joinRanges(left.postfix.range, right.range))
+							);
+						} else if (right.isString()) {
+							res.setWrapped(left.prefix, right);
+						} else if (right.isNumber()) {
+							res.setWrapped(
+								left.prefix,
+								new BasicEvaluatedExpression()
+									.setString(right.number + "")
+									.setRange(right.range)
+							);
+						} else {
+							res.setWrapped(left.prefix, new BasicEvaluatedExpression());
+						}
 					} else {
-						res.setWrapped(left, null);
-					}
-				} else if (left.isNumber()) {
-					if (right.isString()) {
-						res.setString(left.number + right.string);
-					} else if (right.isNumber()) {
-						res.setNumber(left.number + right.number);
+						if (right.isString()) {
+							res.setWrapped(null, right);
+						}
 					}
-				} else if (left.isWrapped()) {
-					if (left.postfix && left.postfix.isString() && right.isString()) {
-						res.setWrapped(
-							left.prefix,
-							new BasicEvaluatedExpression()
-								.setString(left.postfix.string + right.string)
-								.setRange(joinRanges(left.postfix.range, right.range))
-						);
-					} else if (
-						left.postfix &&
-						left.postfix.isString() &&
-						right.isNumber()
-					) {
-						res.setWrapped(
-							left.prefix,
-							new BasicEvaluatedExpression()
-								.setString(left.postfix.string + right.number)
-								.setRange(joinRanges(left.postfix.range, right.range))
-						);
-					} else if (right.isString()) {
-						res.setWrapped(left.prefix, right);
-					} else if (right.isNumber()) {
-						res.setWrapped(
-							left.prefix,
-							new BasicEvaluatedExpression()
-								.setString(right.number + "")
-								.setRange(right.range)
-						);
-					} else {
-						res.setWrapped(left.prefix, new BasicEvaluatedExpression());
+					res.setRange(expr.range);
+					return res;
+				} else if (expr.operator === "-") {
+					left = this.evaluateExpression(expr.left);
+					right = this.evaluateExpression(expr.right);
+					if (!left || !right) return;
+					if (!left.isNumber() || !right.isNumber()) return;
+					res = new BasicEvaluatedExpression();
+					res.setNumber(left.number - right.number);
+					res.setRange(expr.range);
+					return res;
+				} else if (expr.operator === "*") {
+					left = this.evaluateExpression(expr.left);
+					right = this.evaluateExpression(expr.right);
+					if (!left || !right) return;
+					if (!left.isNumber() || !right.isNumber()) return;
+					res = new BasicEvaluatedExpression();
+					res.setNumber(left.number * right.number);
+					res.setRange(expr.range);
+					return res;
+				} else if (expr.operator === "/") {
+					left = this.evaluateExpression(expr.left);
+					right = this.evaluateExpression(expr.right);
+					if (!left || !right) return;
+					if (!left.isNumber() || !right.isNumber()) return;
+					res = new BasicEvaluatedExpression();
+					res.setNumber(left.number / right.number);
+					res.setRange(expr.range);
+					return res;
+				} else if (expr.operator === "**") {
+					left = this.evaluateExpression(expr.left);
+					right = this.evaluateExpression(expr.right);
+					if (!left || !right) return;
+					if (!left.isNumber() || !right.isNumber()) return;
+					res = new BasicEvaluatedExpression();
+					res.setNumber(Math.pow(left.number, right.number));
+					res.setRange(expr.range);
+					return res;
+				} else if (expr.operator === "==" || expr.operator === "===") {
+					left = this.evaluateExpression(expr.left);
+					right = this.evaluateExpression(expr.right);
+					if (!left || !right) return;
+					res = new BasicEvaluatedExpression();
+					res.setRange(expr.range);
+					if (left.isString() && right.isString()) {
+						return res.setBoolean(left.string === right.string);
+					} else if (left.isNumber() && right.isNumber()) {
+						return res.setBoolean(left.number === right.number);
+					} else if (left.isBoolean() && right.isBoolean()) {
+						return res.setBoolean(left.bool === right.bool);
 					}
-				} else {
-					if (right.isString()) {
-						res.setWrapped(null, right);
+				} else if (expr.operator === "!=" || expr.operator === "!==") {
+					left = this.evaluateExpression(expr.left);
+					right = this.evaluateExpression(expr.right);
+					if (!left || !right) return;
+					res = new BasicEvaluatedExpression();
+					res.setRange(expr.range);
+					if (left.isString() && right.isString()) {
+						return res.setBoolean(left.string !== right.string);
+					} else if (left.isNumber() && right.isNumber()) {
+						return res.setBoolean(left.number !== right.number);
+					} else if (left.isBoolean() && right.isBoolean()) {
+						return res.setBoolean(left.bool !== right.bool);
 					}
+				} else if (expr.operator === "&") {
+					left = this.evaluateExpression(expr.left);
+					right = this.evaluateExpression(expr.right);
+					if (!left || !right) return;
+					if (!left.isNumber() || !right.isNumber()) return;
+					res = new BasicEvaluatedExpression();
+					res.setNumber(left.number & right.number);
+					res.setRange(expr.range);
+					return res;
+				} else if (expr.operator === "|") {
+					left = this.evaluateExpression(expr.left);
+					right = this.evaluateExpression(expr.right);
+					if (!left || !right) return;
+					if (!left.isNumber() || !right.isNumber()) return;
+					res = new BasicEvaluatedExpression();
+					res.setNumber(left.number | right.number);
+					res.setRange(expr.range);
+					return res;
+				} else if (expr.operator === "^") {
+					left = this.evaluateExpression(expr.left);
+					right = this.evaluateExpression(expr.right);
+					if (!left || !right) return;
+					if (!left.isNumber() || !right.isNumber()) return;
+					res = new BasicEvaluatedExpression();
+					res.setNumber(left.number ^ right.number);
+					res.setRange(expr.range);
+					return res;
+				} else if (expr.operator === ">>>") {
+					left = this.evaluateExpression(expr.left);
+					right = this.evaluateExpression(expr.right);
+					if (!left || !right) return;
+					if (!left.isNumber() || !right.isNumber()) return;
+					res = new BasicEvaluatedExpression();
+					res.setNumber(left.number >>> right.number);
+					res.setRange(expr.range);
+					return res;
+				} else if (expr.operator === ">>") {
+					left = this.evaluateExpression(expr.left);
+					right = this.evaluateExpression(expr.right);
+					if (!left || !right) return;
+					if (!left.isNumber() || !right.isNumber()) return;
+					res = new BasicEvaluatedExpression();
+					res.setNumber(left.number >> right.number);
+					res.setRange(expr.range);
+					return res;
+				} else if (expr.operator === "<<") {
+					left = this.evaluateExpression(expr.left);
+					right = this.evaluateExpression(expr.right);
+					if (!left || !right) return;
+					if (!left.isNumber() || !right.isNumber()) return;
+					res = new BasicEvaluatedExpression();
+					res.setNumber(left.number << right.number);
+					res.setRange(expr.range);
+					return res;
 				}
-				res.setRange(expr.range);
-				return res;
-			} else if (expr.operator === "-") {
-				left = this.evaluateExpression(expr.left);
-				right = this.evaluateExpression(expr.right);
-				if (!left || !right) return;
-				if (!left.isNumber() || !right.isNumber()) return;
-				res = new BasicEvaluatedExpression();
-				res.setNumber(left.number - right.number);
-				res.setRange(expr.range);
-				return res;
-			} else if (expr.operator === "*") {
-				left = this.evaluateExpression(expr.left);
-				right = this.evaluateExpression(expr.right);
-				if (!left || !right) return;
-				if (!left.isNumber() || !right.isNumber()) return;
-				res = new BasicEvaluatedExpression();
-				res.setNumber(left.number * right.number);
-				res.setRange(expr.range);
-				return res;
-			} else if (expr.operator === "/") {
-				left = this.evaluateExpression(expr.left);
-				right = this.evaluateExpression(expr.right);
-				if (!left || !right) return;
-				if (!left.isNumber() || !right.isNumber()) return;
-				res = new BasicEvaluatedExpression();
-				res.setNumber(left.number / right.number);
-				res.setRange(expr.range);
-				return res;
-			} else if (expr.operator === "**") {
-				left = this.evaluateExpression(expr.left);
-				right = this.evaluateExpression(expr.right);
-				if (!left || !right) return;
-				if (!left.isNumber() || !right.isNumber()) return;
-				res = new BasicEvaluatedExpression();
-				res.setNumber(Math.pow(left.number, right.number));
-				res.setRange(expr.range);
-				return res;
-			} else if (expr.operator === "==" || expr.operator === "===") {
-				left = this.evaluateExpression(expr.left);
-				right = this.evaluateExpression(expr.right);
-				if (!left || !right) return;
-				res = new BasicEvaluatedExpression();
-				res.setRange(expr.range);
-				if (left.isString() && right.isString()) {
-					return res.setBoolean(left.string === right.string);
-				} else if (left.isNumber() && right.isNumber()) {
-					return res.setBoolean(left.number === right.number);
-				} else if (left.isBoolean() && right.isBoolean()) {
-					return res.setBoolean(left.bool === right.bool);
-				}
-			} else if (expr.operator === "!=" || expr.operator === "!==") {
-				left = this.evaluateExpression(expr.left);
-				right = this.evaluateExpression(expr.right);
-				if (!left || !right) return;
-				res = new BasicEvaluatedExpression();
-				res.setRange(expr.range);
-				if (left.isString() && right.isString()) {
-					return res.setBoolean(left.string !== right.string);
-				} else if (left.isNumber() && right.isNumber()) {
-					return res.setBoolean(left.number !== right.number);
-				} else if (left.isBoolean() && right.isBoolean()) {
-					return res.setBoolean(left.bool !== right.bool);
-				}
-			} else if (expr.operator === "&") {
-				left = this.evaluateExpression(expr.left);
-				right = this.evaluateExpression(expr.right);
-				if (!left || !right) return;
-				if (!left.isNumber() || !right.isNumber()) return;
-				res = new BasicEvaluatedExpression();
-				res.setNumber(left.number & right.number);
-				res.setRange(expr.range);
-				return res;
-			} else if (expr.operator === "|") {
-				left = this.evaluateExpression(expr.left);
-				right = this.evaluateExpression(expr.right);
-				if (!left || !right) return;
-				if (!left.isNumber() || !right.isNumber()) return;
-				res = new BasicEvaluatedExpression();
-				res.setNumber(left.number | right.number);
-				res.setRange(expr.range);
-				return res;
-			} else if (expr.operator === "^") {
-				left = this.evaluateExpression(expr.left);
-				right = this.evaluateExpression(expr.right);
-				if (!left || !right) return;
-				if (!left.isNumber() || !right.isNumber()) return;
-				res = new BasicEvaluatedExpression();
-				res.setNumber(left.number ^ right.number);
-				res.setRange(expr.range);
-				return res;
-			} else if (expr.operator === ">>>") {
-				left = this.evaluateExpression(expr.left);
-				right = this.evaluateExpression(expr.right);
-				if (!left || !right) return;
-				if (!left.isNumber() || !right.isNumber()) return;
-				res = new BasicEvaluatedExpression();
-				res.setNumber(left.number >>> right.number);
-				res.setRange(expr.range);
-				return res;
-			} else if (expr.operator === ">>") {
-				left = this.evaluateExpression(expr.left);
-				right = this.evaluateExpression(expr.right);
-				if (!left || !right) return;
-				if (!left.isNumber() || !right.isNumber()) return;
-				res = new BasicEvaluatedExpression();
-				res.setNumber(left.number >> right.number);
-				res.setRange(expr.range);
-				return res;
-			} else if (expr.operator === "<<") {
-				left = this.evaluateExpression(expr.left);
-				right = this.evaluateExpression(expr.right);
-				if (!left || !right) return;
-				if (!left.isNumber() || !right.isNumber()) return;
-				res = new BasicEvaluatedExpression();
-				res.setNumber(left.number << right.number);
-				res.setRange(expr.range);
-				return res;
-			}
-		});
-		this.hooks.evaluate.for("UnaryExpression").tap("Parser", expr => {
+			});
+		this.hooks.evaluate.for("UnaryExpression").tap("JavascriptParser", expr => {
 			if (expr.operator === "typeof") {
 				let res;
 				let name;
@@ -436,12 +440,12 @@ class Parser {
 				return res;
 			}
 		});
-		this.hooks.evaluateTypeof.for("undefined").tap("Parser", expr => {
+		this.hooks.evaluateTypeof.for("undefined").tap("JavascriptParser", expr => {
 			return new BasicEvaluatedExpression()
 				.setString("undefined")
 				.setRange(expr.range);
 		});
-		this.hooks.evaluate.for("Identifier").tap("Parser", expr => {
+		this.hooks.evaluate.for("Identifier").tap("JavascriptParser", expr => {
 			const name = this.scope.renames.get(expr.name) || expr.name;
 			if (!this.scope.definitions.has(expr.name)) {
 				const hook = this.hooks.evaluateIdentifier.get(name);
@@ -459,7 +463,7 @@ class Parser {
 				}
 			}
 		});
-		this.hooks.evaluate.for("ThisExpression").tap("Parser", expr => {
+		this.hooks.evaluate.for("ThisExpression").tap("JavascriptParser", expr => {
 			const name = this.scope.renames.get("this");
 			if (name) {
 				const hook = this.hooks.evaluateIdentifier.get(name);
@@ -472,27 +476,31 @@ class Parser {
 					.setRange(expr.range);
 			}
 		});
-		this.hooks.evaluate.for("MemberExpression").tap("Parser", expression => {
-			let exprName = this.getNameForExpression(expression);
-			if (exprName) {
-				if (exprName.free) {
-					const hook = this.hooks.evaluateIdentifier.get(exprName.name);
-					if (hook !== undefined) {
-						const result = hook.call(expression);
-						if (result) return result;
-					}
-					return new BasicEvaluatedExpression()
-						.setIdentifier(exprName.name)
-						.setRange(expression.range);
-				} else {
-					const hook = this.hooks.evaluateDefinedIdentifier.get(exprName.name);
-					if (hook !== undefined) {
-						return hook.call(expression);
+		this.hooks.evaluate
+			.for("MemberExpression")
+			.tap("JavascriptParser", expression => {
+				let exprName = this.getNameForExpression(expression);
+				if (exprName) {
+					if (exprName.free) {
+						const hook = this.hooks.evaluateIdentifier.get(exprName.name);
+						if (hook !== undefined) {
+							const result = hook.call(expression);
+							if (result) return result;
+						}
+						return new BasicEvaluatedExpression()
+							.setIdentifier(exprName.name)
+							.setRange(expression.range);
+					} else {
+						const hook = this.hooks.evaluateDefinedIdentifier.get(
+							exprName.name
+						);
+						if (hook !== undefined) {
+							return hook.call(expression);
+						}
 					}
 				}
-			}
-		});
-		this.hooks.evaluate.for("CallExpression").tap("Parser", expr => {
+			});
+		this.hooks.evaluate.for("CallExpression").tap("JavascriptParser", expr => {
 			if (expr.callee.type !== "MemberExpression") return;
 			if (
 				expr.callee.property.type !==
@@ -509,7 +517,7 @@ class Parser {
 		});
 		this.hooks.evaluateCallExpressionMember
 			.for("replace")
-			.tap("Parser", (expr, param) => {
+			.tap("JavascriptParser", (expr, param) => {
 				if (!param.isString()) return;
 				if (expr.arguments.length !== 2) return;
 				let arg1 = this.evaluateExpression(expr.arguments[0]);
@@ -525,7 +533,7 @@ class Parser {
 		["substr", "substring"].forEach(fn => {
 			this.hooks.evaluateCallExpressionMember
 				.for(fn)
-				.tap("Parser", (expr, param) => {
+				.tap("JavascriptParser", (expr, param) => {
 					if (!param.isString()) return;
 					let arg1;
 					let result,
@@ -587,7 +595,7 @@ class Parser {
 			return parts;
 		};
 
-		this.hooks.evaluate.for("TemplateLiteral").tap("Parser", node => {
+		this.hooks.evaluate.for("TemplateLiteral").tap("JavascriptParser", node => {
 			const parts = getSimplifiedTemplateResult.call(
 				this,
 				"cooked",
@@ -601,22 +609,25 @@ class Parser {
 				.setTemplateString(parts)
 				.setRange(node.range);
 		});
-		this.hooks.evaluate.for("TaggedTemplateExpression").tap("Parser", node => {
-			if (this.evaluateExpression(node.tag).identifier !== "String.raw") return;
-			const parts = getSimplifiedTemplateResult.call(
-				this,
-				"raw",
-				node.quasi.quasis,
-				node.quasi.expressions
-			);
-			return new BasicEvaluatedExpression()
-				.setTemplateString(parts)
-				.setRange(node.range);
-		});
+		this.hooks.evaluate
+			.for("TaggedTemplateExpression")
+			.tap("JavascriptParser", node => {
+				if (this.evaluateExpression(node.tag).identifier !== "String.raw")
+					return;
+				const parts = getSimplifiedTemplateResult.call(
+					this,
+					"raw",
+					node.quasi.quasis,
+					node.quasi.expressions
+				);
+				return new BasicEvaluatedExpression()
+					.setTemplateString(parts)
+					.setRange(node.range);
+			});
 
 		this.hooks.evaluateCallExpressionMember
 			.for("concat")
-			.tap("Parser", (expr, param) => {
+			.tap("JavascriptParser", (expr, param) => {
 				if (!param.isString() && !param.isWrapped()) return;
 
 				let stringSuffix = null;
@@ -662,7 +673,7 @@ class Parser {
 			});
 		this.hooks.evaluateCallExpressionMember
 			.for("split")
-			.tap("Parser", (expr, param) => {
+			.tap("JavascriptParser", (expr, param) => {
 				if (!param.isString()) return;
 				if (expr.arguments.length !== 1) return;
 				let result;
@@ -678,34 +689,36 @@ class Parser {
 					.setArray(result)
 					.setRange(expr.range);
 			});
-		this.hooks.evaluate.for("ConditionalExpression").tap("Parser", expr => {
-			const condition = this.evaluateExpression(expr.test);
-			const conditionValue = condition.asBool();
-			let res;
-			if (conditionValue === undefined) {
-				const consequent = this.evaluateExpression(expr.consequent);
-				const alternate = this.evaluateExpression(expr.alternate);
-				if (!consequent || !alternate) return;
-				res = new BasicEvaluatedExpression();
-				if (consequent.isConditional()) {
-					res.setOptions(consequent.options);
-				} else {
-					res.setOptions([consequent]);
-				}
-				if (alternate.isConditional()) {
-					res.addOptions(alternate.options);
+		this.hooks.evaluate
+			.for("ConditionalExpression")
+			.tap("JavascriptParser", expr => {
+				const condition = this.evaluateExpression(expr.test);
+				const conditionValue = condition.asBool();
+				let res;
+				if (conditionValue === undefined) {
+					const consequent = this.evaluateExpression(expr.consequent);
+					const alternate = this.evaluateExpression(expr.alternate);
+					if (!consequent || !alternate) return;
+					res = new BasicEvaluatedExpression();
+					if (consequent.isConditional()) {
+						res.setOptions(consequent.options);
+					} else {
+						res.setOptions([consequent]);
+					}
+					if (alternate.isConditional()) {
+						res.addOptions(alternate.options);
+					} else {
+						res.addOptions([alternate]);
+					}
 				} else {
-					res.addOptions([alternate]);
+					res = this.evaluateExpression(
+						conditionValue ? expr.consequent : expr.alternate
+					);
 				}
-			} else {
-				res = this.evaluateExpression(
-					conditionValue ? expr.consequent : expr.alternate
-				);
-			}
-			res.setRange(expr.range);
-			return res;
-		});
-		this.hooks.evaluate.for("ArrayExpression").tap("Parser", expr => {
+				res.setRange(expr.range);
+				return res;
+			});
+		this.hooks.evaluate.for("ArrayExpression").tap("JavascriptParser", expr => {
 			const items = expr.elements.map(element => {
 				return element !== null && this.evaluateExpression(element);
 			});
@@ -1981,7 +1994,7 @@ class Parser {
 			comments = source.comments;
 		} else {
 			comments = [];
-			ast = Parser.parse(source, {
+			ast = JavascriptParser.parse(source, {
 				sourceType: this.sourceType,
 				onComment: comments
 			});
@@ -2012,7 +2025,7 @@ class Parser {
 	}
 
 	evaluate(source) {
-		const ast = Parser.parse("(" + source + ")", {
+		const ast = JavascriptParser.parse("(" + source + ")", {
 			sourceType: this.sourceType,
 			locations: false
 		});
@@ -2136,4 +2149,4 @@ class Parser {
 	}
 }
 
-module.exports = Parser;
+module.exports = JavascriptParser;
diff --git a/lib/ParserHelpers.js b/lib/JavascriptParserHelpers.js
similarity index 76%
rename from lib/ParserHelpers.js
rename to lib/JavascriptParserHelpers.js
index 5248f12fe..128d72a6c 100644
--- a/lib/ParserHelpers.js
+++ b/lib/JavascriptParserHelpers.js
@@ -9,9 +9,7 @@ const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
 const ConstDependency = require("./dependencies/ConstDependency");
 const UnsupportedFeatureWarning = require("./UnsupportedFeatureWarning");
 
-const ParserHelpers = exports;
-
-ParserHelpers.addParsedVariableToModule = (parser, name, expression) => {
+exports.addParsedVariableToModule = (parser, name, expression) => {
 	if (!parser.state.current.addVariable) return false;
 	var deps = [];
 	parser.parse(expression, {
@@ -27,7 +25,7 @@ ParserHelpers.addParsedVariableToModule = (parser, name, expression) => {
 	return true;
 };
 
-ParserHelpers.requireFileAsExpression = (context, pathToModule) => {
+exports.requireFileAsExpression = (context, pathToModule) => {
 	var moduleJsPath = path.relative(context, pathToModule);
 	if (!/^[A-Z]:/i.test(moduleJsPath)) {
 		moduleJsPath = "./" + moduleJsPath.replace(/\\/g, "/");
@@ -35,7 +33,7 @@ ParserHelpers.requireFileAsExpression = (context, pathToModule) => {
 	return "require(" + JSON.stringify(moduleJsPath) + ")";
 };
 
-ParserHelpers.toConstantDependency = (parser, value) => {
+exports.toConstantDependency = (parser, value) => {
 	return function constDependency(expr) {
 		var dep = new ConstDependency(value, expr.range, false);
 		dep.loc = expr.loc;
@@ -44,7 +42,7 @@ ParserHelpers.toConstantDependency = (parser, value) => {
 	};
 };
 
-ParserHelpers.toConstantDependencyWithWebpackRequire = (parser, value) => {
+exports.toConstantDependencyWithWebpackRequire = (parser, value) => {
 	return function constDependencyWithWebpackRequire(expr) {
 		var dep = new ConstDependency(value, expr.range, true);
 		dep.loc = expr.loc;
@@ -53,13 +51,13 @@ ParserHelpers.toConstantDependencyWithWebpackRequire = (parser, value) => {
 	};
 };
 
-ParserHelpers.evaluateToString = value => {
+exports.evaluateToString = value => {
 	return function stringExpression(expr) {
 		return new BasicEvaluatedExpression().setString(value).setRange(expr.range);
 	};
 };
 
-ParserHelpers.evaluateToBoolean = value => {
+exports.evaluateToBoolean = value => {
 	return function booleanExpression(expr) {
 		return new BasicEvaluatedExpression()
 			.setBoolean(value)
@@ -67,7 +65,7 @@ ParserHelpers.evaluateToBoolean = value => {
 	};
 };
 
-ParserHelpers.evaluateToIdentifier = (identifier, truthy) => {
+exports.evaluateToIdentifier = (identifier, truthy) => {
 	return function identifierExpression(expr) {
 		let evex = new BasicEvaluatedExpression()
 			.setIdentifier(identifier)
@@ -81,7 +79,7 @@ ParserHelpers.evaluateToIdentifier = (identifier, truthy) => {
 	};
 };
 
-ParserHelpers.expressionIsUnsupported = (parser, message) => {
+exports.expressionIsUnsupported = (parser, message) => {
 	return function unsupportedExpression(expr) {
 		var dep = new ConstDependency("(void 0)", expr.range, false);
 		dep.loc = expr.loc;
@@ -94,10 +92,6 @@ ParserHelpers.expressionIsUnsupported = (parser, message) => {
 	};
 };
 
-ParserHelpers.skipTraversal = function skipTraversal() {
-	return true;
-};
+exports.skipTraversal = () => true;
 
-ParserHelpers.approve = function approve() {
-	return true;
-};
+exports.approve = () => true;
diff --git a/lib/NodeStuffPlugin.js b/lib/NodeStuffPlugin.js
index 9ee407cd6..c15c3857d 100644
--- a/lib/NodeStuffPlugin.js
+++ b/lib/NodeStuffPlugin.js
@@ -5,9 +5,15 @@
 "use strict";
 
 const path = require("path");
-const ParserHelpers = require("./ParserHelpers");
 const ConstDependency = require("./dependencies/ConstDependency");
-
+const {
+	addParsedVariableToModule,
+	evaluateToIdentifier,
+	evaluateToString,
+	expressionIsUnsupported,
+	toConstantDependency,
+	toConstantDependencyWithWebpackRequire
+} = require("./JavascriptParserHelpers");
 const NullFactory = require("./NullFactory");
 
 class NodeStuffPlugin {
@@ -71,9 +77,9 @@ class NodeStuffPlugin {
 							if (!parser.state.module) return;
 							const resource = parser.state.module.resource;
 							const i = resource.indexOf("?");
-							return ParserHelpers.evaluateToString(
-								i < 0 ? resource : resource.substr(0, i)
-							)(expr);
+							return evaluateToString(i < 0 ? resource : resource.substr(0, i))(
+								expr
+							);
 						});
 					if (localOptions.__dirname === "mock") {
 						setConstant("__dirname", "/");
@@ -86,15 +92,13 @@ class NodeStuffPlugin {
 						.for("__dirname")
 						.tap("NodeStuffPlugin", expr => {
 							if (!parser.state.module) return;
-							return ParserHelpers.evaluateToString(
-								parser.state.module.context
-							)(expr);
+							return evaluateToString(parser.state.module.context)(expr);
 						});
 					parser.hooks.expression
 						.for("require.main")
 						.tap(
 							"NodeStuffPlugin",
-							ParserHelpers.toConstantDependencyWithWebpackRequire(
+							toConstantDependencyWithWebpackRequire(
 								parser,
 								"__webpack_require__.c[__webpack_require__.s]"
 							)
@@ -103,7 +107,7 @@ class NodeStuffPlugin {
 						.for("require.extensions")
 						.tap(
 							"NodeStuffPlugin",
-							ParserHelpers.expressionIsUnsupported(
+							expressionIsUnsupported(
 								parser,
 								"require.extensions is not supported by webpack. Use a loader instead."
 							)
@@ -113,18 +117,14 @@ class NodeStuffPlugin {
 						.tap("NodeStuffPlugin", expr => {
 							parser.state.module.buildMeta.moduleConcatenationBailout =
 								"module.loaded";
-							return ParserHelpers.toConstantDependency(parser, "module.l")(
-								expr
-							);
+							return toConstantDependency(parser, "module.l")(expr);
 						});
 					parser.hooks.expression
 						.for("module.id")
 						.tap("NodeStuffPlugin", expr => {
 							parser.state.module.buildMeta.moduleConcatenationBailout =
 								"module.id";
-							return ParserHelpers.toConstantDependency(parser, "module.i")(
-								expr
-							);
+							return toConstantDependency(parser, "module.i")(expr);
 						});
 					parser.hooks.expression
 						.for("module.exports")
@@ -136,10 +136,7 @@ class NodeStuffPlugin {
 						});
 					parser.hooks.evaluateIdentifier
 						.for("module.hot")
-						.tap(
-							"NodeStuffPlugin",
-							ParserHelpers.evaluateToIdentifier("module.hot", false)
-						);
+						.tap("NodeStuffPlugin", evaluateToIdentifier("module.hot", false));
 					parser.hooks.expression.for("module").tap("NodeStuffPlugin", () => {
 						const module = parser.state.module;
 						const isHarmony = module.buildMeta && module.buildMeta.exportsType;
@@ -158,7 +155,7 @@ class NodeStuffPlugin {
 								moduleJsPath = `./${moduleJsPath.replace(/\\/g, "/")}`;
 							}
 						}
-						return ParserHelpers.addParsedVariableToModule(
+						return addParsedVariableToModule(
 							parser,
 							"module",
 							`require(${JSON.stringify(moduleJsPath)})(module)`
diff --git a/lib/ProvidePlugin.js b/lib/ProvidePlugin.js
index b09d8c864..abd2cfe1f 100644
--- a/lib/ProvidePlugin.js
+++ b/lib/ProvidePlugin.js
@@ -4,9 +4,12 @@
 */
 "use strict";
 
-const ParserHelpers = require("./ParserHelpers");
 const ConstDependency = require("./dependencies/ConstDependency");
-
+const {
+	addParsedVariableToModule,
+	approve,
+	toConstantDependency
+} = require("./JavascriptParserHelpers");
 const NullFactory = require("./NullFactory");
 
 class ProvidePlugin {
@@ -31,9 +34,7 @@ class ProvidePlugin {
 						if (splittedName.length > 0) {
 							splittedName.slice(1).forEach((_, i) => {
 								const name = splittedName.slice(0, i + 1).join(".");
-								parser.hooks.canRename
-									.for(name)
-									.tap("ProvidePlugin", ParserHelpers.approve);
+								parser.hooks.canRename.for(name).tap("ProvidePlugin", approve);
 							});
 						}
 						parser.hooks.expression.for(name).tap("ProvidePlugin", expr => {
@@ -53,18 +54,12 @@ class ProvidePlugin {
 									.join("");
 							}
 							if (
-								!ParserHelpers.addParsedVariableToModule(
-									parser,
-									nameIdentifier,
-									expression
-								)
+								!addParsedVariableToModule(parser, nameIdentifier, expression)
 							) {
 								return false;
 							}
 							if (scopedName) {
-								ParserHelpers.toConstantDependency(parser, nameIdentifier)(
-									expr
-								);
+								toConstantDependency(parser, nameIdentifier)(expr);
 							}
 							return true;
 						});
diff --git a/lib/RequireJsStuffPlugin.js b/lib/RequireJsStuffPlugin.js
index c9888056a..88a7bb443 100644
--- a/lib/RequireJsStuffPlugin.js
+++ b/lib/RequireJsStuffPlugin.js
@@ -4,9 +4,12 @@
 */
 "use strict";
 
-const ParserHelpers = require("./ParserHelpers");
 const ConstDependency = require("./dependencies/ConstDependency");
 const NullFactory = require("./NullFactory");
+const {
+	toConstantDependency,
+	toConstantDependencyWithWebpackRequire
+} = require("./JavascriptParserHelpers");
 
 module.exports = class RequireJsStuffPlugin {
 	apply(compiler) {
@@ -30,29 +33,26 @@ module.exports = class RequireJsStuffPlugin {
 						.for("require.config")
 						.tap(
 							"RequireJsStuffPlugin",
-							ParserHelpers.toConstantDependency(parser, "undefined")
+							toConstantDependency(parser, "undefined")
 						);
 					parser.hooks.call
 						.for("requirejs.config")
 						.tap(
 							"RequireJsStuffPlugin",
-							ParserHelpers.toConstantDependency(parser, "undefined")
+							toConstantDependency(parser, "undefined")
 						);
 
 					parser.hooks.expression
 						.for("require.version")
 						.tap(
 							"RequireJsStuffPlugin",
-							ParserHelpers.toConstantDependency(
-								parser,
-								JSON.stringify("0.0.0")
-							)
+							toConstantDependency(parser, JSON.stringify("0.0.0"))
 						);
 					parser.hooks.expression
 						.for("requirejs.onError")
 						.tap(
 							"RequireJsStuffPlugin",
-							ParserHelpers.toConstantDependencyWithWebpackRequire(
+							toConstantDependencyWithWebpackRequire(
 								parser,
 								"__webpack_require__.oe"
 							)
diff --git a/lib/dependencies/AMDPlugin.js b/lib/dependencies/AMDPlugin.js
index 06b8cd730..de06dbfbe 100644
--- a/lib/dependencies/AMDPlugin.js
+++ b/lib/dependencies/AMDPlugin.js
@@ -20,7 +20,12 @@ const AMDDefineDependencyParserPlugin = require("./AMDDefineDependencyParserPlug
 
 const AliasPlugin = require("enhanced-resolve/lib/AliasPlugin");
 
-const ParserHelpers = require("../ParserHelpers");
+const {
+	approve,
+	evaluateToIdentifier,
+	evaluateToString,
+	toConstantDependency
+} = require("../JavascriptParserHelpers");
 
 class AMDPlugin {
 	constructor(options, amdOptions) {
@@ -128,43 +133,26 @@ class AMDPlugin {
 						);
 					parser.hooks.evaluateTypeof
 						.for("define.amd")
-						.tap(
-							"AMDPlugin",
-							ParserHelpers.evaluateToString(typeof amdOptions)
-						);
+						.tap("AMDPlugin", evaluateToString(typeof amdOptions));
 					parser.hooks.evaluateTypeof
 						.for("require.amd")
-						.tap(
-							"AMDPlugin",
-							ParserHelpers.evaluateToString(typeof amdOptions)
-						);
+						.tap("AMDPlugin", evaluateToString(typeof amdOptions));
 					parser.hooks.evaluateIdentifier
 						.for("define.amd")
-						.tap(
-							"AMDPlugin",
-							ParserHelpers.evaluateToIdentifier("define.amd", true)
-						);
+						.tap("AMDPlugin", evaluateToIdentifier("define.amd", true));
 					parser.hooks.evaluateIdentifier
 						.for("require.amd")
-						.tap(
-							"AMDPlugin",
-							ParserHelpers.evaluateToIdentifier("require.amd", true)
-						);
+						.tap("AMDPlugin", evaluateToIdentifier("require.amd", true));
 					parser.hooks.typeof
 						.for("define")
 						.tap(
 							"AMDPlugin",
-							ParserHelpers.toConstantDependency(
-								parser,
-								JSON.stringify("function")
-							)
+							toConstantDependency(parser, JSON.stringify("function"))
 						);
 					parser.hooks.evaluateTypeof
 						.for("define")
-						.tap("AMDPlugin", ParserHelpers.evaluateToString("function"));
-					parser.hooks.canRename
-						.for("define")
-						.tap("AMDPlugin", ParserHelpers.approve);
+						.tap("AMDPlugin", evaluateToString("function"));
+					parser.hooks.canRename.for("define").tap("AMDPlugin", approve);
 					parser.hooks.rename.for("define").tap("AMDPlugin", expr => {
 						const dep = new AMDRequireItemDependency(
 							"!!webpack amd define",
@@ -179,14 +167,11 @@ class AMDPlugin {
 						.for("require")
 						.tap(
 							"AMDPlugin",
-							ParserHelpers.toConstantDependency(
-								parser,
-								JSON.stringify("function")
-							)
+							toConstantDependency(parser, JSON.stringify("function"))
 						);
 					parser.hooks.evaluateTypeof
 						.for("require")
-						.tap("AMDPlugin", ParserHelpers.evaluateToString("function"));
+						.tap("AMDPlugin", evaluateToString("function"));
 				};
 
 				normalModuleFactory.hooks.parser
diff --git a/lib/dependencies/CommonJsPlugin.js b/lib/dependencies/CommonJsPlugin.js
index fc6cae7ec..560c8e7f9 100644
--- a/lib/dependencies/CommonJsPlugin.js
+++ b/lib/dependencies/CommonJsPlugin.js
@@ -16,7 +16,11 @@ const NullFactory = require("../NullFactory");
 const RequireResolveDependencyParserPlugin = require("./RequireResolveDependencyParserPlugin");
 const CommonJsRequireDependencyParserPlugin = require("./CommonJsRequireDependencyParserPlugin");
 
-const ParserHelpers = require("../ParserHelpers");
+const {
+	evaluateToIdentifier,
+	evaluateToString,
+	toConstantDependency
+} = require("../JavascriptParserHelpers");
 
 class CommonJsPlugin {
 	constructor(options) {
@@ -99,28 +103,19 @@ class CommonJsPlugin {
 							.for(expression)
 							.tap(
 								"CommonJsPlugin",
-								ParserHelpers.toConstantDependency(
-									parser,
-									JSON.stringify("function")
-								)
+								toConstantDependency(parser, JSON.stringify("function"))
 							);
 						parser.hooks.evaluateTypeof
 							.for(expression)
-							.tap(
-								"CommonJsPlugin",
-								ParserHelpers.evaluateToString("function")
-							);
+							.tap("CommonJsPlugin", evaluateToString("function"));
 						parser.hooks.evaluateIdentifier
 							.for(expression)
-							.tap(
-								"CommonJsPlugin",
-								ParserHelpers.evaluateToIdentifier(expression, true)
-							);
+							.tap("CommonJsPlugin", evaluateToIdentifier(expression, true));
 					}
 
 					parser.hooks.evaluateTypeof
 						.for("module")
-						.tap("CommonJsPlugin", ParserHelpers.evaluateToString("object"));
+						.tap("CommonJsPlugin", evaluateToString("object"));
 					parser.hooks.assign.for("require").tap("CommonJsPlugin", expr => {
 						// to not leak to global "require", we need to define a local require here.
 						const dep = new ConstDependency("var require;", 0);
@@ -142,7 +137,7 @@ class CommonJsPlugin {
 					parser.hooks.typeof.for("module").tap("CommonJsPlugin", () => true);
 					parser.hooks.evaluateTypeof
 						.for("exports")
-						.tap("CommonJsPlugin", ParserHelpers.evaluateToString("object"));
+						.tap("CommonJsPlugin", evaluateToString("object"));
 
 					new CommonJsRequireDependencyParserPlugin(options).apply(parser);
 					new RequireResolveDependencyParserPlugin(options).apply(parser);
diff --git a/lib/dependencies/CommonJsRequireDependencyParserPlugin.js b/lib/dependencies/CommonJsRequireDependencyParserPlugin.js
index 29dc81749..b7091d70b 100644
--- a/lib/dependencies/CommonJsRequireDependencyParserPlugin.js
+++ b/lib/dependencies/CommonJsRequireDependencyParserPlugin.js
@@ -10,7 +10,9 @@ const RequireHeaderDependency = require("./RequireHeaderDependency");
 const LocalModuleDependency = require("./LocalModuleDependency");
 const ContextDependencyHelpers = require("./ContextDependencyHelpers");
 const LocalModulesHelpers = require("./LocalModulesHelpers");
-const ParserHelpers = require("../ParserHelpers");
+const {
+	toConstantDependencyWithWebpackRequire
+} = require("../JavascriptParserHelpers");
 
 class CommonJsRequireDependencyParserPlugin {
 	constructor(options) {
@@ -48,10 +50,7 @@ class CommonJsRequireDependencyParserPlugin {
 			.for("require.cache")
 			.tap(
 				"CommonJsRequireDependencyParserPlugin",
-				ParserHelpers.toConstantDependencyWithWebpackRequire(
-					parser,
-					"__webpack_require__.c"
-				)
+				toConstantDependencyWithWebpackRequire(parser, "__webpack_require__.c")
 			);
 		parser.hooks.expression
 			.for("require")
diff --git a/lib/dependencies/RequireEnsurePlugin.js b/lib/dependencies/RequireEnsurePlugin.js
index e508ec4fc..d31d262d2 100644
--- a/lib/dependencies/RequireEnsurePlugin.js
+++ b/lib/dependencies/RequireEnsurePlugin.js
@@ -11,7 +11,10 @@ const NullFactory = require("../NullFactory");
 
 const RequireEnsureDependenciesBlockParserPlugin = require("./RequireEnsureDependenciesBlockParserPlugin");
 
-const ParserHelpers = require("../ParserHelpers");
+const {
+	evaluateToString,
+	toConstantDependency
+} = require("../JavascriptParserHelpers");
 
 class RequireEnsurePlugin {
 	apply(compiler) {
@@ -46,18 +49,12 @@ class RequireEnsurePlugin {
 					new RequireEnsureDependenciesBlockParserPlugin().apply(parser);
 					parser.hooks.evaluateTypeof
 						.for("require.ensure")
-						.tap(
-							"RequireEnsurePlugin",
-							ParserHelpers.evaluateToString("function")
-						);
+						.tap("RequireEnsurePlugin", evaluateToString("function"));
 					parser.hooks.typeof
 						.for("require.ensure")
 						.tap(
 							"RequireEnsurePlugin",
-							ParserHelpers.toConstantDependency(
-								parser,
-								JSON.stringify("function")
-							)
+							toConstantDependency(parser, JSON.stringify("function"))
 						);
 				};
 
diff --git a/lib/dependencies/RequireIncludePlugin.js b/lib/dependencies/RequireIncludePlugin.js
index e5811a07e..98d77f04a 100644
--- a/lib/dependencies/RequireIncludePlugin.js
+++ b/lib/dependencies/RequireIncludePlugin.js
@@ -7,7 +7,10 @@
 const RequireIncludeDependency = require("./RequireIncludeDependency");
 const RequireIncludeDependencyParserPlugin = require("./RequireIncludeDependencyParserPlugin");
 
-const ParserHelpers = require("../ParserHelpers");
+const {
+	evaluateToString,
+	toConstantDependency
+} = require("../JavascriptParserHelpers");
 
 class RequireIncludePlugin {
 	apply(compiler) {
@@ -33,18 +36,12 @@ class RequireIncludePlugin {
 					new RequireIncludeDependencyParserPlugin().apply(parser);
 					parser.hooks.evaluateTypeof
 						.for("require.include")
-						.tap(
-							"RequireIncludePlugin",
-							ParserHelpers.evaluateToString("function")
-						);
+						.tap("RequireIncludePlugin", evaluateToString("function"));
 					parser.hooks.typeof
 						.for("require.include")
 						.tap(
 							"RequireIncludePlugin",
-							ParserHelpers.toConstantDependency(
-								parser,
-								JSON.stringify("function")
-							)
+							toConstantDependency(parser, JSON.stringify("function"))
 						);
 				};
 
diff --git a/lib/dependencies/SystemPlugin.js b/lib/dependencies/SystemPlugin.js
index 5caf3d965..e615341de 100644
--- a/lib/dependencies/SystemPlugin.js
+++ b/lib/dependencies/SystemPlugin.js
@@ -4,7 +4,13 @@
 */
 "use strict";
 
-const ParserHelpers = require("../ParserHelpers");
+const {
+	addParsedVariableToModule,
+	evaluateToString,
+	expressionIsUnsupported,
+	requireFileAsExpression,
+	toConstantDependency
+} = require("../JavascriptParserHelpers");
 const WebpackError = require("../WebpackError");
 
 class SystemPlugin {
@@ -27,12 +33,12 @@ class SystemPlugin {
 					const setNotSupported = name => {
 						parser.hooks.evaluateTypeof
 							.for(name)
-							.tap("SystemPlugin", ParserHelpers.evaluateToString("undefined"));
+							.tap("SystemPlugin", evaluateToString("undefined"));
 						parser.hooks.expression
 							.for(name)
 							.tap(
 								"SystemPlugin",
-								ParserHelpers.expressionIsUnsupported(
+								expressionIsUnsupported(
 									parser,
 									name + " is not supported by webpack."
 								)
@@ -43,37 +49,31 @@ class SystemPlugin {
 						.for("System.import")
 						.tap(
 							"SystemPlugin",
-							ParserHelpers.toConstantDependency(
-								parser,
-								JSON.stringify("function")
-							)
+							toConstantDependency(parser, JSON.stringify("function"))
 						);
 					parser.hooks.evaluateTypeof
 						.for("System.import")
-						.tap("SystemPlugin", ParserHelpers.evaluateToString("function"));
+						.tap("SystemPlugin", evaluateToString("function"));
 					parser.hooks.typeof
 						.for("System")
 						.tap(
 							"SystemPlugin",
-							ParserHelpers.toConstantDependency(
-								parser,
-								JSON.stringify("object")
-							)
+							toConstantDependency(parser, JSON.stringify("object"))
 						);
 					parser.hooks.evaluateTypeof
 						.for("System")
-						.tap("SystemPlugin", ParserHelpers.evaluateToString("object"));
+						.tap("SystemPlugin", evaluateToString("object"));
 
 					setNotSupported("System.set");
 					setNotSupported("System.get");
 					setNotSupported("System.register");
 
 					parser.hooks.expression.for("System").tap("SystemPlugin", () => {
-						const systemPolyfillRequire = ParserHelpers.requireFileAsExpression(
+						const systemPolyfillRequire = requireFileAsExpression(
 							parser.state.module.context,
 							require.resolve("../../buildin/system.js")
 						);
-						return ParserHelpers.addParsedVariableToModule(
+						return addParsedVariableToModule(
 							parser,
 							"System",
 							systemPolyfillRequire
diff --git a/lib/node/NodeSourcePlugin.js b/lib/node/NodeSourcePlugin.js
index 31825bb5c..3acc100cb 100644
--- a/lib/node/NodeSourcePlugin.js
+++ b/lib/node/NodeSourcePlugin.js
@@ -3,9 +3,13 @@
 	Author Tobias Koppers @sokra
 */
 "use strict";
+
 const AliasPlugin = require("enhanced-resolve/lib/AliasPlugin");
-const ParserHelpers = require("../ParserHelpers");
 const nodeLibsBrowser = require("node-libs-browser");
+const {
+	addParsedVariableToModule,
+	requireFileAsExpression
+} = require("../JavascriptParserHelpers");
 
 module.exports = class NodeSourcePlugin {
 	constructor(options) {
@@ -43,15 +47,11 @@ module.exports = class NodeSourcePlugin {
 					parser.state.module.resource === getPathToModule(module, type)
 				)
 					return;
-				const mockModule = ParserHelpers.requireFileAsExpression(
+				const mockModule = requireFileAsExpression(
 					parser.state.module.context,
 					getPathToModule(module, type)
 				);
-				return ParserHelpers.addParsedVariableToModule(
-					parser,
-					name,
-					mockModule + suffix
-				);
+				return addParsedVariableToModule(parser, name, mockModule + suffix);
 			});
 		};
 
@@ -69,11 +69,11 @@ module.exports = class NodeSourcePlugin {
 						parser.hooks.expression
 							.for("global")
 							.tap("NodeSourcePlugin", () => {
-								const retrieveGlobalModule = ParserHelpers.requireFileAsExpression(
+								const retrieveGlobalModule = requireFileAsExpression(
 									parser.state.module.context,
 									require.resolve("../../buildin/global.js")
 								);
-								return ParserHelpers.addParsedVariableToModule(
+								return addParsedVariableToModule(
 									parser,
 									"global",
 									retrieveGlobalModule
diff --git a/lib/optimize/ConcatenatedModule.js b/lib/optimize/ConcatenatedModule.js
index 2ec0d4bc7..555e5c28e 100644
--- a/lib/optimize/ConcatenatedModule.js
+++ b/lib/optimize/ConcatenatedModule.js
@@ -6,7 +6,7 @@
 
 const Module = require("../Module");
 const Template = require("../Template");
-const Parser = require("../Parser");
+const JavascriptParser = require("../JavascriptParser");
 const eslintScope = require("eslint-scope");
 const { ConcatSource, ReplaceSource } = require("webpack-sources");
 const DependencyReference = require("../dependencies/DependencyReference");
@@ -637,7 +637,7 @@ class ConcatenatedModule extends Module {
 				const code = source.source();
 				let ast;
 				try {
-					ast = Parser.parse(code, {
+					ast = JavascriptParser.parse(code, {
 						sourceType: "module"
 					});
 				} catch (err) {


Test patch:
diff --git a/test/Parser.unittest.js b/test/JavascriptParser.unittest.js
similarity index 87%
rename from test/Parser.unittest.js
rename to test/JavascriptParser.unittest.js
index 3d3fdeeca..2abd9d88e 100644
--- a/test/Parser.unittest.js
+++ b/test/JavascriptParser.unittest.js
@@ -1,9 +1,9 @@
 "use strict";
 
-const Parser = require("../lib/Parser");
 const BasicEvaluatedExpression = require("../lib/BasicEvaluatedExpression");
+const JavascriptParser = require("../lib/JavascriptParser");
 
-describe("Parser", () => {
+describe("JavascriptParser", () => {
 	/* eslint-disable no-undef */
 	/* eslint-disable no-unused-vars */
 	/* eslint-disable no-inner-declarations */
@@ -258,49 +258,71 @@ describe("Parser", () => {
 			source = source.substr(13, source.length - 14).trim();
 			const state = testCases[name][1];
 
-			const testParser = new Parser({});
-			testParser.hooks.canRename.tap("abc", "ParserTest", expr => true);
-			testParser.hooks.canRename.tap("ijk", "ParserTest", expr => true);
-			testParser.hooks.call.tap("abc", "ParserTest", expr => {
+			const testParser = new JavascriptParser({});
+			testParser.hooks.canRename.tap(
+				"abc",
+				"JavascriptParserTest",
+				expr => true
+			);
+			testParser.hooks.canRename.tap(
+				"ijk",
+				"JavascriptParserTest",
+				expr => true
+			);
+			testParser.hooks.call.tap("abc", "JavascriptParserTest", expr => {
 				if (!testParser.state.abc) testParser.state.abc = [];
 				testParser.state.abc.push(testParser.parseString(expr.arguments[0]));
 				return true;
 			});
-			testParser.hooks.call.tap("cde.abc", "ParserTest", expr => {
+			testParser.hooks.call.tap("cde.abc", "JavascriptParserTest", expr => {
 				if (!testParser.state.cdeabc) testParser.state.cdeabc = [];
 				testParser.state.cdeabc.push(testParser.parseString(expr.arguments[0]));
 				return true;
 			});
-			testParser.hooks.call.tap("cde.ddd.abc", "ParserTest", expr => {
+			testParser.hooks.call.tap("cde.ddd.abc", "JavascriptParserTest", expr => {
 				if (!testParser.state.cdedddabc) testParser.state.cdedddabc = [];
 				testParser.state.cdedddabc.push(
 					testParser.parseString(expr.arguments[0])
 				);
 				return true;
 			});
-			testParser.hooks.expression.tap("fgh", "ParserTest", expr => {
+			testParser.hooks.expression.tap("fgh", "JavascriptParserTest", expr => {
 				if (!testParser.state.fgh) testParser.state.fgh = [];
 				testParser.state.fgh.push(
 					Array.from(testParser.scope.definitions.asSet()).join(" ")
 				);
 				return true;
 			});
-			testParser.hooks.expression.tap("fgh.sub", "ParserTest", expr => {
-				if (!testParser.state.fghsub) testParser.state.fghsub = [];
-				testParser.state.fghsub.push(testParser.scope.inTry ? "try" : "notry");
-				return true;
-			});
-			testParser.hooks.expression.tap("ijk.sub", "ParserTest", expr => {
-				if (!testParser.state.ijksub) testParser.state.ijksub = [];
-				testParser.state.ijksub.push("test");
-				return true;
-			});
-			testParser.hooks.expression.tap("memberExpr", "ParserTest", expr => {
-				if (!testParser.state.expressions) testParser.state.expressions = [];
-				testParser.state.expressions.push(expr.name);
-				return true;
-			});
-			testParser.hooks.new.tap("xyz", "ParserTest", expr => {
+			testParser.hooks.expression.tap(
+				"fgh.sub",
+				"JavascriptParserTest",
+				expr => {
+					if (!testParser.state.fghsub) testParser.state.fghsub = [];
+					testParser.state.fghsub.push(
+						testParser.scope.inTry ? "try" : "notry"
+					);
+					return true;
+				}
+			);
+			testParser.hooks.expression.tap(
+				"ijk.sub",
+				"JavascriptParserTest",
+				expr => {
+					if (!testParser.state.ijksub) testParser.state.ijksub = [];
+					testParser.state.ijksub.push("test");
+					return true;
+				}
+			);
+			testParser.hooks.expression.tap(
+				"memberExpr",
+				"JavascriptParserTest",
+				expr => {
+					if (!testParser.state.expressions) testParser.state.expressions = [];
+					testParser.state.expressions.push(expr.name);
+					return true;
+				}
+			);
+			testParser.hooks.new.tap("xyz", "JavascriptParserTest", expr => {
 				if (!testParser.state.xyz) testParser.state.xyz = [];
 				testParser.state.xyz.push(testParser.parseString(expr.arguments[0]));
 				return true;
@@ -324,9 +346,9 @@ describe("Parser", () => {
 			}
 		];
 
-		const testParser = new Parser({});
+		const testParser = new JavascriptParser({});
 
-		testParser.hooks.program.tap("ParserTest", (ast, comments) => {
+		testParser.hooks.program.tap("JavascriptParserTest", (ast, comments) => {
 			if (!testParser.state.comments) testParser.state.comments = comments;
 			return true;
 		});
@@ -344,15 +366,23 @@ describe("Parser", () => {
 
 	describe("expression evaluation", () => {
 		function evaluateInParser(source) {
-			const parser = new Parser();
-			parser.hooks.call.tap("test", "ParserTest", expr => {
+			const parser = new JavascriptParser();
+			parser.hooks.call.tap("test", "JavascriptParserTest", expr => {
 				parser.state.result = parser.evaluateExpression(expr.arguments[0]);
 			});
-			parser.hooks.evaluateIdentifier.tap("aString", "ParserTest", expr =>
-				new BasicEvaluatedExpression().setString("aString").setRange(expr.range)
+			parser.hooks.evaluateIdentifier.tap(
+				"aString",
+				"JavascriptParserTest",
+				expr =>
+					new BasicEvaluatedExpression()
+						.setString("aString")
+						.setRange(expr.range)
 			);
-			parser.hooks.evaluateIdentifier.tap("b.Number", "ParserTest", expr =>
-				new BasicEvaluatedExpression().setNumber(123).setRange(expr.range)
+			parser.hooks.evaluateIdentifier.tap(
+				"b.Number",
+				"JavascriptParserTest",
+				expr =>
+					new BasicEvaluatedExpression().setNumber(123).setRange(expr.range)
 			);
 			return parser.parse("test(" + source + ");").result;
 		}
@@ -559,7 +589,7 @@ describe("Parser", () => {
 				"await expression": "async function x(y) { await y }",
 				"await iteration": "async function f() { for await (x of xs); }"
 			};
-			const parser = new Parser();
+			const parser = new JavascriptParser();
 			Object.keys(cases).forEach(name => {
 				const expr = cases[name];
 				it(name, () => {
@@ -584,12 +614,12 @@ describe("Parser", () => {
 				]
 			};
 
-			const parser = new Parser();
-			parser.hooks.call.tap("require", "ParserTest", expr => {
+			const parser = new JavascriptParser();
+			parser.hooks.call.tap("require", "JavascriptParserTest", expr => {
 				const param = parser.evaluateExpression(expr.arguments[0]);
 				parser.state.param = param.string;
 			});
-			parser.hooks.importCall.tap("ParserTest", expr => {
+			parser.hooks.importCall.tap("JavascriptParserTest", expr => {
 				const param = parser.evaluateExpression(expr.arguments[0]);
 				parser.state.param = param.string;
 			});
@@ -612,7 +642,7 @@ describe("Parser", () => {
 			Object.keys(cases).forEach(name => {
 				const expr = cases[name];
 				it(name, () => {
-					const actual = Parser.parse(expr);
+					const actual = JavascriptParser.parse(expr);
 					expect(typeof actual).toBe("object");
 				});
 			});
@@ -627,7 +657,7 @@ describe("Parser", () => {
 			Object.keys(cases).forEach(name => {
 				const expr = cases[name];
 				it(name, () => {
-					const actual = Parser.parse(expr);
+					const actual = JavascriptParser.parse(expr);
 					expect(typeof actual).toBe("object");
 				});
 			});