Skip to content

Commit d83087f

Browse files
authored
feat: implement new SourceFilePath to locate source code (#428)
1 parent 9a9a88a commit d83087f

File tree

5 files changed

+99
-1
lines changed

5 files changed

+99
-1
lines changed

.changeset/tired-ends-dream.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@nodesecure/js-x-ray": minor
3+
---
4+
5+
Implement new SourceFilePath to locate source code

workspaces/js-x-ray/docs/AstAnalyser.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ The `analyseFile` and `analyseFileSync` methods is a superset of `analyse` with
6363

6464
```ts
6565
interface RuntimeOptions {
66+
/**
67+
* A filesystem location for the given source code.
68+
*/
69+
location?: string;
6670
/**
6771
* @default true
6872
*/

workspaces/js-x-ray/src/AstAnalyser.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ export interface Dependency {
3636
}
3737

3838
export interface RuntimeOptions {
39+
/**
40+
* A filesystem location for the given source code.
41+
*/
42+
location?: string;
3943
/**
4044
* @default true
4145
*/
@@ -144,6 +148,7 @@ export class AstAnalyser {
144148
options: RuntimeOptions = {}
145149
): Report {
146150
const {
151+
location,
147152
isMinified = false,
148153
module = true,
149154
removeHTMLComments = false,
@@ -155,7 +160,7 @@ export class AstAnalyser {
155160
isEcmaScriptModule: Boolean(module)
156161
});
157162

158-
const source = new SourceFile();
163+
const source = new SourceFile(location);
159164
if (trojan.verify(str)) {
160165
source.warnings.push(
161166
generateWarning("obfuscated-code", { value: "trojan-source" })
@@ -223,6 +228,7 @@ export class AstAnalyser {
223228

224229
const isMin = filePathString.includes(".min") || isMinifiedCode(str);
225230
const data = this.analyse(str, {
231+
location: path.dirname(filePathString),
226232
isMinified: isMin,
227233
module: path.extname(filePathString) === ".mjs" ? true : module,
228234
removeHTMLComments,
@@ -276,6 +282,7 @@ export class AstAnalyser {
276282

277283
const isMin = filePathString.includes(".min") || isMinifiedCode(str);
278284
const data = this.analyse(str, {
285+
location: path.dirname(filePathString),
279286
isMinified: isMin,
280287
module: path.extname(filePathString) === ".mjs" ? true : module,
281288
removeHTMLComments,

workspaces/js-x-ray/src/SourceFile.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// Import Node.js Dependencies
2+
import path from "node:path";
3+
14
// Import Third-party Dependencies
25
import { Utils, Literal } from "@nodesecure/sec-literal";
36
import { VariableTracer } from "@nodesecure/tracer";
@@ -29,6 +32,12 @@ export class SourceFile {
2932
encodedLiterals = new Map<string, string>();
3033
warnings: Warning[] = [];
3134
flags = new Set<SourceFlags>();
35+
path = new SourceFilePath();
36+
37+
constructor(sourceLocation?: string) {
38+
this.path.use(sourceLocation);
39+
}
40+
3241
addDependency(
3342
name: string,
3443
location?: ESTree.SourceLocation | null,
@@ -159,6 +168,26 @@ export class SourceFile {
159168
}
160169
}
161170

171+
export class SourceFilePath {
172+
location: string | null = null;
173+
174+
use(
175+
location?: string
176+
) {
177+
this.location = location ?? null;
178+
}
179+
180+
resolve(
181+
...parts: string[]
182+
) {
183+
if (this.location === null) {
184+
return path.posix.join(...parts);
185+
}
186+
187+
return path.posix.join(this.location, ...parts);
188+
}
189+
}
190+
162191
function sum(
163192
arr: number[] = []
164193
): number {
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Import Node.js Dependencies
2+
import { describe, it } from "node:test";
3+
import assert from "node:assert";
4+
5+
// Import Internal Dependencies
6+
import { SourceFile, SourceFilePath } from "../src/SourceFile.js";
7+
8+
describe("SourceFile", () => {
9+
describe("constructor() with sourceLocation", () => {
10+
it("should set the path location", () => {
11+
const sourceFile = new SourceFile("/path/to/file.js");
12+
assert.ok(sourceFile.path instanceof SourceFilePath);
13+
assert.strictEqual(sourceFile.path.location, "/path/to/file.js");
14+
});
15+
});
16+
});
17+
18+
describe("SourceFilePath", () => {
19+
describe("constructor", () => {
20+
it("should have location set to null by default", () => {
21+
const sfp = new SourceFilePath();
22+
assert.strictEqual(sfp.location, null);
23+
});
24+
});
25+
26+
describe("use()", () => {
27+
it("should set location when provided", () => {
28+
const sfp = new SourceFilePath();
29+
sfp.use("/foo/bar");
30+
assert.strictEqual(sfp.location, "/foo/bar");
31+
});
32+
33+
it("should set location to null when undefined", () => {
34+
const sfp = new SourceFilePath();
35+
sfp.use("/foo");
36+
sfp.use(undefined);
37+
assert.strictEqual(sfp.location, null);
38+
});
39+
});
40+
41+
describe("resolve()", () => {
42+
it("should join parts without base location", () => {
43+
const sfp = new SourceFilePath();
44+
assert.strictEqual(sfp.resolve("foo", "bar.js"), "foo/bar.js");
45+
});
46+
47+
it("should join parts with base location", () => {
48+
const sfp = new SourceFilePath();
49+
sfp.use("/base");
50+
assert.strictEqual(sfp.resolve("foo", "bar.js"), "/base/foo/bar.js");
51+
});
52+
});
53+
});

0 commit comments

Comments
 (0)