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
This commit is contained in:
Tobias Koppers 2018-11-05 15:17:10 +01:00
parent dcd0d59d62
commit babe736cfa
5 changed files with 90 additions and 22 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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(

View File

@ -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);
});