@keepsnappy/react-native 0.1.0-alpha.11 → 0.1.0-alpha.13

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.
package/js/sdk/core.ts CHANGED
@@ -1,12 +1,12 @@
1
- // perf-lab core: settings, windows, the commit walk, observers, faults, logs.
1
+ // keepsnappy core: settings, windows, the commit walk, observers, faults, logs.
2
2
  // Loaded by boot.ts, which Metro runs before the app's entry module.
3
3
 
4
4
  import {
5
5
  type ActivationStore,
6
6
  type Decision,
7
7
  MODE,
8
- PERF_LAB_DEEP_LINK_PATH,
9
- PERF_LAB_ENABLED,
8
+ KEEPSNAPPY_DEEP_LINK_PATH,
9
+ KEEPSNAPPY_ENABLED,
10
10
  parseQuery,
11
11
  type PolyfillActivation,
12
12
  } from './activation';
@@ -90,7 +90,7 @@ import {
90
90
  windowAggregate,
91
91
  } from './sampler';
92
92
 
93
- export { PERF_LAB_DEEP_LINK_PATH, PERF_LAB_ENABLED, parseQuery };
93
+ export { KEEPSNAPPY_DEEP_LINK_PATH, KEEPSNAPPY_ENABLED, parseQuery };
94
94
 
95
95
  type LogSink = 'console' | 'native' | 'both';
96
96
 
@@ -126,7 +126,7 @@ interface Settings extends SamplerSettings {
126
126
  diag: boolean;
127
127
  }
128
128
 
129
- interface PerfLabNative extends Partial<CpuProfileNative> {
129
+ interface KeepSnappyNative extends Partial<CpuProfileNative> {
130
130
  beginAsyncSection(name: string, cookie: number): void;
131
131
  endAsyncSection(name: string, cookie: number): void;
132
132
  setCounter(name: string, value: number): void;
@@ -143,13 +143,13 @@ interface PerfLabNative extends Partial<CpuProfileNative> {
143
143
  samplerRecent(sinceT: number): SamplerRecord[];
144
144
  samplerNow(): number;
145
145
  flushSignal?(status: string, detail: string): void;
146
- // GC before the action: Android finishes the pending command broadcast with this result; iOS shows it on `perflab.ack`.
146
+ // GC before the action: Android finishes the pending command broadcast with this result; iOS shows it on `keepsnappy.ack`.
147
147
  commandDone?(n: number, data: string): void;
148
148
  /** Android: whether the broadcast of command n still waits for its answer (native finishes it at a deadline). */
149
149
  commandPending?(n: number): boolean;
150
150
  ackSignal?(text: string): void;
151
151
  commandListen?(on: boolean): void;
152
- addListener?(event: 'perflabCommand', listener: (e: { cmd: string; n: number; tNative: number }) => void): { remove(): void };
152
+ addListener?(event: 'keepsnappyCommand', listener: (e: { cmd: string; n: number; tNative: number }) => void): { remove(): void };
153
153
  }
154
154
 
155
155
  interface RendererInternals {
@@ -232,7 +232,7 @@ interface PolyfillHook {
232
232
  attach: (listener: HookListener | null) => void;
233
233
  }
234
234
 
235
- interface PerfLabGlobal {
235
+ interface KeepSnappyGlobal {
236
236
  HermesInternal?: HermesInternalApi;
237
237
  PerformanceObserver?: PerfObserverCtor & { supportedEntryTypes?: string[] };
238
238
  performance?: PerformanceLike;
@@ -240,12 +240,12 @@ interface PerfLabGlobal {
240
240
  console: { log: (...args: unknown[]) => void; timeStamp?: unknown };
241
241
  expo?: { modules?: Record<string, unknown> };
242
242
  __REACT_DEVTOOLS_GLOBAL_HOOK__?: Record<string, unknown>;
243
- __PERFLAB_HOOK__?: PolyfillHook;
244
- __PERFLAB_ACTIVATION__?: PolyfillActivation;
245
- __PERF_LAB__?: unknown;
243
+ __KEEPSNAPPY_HOOK__?: PolyfillHook;
244
+ __KEEPSNAPPY_ACTIVATION__?: PolyfillActivation;
245
+ __KEEPSNAPPY__?: unknown;
246
246
  }
247
247
 
248
- const g = globalThis as unknown as PerfLabGlobal;
248
+ const g = globalThis as unknown as KeepSnappyGlobal;
249
249
 
250
250
  const NO_FAULTS: Faults = {
251
251
  cpu: 0,
@@ -275,15 +275,15 @@ const defaultSettings = (): Settings => ({
275
275
  log: AUTO ? 'both' : 'console',
276
276
  faults: { ...NO_FAULTS },
277
277
  faultTarget: DEFAULT_FAULT_TARGET,
278
- profile: (process.env.EXPO_PUBLIC_KEEPSNAPPY_PROFILE ?? process.env.EXPO_PUBLIC_PERF_LAB_PROFILE) === '1',
279
- rexport: (process.env.EXPO_PUBLIC_KEEPSNAPPY_REACT_EXPORT ?? process.env.EXPO_PUBLIC_PERF_LAB_REACT_EXPORT) === '1',
280
- cpuprof: (process.env.EXPO_PUBLIC_KEEPSNAPPY_CPUPROF ?? process.env.EXPO_PUBLIC_PERF_LAB_CPUPROF) === '1',
281
- cpuhz: Number((process.env.EXPO_PUBLIC_KEEPSNAPPY_CPUPROF_HZ ?? process.env.EXPO_PUBLIC_PERF_LAB_CPUPROF_HZ)) || 250,
278
+ profile: (process.env.EXPO_PUBLIC_KEEPSNAPPY_PROFILE) === '1',
279
+ rexport: (process.env.EXPO_PUBLIC_KEEPSNAPPY_REACT_EXPORT) === '1',
280
+ cpuprof: (process.env.EXPO_PUBLIC_KEEPSNAPPY_CPUPROF) === '1',
281
+ cpuhz: Number((process.env.EXPO_PUBLIC_KEEPSNAPPY_CPUPROF_HZ)) || 250,
282
282
  diag: false,
283
283
  ...samplerDefaults({
284
284
  auto: AUTO,
285
- sampler: (process.env.EXPO_PUBLIC_KEEPSNAPPY_SAMPLER ?? process.env.EXPO_PUBLIC_PERF_LAB_SAMPLER),
286
- samplerMs: (process.env.EXPO_PUBLIC_KEEPSNAPPY_SAMPLER_MS ?? process.env.EXPO_PUBLIC_PERF_LAB_SAMPLER_MS),
285
+ sampler: (process.env.EXPO_PUBLIC_KEEPSNAPPY_SAMPLER),
286
+ samplerMs: (process.env.EXPO_PUBLIC_KEEPSNAPPY_SAMPLER_MS),
287
287
  }),
288
288
  });
289
289
 
@@ -296,14 +296,14 @@ export const now = () => (g.performance ? g.performance.now() : Date.now());
296
296
  export const fmt = (ms: number) => ms.toFixed(3);
297
297
  const noop = () => undefined;
298
298
 
299
- let nativeModule: PerfLabNative | null | undefined;
299
+ let nativeModule: KeepSnappyNative | null | undefined;
300
300
  let nativeMissingLogged = false;
301
301
 
302
- const getNative = (): PerfLabNative | null => {
302
+ const getNative = (): KeepSnappyNative | null => {
303
303
  if (nativeModule) {
304
304
  return nativeModule;
305
305
  }
306
- const found = g.expo?.modules?.PerfLab as PerfLabNative | undefined;
306
+ const found = g.expo?.modules?.KeepSnappy as KeepSnappyNative | undefined;
307
307
  if (found) {
308
308
  nativeModule = found;
309
309
  return found;
@@ -311,7 +311,7 @@ const getNative = (): PerfLabNative | null => {
311
311
  if (!nativeMissingLogged) {
312
312
  nativeMissingLogged = true;
313
313
  g.console.log(
314
- 'PERF_LAB native module PerfLab missing (expo.modules.PerfLab)',
314
+ 'KEEPSNAPPY native module KeepSnappy missing (expo.modules.KeepSnappy)',
315
315
  );
316
316
  }
317
317
  return null;
@@ -344,10 +344,10 @@ const cpu = createCpuProfiler({
344
344
  });
345
345
 
346
346
  export const perfLog = (message: string, sink: LogSink = settings.log) => {
347
- if (!PERF_LAB_ENABLED) {
347
+ if (!KEEPSNAPPY_ENABLED) {
348
348
  return;
349
349
  }
350
- const line = `PERF_LAB ${message}`;
350
+ const line = `KEEPSNAPPY ${message}`;
351
351
  if (sink === 'console' || sink === 'both') {
352
352
  g.console.log(line);
353
353
  }
@@ -412,7 +412,7 @@ const nativeSamplerNow = () => {
412
412
 
413
413
  // On-demand sample: logged natively like the automatic ones and returned. Null when the sampler is off.
414
414
  export const sample = (reason = 'manual'): SamplerRecord | null => {
415
- if (!PERF_LAB_ENABLED || samplerState.mode === 'off') {
415
+ if (!KEEPSNAPPY_ENABLED || samplerState.mode === 'off') {
416
416
  return null;
417
417
  }
418
418
  try {
@@ -816,7 +816,7 @@ const clearIdleGc = () => {
816
816
 
817
817
  const scheduleIdleGc = () => {
818
818
  clearIdleGc();
819
- if (!PERF_LAB_ENABLED || !settings.gcwin || openWindows.size > 0) {
819
+ if (!KEEPSNAPPY_ENABLED || !settings.gcwin || openWindows.size > 0) {
820
820
  return;
821
821
  }
822
822
  idleGcTimer = setTimeout(() => {
@@ -835,7 +835,7 @@ export const lastCommitAt = (key: string) =>
835
835
  export const isWindowOpen = (key?: string) =>
836
836
  key ? openWindows.has(key) : openWindows.size > 0;
837
837
 
838
- const traceName = (name: string) => `perf-lab:${name}`;
838
+ const traceName = (name: string) => `keepsnappy:${name}`;
839
839
 
840
840
  interface StartOptions {
841
841
  key?: string;
@@ -962,7 +962,7 @@ const endBackground = (reason: string) => {
962
962
  };
963
963
 
964
964
  const start = (name: string, options: StartOptions = {}) => {
965
- if (!PERF_LAB_ENABLED || !settings.marks) {
965
+ if (!KEEPSNAPPY_ENABLED || !settings.marks) {
966
966
  return null;
967
967
  }
968
968
  const key = options.key ?? name;
@@ -1091,7 +1091,7 @@ const rename = (key: string, name: string) => {
1091
1091
  };
1092
1092
 
1093
1093
  const point = (name: string) => {
1094
- if (!PERF_LAB_ENABLED || !settings.marks) {
1094
+ if (!KEEPSNAPPY_ENABLED || !settings.marks) {
1095
1095
  return;
1096
1096
  }
1097
1097
  const t = now();
@@ -1277,15 +1277,15 @@ const onCommitFiberUnmount = (_rendererId: number, fiber: Fiber) => {
1277
1277
  };
1278
1278
 
1279
1279
  export const lastRoot = (rendererId = 1): FiberRoot | null =>
1280
- g.__PERFLAB_HOOK__?.state.lastRootByRenderer[rendererId] ?? null;
1280
+ g.__KEEPSNAPPY_HOOK__?.state.lastRootByRenderer[rendererId] ?? null;
1281
1281
 
1282
- // The polyfill (withPerfLab) installed the hook before React loaded; attach to
1282
+ // The polyfill (withKeepSnappy) installed the hook before React loaded; attach to
1283
1283
  // it. Without the polyfill, fall back to installing it now, as the prototype did.
1284
1284
  export const attachHook = () => {
1285
- if (!PERF_LAB_ENABLED || hookState.installed) {
1285
+ if (!KEEPSNAPPY_ENABLED || hookState.installed) {
1286
1286
  return;
1287
1287
  }
1288
- const polyfill = g.__PERFLAB_HOOK__;
1288
+ const polyfill = g.__KEEPSNAPPY_HOOK__;
1289
1289
  if (polyfill) {
1290
1290
  polyfill.ensure();
1291
1291
  polyfill.attach({
@@ -1310,7 +1310,7 @@ export const attachHook = () => {
1310
1310
  }
1311
1311
  if (g.__REACT_DEVTOOLS_GLOBAL_HOOK__) {
1312
1312
  hookState.preexisting = true;
1313
- g.console.log('PERF_LAB hook already present, not replacing it');
1313
+ g.console.log('KEEPSNAPPY hook already present, not replacing it');
1314
1314
  return;
1315
1315
  }
1316
1316
  let nextRendererId = 1;
@@ -1327,7 +1327,7 @@ export const attachHook = () => {
1327
1327
  bundleType: internals.bundleType,
1328
1328
  });
1329
1329
  g.console.log(
1330
- `PERF_LAB hook inject id=${id} renderer=${internals.rendererPackageName} version=${internals.version} bundleType=${internals.bundleType}`,
1330
+ `KEEPSNAPPY hook inject id=${id} renderer=${internals.rendererPackageName} version=${internals.version} bundleType=${internals.bundleType}`,
1331
1331
  );
1332
1332
  return id;
1333
1333
  },
@@ -1753,7 +1753,7 @@ const finalizeWindow = (window: MarkerWindow) => {
1753
1753
  const writeWindowRecord = (window: MarkerWindow, summary: Record<string, unknown>) => {
1754
1754
  const json = JSON.stringify(summary);
1755
1755
  perfLog(`window ${json}`);
1756
- windowListener?.(`${Date.now()} PERF_LAB window ${json}`);
1756
+ windowListener?.(`${Date.now()} KEEPSNAPPY window ${json}`);
1757
1757
  if (settings.file) {
1758
1758
  const path = getNative()?.writeText(
1759
1759
  `window-${window.id}-${window.name.replace(/[^\w.:+-]/g, '_')}.json`,
@@ -1948,7 +1948,7 @@ const forwardSamples = () => {
1948
1948
  if (record.t <= samplesSentT) {
1949
1949
  continue;
1950
1950
  }
1951
- windowListener(`${record.wallMs} PERF_LAB sample ${JSON.stringify(record)}`);
1951
+ windowListener(`${record.wallMs} KEEPSNAPPY sample ${JSON.stringify(record)}`);
1952
1952
  samplesSentT = record.t;
1953
1953
  }
1954
1954
  } catch (error) {
@@ -1973,7 +1973,7 @@ export const writeRunEvent = (kind: 'gc' | 'appstate', record: Record<string, un
1973
1973
  const json = JSON.stringify({ ...record, t: now(), wallMs: Date.now() });
1974
1974
  perfLog(`${kind} ${json}`);
1975
1975
  if (inRun() && (kind === 'gc' || gcRanSinceFlush)) {
1976
- windowListener?.(`${Date.now()} PERF_LAB ${kind} ${json}`);
1976
+ windowListener?.(`${Date.now()} KEEPSNAPPY ${kind} ${json}`);
1977
1977
  }
1978
1978
  };
1979
1979
 
@@ -1995,7 +1995,7 @@ export const setFlushHandler = (handler: FlushHandler | null) => {
1995
1995
  };
1996
1996
 
1997
1997
  // `flush=1`: end the open windows, send every unsent line, then show the result
1998
- // to the test driver as an accessibility element (iOS: id `perflab.flushed`,
1998
+ // to the test driver as an accessibility element (iOS: id `keepsnappy.flushed`,
1999
1999
  // label `ok` / `error` / `off`), so a flow can wait for it without network access.
2000
2000
  const flushOnce = async () => {
2001
2001
  // One deadline for the whole flush (lines, clock, artifacts); the end report of the upload comes after it.
@@ -2059,7 +2059,7 @@ export const flushNow = (): Promise<void> => {
2059
2059
 
2060
2060
  // The activation's profile/cpuprof turn those on for the whole process; off
2061
2061
  // leaves the build's env defaults.
2062
- // A PerfLab run (one with a run token) forces an idle GC between windows so heap-after-GC
2062
+ // A KeepSnappy run (one with a run token) forces an idle GC between windows so heap-after-GC
2063
2063
  // readings exist for the leak slope (plan 41 Q7); `gcwin=0` in a link still turns it off.
2064
2064
  const applyDecision = (decision: Decision) => {
2065
2065
  settings.diag = decision.diag;
@@ -2093,13 +2093,13 @@ const activationReport = () => {
2093
2093
  mode: 'active',
2094
2094
  buildMode: decision.mode,
2095
2095
  read: decision.read,
2096
- installMs: g.__PERFLAB_ACTIVATION__?.installMs,
2096
+ installMs: g.__KEEPSNAPPY_ACTIVATION__?.installMs,
2097
2097
  runToken: runToken !== null,
2098
2098
  expiresAt: decision.expiresAt,
2099
2099
  diag: decision.diag,
2100
2100
  profile: decision.profile,
2101
2101
  cpuprof: decision.cpuprof,
2102
- renderer: g.__PERFLAB_ACTIVATION__?.renderer ?? null,
2102
+ renderer: g.__KEEPSNAPPY_ACTIVATION__?.renderer ?? null,
2103
2103
  next: next
2104
2104
  ? {
2105
2105
  active: next.active,
@@ -2258,24 +2258,24 @@ const syncCommandListener = () => {
2258
2258
  if (!native?.commandListen) {
2259
2259
  return;
2260
2260
  }
2261
- const on = PERF_LAB_ENABLED && runToken !== null;
2261
+ const on = KEEPSNAPPY_ENABLED && runToken !== null;
2262
2262
  if (on && commandSubscription === null) {
2263
2263
  commandSubscription =
2264
- native.addListener?.('perflabCommand', e => {
2264
+ native.addListener?.('keepsnappyCommand', e => {
2265
2265
  // A command native already timed out on is not run: its GC would land in the next step's action.
2266
2266
  if (native.commandPending?.(e.n) === false) {
2267
2267
  perfLog(`command gc:${e.n} late, skipped`);
2268
2268
  return;
2269
2269
  }
2270
- handlePerfLabCommand(e.cmd, e.n, e.tNative);
2270
+ handleKeepSnappyCommand(e.cmd, e.n, e.tNative);
2271
2271
  }) ?? null;
2272
2272
  }
2273
2273
  native.commandListen(on);
2274
2274
  };
2275
2275
 
2276
2276
  /** A command (`cmd=<name>&n=<n>`), from a link (iOS) or the native receiver (Android); unknown commands are ignored. */
2277
- export const handlePerfLabCommand = (cmd: string | undefined, n: number, tNative?: number): boolean => {
2278
- if (!PERF_LAB_ENABLED || cmd !== 'gc' || !Number.isInteger(n) || n < 1) {
2277
+ export const handleKeepSnappyCommand = (cmd: string | undefined, n: number, tNative?: number): boolean => {
2278
+ if (!KEEPSNAPPY_ENABLED || cmd !== 'gc' || !Number.isInteger(n) || n < 1) {
2279
2279
  return false;
2280
2280
  }
2281
2281
  // Every received command is answered, so the Android receiver is never left pending.
@@ -2288,14 +2288,14 @@ export const handlePerfLabCommand = (cmd: string | undefined, n: number, tNative
2288
2288
  return true;
2289
2289
  };
2290
2290
 
2291
- export const handlePerfLabDeepLink = (url: string) => {
2292
- if (!PERF_LAB_ENABLED) {
2291
+ export const handleKeepSnappyDeepLink = (url: string) => {
2292
+ if (!KEEPSNAPPY_ENABLED) {
2293
2293
  return;
2294
2294
  }
2295
2295
  const params = parseQuery(url.split('?')[1]);
2296
2296
  // A command changes no settings and writes no activation record.
2297
2297
  if (params.cmd !== undefined) {
2298
- handlePerfLabCommand(params.cmd, Number(params.n));
2298
+ handleKeepSnappyCommand(params.cmd, Number(params.n));
2299
2299
  return;
2300
2300
  }
2301
2301
  const written = activation?.store.apply(params) ?? null;
@@ -2326,7 +2326,7 @@ export const addStartupSection = (name: string, read: () => unknown) => {
2326
2326
 
2327
2327
  export const logStartup = (phase: string) => {
2328
2328
  const native = getNative();
2329
- const polyfill = g.__PERFLAB_HOOK__?.state;
2329
+ const polyfill = g.__KEEPSNAPPY_HOOK__?.state;
2330
2330
  const extra: Record<string, unknown> = {};
2331
2331
  for (const [name, read] of extraStartupSections) {
2332
2332
  extra[name] = safe(read);
@@ -2391,7 +2391,7 @@ export const logStartup = (phase: string) => {
2391
2391
  };
2392
2392
 
2393
2393
  export const exposeGlobal = () => {
2394
- g.__PERF_LAB__ = {
2394
+ g.__KEEPSNAPPY__ = {
2395
2395
  settings,
2396
2396
  set: applySettings,
2397
2397
  markers,
package/js/sdk/cpuprof.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  // overlapping windows (a press and the screen it opens) share one span and one
4
4
  // file. Inside a run it samples on until `flush=1` and writes one file there.
5
5
  // The file is a DevTools .cpuprofile (nodes/samples/timeDeltas) written by the
6
- // native module into Documents/perf-lab.
6
+ // native module into Documents/keepsnappy.
7
7
 
8
8
  export interface CpuProfileNative {
9
9
  cpuProfileStart(hz: number): boolean;
package/js/sdk/dormant.ts CHANGED
@@ -16,14 +16,14 @@ interface DormantNative {
16
16
 
17
17
  interface DormantGlobal {
18
18
  __REACT_DEVTOOLS_GLOBAL_HOOK__?: unknown;
19
- __PERFLAB_HOOK__?: { state?: { mode?: string; listener?: unknown } };
20
- __PERF_LAB__?: unknown;
19
+ __KEEPSNAPPY_HOOK__?: { state?: { mode?: string; listener?: unknown } };
20
+ __KEEPSNAPPY__?: unknown;
21
21
  expo?: { modules?: Record<string, unknown> };
22
22
  }
23
23
 
24
24
  const g = globalThis as unknown as DormantGlobal;
25
25
 
26
- const NET_MARK = '__perflabNet';
26
+ const NET_MARK = '__keepsnappyNet';
27
27
 
28
28
  const marked = (value: unknown) =>
29
29
  (typeof value === 'function' || (typeof value === 'object' && value !== null)) &&
@@ -54,8 +54,8 @@ export const dormantReport = (decision: Decision) => ({
54
54
  buildMode: decision.mode,
55
55
  read: decision.read,
56
56
  reactHook: typeof g.__REACT_DEVTOOLS_GLOBAL_HOOK__,
57
- perflabHook: g.__PERFLAB_HOOK__ ? (g.__PERFLAB_HOOK__.state?.mode ?? 'present') : 'absent',
58
- sdkGlobal: g.__PERF_LAB__ !== undefined,
57
+ keepsnappyHook: g.__KEEPSNAPPY_HOOK__ ? (g.__KEEPSNAPPY_HOOK__.state?.mode ?? 'present') : 'absent',
58
+ sdkGlobal: g.__KEEPSNAPPY__ !== undefined,
59
59
  fetchWrapped: globalWrapped('fetch'),
60
60
  xhrGetterWrapped: globalWrapped('XMLHttpRequest'),
61
61
  xhrPatched: xhrPatched(),
@@ -69,9 +69,9 @@ export const startDormant = (decision: Decision) => {
69
69
  store.apply(params);
70
70
  if (params.dump === '1') {
71
71
  // Asked for: one os_log line (iOS) / logcat line (Android), no log file.
72
- const native = g.expo?.modules?.PerfLab as DormantNative | undefined;
72
+ const native = g.expo?.modules?.KeepSnappy as DormantNative | undefined;
73
73
  const report = { ...dormantReport(decision), activation: store.stats() };
74
- native?.osLog?.(`PERF_LAB dormant ${JSON.stringify(report)}`);
74
+ native?.osLog?.(`KEEPSNAPPY dormant ${JSON.stringify(report)}`);
75
75
  }
76
76
  });
77
77
  };
package/js/sdk/links.ts CHANGED
@@ -1,31 +1,31 @@
1
- // Settings links (`<scheme>://devtools/perf-lab?...`) without app code: the SDK
1
+ // Settings links (`<scheme>://devtools/keepsnappy?...`) without app code: the SDK
2
2
  // runs before the router subscribes to Linking, so it wraps the link sources.
3
- // A perf-lab link goes to the handler here and never reaches the app's
3
+ // A keepsnappy link goes to the handler here and never reaches the app's
4
4
  // listeners, so the router does not navigate to an unmatched route. Only a URL
5
- // whose host and path are exactly `devtools/perf-lab` on a custom (non-web)
5
+ // whose host and path are exactly `devtools/keepsnappy` on a custom (non-web)
6
6
  // scheme is one; every other URL passes through unchanged after one substring
7
7
  // check: in a dormant build this is the only work the SDK does after startup.
8
8
 
9
9
  import { Linking } from 'react-native';
10
10
 
11
- import { PERF_LAB_DEEP_LINK_PATH } from './activation';
11
+ import { KEEPSNAPPY_DEEP_LINK_PATH } from './activation';
12
12
 
13
13
  export type LinkHandler = (url: string, via: string) => void;
14
- // Told when an app URL (not a perf-lab one) is handed to the app, before the
14
+ // Told when an app URL (not a keepsnappy one) is handed to the app, before the
15
15
  // app sees it: the start of a link-driven navigation.
16
16
  export type AppLinkHandler = (url: string, via: string) => void;
17
17
 
18
18
  type UrlListener = (event: { url: string }) => void;
19
19
 
20
- // `<scheme>://devtools/perf-lab[/][?query][#fragment]`, also with an empty host
21
- // (`<scheme>:///devtools/perf-lab`). Universal links (http/https) never match,
20
+ // `<scheme>://devtools/keepsnappy[/][?query][#fragment]`, also with an empty host
21
+ // (`<scheme>:///devtools/keepsnappy`). Universal links (http/https) never match,
22
22
  // so a web page cannot route a link here.
23
- // Spells out PERF_LAB_DEEP_LINK_PATH.
24
- const SETTINGS_LINK = /^([a-z][a-z0-9+.-]*):\/\/\/?devtools\/perf-lab\/?(?:[?#]|$)/i;
23
+ // Spells out KEEPSNAPPY_DEEP_LINK_PATH.
24
+ const SETTINGS_LINK = /^([a-z][a-z0-9+.-]*):\/\/\/?devtools\/keepsnappy\/?(?:[?#]|$)/i;
25
25
  const WEB_SCHEMES = new Set(['http', 'https']);
26
26
 
27
- export const isPerfLabUrl = (url: unknown): url is string => {
28
- if (typeof url !== 'string' || !url.includes(PERF_LAB_DEEP_LINK_PATH)) {
27
+ export const isKeepSnappyUrl = (url: unknown): url is string => {
28
+ if (typeof url !== 'string' || !url.includes(KEEPSNAPPY_DEEP_LINK_PATH)) {
29
29
  return false;
30
30
  }
31
31
  const match = SETTINGS_LINK.exec(url);
@@ -126,7 +126,7 @@ const patch = (
126
126
  };
127
127
 
128
128
  const filterInitial = (url: unknown, via: string) => {
129
- if (isPerfLabUrl(url)) {
129
+ if (isKeepSnappyUrl(url)) {
130
130
  apply(url, via);
131
131
  return null;
132
132
  }
@@ -157,7 +157,7 @@ export const installLinks = (
157
157
  return original(type, listener);
158
158
  }
159
159
  const filtered: UrlListener = event => {
160
- if (isPerfLabUrl(event?.url)) {
160
+ if (isKeepSnappyUrl(event?.url)) {
161
161
  apply(event.url, 'event');
162
162
  return;
163
163
  }
package/js/sdk/net.ts CHANGED
@@ -403,8 +403,8 @@ export type NetCounter = ReturnType<typeof createNetCounter>;
403
403
  // images loaded natively (Image, expo-image), WebSockets, and native SDKs
404
404
  // (Stream, LiveKit, Firebase).
405
405
 
406
- const WRAPPED = '__perflabNet';
407
- const XHR_STATE = '__perflabNetXhr';
406
+ const WRAPPED = '__keepsnappyNet';
407
+ const XHR_STATE = '__keepsnappyNetXhr';
408
408
  const EXPO_BUILTIN = Symbol.for('expo.builtin');
409
409
 
410
410
  type AnyFn = (...args: unknown[]) => unknown;
@@ -178,7 +178,7 @@ const changeDescription = (cause: UpdateCause) => ({
178
178
 
179
179
  export interface ReactExport {
180
180
  version: 5;
181
- source: 'perflab';
181
+ source: 'keepsnappy';
182
182
  captureStart: { clock: 'perf-now-ms'; t0: number };
183
183
  dataForRoots: {
184
184
  rootID: number;
@@ -225,11 +225,11 @@ export const buildReactExport = (t0: number, commits: ExportCommit[]): ReactExpo
225
225
  passiveEffectDuration: null,
226
226
  priorityLevel: null,
227
227
  timestamp: Math.max(0, commit.t - t0),
228
- perflabCauses: commit.causes,
229
- perflabCarrier: commit.carrier,
230
- perflabStore: commit.store,
231
- perflabTask: commit.task,
232
- ...(commit.facts ? { perflabFacts: commit.facts } : {}),
228
+ keepsnappyCauses: commit.causes,
229
+ keepsnappyCarrier: commit.carrier,
230
+ keepsnappyStore: commit.store,
231
+ keepsnappyTask: commit.task,
232
+ ...(commit.facts ? { keepsnappyFacts: commit.facts } : {}),
233
233
  updaters: (commit.updaters ?? []).map(displayName => ({
234
234
  displayName,
235
235
  hocDisplayNames: null,
@@ -241,7 +241,7 @@ export const buildReactExport = (t0: number, commits: ExportCommit[]): ReactExpo
241
241
  });
242
242
  return {
243
243
  version: 5,
244
- source: 'perflab',
244
+ source: 'keepsnappy',
245
245
  captureStart: { clock: 'perf-now-ms', t0 },
246
246
  dataForRoots: [
247
247
  {
@@ -1,6 +1,6 @@
1
1
  // Wires the push client to React Native: env config, device info, AppState.
2
- // Push stays off unless both EXPO_PUBLIC_PERFLAB_INGEST_URL and
3
- // EXPO_PUBLIC_PERFLAB_KEY are set at build time.
2
+ // Push stays off unless both EXPO_PUBLIC_KEEPSNAPPY_INGEST_URL and
3
+ // EXPO_PUBLIC_KEEPSNAPPY_KEY are set at build time.
4
4
 
5
5
  import { AppState, Platform } from 'react-native';
6
6
 
@@ -18,8 +18,8 @@ import {
18
18
  import { ownFetch } from './net-install';
19
19
  import { createPushClient, type DeviceInfo, type PushSpool } from './push';
20
20
 
21
- const INGEST_URL = (process.env.EXPO_PUBLIC_KEEPSNAPPY_INGEST_URL ?? process.env.EXPO_PUBLIC_PERFLAB_INGEST_URL);
22
- const INGEST_KEY = (process.env.EXPO_PUBLIC_KEEPSNAPPY_KEY ?? process.env.EXPO_PUBLIC_PERFLAB_KEY);
21
+ const INGEST_URL = (process.env.EXPO_PUBLIC_KEEPSNAPPY_INGEST_URL);
22
+ const INGEST_KEY = (process.env.EXPO_PUBLIC_KEEPSNAPPY_KEY);
23
23
 
24
24
  const randomId = () =>
25
25
  `r${Date.now().toString(36)}${Math.random().toString(36).slice(2, 10)}`;
@@ -80,7 +80,7 @@ interface SpoolNative {
80
80
  const nativeArtifacts = (): ArtifactUploadNative | null => {
81
81
  const native = (
82
82
  globalThis as unknown as { expo?: { modules?: Record<string, unknown> } }
83
- ).expo?.modules?.PerfLab as Partial<ArtifactUploadNative> | undefined;
83
+ ).expo?.modules?.KeepSnappy as Partial<ArtifactUploadNative> | undefined;
84
84
  if (!native || typeof native.artifactUpload !== 'function') {
85
85
  return null;
86
86
  }
@@ -88,12 +88,12 @@ const nativeArtifacts = (): ArtifactUploadNative | null => {
88
88
  return { artifactUpload: (...args) => artifactUpload.apply(native, args) };
89
89
  };
90
90
 
91
- // The journal file next to the log (perf-lab/push-spool.jsonl). Without these
91
+ // The journal file next to the log (keepsnappy/push-spool.jsonl). Without these
92
92
  // native functions (an older binary) the queue is memory-only, as before.
93
93
  const nativeSpool = (): PushSpool | null => {
94
94
  const native = (
95
95
  globalThis as unknown as { expo?: { modules?: Record<string, unknown> } }
96
- ).expo?.modules?.PerfLab as SpoolNative | undefined;
96
+ ).expo?.modules?.KeepSnappy as SpoolNative | undefined;
97
97
  if (
98
98
  !native ||
99
99
  typeof native.spoolRead !== 'function' ||
package/js/sdk/push.ts CHANGED
@@ -630,10 +630,10 @@ export const createPushClient = (deps: PushDeps) => {
630
630
  });
631
631
  const headers: Record<string, string> = {
632
632
  'content-type': 'application/json',
633
- 'x-perflab-key': deps.key,
633
+ 'x-keepsnappy-key': deps.key,
634
634
  };
635
635
  if (runToken) {
636
- headers['x-perflab-run-token'] = runToken;
636
+ headers['x-keepsnappy-run-token'] = runToken;
637
637
  }
638
638
  const budget = flushLimit !== null ? Math.max(1, Math.min(timeoutMs, flushLimit - deps.now())) : timeoutMs;
639
639
  const controller =
package/js/sdk/sampler.ts CHANGED
@@ -84,7 +84,7 @@ export const SAMPLER_MS_MIN = 250;
84
84
  export const SAMPLER_MS_MAX = 60_000;
85
85
  // Background interval between native samples. 4 s: Arek 2026-10-16 (followups, RULING ~09:00); windows get their own
86
86
  // samples at open and close, so the background ones only serve peak memory in long windows and the heat trend.
87
- // The native samplers keep the same number as their unconfigured fallback (PerfLabSampler.swift / .kt).
87
+ // The native samplers keep the same number as their unconfigured fallback (KeepSnappySampler.swift / .kt).
88
88
  export const SAMPLER_MS_DEFAULT = 4000;
89
89
 
90
90
  export const parseSamplerMode = (
@@ -1,4 +1,4 @@
1
- // zustand/vanilla in a PerfLab bundle. withPerfLab (metro.js) resolves every
1
+ // zustand/vanilla in a KeepSnappy bundle. withKeepSnappy (metro.js) resolves every
2
2
  // `zustand/vanilla` request to this module (zustand 5's index, react and
3
3
  // traditional entries all load it by that name), and the name below to the real
4
4
  // one. Each store's setState goes through the cause tracker's store writer
@@ -10,7 +10,7 @@ var real = require('@keepsnappy/react-native/zustand/vanilla');
10
10
 
11
11
  var wrap = function (createState) {
12
12
  return function (set, get, api) {
13
- var stores = globalThis.__PERFLAB_STORES__;
13
+ var stores = globalThis.__KEEPSNAPPY_STORES__;
14
14
  if (!stores) {
15
15
  return createState(set, get, api);
16
16
  }
package/metro.js CHANGED
@@ -1,6 +1,6 @@
1
- // withPerfLab(metroConfig): the only line an app adds to metro.config.js.
1
+ // withKeepSnappy(metroConfig): the only line an app adds to metro.config.js.
2
2
  //
3
- // With EXPO_PUBLIC_PERF_LAB=1 it
3
+ // With EXPO_PUBLIC_KEEPSNAPPY=1 it
4
4
  // 1. appends the React DevTools hook as a Metro polyfill, so the hook exists
5
5
  // before any module (React included) evaluates;
6
6
  // 2. wraps the Babel transformer so the app's entry module imports the SDK boot
@@ -11,12 +11,12 @@
11
11
  // zustand store's setState through the cause tracker (REQ-MEAS-32 timers).
12
12
  // Without the flag it returns the config object untouched.
13
13
  //
14
- // PERF_LAB_REACT_PROFILING=1 (independent of the flag) resolves React Native's
14
+ // KEEPSNAPPY_REACT_PROFILING=1 (independent of the flag) resolves React Native's
15
15
  // production renderer to its profiling build (fiber actualDuration /
16
16
  // selfBaseDuration, root.memoizedUpdaters), the same rewrite as
17
17
  // @callstack/inspector's withInspector. Nothing else in the bundle changes.
18
18
  //
19
- // PERF_LAB_REACT_PROFILING=switch (flag on only) bundles both Fabric renderers
19
+ // KEEPSNAPPY_REACT_PROFILING=switch (flag on only) bundles both Fabric renderers
20
20
  // behind js/renderer-switch.js, which loads the profiling one only in a process
21
21
  // whose activation asked for it (plan 40 §2.1). Ignored with the flag off.
22
22
 
@@ -31,13 +31,13 @@ const ENV_UPSTREAM = 'KEEPSNAPPY_UPSTREAM_BABEL_TRANSFORMER';
31
31
  const ENV_ENTRY = 'KEEPSNAPPY_ENTRY_FILE';
32
32
  const ENV_BOOT = 'KEEPSNAPPY_BOOT_FILE';
33
33
 
34
- const isEnabled = () => (process.env.EXPO_PUBLIC_KEEPSNAPPY ?? process.env.EXPO_PUBLIC_PERF_LAB) === '1';
35
- const isProfiling = () => (process.env.KEEPSNAPPY_REACT_PROFILING ?? process.env.PERF_LAB_REACT_PROFILING) === '1';
36
- const isSwitch = () => (process.env.KEEPSNAPPY_REACT_PROFILING ?? process.env.PERF_LAB_REACT_PROFILING) === 'switch';
34
+ const isEnabled = () => (process.env.EXPO_PUBLIC_KEEPSNAPPY) === '1';
35
+ const isProfiling = () => (process.env.KEEPSNAPPY_REACT_PROFILING) === '1';
36
+ const isSwitch = () => (process.env.KEEPSNAPPY_REACT_PROFILING) === 'switch';
37
37
 
38
38
  const SWITCH_PATH = path.join(__dirname, 'js', 'renderer-switch.js');
39
39
  // The names renderer-switch.js requires; they resolve next to RN's shim.
40
- const SDK_NAMES = ['@keepsnappy/react-native', '@perf-labs/react-native'];
40
+ const SDK_NAMES = ['@keepsnappy/react-native'];
41
41
  const SWITCH_TARGET_PREFIXES = SDK_NAMES.map(name => `${name}/renderer/`);
42
42
  const FABRIC_RENDERERS = new Set([
43
43
  '../implementations/ReactFabric-prod',
@@ -175,7 +175,7 @@ const resolveEntry = projectRoot => {
175
175
  return null;
176
176
  };
177
177
 
178
- function withPerfLab(input) {
178
+ function withKeepSnappy(input) {
179
179
  if (!isEnabled()) {
180
180
  return isProfiling() ? withReactProfiling(input) : input;
181
181
  }
@@ -225,8 +225,7 @@ function withPerfLab(input) {
225
225
  }
226
226
 
227
227
  module.exports = {
228
- withPerfLab,
229
- withKeepSnappy: withPerfLab,
228
+ withKeepSnappy,
230
229
  withReactProfiling,
231
230
  withRendererSwitch,
232
231
  withStoreWrap,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keepsnappy/react-native",
3
- "version": "0.1.0-alpha.11",
3
+ "version": "0.1.0-alpha.13",
4
4
  "description": "KeepSnappy in-app SDK for React Native / Expo: zero-code measurement windows, React commit hook, native signposts and log file",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {