From babe736cfa1ef7e8014ed32ba4a4ec38049dce14 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Mon, 5 Nov 2018 15:17:10 +0100 Subject: [PATCH] replace prefix/postfix even when equal for wrapped context walk inner expressions in wrapped context add tracking of inner expressions in wrapped BasicEvaluatedExpression fixes #8293 closes ##8337 --- lib/BasicEvaluatedExpression.js | 4 +- lib/Parser.js | 80 +++++++++++++++---- lib/dependencies/ContextDependencyHelpers.js | 11 ++- .../plugins/define-plugin/{ => dir}/a.js | 0 .../plugins/define-plugin/index.js | 17 ++-- 5 files changed, 90 insertions(+), 22 deletions(-) rename test/configCases/plugins/define-plugin/{ => dir}/a.js (100%) diff --git a/lib/BasicEvaluatedExpression.js b/lib/BasicEvaluatedExpression.js index 559c521142a..a0f7bd435b7 100644 --- a/lib/BasicEvaluatedExpression.js +++ b/lib/BasicEvaluatedExpression.js @@ -35,6 +35,7 @@ class BasicEvaluatedExpression { this.options = null; this.prefix = null; this.postfix = null; + this.wrappedInnerExpressions = null; this.expression = null; } @@ -176,10 +177,11 @@ class BasicEvaluatedExpression { return this; } - setWrapped(prefix, postfix) { + setWrapped(prefix, postfix, innerExpressions) { this.type = TypeWrapped; this.prefix = prefix; this.postfix = postfix; + this.wrappedInnerExpressions = innerExpressions; return this; } diff --git a/lib/Parser.js b/lib/Parser.js index 0ff49bb7b76..23a96119f61 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -216,62 +216,114 @@ class Parser extends Tapable { right.prefix && right.prefix.isString() ) { + // "left" + ("prefix" + inner + "postfix") + // => ("leftprefix" + inner + "postfix") res.setWrapped( new BasicEvaluatedExpression() .setString(left.string + right.prefix.string) .setRange(joinRanges(left.range, right.prefix.range)), - right.postfix + right.postfix, + right.wrappedInnerExpressions ); } else if (right.isWrapped()) { - res.setWrapped( - new BasicEvaluatedExpression() - .setString(left.string) - .setRange(left.range), - right.postfix - ); + // "left" + ([null] + inner + "postfix") + // => ("left" + inner + "postfix") + res.setWrapped(left, right.postfix, right.wrappedInnerExpressions); } else { - res.setWrapped(left, null); + // "left" + expr + // => ("left" + expr + "") + res.setWrapped(left, null, [right]); } } else if (left.isNumber()) { if (right.isString()) { res.setString(left.number + right.string); } else if (right.isNumber()) { res.setNumber(left.number + right.number); + } else { + return; } } else if (left.isWrapped()) { if (left.postfix && left.postfix.isString() && right.isString()) { + // ("prefix" + inner + "postfix") + "right" + // => ("prefix" + inner + "postfixright") res.setWrapped( left.prefix, new BasicEvaluatedExpression() .setString(left.postfix.string + right.string) - .setRange(joinRanges(left.postfix.range, right.range)) + .setRange(joinRanges(left.postfix.range, right.range)), + left.wrappedInnerExpressions ); } else if ( left.postfix && left.postfix.isString() && right.isNumber() ) { + // ("prefix" + inner + "postfix") + 123 + // => ("prefix" + inner + "postfix123") res.setWrapped( left.prefix, new BasicEvaluatedExpression() .setString(left.postfix.string + right.number) - .setRange(joinRanges(left.postfix.range, right.range)) + .setRange(joinRanges(left.postfix.range, right.range)), + left.wrappedInnerExpressions ); } else if (right.isString()) { - res.setWrapped(left.prefix, right); + // ("prefix" + inner + [null]) + "right" + // => ("prefix" + inner + "right") + res.setWrapped(left.prefix, right, left.wrappedInnerExpressions); } else if (right.isNumber()) { + // ("prefix" + inner + [null]) + 123 + // => ("prefix" + inner + "123") res.setWrapped( left.prefix, new BasicEvaluatedExpression() .setString(right.number + "") - .setRange(right.range) + .setRange(right.range), + left.wrappedInnerExpressions + ); + } else if (right.isWrapped()) { + // ("prefix1" + inner1 + "postfix1") + ("prefix2" + inner2 + "postfix2") + // ("prefix1" + inner1 + "postfix1" + "prefix2" + inner2 + "postfix2") + res.setWrapped( + left.prefix, + right.postfix, + left.wrappedInnerExpressions && + right.wrappedInnerExpressions && + left.wrappedInnerExpressions + .concat(left.postfix ? [left.postfix] : []) + .concat(right.prefix ? [right.prefix] : []) + .concat(right.wrappedInnerExpressions) ); } else { - res.setWrapped(left.prefix, new BasicEvaluatedExpression()); + // ("prefix" + inner + postfix) + expr + // => ("prefix" + inner + postfix + expr + [null]) + res.setWrapped( + left.prefix, + null, + left.wrappedInnerExpressions && + left.wrappedInnerExpressions.concat( + left.postfix ? [left.postfix, right] : [right] + ) + ); } } else { if (right.isString()) { - res.setWrapped(null, right); + // left + "right" + // => ([null] + left + "right") + res.setWrapped(null, right, [left]); + } else if (right.isWrapped()) { + // left + (prefix + inner + "postfix") + // => ([null] + left + prefix + inner + "postfix") + res.setWrapped( + null, + right.postfix, + right.wrappedInnerExpressions && + (right.prefix ? [left, right.prefix] : [left]).concat( + right.wrappedInnerExpressions + ) + ); + } else { + return; } } res.setRange(expr.range); diff --git a/lib/dependencies/ContextDependencyHelpers.js b/lib/dependencies/ContextDependencyHelpers.js index 36e2dedee40..377425b2531 100644 --- a/lib/dependencies/ContextDependencyHelpers.js +++ b/lib/dependencies/ContextDependencyHelpers.js @@ -180,13 +180,13 @@ ContextDependencyHelpers.create = ( ); dep.loc = expr.loc; const replaces = []; - if (prefixRange && prefix !== prefixRaw) { + if (prefixRange) { replaces.push({ range: prefixRange, value: JSON.stringify(prefix) }); } - if (postfixRange && postfix !== postfixRaw) { + if (postfixRange) { replaces.push({ range: postfixRange, value: JSON.stringify(postfix) @@ -196,6 +196,13 @@ ContextDependencyHelpers.create = ( dep.critical = options.wrappedContextCritical && "a part of the request of a dependency is an expression"; + + if (parser && param.wrappedInnerExpressions) { + for (const part of param.wrappedInnerExpressions) { + if (part.expression) parser.walkExpression(part.expression); + } + } + return dep; } else { const dep = new Dep( diff --git a/test/configCases/plugins/define-plugin/a.js b/test/configCases/plugins/define-plugin/dir/a.js similarity index 100% rename from test/configCases/plugins/define-plugin/a.js rename to test/configCases/plugins/define-plugin/dir/a.js diff --git a/test/configCases/plugins/define-plugin/index.js b/test/configCases/plugins/define-plugin/index.js index 6e18cbb7432..dfd714a5544 100644 --- a/test/configCases/plugins/define-plugin/index.js +++ b/test/configCases/plugins/define-plugin/index.js @@ -2,8 +2,8 @@ it("should define FALSE", function() { expect(FALSE).toBe(false); expect((typeof TRUE)).toBe("boolean"); - var x = require(FALSE ? "fail" : "./a"); - var y = FALSE ? require("fail") : require("./a"); + var x = require(FALSE ? "fail" : "./dir/a"); + var y = FALSE ? require("fail") : require("./dir/a"); }); it("should define CODE", function() { @@ -120,8 +120,15 @@ it("should check that runtimeValue callback argument is a module", function() { }); it("should expand properly", function() { + const a = require("./dir/a"); var tmp = ''; - expect(function() { - require('./' + A_DOT_J + tmp + 's'); - }).not.toThrowError(ReferenceError, "A_DOT_J is not defined"); + expect(require('./dir/' + A_DOT_J + tmp + 's')).toBe(a); + expect(require('./dir/' + tmp + A_DOT_J + 's')).toBe(a); + expect(require('./dir/' + tmp + A_DOT_J + tmp + 's')).toBe(a); + expect(require('./dir/' + tmp + A_DOT_J + (tmp + 's'))).toBe(a); + expect(require('./dir/' + tmp + (A_DOT_J + tmp + 's'))).toBe(a); + expect(require('./dir/' + tmp + (A_DOT_J + tmp) + 's')).toBe(a); + expect(require('./dir/' + (tmp + A_DOT_J + tmp + 's'))).toBe(a); + expect(require('./dir/' + (tmp + A_DOT_J + tmp) + 's')).toBe(a); + expect(require('./dir/' + (tmp + A_DOT_J) + tmp + 's')).toBe(a); });