From e51a91e131518fa650a998649d4159b4f32428d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hu=C3=A1ng=20J=C3=B9nli=C3=A0ng?= Date: Mon, 20 Jul 2020 17:06:27 -0400 Subject: [PATCH] fix: eval?.() is indirect (#11850) --- .../src/index.js | 6 ++++- .../general/optional-eval-call-loose/input.js | 22 +++++++++++++++++++ .../optional-eval-call-loose/options.json | 3 +++ .../optional-eval-call-loose/output.js | 17 ++++++++++++++ .../general/optional-eval-call/input.js | 22 +++++++++++++++++++ .../general/optional-eval-call/output.js | 17 ++++++++++++++ 6 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/optional-eval-call-loose/input.js create mode 100644 packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/optional-eval-call-loose/options.json create mode 100644 packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/optional-eval-call-loose/output.js create mode 100644 packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/optional-eval-call/input.js create mode 100644 packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/optional-eval-call/output.js diff --git a/packages/babel-plugin-proposal-optional-chaining/src/index.js b/packages/babel-plugin-proposal-optional-chaining/src/index.js index a1f03bf94c95..3c80d4238c7a 100644 --- a/packages/babel-plugin-proposal-optional-chaining/src/index.js +++ b/packages/babel-plugin-proposal-optional-chaining/src/index.js @@ -78,7 +78,11 @@ export default declare((api, options) => { let ref; let check; - if (loose && isCall && isSimpleMemberExpression(chain)) { + if (isCall && t.isIdentifier(chain, { name: "eval" })) { + check = ref = chain; + // `eval?.()` is an indirect eval call transformed to `(0,eval)()` + node[replaceKey] = t.sequenceExpression([t.numericLiteral(0), ref]); + } else if (loose && isCall && isSimpleMemberExpression(chain)) { // If we are using a loose transform (avoiding a Function#call) and we are at the call, // we can avoid a needless memoize. We only do this if the callee is a simple member // expression, to avoid multiple calls to nested call expressions. diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/optional-eval-call-loose/input.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/optional-eval-call-loose/input.js new file mode 100644 index 000000000000..731610528ac4 --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/optional-eval-call-loose/input.js @@ -0,0 +1,22 @@ +var foo; + +/* indirect eval calls */ +eval?.(foo); + +(eval)?.(foo); + +eval?.()(); + +eval?.().foo; + +/* direct eval calls */ + +eval()?.(); + +eval()?.foo; + +/* plain function calls */ + +foo.eval?.(foo); + +eval.foo?.(foo); diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/optional-eval-call-loose/options.json b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/optional-eval-call-loose/options.json new file mode 100644 index 000000000000..39ea3f99c7ff --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/optional-eval-call-loose/options.json @@ -0,0 +1,3 @@ +{ + "plugins": [["proposal-optional-chaining", { "loose": true }]] +} diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/optional-eval-call-loose/output.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/optional-eval-call-loose/output.js new file mode 100644 index 000000000000..11a20e703be4 --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/optional-eval-call-loose/output.js @@ -0,0 +1,17 @@ +var _eval, _eval2; + +var foo; +/* indirect eval calls */ + +eval == null ? void 0 : (0, eval)(foo); +eval == null ? void 0 : (0, eval)(foo); +eval == null ? void 0 : (0, eval)()(); +eval == null ? void 0 : (0, eval)().foo; +/* direct eval calls */ + +(_eval = eval()) == null ? void 0 : _eval(); +(_eval2 = eval()) == null ? void 0 : _eval2.foo; +/* plain function calls */ + +foo.eval == null ? void 0 : foo.eval(foo); +eval.foo == null ? void 0 : eval.foo(foo); diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/optional-eval-call/input.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/optional-eval-call/input.js new file mode 100644 index 000000000000..731610528ac4 --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/optional-eval-call/input.js @@ -0,0 +1,22 @@ +var foo; + +/* indirect eval calls */ +eval?.(foo); + +(eval)?.(foo); + +eval?.()(); + +eval?.().foo; + +/* direct eval calls */ + +eval()?.(); + +eval()?.foo; + +/* plain function calls */ + +foo.eval?.(foo); + +eval.foo?.(foo); diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/optional-eval-call/output.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/optional-eval-call/output.js new file mode 100644 index 000000000000..2bb22ae870b0 --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/general/optional-eval-call/output.js @@ -0,0 +1,17 @@ +var _eval, _eval2, _foo$eval, _eval$foo; + +var foo; +/* indirect eval calls */ + +eval === null || eval === void 0 ? void 0 : (0, eval)(foo); +eval === null || eval === void 0 ? void 0 : (0, eval)(foo); +eval === null || eval === void 0 ? void 0 : (0, eval)()(); +eval === null || eval === void 0 ? void 0 : (0, eval)().foo; +/* direct eval calls */ + +(_eval = eval()) === null || _eval === void 0 ? void 0 : _eval(); +(_eval2 = eval()) === null || _eval2 === void 0 ? void 0 : _eval2.foo; +/* plain function calls */ + +(_foo$eval = foo.eval) === null || _foo$eval === void 0 ? void 0 : _foo$eval.call(foo, foo); +(_eval$foo = eval.foo) === null || _eval$foo === void 0 ? void 0 : _eval$foo.call(eval, foo);