From 328a88ef45f63b0207e9b63db98f8857fbfa1ef0 Mon Sep 17 00:00:00 2001 From: lorenzoferre Date: Tue, 18 Jul 2023 16:02:22 +0200 Subject: [PATCH 01/14] add global built-in --- packages/babel-traverse/src/path/evaluation.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/babel-traverse/src/path/evaluation.ts b/packages/babel-traverse/src/path/evaluation.ts index c4a39df798c0..47c442602c39 100644 --- a/packages/babel-traverse/src/path/evaluation.ts +++ b/packages/babel-traverse/src/path/evaluation.ts @@ -3,7 +3,8 @@ import type * as t from "@babel/types"; // This file contains Babels metainterpreter that can evaluate static code. -const VALID_CALLEES = ["String", "Number", "Math"] as const; +const VALID_CALLEES = ["Number", "String", "Math"] as const; +const GLOBAL_VALID_CALLEES = ["isFinite", "isNaN", "parseFloat", "parseInt", "decodeURI", "decodeURIComponent", "encodeURI", "encodeURIComponent", "btoa", "atob"] as const; const INVALID_METHODS = ["random"] as const; function isValidCallee(val: string): val is (typeof VALID_CALLEES)[number] { @@ -13,6 +14,13 @@ function isValidCallee(val: string): val is (typeof VALID_CALLEES)[number] { ); } +function isGlobalValidCallee(val: string): val is (typeof GLOBAL_VALID_CALLEES)[number] { + return GLOBAL_VALID_CALLEES.includes( + // @ts-expect-error val is a string + val, + ); +} + function isInvalidMethod(val: string): val is (typeof INVALID_METHODS)[number] { return INVALID_METHODS.includes( // @ts-expect-error val is a string @@ -402,7 +410,10 @@ function _evaluate(path: NodePath, state: State): any { if ( callee.isIdentifier() && !path.scope.getBinding(callee.node.name) && - isValidCallee(callee.node.name) + ( + isValidCallee(callee.node.name) || + isGlobalValidCallee(callee.node.name) + ) ) { func = global[callee.node.name]; } From 83e837fc16186c055dfa97c54c5e35bb485e9acd Mon Sep 17 00:00:00 2001 From: lorenzoferre Date: Tue, 18 Jul 2023 16:41:57 +0200 Subject: [PATCH 02/14] add test for global built-in --- packages/babel-traverse/test/evaluation.js | 75 ++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/packages/babel-traverse/test/evaluation.js b/packages/babel-traverse/test/evaluation.js index a1e2aadca3d7..622b13fc9d36 100644 --- a/packages/babel-traverse/test/evaluation.js +++ b/packages/babel-traverse/test/evaluation.js @@ -152,6 +152,81 @@ describe("evaluation", function () { expect(eval_invalid_call.confident).toBe(false); }); + it("should evaluate global call expressions", function() { + expect( + getPath("isFinite(1);") + .get("body.0.expression") + .evaluate().value, + ).toBe(true); + + expect( + getPath("isFinite(Infinity);") + .get("body.0.expression") + .evaluate().value, + ).toBe(false); + + expect( + getPath("isNaN(NaN);") + .get("body.0.expression") + .evaluate().value, + ).toBe(true); + + expect( + getPath("isNaN(1);") + .get("body.0.expression") + .evaluate().value, + ).toBe(false); + + expect( + getPath("parseFloat('1.1');") + .get("body.0.expression") + .evaluate().value, + ).toBe(1.1); + + expect( + getPath("parseFloat('1');") + .get("body.0.expression") + .evaluate().value, + ).toBe(1); + + expect( + getPath("encodeURI('x 1');") + .get("body.0.expression") + .evaluate().value, + ).toBe("x%201"); + + expect( + getPath("decodeURI('x%201');") + .get("body.0.expression") + .evaluate().value, + ).toBe("x 1"); + + expect( + getPath("encodeURIComponent('?x=1');") + .get("body.0.expression") + .evaluate().value, + ).toBe("%3Fx%3D1"); + + expect( + getPath("decodeURIComponent('%3Fx%3D1');") + .get("body.0.expression") + .evaluate().value, + ).toBe("?x=1"); + + expect( + getPath("btoa('hello');") + .get("body.0.expression") + .evaluate().value, + ).toBe("aGVsbG8="); + + expect( + getPath("atob('aGVsbG8=');") + .get("body.0.expression") + .evaluate().value, + ).toBe("hello"); + + }); + it("should not deopt vars in different scope", function () { const input = "var a = 5; function x() { var a = 5; var b = a + 1; } var b = a + 2"; From 5868b179ad2be61dd06b98e05c7a4e2cfd9ecd86 Mon Sep 17 00:00:00 2001 From: = <=> Date: Thu, 20 Jul 2023 17:34:12 +0200 Subject: [PATCH 03/14] fix lint errors --- .../babel-traverse/src/path/evaluation.ts | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/packages/babel-traverse/src/path/evaluation.ts b/packages/babel-traverse/src/path/evaluation.ts index 47c442602c39..0583577176ea 100644 --- a/packages/babel-traverse/src/path/evaluation.ts +++ b/packages/babel-traverse/src/path/evaluation.ts @@ -4,7 +4,18 @@ import type * as t from "@babel/types"; // This file contains Babels metainterpreter that can evaluate static code. const VALID_CALLEES = ["Number", "String", "Math"] as const; -const GLOBAL_VALID_CALLEES = ["isFinite", "isNaN", "parseFloat", "parseInt", "decodeURI", "decodeURIComponent", "encodeURI", "encodeURIComponent", "btoa", "atob"] as const; +const GLOBAL_VALID_CALLEES = [ + "isFinite", + "isNaN", + "parseFloat", + "parseInt", + "decodeURI", + "decodeURIComponent", + "encodeURI", + "encodeURIComponent", + "btoa", + "atob", +] as const; const INVALID_METHODS = ["random"] as const; function isValidCallee(val: string): val is (typeof VALID_CALLEES)[number] { @@ -14,7 +25,9 @@ function isValidCallee(val: string): val is (typeof VALID_CALLEES)[number] { ); } -function isGlobalValidCallee(val: string): val is (typeof GLOBAL_VALID_CALLEES)[number] { +function isGlobalValidCallee( + val: string, +): val is (typeof GLOBAL_VALID_CALLEES)[number] { return GLOBAL_VALID_CALLEES.includes( // @ts-expect-error val is a string val, @@ -410,10 +423,7 @@ function _evaluate(path: NodePath, state: State): any { if ( callee.isIdentifier() && !path.scope.getBinding(callee.node.name) && - ( - isValidCallee(callee.node.name) || - isGlobalValidCallee(callee.node.name) - ) + (isValidCallee(callee.node.name) || isGlobalValidCallee(callee.node.name)) ) { func = global[callee.node.name]; } From 3a7024aa5cd7452c92d45f4511fe7659636961d1 Mon Sep 17 00:00:00 2001 From: lorenzoferre Date: Fri, 21 Jul 2023 11:33:27 +0200 Subject: [PATCH 04/14] remove btoa and atob functions --- packages/babel-traverse/src/path/evaluation.ts | 2 -- packages/babel-traverse/test/evaluation.js | 12 ------------ 2 files changed, 14 deletions(-) diff --git a/packages/babel-traverse/src/path/evaluation.ts b/packages/babel-traverse/src/path/evaluation.ts index 0583577176ea..76166eae6af3 100644 --- a/packages/babel-traverse/src/path/evaluation.ts +++ b/packages/babel-traverse/src/path/evaluation.ts @@ -13,8 +13,6 @@ const GLOBAL_VALID_CALLEES = [ "decodeURIComponent", "encodeURI", "encodeURIComponent", - "btoa", - "atob", ] as const; const INVALID_METHODS = ["random"] as const; diff --git a/packages/babel-traverse/test/evaluation.js b/packages/babel-traverse/test/evaluation.js index 622b13fc9d36..5521c72d0c44 100644 --- a/packages/babel-traverse/test/evaluation.js +++ b/packages/babel-traverse/test/evaluation.js @@ -213,18 +213,6 @@ describe("evaluation", function () { .evaluate().value, ).toBe("?x=1"); - expect( - getPath("btoa('hello');") - .get("body.0.expression") - .evaluate().value, - ).toBe("aGVsbG8="); - - expect( - getPath("atob('aGVsbG8=');") - .get("body.0.expression") - .evaluate().value, - ).toBe("hello"); - }); it("should not deopt vars in different scope", function () { From 0b61dbabc8b712a1bd1fb1ab219a65a8241bd3f2 Mon Sep 17 00:00:00 2001 From: lorenzoferre Date: Wed, 26 Jul 2023 13:35:37 +0200 Subject: [PATCH 05/14] rename of constants and methods --- .../babel-traverse/src/path/evaluation.ts | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/packages/babel-traverse/src/path/evaluation.ts b/packages/babel-traverse/src/path/evaluation.ts index 76166eae6af3..233377fd86ea 100644 --- a/packages/babel-traverse/src/path/evaluation.ts +++ b/packages/babel-traverse/src/path/evaluation.ts @@ -3,8 +3,8 @@ import type * as t from "@babel/types"; // This file contains Babels metainterpreter that can evaluate static code. -const VALID_CALLEES = ["Number", "String", "Math"] as const; -const GLOBAL_VALID_CALLEES = [ +const VALID_OBJECT_CALLEES = ["Number", "String", "Math"] as const; +const VALID_IDENTIFIER_CALLEES = [ "isFinite", "isNaN", "parseFloat", @@ -16,17 +16,19 @@ const GLOBAL_VALID_CALLEES = [ ] as const; const INVALID_METHODS = ["random"] as const; -function isValidCallee(val: string): val is (typeof VALID_CALLEES)[number] { - return VALID_CALLEES.includes( +function isValidObjectCallee( + val: string, +): val is (typeof VALID_OBJECT_CALLEES)[number] { + return VALID_OBJECT_CALLEES.includes( // @ts-expect-error val is a string val, ); } -function isGlobalValidCallee( +function isValidIdentifierCallee( val: string, -): val is (typeof GLOBAL_VALID_CALLEES)[number] { - return GLOBAL_VALID_CALLEES.includes( +): val is (typeof VALID_IDENTIFIER_CALLEES)[number] { + return VALID_IDENTIFIER_CALLEES.includes( // @ts-expect-error val is a string val, ); @@ -421,7 +423,8 @@ function _evaluate(path: NodePath, state: State): any { if ( callee.isIdentifier() && !path.scope.getBinding(callee.node.name) && - (isValidCallee(callee.node.name) || isGlobalValidCallee(callee.node.name)) + (isValidObjectCallee(callee.node.name) || + isValidIdentifierCallee(callee.node.name)) ) { func = global[callee.node.name]; } @@ -434,7 +437,7 @@ function _evaluate(path: NodePath, state: State): any { if ( object.isIdentifier() && property.isIdentifier() && - isValidCallee(object.node.name) && + isValidObjectCallee(object.node.name) && !isInvalidMethod(property.node.name) ) { context = global[object.node.name]; From 9ada20a28b155b2c420707c3f975744096475f60 Mon Sep 17 00:00:00 2001 From: lorenzoferre Date: Wed, 26 Jul 2023 14:01:11 +0200 Subject: [PATCH 06/14] retrigger checks From d0db3c100acd4011e2afebbc2e6ff75c5325c22f Mon Sep 17 00:00:00 2001 From: lorenzoferre Date: Thu, 27 Jul 2023 12:34:55 +0200 Subject: [PATCH 07/14] prettier changes file --- packages/babel-traverse/test/evaluation.js | 52 +++++++--------------- 1 file changed, 17 insertions(+), 35 deletions(-) diff --git a/packages/babel-traverse/test/evaluation.js b/packages/babel-traverse/test/evaluation.js index 5521c72d0c44..1d7352d69e0f 100644 --- a/packages/babel-traverse/test/evaluation.js +++ b/packages/babel-traverse/test/evaluation.js @@ -152,59 +152,42 @@ describe("evaluation", function () { expect(eval_invalid_call.confident).toBe(false); }); - it("should evaluate global call expressions", function() { + it("should evaluate global call expressions", function () { expect( - getPath("isFinite(1);") - .get("body.0.expression") - .evaluate().value, + getPath("isFinite(1);").get("body.0.expression").evaluate().value, ).toBe(true); - + expect( - getPath("isFinite(Infinity);") - .get("body.0.expression") - .evaluate().value, + getPath("isFinite(Infinity);").get("body.0.expression").evaluate().value, ).toBe(false); - + expect( - getPath("isNaN(NaN);") - .get("body.0.expression") - .evaluate().value, + getPath("isNaN(NaN);").get("body.0.expression").evaluate().value, ).toBe(true); - - expect( - getPath("isNaN(1);") - .get("body.0.expression") - .evaluate().value, - ).toBe(false); + + expect(getPath("isNaN(1);").get("body.0.expression").evaluate().value).toBe( + false, + ); expect( - getPath("parseFloat('1.1');") - .get("body.0.expression") - .evaluate().value, + getPath("parseFloat('1.1');").get("body.0.expression").evaluate().value, ).toBe(1.1); - + expect( - getPath("parseFloat('1');") - .get("body.0.expression") - .evaluate().value, + getPath("parseFloat('1');").get("body.0.expression").evaluate().value, ).toBe(1); expect( - getPath("encodeURI('x 1');") - .get("body.0.expression") - .evaluate().value, + getPath("encodeURI('x 1');").get("body.0.expression").evaluate().value, ).toBe("x%201"); expect( - getPath("decodeURI('x%201');") - .get("body.0.expression") - .evaluate().value, + getPath("decodeURI('x%201');").get("body.0.expression").evaluate().value, ).toBe("x 1"); expect( - getPath("encodeURIComponent('?x=1');") - .get("body.0.expression") - .evaluate().value, + getPath("encodeURIComponent('?x=1');").get("body.0.expression").evaluate() + .value, ).toBe("%3Fx%3D1"); expect( @@ -212,7 +195,6 @@ describe("evaluation", function () { .get("body.0.expression") .evaluate().value, ).toBe("?x=1"); - }); it("should not deopt vars in different scope", function () { From b926cefd54807c0d929a8c3e39d7cbe20ddd2127 Mon Sep 17 00:00:00 2001 From: lorenzoferre Date: Thu, 27 Jul 2023 12:35:55 +0200 Subject: [PATCH 08/14] add node version check --- packages/babel-traverse/src/path/evaluation.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/babel-traverse/src/path/evaluation.ts b/packages/babel-traverse/src/path/evaluation.ts index 233377fd86ea..eafa4b178b80 100644 --- a/packages/babel-traverse/src/path/evaluation.ts +++ b/packages/babel-traverse/src/path/evaluation.ts @@ -4,6 +4,7 @@ import type * as t from "@babel/types"; // This file contains Babels metainterpreter that can evaluate static code. const VALID_OBJECT_CALLEES = ["Number", "String", "Math"] as const; +const NODE_MAJOR_VERSION = parseInt(process.versions.node.split(".")[0]); const VALID_IDENTIFIER_CALLEES = [ "isFinite", "isNaN", @@ -13,7 +14,10 @@ const VALID_IDENTIFIER_CALLEES = [ "decodeURIComponent", "encodeURI", "encodeURIComponent", + NODE_MAJOR_VERSION >= 16 ? "btoa" : null, + NODE_MAJOR_VERSION >= 16 ? "atob" : null, ] as const; + const INVALID_METHODS = ["random"] as const; function isValidObjectCallee( From 2846af384cac2017c4d1bcd133a07b04b59926a5 Mon Sep 17 00:00:00 2001 From: lorenzoferre Date: Thu, 27 Jul 2023 12:36:46 +0200 Subject: [PATCH 09/14] add tests for the node version check --- packages/babel-traverse/test/evaluation.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/babel-traverse/test/evaluation.js b/packages/babel-traverse/test/evaluation.js index 1d7352d69e0f..6220a5242ae4 100644 --- a/packages/babel-traverse/test/evaluation.js +++ b/packages/babel-traverse/test/evaluation.js @@ -195,6 +195,21 @@ describe("evaluation", function () { .get("body.0.expression") .evaluate().value, ).toBe("?x=1"); + + // the two tests below produce an undefined result when the node version is less than 16 + expect( + getPath("btoa('babel');").get("body.0.expression").evaluate().value === + "YmFiZWw=" || + getPath("btoa('babel');").get("body.0.expression").evaluate().value === + undefined, + ).toBeTruthy(); + + expect( + getPath("atob('YmFiZWw=');").get("body.0.expression").evaluate().value === + "babel" || + getPath("atob('YmFiZWw=');").get("body.0.expression").evaluate() + .value === undefined, + ).toBeTruthy(); }); it("should not deopt vars in different scope", function () { From edc24cafd6618fc0fbc7477ba5a8d43b040224bc Mon Sep 17 00:00:00 2001 From: lorenzoferre Date: Thu, 27 Jul 2023 13:47:31 +0200 Subject: [PATCH 10/14] add a check for the split node version --- packages/babel-traverse/src/path/evaluation.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/babel-traverse/src/path/evaluation.ts b/packages/babel-traverse/src/path/evaluation.ts index eafa4b178b80..2bf652c9a510 100644 --- a/packages/babel-traverse/src/path/evaluation.ts +++ b/packages/babel-traverse/src/path/evaluation.ts @@ -4,7 +4,9 @@ import type * as t from "@babel/types"; // This file contains Babels metainterpreter that can evaluate static code. const VALID_OBJECT_CALLEES = ["Number", "String", "Math"] as const; -const NODE_MAJOR_VERSION = parseInt(process.versions.node.split(".")[0]); +const NODE_MAJOR_VERSION = process.versions.node + ? parseInt(process.versions.node.split(".")[0]) + : null; const VALID_IDENTIFIER_CALLEES = [ "isFinite", "isNaN", From 0084a6b3f53360914df8e96e79ea4e7d05c38578 Mon Sep 17 00:00:00 2001 From: Lorenzo Ferretti <131382232+lorenzoferre@users.noreply.github.com> Date: Tue, 1 Aug 2023 19:36:26 +0200 Subject: [PATCH 11/14] Update packages/babel-traverse/src/path/evaluation.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Huáng Jùnliàng --- packages/babel-traverse/src/path/evaluation.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/babel-traverse/src/path/evaluation.ts b/packages/babel-traverse/src/path/evaluation.ts index 2bf652c9a510..6a3308cd78e9 100644 --- a/packages/babel-traverse/src/path/evaluation.ts +++ b/packages/babel-traverse/src/path/evaluation.ts @@ -16,8 +16,8 @@ const VALID_IDENTIFIER_CALLEES = [ "decodeURIComponent", "encodeURI", "encodeURIComponent", - NODE_MAJOR_VERSION >= 16 ? "btoa" : null, - NODE_MAJOR_VERSION >= 16 ? "atob" : null, + process.env.BABEL_8_BREAKING ? "btoa" : null, + process.env.BABEL_8_BREAKING ? "atob" : null, ] as const; const INVALID_METHODS = ["random"] as const; From ae7c04b7be667ef81c332577d52c331968d5ed2a Mon Sep 17 00:00:00 2001 From: lorenzoferre Date: Tue, 1 Aug 2023 20:03:00 +0200 Subject: [PATCH 12/14] remove unused constant --- packages/babel-traverse/src/path/evaluation.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/babel-traverse/src/path/evaluation.ts b/packages/babel-traverse/src/path/evaluation.ts index 6a3308cd78e9..e1cde714efc7 100644 --- a/packages/babel-traverse/src/path/evaluation.ts +++ b/packages/babel-traverse/src/path/evaluation.ts @@ -4,9 +4,6 @@ import type * as t from "@babel/types"; // This file contains Babels metainterpreter that can evaluate static code. const VALID_OBJECT_CALLEES = ["Number", "String", "Math"] as const; -const NODE_MAJOR_VERSION = process.versions.node - ? parseInt(process.versions.node.split(".")[0]) - : null; const VALID_IDENTIFIER_CALLEES = [ "isFinite", "isNaN", From 6c228469849363a5005303397f7f4fd783469a61 Mon Sep 17 00:00:00 2001 From: lorenzoferre Date: Tue, 1 Aug 2023 20:47:33 +0200 Subject: [PATCH 13/14] update btoa and atob tests --- packages/babel-traverse/test/evaluation.js | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/packages/babel-traverse/test/evaluation.js b/packages/babel-traverse/test/evaluation.js index 6220a5242ae4..f1386724c2c7 100644 --- a/packages/babel-traverse/test/evaluation.js +++ b/packages/babel-traverse/test/evaluation.js @@ -197,19 +197,15 @@ describe("evaluation", function () { ).toBe("?x=1"); // the two tests below produce an undefined result when the node version is less than 16 - expect( - getPath("btoa('babel');").get("body.0.expression").evaluate().value === - "YmFiZWw=" || - getPath("btoa('babel');").get("body.0.expression").evaluate().value === - undefined, - ).toBeTruthy(); + if (process.env.BABEL_8_BREAKING) { + expect( + getPath("btoa('babel');").get("body.0.expression").evaluate().value, + ).toBe("YmFiZWw="); - expect( - getPath("atob('YmFiZWw=');").get("body.0.expression").evaluate().value === - "babel" || - getPath("atob('YmFiZWw=');").get("body.0.expression").evaluate() - .value === undefined, - ).toBeTruthy(); + expect( + getPath("atob('YmFiZWw=');").get("body.0.expression").evaluate().value, + ).toBe("babel"); + } }); it("should not deopt vars in different scope", function () { From 27bbd12ffd26ef964ed19f960c12dc130a059c94 Mon Sep 17 00:00:00 2001 From: Lorenzo Ferretti <131382232+lorenzoferre@users.noreply.github.com> Date: Tue, 1 Aug 2023 21:37:28 +0200 Subject: [PATCH 14/14] Update packages/babel-traverse/test/evaluation.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Huáng Jùnliàng --- packages/babel-traverse/test/evaluation.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/babel-traverse/test/evaluation.js b/packages/babel-traverse/test/evaluation.js index f1386724c2c7..a791df014d36 100644 --- a/packages/babel-traverse/test/evaluation.js +++ b/packages/babel-traverse/test/evaluation.js @@ -196,7 +196,6 @@ describe("evaluation", function () { .evaluate().value, ).toBe("?x=1"); - // the two tests below produce an undefined result when the node version is less than 16 if (process.env.BABEL_8_BREAKING) { expect( getPath("btoa('babel');").get("body.0.expression").evaluate().value,