Skip to content

Commit

Permalink
improve optional chaining handling
Browse files Browse the repository at this point in the history
  • Loading branch information
sokra committed Aug 7, 2020
1 parent fb561e9 commit 0fbb348
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 13 deletions.
5 changes: 4 additions & 1 deletion lib/ConstPlugin.js
Expand Up @@ -420,7 +420,10 @@ class ConstPlugin {
//
// ------------------------------------------
//
const dep = new ConstDependency(" undefined", expr.range);
const dep = new ConstDependency(
evaluated.isNull() ? " null" : " undefined",
expr.range
);
dep.loc = expr.loc;
parser.state.module.addPresentationalDependency(dep);
return true;
Expand Down
1 change: 1 addition & 0 deletions lib/javascript/BasicEvaluatedExpression.js
Expand Up @@ -405,6 +405,7 @@ class BasicEvaluatedExpression {
setTruthy() {
this.falsy = false;
this.truthy = true;
this.nullish = false;
return this;
}

Expand Down
18 changes: 18 additions & 0 deletions lib/javascript/JavascriptParser.js
Expand Up @@ -758,6 +758,15 @@ class JavascriptParser extends Parser {
if (res !== undefined) return res;
break;
}
case "ChainExpression": {
const res = this.callHooksForExpression(
this.hooks.evaluateTypeof,
expr.argument.expression,
expr
);
if (res !== undefined) return res;
break;
}
case "FunctionExpression": {
return new BasicEvaluatedExpression()
.setString("function")
Expand Down Expand Up @@ -1266,6 +1275,7 @@ class JavascriptParser extends Parser {
return evaluated.setRange(_expr.range);
}
}
return this.evaluateExpression(expr.expression);
});
}

Expand Down Expand Up @@ -2229,6 +2239,14 @@ class JavascriptParser extends Parser {
expression
);
if (result === true) return;
if (expression.argument.type === "ChainExpression") {
const result = this.callHooksForExpression(
this.hooks.typeof,
expression.argument.expression,
expression
);
if (result === true) return;
}
}
this.walkExpression(expression.argument);
}
Expand Down
1 change: 1 addition & 0 deletions test/TestCasesProduction.test.js
Expand Up @@ -4,6 +4,7 @@ describe("TestCases", () => {
describeCases({
name: "production",
mode: "production",
minimize: true,
deprecations: [
// TODO update terser-webpack-plugin to use getCache()
expect.objectContaining({ code: "DEP_WEBPACK_COMPILATION_CACHE" })
Expand Down
9 changes: 1 addition & 8 deletions test/cases/parsing/optional-chaining/test.filter.js
@@ -1,12 +1,5 @@
const supportsOptionalChaining = require("../../../helpers/supportsOptionalChaining");

/**
* @param {import("../../../../").Configuration} config
* @returns {boolean}
*/
module.exports = function (config) {
if (config.mode === "production") return false;
if (config.optimization && config.optimization.minimizer) return false;

return supportsOptionalChaining();
return !config.minimize && supportsOptionalChaining();
};
18 changes: 18 additions & 0 deletions test/configCases/parsing/optional-chaining/index.js
Expand Up @@ -5,6 +5,24 @@ it("should correctly render defined data #1", () => {
it("should correctly render defined data #2", () => {
const val1 = _VALUE_?._PROP_?._DEFINED_;
const val2 = _VALUE_?._PROP_?._UNDEFINED_;
const val3 = typeof _VALUE_?._PROP_?._DEFINED_;
const val4 = typeof _VALUE_?._PROP_?._UNDEFINED_;
const val5 = _VALUE_?._PROP_;
const val6 = typeof _VALUE_?._PROP_;
expect(val1).toBe(2);
expect(val2).toBeUndefined();
expect(val3).toBe("number");
expect(val4).toBe("undefined");
expect(val5).toEqual({ _DEFINED_: 2 });
expect(val6).toBe("object");
expect((() => typeof _VALUE_?._PROP_?._DEFINED_).toString()).toContain(
"number"
);
expect((() => typeof _VALUE_?._PROP_).toString()).toContain("object");
if (_VALUE_._PROP_._DEFINED_ !== 2) require("fail");
if (_VALUE_?._PROP_?._DEFINED_ !== 2) require("fail");
if (typeof _VALUE_._PROP_._DEFINED_ !== "number") require("fail");
if (typeof _VALUE_?._PROP_?._DEFINED_ !== "number") require("fail");
if (typeof _VALUE_._PROP_ !== "object") require("fail");
if (typeof _VALUE_?._PROP_ !== "object") require("fail");
});
4 changes: 3 additions & 1 deletion test/hotCases/parsing/hot-api-optional-chaining/a.js
@@ -1 +1,3 @@
module.exports = "a";
export default 1;
---
export default 2;
14 changes: 11 additions & 3 deletions test/hotCases/parsing/hot-api-optional-chaining/index.js
@@ -1,4 +1,12 @@
it("should run module.hot.accept(…)", function() {
module?.hot?.accept("./a", function() {});
module?.hot.accept();
import value from "./a";

it("should run module.hot.accept(…)", function (done) {
expect(value).toBe(1);
module?.hot?.accept("./a", function () {});
NEXT(
require("../../update")(done, true, () => {
expect(value).toBe(2);
done();
})
);
});

0 comments on commit 0fbb348

Please sign in to comment.