Skip to content
Source
Sign inSign up

nativeReviewDiffTrace.ts

70 lines2.2 KB

1// Opt in at bundle time for bounded Release diagnostics; never log source or RPC payloads.
2const MAX_TRACE_EVENTS = 1_000;
3let eventCount = 0;
4let nextId = 0;
5// Diagnostics must not keep requests, source loaders, or their row graphs alive.
6const objectIds = new WeakMap<object, number>();
7const primitiveIds = new Map<unknown, number>();
8let fileSink: Promise<import("expo-file-system").File | null> | undefined;
9​
10export function diffHighlightTraceHash(value: string): number {
11 let hash = 2166136261;
12 for (let index = 0; index < value.length; index++)
13 hash = Math.imul(hash ^ value.charCodeAt(index), 16777619);
14 return hash >>> 0;
16​
17function appendTraceLine(line: string) {
18 fileSink ??= import("expo-file-system")
19 .then(({ File, Paths }) => {
20 const file = new File(Paths.document, "t3-diff-highlight-trace.jsonl");
21 file.create({ overwrite: true, intermediates: true });
22 return file;
23 })
24 .catch(() => null);
25 // File.write is async in Expo 58. Serialize appends to preserve sequence order.
26 fileSink = fileSink.then(async (file) => {
27 if (!file) return null;
28 try {
29 await file.write(line + "\n", { append: true });
30 return file;
31 } catch {
32 return null;
33 }
34 });
36​
37export function diffHighlightTraceId(value: unknown): number {
38 if (process.env.EXPO_PUBLIC_T3_DIFF_TRACE !== "1" || eventCount >= MAX_TRACE_EVENTS) return 0;
39 if ((typeof value === "object" && value !== null) || typeof value === "function") {
40 let id = objectIds.get(value);
41 if (id === undefined) {
42 id = ++nextId;
43 objectIds.set(value, id);
44 }
45 return id;
46 }
47 let id = primitiveIds.get(value);
48 if (id === undefined) {
49 id = ++nextId;
50 primitiveIds.set(value, id);
51 }
52 return id;
54​
55export function traceDiffHighlight(
56 event: string,
57 fields: Readonly<Record<string, number | boolean | string | undefined>> = {},
58) {
59 if (process.env.EXPO_PUBLIC_T3_DIFF_TRACE !== "1" || eventCount >= MAX_TRACE_EVENTS) return;
60 eventCount += 1;
61 const line = JSON.stringify({
62 event,
63 seq: eventCount,
64 at: Math.round(performance.now()),
65 ...fields,
66 });
67 appendTraceLine(line);
68 console.warn("[diff-highlight-trace] " + line);
69 if (eventCount === MAX_TRACE_EVENTS) primitiveIds.clear();