@frida/injest 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,50 @@
1
+ import type { Script, Session } from "frida";
2
+ export declare function toProjectRelative(file: string | undefined): string | undefined;
3
+ export type TestStatus = "passed" | "failed" | "timeout" | "crashed" | "skipped" | "incomplete";
4
+ export interface TestError {
5
+ name: string;
6
+ message: string;
7
+ stack?: string;
8
+ expected?: string;
9
+ actual?: string;
10
+ }
11
+ export interface TestResult {
12
+ index: number;
13
+ id?: string;
14
+ name: string;
15
+ durationMs: number;
16
+ status: TestStatus;
17
+ file?: string;
18
+ line?: number;
19
+ error?: TestError;
20
+ }
21
+ export type Reporter = "pretty" | "json";
22
+ export interface TestMeta {
23
+ id?: string;
24
+ name?: string;
25
+ file?: string;
26
+ line?: number;
27
+ }
28
+ export interface RunOptions {
29
+ timeoutMs: number;
30
+ grep?: string;
31
+ reporter?: Reporter;
32
+ only?: number[];
33
+ metaByIndex?: Map<number, TestMeta>;
34
+ onResume?: () => Promise<void>;
35
+ }
36
+ export declare function runSuite(script: Script, session: Session, opts: RunOptions): Promise<TestResult[]>;
37
+ export declare function reportResult(r: TestResult, reporter: Reporter): void;
38
+ export interface OutputRecord {
39
+ level: string;
40
+ text: string;
41
+ name?: string;
42
+ file?: string;
43
+ line?: number;
44
+ }
45
+ export declare function reportOutput(o: OutputRecord, reporter: Reporter): void;
46
+ export declare function summarize(results: TestResult[], reporter?: Reporter): {
47
+ passed: number;
48
+ failed: number;
49
+ };
50
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/host/run.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAE7C,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAI9E;AAED,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,YAAY,CAAC;AAEhG,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEzC,MAAM,WAAW,QAAQ;IACvB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACpC,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAChC;AAED,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,UAAU,EAAE,CAAC,CA4KvB;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAGpE;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAwBtE;AAuDD,wBAAgB,SAAS,CACvB,OAAO,EAAE,UAAU,EAAE,EACrB,QAAQ,GAAE,QAAmB,GAC5B;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CA6BpC"}
@@ -0,0 +1,270 @@
1
+ import { isAbsolute, relative, resolve } from "node:path";
2
+ export function toProjectRelative(file) {
3
+ if (!file)
4
+ return file;
5
+ const cwd = process.cwd();
6
+ return relative(cwd, isAbsolute(file) ? file : resolve(cwd, file));
7
+ }
8
+ export async function runSuite(script, session, opts) {
9
+ const results = [];
10
+ let names = [];
11
+ let total = 0;
12
+ let current = -1;
13
+ let currentFile;
14
+ let currentLine;
15
+ let timer;
16
+ let done = false;
17
+ let settle;
18
+ const finished = new Promise((res) => {
19
+ settle = res;
20
+ });
21
+ const finish = () => {
22
+ if (done)
23
+ return;
24
+ done = true;
25
+ if (timer)
26
+ clearTimeout(timer);
27
+ settle();
28
+ };
29
+ const reporter = opts.reporter ?? "pretty";
30
+ const record = (r) => {
31
+ results[r.index] = r;
32
+ reportResult(r, reporter);
33
+ };
34
+ const metaOf = (testIndex) => (typeof testIndex === "number" ? opts.metaByIndex?.get(testIndex) : undefined) ?? {};
35
+ const fillRemaining = (from, status) => {
36
+ for (let i = from; i < total; i++) {
37
+ if (!results[i]) {
38
+ record({ index: i, name: names[i] ?? `#${i}`, durationMs: 0, status });
39
+ }
40
+ }
41
+ };
42
+ const onTimeout = (index, timeoutMs) => {
43
+ record({
44
+ index,
45
+ name: names[index] ?? `#${index}`,
46
+ durationMs: timeoutMs,
47
+ status: "timeout",
48
+ error: { name: "TimeoutError", message: `exceeded ${timeoutMs}ms` },
49
+ });
50
+ fillRemaining(index + 1, "incomplete");
51
+ // The agent thread is wedged; force-detach so we don't hang.
52
+ session.detach().catch(() => { });
53
+ finish();
54
+ };
55
+ // abnormal end: never let un-run tests look passed — mark them incomplete (which counts as failure)
56
+ const abort = (reason, crashCurrent) => {
57
+ if (crashCurrent && current >= 0) {
58
+ record({
59
+ index: current,
60
+ name: names[current] ?? `#${current}`,
61
+ durationMs: 0,
62
+ status: "crashed",
63
+ error: { name: "CrashError", message: reason },
64
+ });
65
+ }
66
+ fillRemaining(0, "incomplete");
67
+ if (!results.some(Boolean)) {
68
+ record({
69
+ index: 0,
70
+ name: "(suite did not run)",
71
+ durationMs: 0,
72
+ status: "incomplete",
73
+ error: { name: "AbortError", message: reason },
74
+ });
75
+ }
76
+ finish();
77
+ };
78
+ script.message.connect((message) => {
79
+ if (message.type === "error") {
80
+ console.error("[agent error]", message.stack ?? message.description);
81
+ return;
82
+ }
83
+ if (message.type !== "send")
84
+ return;
85
+ const p = message.payload;
86
+ if (!p || typeof p !== "object" || typeof p.ft !== "string")
87
+ return;
88
+ switch (p.ft) {
89
+ case "plan":
90
+ total = Number(p.total) || 0;
91
+ names = Array.isArray(p.names) ? p.names : [];
92
+ break;
93
+ case "resume":
94
+ Promise.resolve(opts.onResume?.())
95
+ .catch(() => { })
96
+ .then(() => script.post({ type: "ft:resume-ack" }));
97
+ break;
98
+ case "start": {
99
+ current = Number(p.index);
100
+ const meta = metaOf(p.testIndex);
101
+ currentFile = meta.file;
102
+ currentLine = meta.line;
103
+ if (timer)
104
+ clearTimeout(timer);
105
+ const perTestTimeout = typeof p.timeout === "number" && p.timeout > 0 ? p.timeout : opts.timeoutMs;
106
+ const index = Number(p.index);
107
+ timer = setTimeout(() => onTimeout(index, perTestTimeout), perTestTimeout);
108
+ break;
109
+ }
110
+ case "result": {
111
+ if (timer)
112
+ clearTimeout(timer);
113
+ const index = Number(p.index);
114
+ const meta = metaOf(p.testIndex);
115
+ const name = String(p.name);
116
+ if (meta.name !== undefined && meta.name !== name) {
117
+ console.error(`[injest] selection drift at index ${Number(p.testIndex)}: ` +
118
+ `expected "${meta.name}", agent ran "${name}"`);
119
+ }
120
+ record({
121
+ index,
122
+ id: meta.id,
123
+ name,
124
+ durationMs: Number(p.durationMs) || 0,
125
+ status: p.skipped ? "skipped" : p.passed ? "passed" : "failed",
126
+ file: meta.file,
127
+ line: meta.line,
128
+ error: p.error,
129
+ });
130
+ current = -1;
131
+ currentFile = undefined;
132
+ currentLine = undefined;
133
+ break;
134
+ }
135
+ case "done":
136
+ finish();
137
+ break;
138
+ }
139
+ });
140
+ script.logHandler = (level, text) => {
141
+ if (done)
142
+ return;
143
+ reportOutput({
144
+ level: String(level),
145
+ text,
146
+ name: current >= 0 ? names[current] : undefined,
147
+ file: current >= 0 ? currentFile : undefined,
148
+ line: current >= 0 ? currentLine : undefined,
149
+ }, reporter);
150
+ };
151
+ session.detached.connect((reason) => {
152
+ if (done)
153
+ return; // our own teardown
154
+ // detach before "done" means the target died mid-run
155
+ abort(`target detached: ${reason}`, true);
156
+ });
157
+ const api = script.exports;
158
+ api.run({ grep: opts.grep, only: opts.only }).catch((err) => {
159
+ if (done)
160
+ return;
161
+ const message = err instanceof Error ? err.message : String(err);
162
+ console.error("[injest] run() failed:", message);
163
+ abort(`run() failed: ${message}`, false);
164
+ });
165
+ await finished;
166
+ fillRemaining(0, "skipped");
167
+ return results.slice(0, Math.max(total, results.length));
168
+ }
169
+ export function reportResult(r, reporter) {
170
+ if (reporter === "json")
171
+ emitJson(r);
172
+ else
173
+ printResult(r);
174
+ }
175
+ export function reportOutput(o, reporter) {
176
+ if (reporter === "json") {
177
+ process.stdout.write(JSON.stringify({
178
+ type: "output",
179
+ level: o.level,
180
+ text: o.text,
181
+ name: o.name,
182
+ file: o.file,
183
+ line: o.line,
184
+ }) + "\n");
185
+ return;
186
+ }
187
+ // pretty: indent under the running test (logs arrive before its result line)
188
+ const prefix = " │ ";
189
+ process.stdout.write(prefix +
190
+ o.text
191
+ .replace(/\n$/, "")
192
+ .split("\n")
193
+ .join("\n" + prefix) +
194
+ "\n");
195
+ }
196
+ function printResult(r) {
197
+ const ms = `(${r.durationMs}ms)`;
198
+ if (r.status === "passed") {
199
+ console.log(` ✓ ${r.name} ${ms}`);
200
+ return;
201
+ }
202
+ if (r.status === "skipped") {
203
+ const why = r.error ? `: ${r.error.message}` : "";
204
+ console.log(` - ${r.name} (skipped${why})`);
205
+ return;
206
+ }
207
+ const tag = r.status === "failed" ? "" : ` [${r.status}]`;
208
+ console.log(` ✗ ${r.name} ${ms}${tag}`);
209
+ if (r.error) {
210
+ console.log(` ${r.error.name}: ${r.error.message}`);
211
+ if (r.error.expected !== undefined || r.error.actual !== undefined) {
212
+ console.log(` expected: ${indentMultiline(r.error.expected)}`);
213
+ console.log(` actual: ${indentMultiline(r.error.actual)}`);
214
+ }
215
+ if (r.error.stack) {
216
+ const frames = r.error.stack
217
+ .split("\n")
218
+ .map((l) => l.trim())
219
+ .filter((l) => l.startsWith("at") && !isRunnerFrame(l))
220
+ .slice(0, 3);
221
+ for (const f of frames)
222
+ console.log(` ${f}`);
223
+ }
224
+ }
225
+ }
226
+ function isRunnerFrame(frame) {
227
+ return /agent\/(runtime|expect)\.|[/\\]entry\.|\.injest/.test(frame);
228
+ }
229
+ function indentMultiline(value) {
230
+ return (value ?? "").split("\n").join("\n ");
231
+ }
232
+ function emitJson(r) {
233
+ process.stdout.write(JSON.stringify({
234
+ type: "test",
235
+ id: r.id,
236
+ name: r.name,
237
+ status: r.status,
238
+ durationMs: r.durationMs,
239
+ file: r.file,
240
+ line: r.line,
241
+ error: r.error,
242
+ }) + "\n");
243
+ }
244
+ export function summarize(results, reporter = "pretty") {
245
+ const count = (s) => results.filter((r) => r.status === s).length;
246
+ const passed = count("passed");
247
+ const failed = count("failed") + count("timeout") + count("crashed") + count("incomplete");
248
+ if (reporter === "json") {
249
+ process.stdout.write(JSON.stringify({
250
+ type: "end",
251
+ passed,
252
+ failed,
253
+ skipped: count("skipped"),
254
+ total: results.length,
255
+ }) + "\n");
256
+ return { passed, failed };
257
+ }
258
+ const parts = [
259
+ `${passed} passed`,
260
+ `${count("failed")} failed`,
261
+ `${count("timeout")} timeout`,
262
+ `${count("crashed")} crashed`,
263
+ `${count("incomplete")} incomplete`,
264
+ `${count("skipped")} skipped`,
265
+ `${results.length} total`,
266
+ ];
267
+ console.log(`\n${parts.join(", ")}`);
268
+ return { passed, failed };
269
+ }
270
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/host/run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import * as frida from "frida";
2
+ import type { Runtime, TargetConfig } from "./config.js";
3
+ export declare function getDevice(target: TargetConfig): Promise<frida.Device>;
4
+ export interface OpenedSession {
5
+ session: frida.Session;
6
+ /** Resume a gated spawn (idempotent); no-op for the system session. */
7
+ resume(): Promise<void>;
8
+ /** Kill the process if we spawned it, else detach. */
9
+ close(): Promise<void>;
10
+ }
11
+ export declare function openSession(device: frida.Device, target: TargetConfig): Promise<OpenedSession>;
12
+ export declare function runtimeOption(runtime?: Runtime): frida.ScriptRuntime;
13
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/host/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIzD,wBAAsB,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAM3E;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC;IACvB,uEAAuE;IACvE,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,sDAAsD;IACtD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,KAAK,CAAC,MAAM,EACpB,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,aAAa,CAAC,CA8BxB;AAED,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC,aAAa,CASpE"}
@@ -0,0 +1,55 @@
1
+ import * as frida from "frida";
2
+ const SYSTEM_SESSION_PID = 0;
3
+ export async function getDevice(target) {
4
+ const { device } = target;
5
+ if (device === "local")
6
+ return frida.getLocalDevice();
7
+ if (device === "usb")
8
+ return frida.getUsbDevice();
9
+ if (typeof device === "object" && device.id)
10
+ return frida.getDevice(device.id);
11
+ throw new Error(`invalid "device" in target config: ${JSON.stringify(device)}`);
12
+ }
13
+ export async function openSession(device, target) {
14
+ const { session } = target;
15
+ if (session === "system") {
16
+ const s = await device.attach(SYSTEM_SESSION_PID);
17
+ return { session: s, resume: async () => { }, close: () => s.detach() };
18
+ }
19
+ if ("spawn" in session) {
20
+ // spawn gating: the process starts suspended so the agent can hook before any of its code runs
21
+ const argv = session.args ? [session.spawn, ...session.args] : undefined;
22
+ const pid = await device.spawn(session.spawn, argv ? { argv } : undefined);
23
+ const s = await device.attach(pid);
24
+ let resumed = false;
25
+ return {
26
+ session: s,
27
+ resume: async () => {
28
+ if (resumed)
29
+ return;
30
+ resumed = true;
31
+ await device.resume(pid);
32
+ },
33
+ close: async () => {
34
+ try {
35
+ await device.kill(pid);
36
+ }
37
+ catch {
38
+ // already gone (crashed / exited)
39
+ }
40
+ },
41
+ };
42
+ }
43
+ throw new Error('invalid "session" in target config');
44
+ }
45
+ export function runtimeOption(runtime) {
46
+ switch (runtime) {
47
+ case "qjs":
48
+ return frida.ScriptRuntime.QJS;
49
+ case "v8":
50
+ return frida.ScriptRuntime.V8;
51
+ default:
52
+ return frida.ScriptRuntime.Default;
53
+ }
54
+ }
55
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/host/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAE7B,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAoB;IAClD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAC1B,IAAI,MAAM,KAAK,OAAO;QAAE,OAAO,KAAK,CAAC,cAAc,EAAE,CAAC;IACtD,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC,YAAY,EAAE,CAAC;IAClD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,EAAE;QAAE,OAAO,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC/E,MAAM,IAAI,KAAK,CAAC,sCAAsC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAClF,CAAC;AAUD,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAoB,EACpB,MAAoB;IAEpB,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IAE3B,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QACzB,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAClD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;IACzE,CAAC;IACD,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC;QACvB,+FAA+F;QAC/F,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACzE,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAC3E,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,OAAO;YACL,OAAO,EAAE,CAAC;YACV,MAAM,EAAE,KAAK,IAAI,EAAE;gBACjB,IAAI,OAAO;oBAAE,OAAO;gBACpB,OAAO,GAAG,IAAI,CAAC;gBACf,MAAM,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC3B,CAAC;YACD,KAAK,EAAE,KAAK,IAAI,EAAE;gBAChB,IAAI,CAAC;oBACH,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACzB,CAAC;gBAAC,MAAM,CAAC;oBACP,kCAAkC;gBACpC,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAiB;IAC7C,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,KAAK;YACR,OAAO,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC;QACjC,KAAK,IAAI;YACP,OAAO,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC;QAChC;YACE,OAAO,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC;IACvC,CAAC;AACH,CAAC"}
@@ -0,0 +1,14 @@
1
+ export type Mode = "run" | "skip";
2
+ export type Launch = "shared" | "isolated" | "suspended";
3
+ export interface TestInfo {
4
+ id: string;
5
+ index: number;
6
+ name: string;
7
+ mode: Mode;
8
+ launch: Launch;
9
+ file?: string;
10
+ line?: number;
11
+ }
12
+ export declare function discoverTestInfo(files: string[]): TestInfo[];
13
+ export declare function matchTestName(grep: string | undefined): (name: string) => boolean;
14
+ //# sourceMappingURL=source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../src/host/source.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,IAAI,GAAG,KAAK,GAAG,MAAM,CAAC;AAClC,MAAM,MAAM,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,WAAW,CAAC;AAEzD,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAiED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAa5D;AAGD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAQjF"}
@@ -0,0 +1,83 @@
1
+ import { readFileSync } from "node:fs";
2
+ import * as ts from "typescript";
3
+ const LAUNCH_BY_MEMBER = {
4
+ isolated: "isolated",
5
+ suspended: "suspended",
6
+ };
7
+ function classifyTestCallee(callee) {
8
+ if (ts.isIdentifier(callee)) {
9
+ return callee.text === "test" ? { mode: "run", launch: "shared" } : null;
10
+ }
11
+ if (ts.isPropertyAccessExpression(callee) &&
12
+ ts.isIdentifier(callee.expression) &&
13
+ callee.expression.text === "test") {
14
+ if (callee.name.text === "skip")
15
+ return { mode: "skip", launch: "shared" };
16
+ const launch = LAUNCH_BY_MEMBER[callee.name.text];
17
+ if (launch)
18
+ return { mode: "run", launch };
19
+ }
20
+ return null;
21
+ }
22
+ function isDescribeCallee(callee) {
23
+ return ts.isIdentifier(callee) && callee.text === "describe";
24
+ }
25
+ function testsInFile(absoluteFile) {
26
+ let text;
27
+ try {
28
+ text = readFileSync(absoluteFile, "utf8");
29
+ }
30
+ catch {
31
+ return [];
32
+ }
33
+ const sourceFile = ts.createSourceFile(absoluteFile, text, ts.ScriptTarget.Latest, true);
34
+ const out = [];
35
+ // mirrors the agent's suiteStack (runtime.ts) so discovered names match registered ones
36
+ const suiteStack = [];
37
+ const visit = (node) => {
38
+ if (ts.isCallExpression(node)) {
39
+ const first = node.arguments[0];
40
+ const label = first && ts.isStringLiteralLike(first) ? first.text : undefined;
41
+ if (label !== undefined && isDescribeCallee(node.expression)) {
42
+ suiteStack.push(label);
43
+ ts.forEachChild(node, visit);
44
+ suiteStack.pop();
45
+ return;
46
+ }
47
+ const kind = label !== undefined ? classifyTestCallee(node.expression) : null;
48
+ if (label !== undefined && kind) {
49
+ const line = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;
50
+ out.push({ name: [...suiteStack, label].join(" › "), file: absoluteFile, line, ...kind });
51
+ }
52
+ }
53
+ ts.forEachChild(node, visit);
54
+ };
55
+ visit(sourceFile);
56
+ return out;
57
+ }
58
+ export function discoverTestInfo(files) {
59
+ const discovered = files.flatMap(testsInFile);
60
+ const totals = new Map();
61
+ for (const t of discovered)
62
+ totals.set(t.name, (totals.get(t.name) ?? 0) + 1);
63
+ const seen = new Map();
64
+ return discovered.map((t, index) => {
65
+ const occurrence = (seen.get(t.name) ?? 0) + 1;
66
+ seen.set(t.name, occurrence);
67
+ const id = (totals.get(t.name) ?? 0) > 1 ? `${t.name}#${occurrence}` : t.name;
68
+ return { id, index, ...t };
69
+ });
70
+ }
71
+ // regex, else substring fallback — must stay in sync with the agent's makeMatcher (runtime.ts)
72
+ export function matchTestName(grep) {
73
+ if (!grep)
74
+ return () => true;
75
+ try {
76
+ const re = new RegExp(grep);
77
+ return (name) => re.test(name);
78
+ }
79
+ catch {
80
+ return (name) => name.includes(grep);
81
+ }
82
+ }
83
+ //# sourceMappingURL=source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.js","sourceRoot":"","sources":["../../src/host/source.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "@frida/injest",
3
+ "version": "0.1.0",
4
+ "description": "A test runner for code running inside Frida's GumJS runtime.",
5
+ "license": "MIT",
6
+ "author": "Håvard Sørbø <havard@hsorbo.no>",
7
+ "homepage": "https://github.com/frida/injest/tree/main/packages/injest#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/frida/injest.git",
11
+ "directory": "packages/injest"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/frida/injest/issues"
15
+ },
16
+ "keywords": [
17
+ "frida",
18
+ "gumjs",
19
+ "gum",
20
+ "testing",
21
+ "test-runner",
22
+ "instrumentation",
23
+ "dynamic-analysis"
24
+ ],
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "type": "module",
29
+ "bin": {
30
+ "injest": "dist/host/cli.js"
31
+ },
32
+ "main": "dist/host/index.js",
33
+ "types": "dist/host/index.d.ts",
34
+ "exports": {
35
+ ".": {
36
+ "types": "./dist/host/index.d.ts",
37
+ "import": "./dist/host/index.js"
38
+ },
39
+ "./agent": {
40
+ "types": "./dist/agent/runtime.d.ts",
41
+ "import": "./dist/agent/runtime.js"
42
+ }
43
+ },
44
+ "files": [
45
+ "dist",
46
+ "schema",
47
+ "LICENSE.md"
48
+ ],
49
+ "scripts": {
50
+ "build": "tsc -p tsconfig.json && chmod +x dist/host/cli.js",
51
+ "typecheck:agent": "tsc -p tsconfig.agent.json",
52
+ "test": "tsx --test \"test/**/*.spec.ts\"",
53
+ "test:watch": "tsx --test --watch \"test/**/*.spec.ts\"",
54
+ "injest": "node dist/host/cli.js",
55
+ "prepublishOnly": "npm run build"
56
+ },
57
+ "dependencies": {
58
+ "ajv": "^8.17.1",
59
+ "deep-eql": "^5.0.2",
60
+ "frida": "^17.10.1",
61
+ "typescript": "^6.0.3"
62
+ },
63
+ "devDependencies": {
64
+ "@types/deep-eql": "^4.0.2",
65
+ "@types/frida-gum": "^19.4.0",
66
+ "@types/node": "^25.9.1",
67
+ "prettier": "^3.8.3",
68
+ "tsx": "^4.20.6"
69
+ },
70
+ "engines": {
71
+ "node": ">=22"
72
+ }
73
+ }