Skip to content

Commit 38ee8b4

Browse files
Expand evaluation of global built-ins in @babel/traverse (#15797)
* add global built-in * add test for global built-in * fix lint errors * remove btoa and atob functions * rename of constants and methods * retrigger checks * prettier changes file * add node version check * add tests for the node version check * add a check for the split node version * Update packages/babel-traverse/src/path/evaluation.ts Co-authored-by: Huáng Jùnliàng <[email protected]> * remove unused constant * update btoa and atob tests * Update packages/babel-traverse/test/evaluation.js Co-authored-by: Huáng Jùnliàng <[email protected]> --------- Co-authored-by: = <=> Co-authored-by: Huáng Jùnliàng <[email protected]>
1 parent 54d30f2 commit 38ee8b4

File tree

2 files changed

+85
-5
lines changed

2 files changed

+85
-5
lines changed

packages/babel-traverse/src/path/evaluation.ts

+30-5
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,35 @@ import type * as t from "@babel/types";
33

44
// This file contains Babels metainterpreter that can evaluate static code.
55

6-
const VALID_CALLEES = ["String", "Number", "Math"] as const;
6+
const VALID_OBJECT_CALLEES = ["Number", "String", "Math"] as const;
7+
const VALID_IDENTIFIER_CALLEES = [
8+
"isFinite",
9+
"isNaN",
10+
"parseFloat",
11+
"parseInt",
12+
"decodeURI",
13+
"decodeURIComponent",
14+
"encodeURI",
15+
"encodeURIComponent",
16+
process.env.BABEL_8_BREAKING ? "btoa" : null,
17+
process.env.BABEL_8_BREAKING ? "atob" : null,
18+
] as const;
19+
720
const INVALID_METHODS = ["random"] as const;
821

9-
function isValidCallee(val: string): val is (typeof VALID_CALLEES)[number] {
10-
return VALID_CALLEES.includes(
22+
function isValidObjectCallee(
23+
val: string,
24+
): val is (typeof VALID_OBJECT_CALLEES)[number] {
25+
return VALID_OBJECT_CALLEES.includes(
26+
// @ts-expect-error val is a string
27+
val,
28+
);
29+
}
30+
31+
function isValidIdentifierCallee(
32+
val: string,
33+
): val is (typeof VALID_IDENTIFIER_CALLEES)[number] {
34+
return VALID_IDENTIFIER_CALLEES.includes(
1135
// @ts-expect-error val is a string
1236
val,
1337
);
@@ -402,7 +426,8 @@ function _evaluate(path: NodePath, state: State): any {
402426
if (
403427
callee.isIdentifier() &&
404428
!path.scope.getBinding(callee.node.name) &&
405-
isValidCallee(callee.node.name)
429+
(isValidObjectCallee(callee.node.name) ||
430+
isValidIdentifierCallee(callee.node.name))
406431
) {
407432
func = global[callee.node.name];
408433
}
@@ -415,7 +440,7 @@ function _evaluate(path: NodePath, state: State): any {
415440
if (
416441
object.isIdentifier() &&
417442
property.isIdentifier() &&
418-
isValidCallee(object.node.name) &&
443+
isValidObjectCallee(object.node.name) &&
419444
!isInvalidMethod(property.node.name)
420445
) {
421446
context = global[object.node.name];

packages/babel-traverse/test/evaluation.js

+55
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,61 @@ describe("evaluation", function () {
152152
expect(eval_invalid_call.confident).toBe(false);
153153
});
154154

155+
it("should evaluate global call expressions", function () {
156+
expect(
157+
getPath("isFinite(1);").get("body.0.expression").evaluate().value,
158+
).toBe(true);
159+
160+
expect(
161+
getPath("isFinite(Infinity);").get("body.0.expression").evaluate().value,
162+
).toBe(false);
163+
164+
expect(
165+
getPath("isNaN(NaN);").get("body.0.expression").evaluate().value,
166+
).toBe(true);
167+
168+
expect(getPath("isNaN(1);").get("body.0.expression").evaluate().value).toBe(
169+
false,
170+
);
171+
172+
expect(
173+
getPath("parseFloat('1.1');").get("body.0.expression").evaluate().value,
174+
).toBe(1.1);
175+
176+
expect(
177+
getPath("parseFloat('1');").get("body.0.expression").evaluate().value,
178+
).toBe(1);
179+
180+
expect(
181+
getPath("encodeURI('x 1');").get("body.0.expression").evaluate().value,
182+
).toBe("x%201");
183+
184+
expect(
185+
getPath("decodeURI('x%201');").get("body.0.expression").evaluate().value,
186+
).toBe("x 1");
187+
188+
expect(
189+
getPath("encodeURIComponent('?x=1');").get("body.0.expression").evaluate()
190+
.value,
191+
).toBe("%3Fx%3D1");
192+
193+
expect(
194+
getPath("decodeURIComponent('%3Fx%3D1');")
195+
.get("body.0.expression")
196+
.evaluate().value,
197+
).toBe("?x=1");
198+
199+
if (process.env.BABEL_8_BREAKING) {
200+
expect(
201+
getPath("btoa('babel');").get("body.0.expression").evaluate().value,
202+
).toBe("YmFiZWw=");
203+
204+
expect(
205+
getPath("atob('YmFiZWw=');").get("body.0.expression").evaluate().value,
206+
).toBe("babel");
207+
}
208+
});
209+
155210
it("should not deopt vars in different scope", function () {
156211
const input =
157212
"var a = 5; function x() { var a = 5; var b = a + 1; } var b = a + 2";

0 commit comments

Comments
 (0)