Skip to content

Commit 7927535

Browse files
authored
refactor(tracer): implement a new generic util fn to remove global ids prefix (#390)
1 parent f037105 commit 7927535

File tree

5 files changed

+75
-17
lines changed

5 files changed

+75
-17
lines changed

.changeset/cool-bottles-feel.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@nodesecure/tracer": minor
3+
---
4+
5+
Refactor global id prefix removal by implementing a new generic Util function

workspaces/tracer/src/VariableTracer.ts

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ import {
1616
notNullOrUndefined,
1717
isEvilIdentifierPath,
1818
isNeutralCallable,
19-
getSubMemberExpressionSegments
19+
getSubMemberExpressionSegments,
20+
makePrefixRemover
2021
} from "./utils/index.js";
2122

2223
// CONSTANTS
@@ -27,6 +28,7 @@ const kGlobalIdentifiersToTrace = new Set([
2728
"GLOBAL",
2829
"window"
2930
]);
31+
const kGlobalIdentifiersRemover = makePrefixRemover(kGlobalIdentifiersToTrace);
3032
const kRequirePatterns = new Set([
3133
"require",
3234
"require.resolve",
@@ -136,29 +138,14 @@ export class VariableTracer extends EventEmitter {
136138
return this;
137139
}
138140

139-
removeGlobalIdentifier(
140-
identifierOrMemberExpr: string
141-
): string {
142-
if (!identifierOrMemberExpr.includes(".")) {
143-
return identifierOrMemberExpr;
144-
}
145-
146-
const globalIdentifier = [...kGlobalIdentifiersToTrace]
147-
.find((globalId) => identifierOrMemberExpr.startsWith(globalId));
148-
149-
return globalIdentifier ?
150-
identifierOrMemberExpr.slice(globalIdentifier.length + 1) :
151-
identifierOrMemberExpr;
152-
}
153-
154141
getDataFromIdentifier(
155142
identifierOrMemberExpr: string,
156143
options: DataIdentifierOptions = {}
157144
): null | TracedIdentifierReport {
158145
const { removeGlobalIdentifier = false } = options;
159146
if (removeGlobalIdentifier) {
160147
// eslint-disable-next-line no-param-reassign
161-
identifierOrMemberExpr = this.removeGlobalIdentifier(identifierOrMemberExpr);
148+
identifierOrMemberExpr = kGlobalIdentifiersRemover(identifierOrMemberExpr);
162149
}
163150

164151
const isMemberExpr = identifierOrMemberExpr.includes(".");

workspaces/tracer/src/utils/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export * from "./isEvilIdentifierPath.js";
22
export * from "./getSubMemberExpressionSegments.js";
33
export * from "./notNullOrUndefined.js";
4+
export * from "./makePrefixRemover.js";
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
export function makePrefixRemover(
3+
prefixes: Iterable<string>
4+
): (expr: string) => string {
5+
return (
6+
expr
7+
) => {
8+
if (!expr.includes(".")) {
9+
return expr;
10+
}
11+
12+
const matchedPrefix = Array.from(prefixes)
13+
.find((globalId) => expr.startsWith(globalId));
14+
15+
return matchedPrefix ?
16+
expr.slice(matchedPrefix.length + 1) :
17+
expr;
18+
};
19+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Import Node.js Dependencies
2+
import { describe, it } from "node:test";
3+
import assert from "node:assert/strict";
4+
5+
// Import Internal Dependencies
6+
import { makePrefixRemover } from "../../src/utils/index.js";
7+
8+
describe("makePrefixRemover", () => {
9+
it("returns the original string when no dot is present", () => {
10+
const strip = makePrefixRemover(["window"]);
11+
assert.strictEqual(strip("foo"), "foo");
12+
});
13+
14+
it("returns the original string when the identifier is not at the start of the string", () => {
15+
const strip = makePrefixRemover(["window"]);
16+
assert.strictEqual(strip("foo.window"), "foo.window");
17+
});
18+
19+
it("removes a matching prefix at the start of the expression", () => {
20+
const strip = makePrefixRemover(["window", "globalThis"]);
21+
assert.strictEqual(strip("window.bar"), "bar");
22+
assert.strictEqual(strip("globalThis.console"), "console");
23+
});
24+
25+
it("returns the original string when no prefix matches", () => {
26+
const strip = makePrefixRemover(["window"]);
27+
assert.strictEqual(strip("document.title"), "document.title");
28+
});
29+
30+
it("handles nested member expressions", () => {
31+
const strip = makePrefixRemover(["window"]);
32+
assert.strictEqual(strip("window.document.title"), "document.title");
33+
});
34+
35+
it("accepts any iterable of prefixes", () => {
36+
const strip = makePrefixRemover(new Set(["window"]));
37+
assert.strictEqual(strip("window.location"), "location");
38+
});
39+
40+
it("uses the first matching prefix based on input order", () => {
41+
const strip1 = makePrefixRemover(["window.document", "window"]);
42+
assert.strictEqual(strip1("window.document.title"), "title");
43+
const strip2 = makePrefixRemover(["window", "window.document"]);
44+
assert.strictEqual(strip2("window.document.title"), "document.title");
45+
});
46+
});

0 commit comments

Comments
 (0)