@goliapkg/sentori-react-native 5.2.0 → 5.3.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.
- package/lib/handlers/dev-symbolicate.d.ts +16 -0
- package/lib/handlers/dev-symbolicate.d.ts.map +1 -1
- package/lib/handlers/dev-symbolicate.js +60 -1
- package/lib/handlers/dev-symbolicate.js.map +1 -1
- package/lib/rage-tap.d.ts.map +1 -1
- package/lib/rage-tap.js +12 -1
- package/lib/rage-tap.js.map +1 -1
- package/lib/transport.js +1 -1
- package/package.json +2 -2
- package/src/__tests__/dev-symbolicate.test.ts +62 -1
- package/src/handlers/dev-symbolicate.ts +68 -2
- package/src/rage-tap.tsx +12 -1
- package/src/transport.ts +1 -1
|
@@ -1,4 +1,20 @@
|
|
|
1
1
|
import type { Frame, SentoriError } from '@goliapkg/sentori-core';
|
|
2
|
+
/** Metro's `codeFrame.content` is an ANSI-coloured code frame:
|
|
3
|
+
*
|
|
4
|
+
* 140 | return
|
|
5
|
+
* > 142 | const sid = target.session.sessionId
|
|
6
|
+
* | ^
|
|
7
|
+
* 143 | await api.adoptSession(sid)
|
|
8
|
+
*
|
|
9
|
+
* Parse it into the wire's source-window fields so the dev
|
|
10
|
+
* dashboard shows the failing line in context, same as release
|
|
11
|
+
* builds get from the sourcemap's sourcesContent. */
|
|
12
|
+
export declare function parseCodeFrame(content: string): null | {
|
|
13
|
+
line: number;
|
|
14
|
+
preContext: string[];
|
|
15
|
+
contextLine: string;
|
|
16
|
+
postContext: string[];
|
|
17
|
+
};
|
|
2
18
|
/**
|
|
3
19
|
* POST the frames to Metro's `/symbolicate` and return the mapped-back
|
|
4
20
|
* stack, or `null` if it can't be done (not a dev server, Metro down,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev-symbolicate.d.ts","sourceRoot":"","sources":["../../src/handlers/dev-symbolicate.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"dev-symbolicate.d.ts","sourceRoot":"","sources":["../../src/handlers/dev-symbolicate.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAyFlE;;;;;;;;;sDASsD;AACtD,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAoBA;AAED;;;;GAIG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,KAAK,EAAE,EACf,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAC1B,OAAO,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,CAiDzB;AAED;+DAC+D;AAC/D,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,YAAY,EACjB,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAC1B,OAAO,CAAC,IAAI,CAAC,CAKf"}
|
|
@@ -69,8 +69,47 @@ function fromMetroFrame(m, fallback) {
|
|
|
69
69
|
function: m.methodName ?? undefined,
|
|
70
70
|
inApp: !m.collapse && !m.file.includes('node_modules'),
|
|
71
71
|
line: typeof m.lineNumber === 'number' ? m.lineNumber : 0,
|
|
72
|
+
// These ARE real source positions — without the flag the
|
|
73
|
+
// dashboard stamped Metro-resolved dev frames MINIFIED
|
|
74
|
+
// (insight round-4 A5).
|
|
75
|
+
symbolicated: true,
|
|
72
76
|
};
|
|
73
77
|
}
|
|
78
|
+
/** Metro's `codeFrame.content` is an ANSI-coloured code frame:
|
|
79
|
+
*
|
|
80
|
+
* 140 | return
|
|
81
|
+
* > 142 | const sid = target.session.sessionId
|
|
82
|
+
* | ^
|
|
83
|
+
* 143 | await api.adoptSession(sid)
|
|
84
|
+
*
|
|
85
|
+
* Parse it into the wire's source-window fields so the dev
|
|
86
|
+
* dashboard shows the failing line in context, same as release
|
|
87
|
+
* builds get from the sourcemap's sourcesContent. */
|
|
88
|
+
export function parseCodeFrame(content) {
|
|
89
|
+
// eslint-disable-next-line no-control-regex
|
|
90
|
+
const clean = content.replace(/\u001b\[[0-9;]*m/g, '');
|
|
91
|
+
const pre = [];
|
|
92
|
+
const post = [];
|
|
93
|
+
let hit = null;
|
|
94
|
+
for (const raw of clean.split('\n')) {
|
|
95
|
+
const m = /^(>?)\s*(\d+)\s\|(.*)$/.exec(raw);
|
|
96
|
+
if (!m)
|
|
97
|
+
continue; // gutter-only rows (the ^ pointer) carry no source
|
|
98
|
+
const text = m[3] ?? '';
|
|
99
|
+
if (m[1] === '>') {
|
|
100
|
+
hit = { line: Number(m[2]), text };
|
|
101
|
+
}
|
|
102
|
+
else if (hit) {
|
|
103
|
+
post.push(text);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
pre.push(text);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (!hit)
|
|
110
|
+
return null;
|
|
111
|
+
return { contextLine: hit.text, line: hit.line, postContext: post, preContext: pre };
|
|
112
|
+
}
|
|
74
113
|
/**
|
|
75
114
|
* POST the frames to Metro's `/symbolicate` and return the mapped-back
|
|
76
115
|
* stack, or `null` if it can't be done (not a dev server, Metro down,
|
|
@@ -100,7 +139,27 @@ export async function symbolicateStackViaMetro(frames, opts = {}) {
|
|
|
100
139
|
const body = (await resp.json());
|
|
101
140
|
if (!Array.isArray(body.stack) || body.stack.length !== frames.length)
|
|
102
141
|
return null;
|
|
103
|
-
|
|
142
|
+
const mapped = body.stack.map((m, i) => fromMetroFrame(m, frames[i]));
|
|
143
|
+
// Metro sends one codeFrame (for the crashing frame): attach its
|
|
144
|
+
// source window to the frame it belongs to, or the top in-app
|
|
145
|
+
// frame when the location doesn't match any.
|
|
146
|
+
const codeFrame = body.codeFrame;
|
|
147
|
+
if (typeof codeFrame?.content === 'string') {
|
|
148
|
+
const win = parseCodeFrame(codeFrame.content);
|
|
149
|
+
if (win) {
|
|
150
|
+
const exact = mapped.findIndex((f) => f.file === codeFrame.fileName && f.line === codeFrame.location?.row);
|
|
151
|
+
const at = exact >= 0 ? exact : mapped.findIndex((f) => f.inApp);
|
|
152
|
+
if (at >= 0) {
|
|
153
|
+
mapped[at] = {
|
|
154
|
+
...mapped[at],
|
|
155
|
+
contextLine: win.contextLine,
|
|
156
|
+
postContext: win.postContext,
|
|
157
|
+
preContext: win.preContext,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return mapped;
|
|
104
163
|
}
|
|
105
164
|
catch {
|
|
106
165
|
return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev-symbolicate.js","sourceRoot":"","sources":["../../src/handlers/dev-symbolicate.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,oEAAoE;AACpE,sEAAsE;AACtE,qEAAqE;AACrE,gEAAgE;AAChE,EAAE;AACF,qEAAqE;AACrE,0DAA0D;AAI1D,MAAM,UAAU,GAAG,IAAI,CAAC;AAWxB;;;;;;;;;;;;;;;GAeG;AACH,SAAS,mBAAmB;IAC1B,IAAI,CAAC;QACH,iEAAiE;QACjE,MAAM,GAAG,GAAG,OAAO,CAAC,mDAAmD,CAEtE,CAAC;QACF,MAAM,YAAY,GAAG,GAAG,CAAC,OAAO,IAAK,GAAyE,CAAC;QAC/G,MAAM,EAAE,GAAG,YAAY,EAAE,CAAC;QAC1B,IAAI,EAAE,CAAC,sBAAsB,IAAI,OAAO,EAAE,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5D,OAAO,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,cAAc,CAAC;QACpD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,0EAA0E;IAC5E,CAAC;IACD,IAAI,CAAC;QACH,iEAAiE;QACjE,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,CAOhC,CAAC;QACF,MAAM,EAAE,GAAG,EAAE,CAAC,aAAa,EAAE,UAAU,CAAC;QACxC,MAAM,SAAS,GAAG,EAAE,EAAE,SAAS,IAAI,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,SAAS,CAAC;QACnE,IAAI,CAAC,SAAS,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC;YAAE,OAAO,IAAI,CAAC;QAC/D,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;QAC7B,OAAO,GAAG,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,IAAI,cAAc,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,CAAQ;IAC5B,OAAO;QACL,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC;QACrB,IAAI,EAAE,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,IAAI;QAC9B,UAAU,EAAE,CAAC,CAAC,IAAI;QAClB,UAAU,EAAE,CAAC,CAAC,QAAQ,IAAI,IAAI;KAC/B,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,CAAa,EAAE,QAAe;IACpD,qEAAqE;IACrE,IAAI,CAAC,CAAC,CAAC,IAAI;QAAE,OAAO,QAAQ,CAAC;IAC7B,OAAO;QACL,YAAY,EAAE,CAAC,CAAC,IAAI;QACpB,MAAM,EAAE,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;QAC3D,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,QAAQ,EAAE,CAAC,CAAC,UAAU,IAAI,SAAS;QACnC,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC;QACtD,IAAI,EAAE,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"dev-symbolicate.js","sourceRoot":"","sources":["../../src/handlers/dev-symbolicate.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,oEAAoE;AACpE,sEAAsE;AACtE,qEAAqE;AACrE,gEAAgE;AAChE,EAAE;AACF,qEAAqE;AACrE,0DAA0D;AAI1D,MAAM,UAAU,GAAG,IAAI,CAAC;AAWxB;;;;;;;;;;;;;;;GAeG;AACH,SAAS,mBAAmB;IAC1B,IAAI,CAAC;QACH,iEAAiE;QACjE,MAAM,GAAG,GAAG,OAAO,CAAC,mDAAmD,CAEtE,CAAC;QACF,MAAM,YAAY,GAAG,GAAG,CAAC,OAAO,IAAK,GAAyE,CAAC;QAC/G,MAAM,EAAE,GAAG,YAAY,EAAE,CAAC;QAC1B,IAAI,EAAE,CAAC,sBAAsB,IAAI,OAAO,EAAE,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5D,OAAO,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,cAAc,CAAC;QACpD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,0EAA0E;IAC5E,CAAC;IACD,IAAI,CAAC;QACH,iEAAiE;QACjE,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,CAOhC,CAAC;QACF,MAAM,EAAE,GAAG,EAAE,CAAC,aAAa,EAAE,UAAU,CAAC;QACxC,MAAM,SAAS,GAAG,EAAE,EAAE,SAAS,IAAI,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,SAAS,CAAC;QACnE,IAAI,CAAC,SAAS,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC;YAAE,OAAO,IAAI,CAAC;QAC/D,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;QAC7B,OAAO,GAAG,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,IAAI,cAAc,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,CAAQ;IAC5B,OAAO;QACL,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC;QACrB,IAAI,EAAE,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,IAAI;QAC9B,UAAU,EAAE,CAAC,CAAC,IAAI;QAClB,UAAU,EAAE,CAAC,CAAC,QAAQ,IAAI,IAAI;KAC/B,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,CAAa,EAAE,QAAe;IACpD,qEAAqE;IACrE,IAAI,CAAC,CAAC,CAAC,IAAI;QAAE,OAAO,QAAQ,CAAC;IAC7B,OAAO;QACL,YAAY,EAAE,CAAC,CAAC,IAAI;QACpB,MAAM,EAAE,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;QAC3D,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,QAAQ,EAAE,CAAC,CAAC,UAAU,IAAI,SAAS;QACnC,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC;QACtD,IAAI,EAAE,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACzD,yDAAyD;QACzD,uDAAuD;QACvD,wBAAwB;QACxB,YAAY,EAAE,IAAI;KACnB,CAAC;AACJ,CAAC;AAED;;;;;;;;;sDASsD;AACtD,MAAM,UAAU,cAAc,CAAC,OAAe;IAM5C,4CAA4C;IAC5C,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;IACvD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,GAAG,GAA0C,IAAI,CAAC;IACtD,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,MAAM,CAAC,GAAG,wBAAwB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7C,IAAI,CAAC,CAAC;YAAE,SAAS,CAAC,mDAAmD;QACrE,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACjB,GAAG,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;QACrC,CAAC;aAAM,IAAI,GAAG,EAAE,CAAC;YACf,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjB,CAAC;IACH,CAAC;IACD,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,OAAO,EAAE,WAAW,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC;AACvF,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,MAAe,EACf,IAAI,GAAqB,EAAE;IAE3B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,mBAAmB,EAAE,CAAC;IAC9C,IAAI,CAAC,GAAG,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7C,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,eAAe,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,UAAU,CAAC,CAAC;QACzD,IAAI,IAAc,CAAC;QACnB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBACtB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;gBACzD,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC,CAAC;QACL,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QAC1B,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAG9B,CAAC;QACF,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QACnF,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC;QACvE,iEAAiE;QACjE,8DAA8D;QAC9D,6CAA6C;QAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QACjC,IAAI,OAAO,SAAS,EAAE,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC3C,MAAM,GAAG,GAAG,cAAc,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YAC9C,IAAI,GAAG,EAAE,CAAC;gBACR,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAC5B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,QAAQ,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,QAAQ,EAAE,GAAG,CAC3E,CAAC;gBACF,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;gBACjE,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;oBACZ,MAAM,CAAC,EAAE,CAAC,GAAG;wBACX,GAAG,MAAM,CAAC,EAAE,CAAE;wBACd,WAAW,EAAE,GAAG,CAAC,WAAW;wBAC5B,WAAW,EAAE,GAAG,CAAC,WAAW;wBAC5B,UAAU,EAAE,GAAG,CAAC,UAAU;qBAC3B,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;+DAC+D;AAC/D,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,GAAiB,EACjB,IAAI,GAAqB,EAAE;IAE3B,IAAI,CAAC,GAAG,CAAC,KAAK;QAAE,OAAO;IACvB,MAAM,GAAG,GAAG,MAAM,wBAAwB,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC5D,IAAI,GAAG;QAAE,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC;IACzB,IAAI,GAAG,CAAC,KAAK;QAAE,MAAM,wBAAwB,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AACjE,CAAC"}
|
package/lib/rage-tap.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rage-tap.d.ts","sourceRoot":"","sources":["../src/rage-tap.tsx"],"names":[],"mappings":"AAYA,OAAO,KAA8B,MAAM,OAAO,CAAC;AACnD,OAAO,EAAoC,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAgBhF,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,GAAG,IAAI,EACR,EAAE,SAAS,GAAG;IAAE,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,
|
|
1
|
+
{"version":3,"file":"rage-tap.d.ts","sourceRoot":"","sources":["../src/rage-tap.tsx"],"names":[],"mappings":"AAYA,OAAO,KAA8B,MAAM,OAAO,CAAC;AACnD,OAAO,EAAoC,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAgBhF,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,GAAG,IAAI,EACR,EAAE,SAAS,GAAG;IAAE,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAyEhE"}
|
package/lib/rage-tap.js
CHANGED
|
@@ -28,7 +28,18 @@ export function RageTapCapture({ children, ...rest }) {
|
|
|
28
28
|
if (typeof target !== 'number')
|
|
29
29
|
return;
|
|
30
30
|
const tapAt = Date.now();
|
|
31
|
-
|
|
31
|
+
// pageX/pageY (logical pt, same space as the wireframe frames)
|
|
32
|
+
// let the dashboard draw the tap on the replay; `target` is
|
|
33
|
+
// RN's internal node tag and is only kept for the dead-tap
|
|
34
|
+
// bucketing below (insight round-4 A2).
|
|
35
|
+
const px = e.nativeEvent?.pageX;
|
|
36
|
+
const py = e.nativeEvent?.pageY;
|
|
37
|
+
pushSignal('tap', {
|
|
38
|
+
target,
|
|
39
|
+
...(typeof px === 'number' && typeof py === 'number'
|
|
40
|
+
? { x: Math.round(px), y: Math.round(py) }
|
|
41
|
+
: {}),
|
|
42
|
+
});
|
|
32
43
|
// Responsiveness verdict lands after the window closes: the
|
|
33
44
|
// ring tells us whether the app reacted to this tap at all.
|
|
34
45
|
setTimeout(() => {
|
package/lib/rage-tap.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rage-tap.js","sourceRoot":"","sources":["../src/rage-tap.tsx"],"names":[],"mappings":";AAAA,6DAA6D;AAC7D,6BAA6B;AAC7B,EAAE;AACF,iDAAiD;AACjD,8DAA8D;AAC9D,iEAAiE;AACjE,EAAE;AACF,mEAAmE;AACnE,gEAAgE;AAChE,kEAAkE;AAClE,oEAAoE;AAEpE,OAAc,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AACnD,OAAO,EAAE,IAAI,EAA8C,MAAM,cAAc,CAAC;AAEhF,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAErE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChF,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,WAAW,EACX,aAAa,EACb,cAAc,GACf,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,MAAM,UAAU,cAAc,CAAC,EAC7B,QAAQ,EACR,GAAG,IAAI,EACoC;IAC3C,MAAM,MAAM,GAAG,MAAM,CAAwB,IAAI,GAAG,EAAE,CAAC,CAAC;IACxD,MAAM,WAAW,GAAG,MAAM,CAAwB,IAAI,GAAG,EAAE,CAAC,CAAC;IAC7D,MAAM,aAAa,GAAG,MAAM,CAAsB,IAAI,GAAG,EAAE,CAAC,CAAC;IAE7D,MAAM,UAAU,GAAG,WAAW,CAAC,CAAC,CAAwB,EAAE,EAAE;QAC1D,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC;YACrC,IAAI,OAAO,MAAM,KAAK,QAAQ;gBAAE,OAAO;YACvC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACzB,
|
|
1
|
+
{"version":3,"file":"rage-tap.js","sourceRoot":"","sources":["../src/rage-tap.tsx"],"names":[],"mappings":";AAAA,6DAA6D;AAC7D,6BAA6B;AAC7B,EAAE;AACF,iDAAiD;AACjD,8DAA8D;AAC9D,iEAAiE;AACjE,EAAE;AACF,mEAAmE;AACnE,gEAAgE;AAChE,kEAAkE;AAClE,oEAAoE;AAEpE,OAAc,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AACnD,OAAO,EAAE,IAAI,EAA8C,MAAM,cAAc,CAAC;AAEhF,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAErE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChF,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,WAAW,EACX,aAAa,EACb,cAAc,GACf,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,MAAM,UAAU,cAAc,CAAC,EAC7B,QAAQ,EACR,GAAG,IAAI,EACoC;IAC3C,MAAM,MAAM,GAAG,MAAM,CAAwB,IAAI,GAAG,EAAE,CAAC,CAAC;IACxD,MAAM,WAAW,GAAG,MAAM,CAAwB,IAAI,GAAG,EAAE,CAAC,CAAC;IAC7D,MAAM,aAAa,GAAG,MAAM,CAAsB,IAAI,GAAG,EAAE,CAAC,CAAC;IAE7D,MAAM,UAAU,GAAG,WAAW,CAAC,CAAC,CAAwB,EAAE,EAAE;QAC1D,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC;YACrC,IAAI,OAAO,MAAM,KAAK,QAAQ;gBAAE,OAAO;YACvC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACzB,+DAA+D;YAC/D,4DAA4D;YAC5D,2DAA2D;YAC3D,wCAAwC;YACxC,MAAM,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,KAAK,CAAC;YAChC,MAAM,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,KAAK,CAAC;YAChC,UAAU,CAAC,KAAK,EAAE;gBAChB,MAAM;gBACN,GAAG,CAAC,OAAO,EAAE,KAAK,QAAQ,IAAI,OAAO,EAAE,KAAK,QAAQ;oBAClD,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE;oBAC1C,CAAC,CAAC,EAAE,CAAC;aACR,CAAC,CAAC;YAEH,4DAA4D;YAC5D,4DAA4D;YAC5D,UAAU,CAAC,GAAG,EAAE;gBACd,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;oBAC/B,6DAA6D;oBAC7D,iDAAiD;oBACjD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;oBACzB,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC;yBACjC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC;yBAC/B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;oBAClC,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;oBAC1C,IAAI,OAAO,KAAK,MAAM,IAAI,aAAa,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;wBACjF,YAAY,CACV,aAAa,EACb,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EACnC,EAAE,QAAQ,EAAE,kBAAkB,EAAE,CACjC,CAAC;oBACJ,CAAC;yBAAM,IACL,OAAO,KAAK,UAAU;wBACtB,cAAc,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,EACzD,CAAC;wBACD,YAAY,CACV,iBAAiB,EACjB,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EACnC,EAAE,WAAW,EAAE,WAAW,EAAE,CAC7B,CAAC;oBACJ,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,kCAAkC;gBACpC,CAAC;YACH,CAAC,EAAE,kBAAkB,GAAG,EAAE,CAAC,CAAC;YAE5B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC;gBAAE,OAAO;YACtD,IAAI,SAAS,EAAE,EAAE,MAAM,CAAC,OAAO,KAAK,KAAK;gBAAE,OAAO;YAClD,YAAY,CACV,UAAU,EACV,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EACpD,EAAE,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,cAAc,EAAE,CACnD,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,6DAA6D;QAC/D,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,CACL,KAAC,IAAI,OAAK,IAAI,EAAE,UAAU,EAAE,UAAU,YACnC,QAAQ,GACJ,CACR,CAAC;AACJ,CAAC"}
|
package/lib/transport.js
CHANGED
|
@@ -15,7 +15,7 @@ const MAX_RETRY = 3;
|
|
|
15
15
|
const STORAGE_KEY = '@sentori/pending';
|
|
16
16
|
const MAX_PERSISTED = 1000;
|
|
17
17
|
// Pinned to package.json by a test — bump both together.
|
|
18
|
-
const SDK_VERSION = '5.
|
|
18
|
+
const SDK_VERSION = '5.3.0';
|
|
19
19
|
let _queue = [];
|
|
20
20
|
let _assertStats = new Map();
|
|
21
21
|
let _flushTimer = null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goliapkg/sentori-react-native",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.3.0",
|
|
4
4
|
"description": "Sentori SDK for React Native \u2014 JS-layer error capture, native crash handlers (iOS / Android), batched transport, fetch + react-navigation tracing.",
|
|
5
5
|
"license": "Apache-2.0 OR MIT",
|
|
6
6
|
"author": "GOLIA K.K. <takagi@golia.jp> (https://golia.jp)",
|
|
@@ -97,6 +97,6 @@
|
|
|
97
97
|
"access": "public"
|
|
98
98
|
},
|
|
99
99
|
"dependencies": {
|
|
100
|
-
"@goliapkg/sentori-core": "^2.
|
|
100
|
+
"@goliapkg/sentori-core": "^2.2.0"
|
|
101
101
|
}
|
|
102
102
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, mock, test } from 'bun:test';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
parseCodeFrame,
|
|
5
|
+
symbolicateErrorViaMetro,
|
|
6
|
+
symbolicateStackViaMetro,
|
|
7
|
+
} from '../handlers/dev-symbolicate';
|
|
4
8
|
import type { Frame, SentoriError } from '../types';
|
|
5
9
|
|
|
6
10
|
const URL = 'http://localhost:8081/symbolicate';
|
|
@@ -72,6 +76,47 @@ describe('symbolicateStackViaMetro', () => {
|
|
|
72
76
|
});
|
|
73
77
|
// node_modules + collapse → not in-app
|
|
74
78
|
expect(out![1]?.inApp).toBe(false);
|
|
79
|
+
// Metro-resolved positions are real source positions — without
|
|
80
|
+
// this the dashboard stamps dev frames MINIFIED (insight A5).
|
|
81
|
+
expect(out![0]?.symbolicated).toBe(true);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('attaches Metro codeFrame as the source window on the matching frame', async () => {
|
|
85
|
+
const esc = String.fromCharCode(27);
|
|
86
|
+
const content = [
|
|
87
|
+
`${esc}[0m 141 | }`,
|
|
88
|
+
`${esc}[31m> 142 | const sid = target.session.sessionId${esc}[0m`,
|
|
89
|
+
` | ^`,
|
|
90
|
+
` 143 | await api.adoptSession(sid)`,
|
|
91
|
+
].join('\n');
|
|
92
|
+
globalThis.fetch = (async () =>
|
|
93
|
+
new Response(
|
|
94
|
+
JSON.stringify({
|
|
95
|
+
codeFrame: {
|
|
96
|
+
content,
|
|
97
|
+
fileName: '/proj/src/hooks/use-auth-listener.ts',
|
|
98
|
+
location: { column: 30, row: 142 },
|
|
99
|
+
},
|
|
100
|
+
stack: [
|
|
101
|
+
{
|
|
102
|
+
collapse: false,
|
|
103
|
+
column: 23,
|
|
104
|
+
file: '/proj/src/hooks/use-auth-listener.ts',
|
|
105
|
+
lineNumber: 142,
|
|
106
|
+
methodName: 'reseedSession',
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
}),
|
|
110
|
+
{ headers: { 'content-type': 'application/json' }, status: 200 },
|
|
111
|
+
)) as typeof fetch;
|
|
112
|
+
|
|
113
|
+
const out = await symbolicateStackViaMetro([minified(1)], { url: URL });
|
|
114
|
+
expect(out![0]).toMatchObject({
|
|
115
|
+
contextLine: ' const sid = target.session.sessionId',
|
|
116
|
+
postContext: [' await api.adoptSession(sid)'],
|
|
117
|
+
preContext: [' }'],
|
|
118
|
+
symbolicated: true,
|
|
119
|
+
});
|
|
75
120
|
});
|
|
76
121
|
|
|
77
122
|
test('keeps the original frame when Metro can’t resolve it (file null)', async () => {
|
|
@@ -107,6 +152,22 @@ describe('symbolicateStackViaMetro', () => {
|
|
|
107
152
|
});
|
|
108
153
|
});
|
|
109
154
|
|
|
155
|
+
describe('parseCodeFrame', () => {
|
|
156
|
+
test('returns null when no marked line exists', () => {
|
|
157
|
+
expect(parseCodeFrame('nothing here')).toBeNull();
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
test('skips gutter-only pointer rows', () => {
|
|
161
|
+
const win = parseCodeFrame([' 1 | a', '> 2 | b', ' | ^', ' 3 | c'].join('\n'));
|
|
162
|
+
expect(win).toEqual({
|
|
163
|
+
contextLine: ' b',
|
|
164
|
+
line: 2,
|
|
165
|
+
postContext: [' c'],
|
|
166
|
+
preContext: [' a'],
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
110
171
|
describe('metroSymbolicateUrl resolution (RN 0.83 new-arch regression)', () => {
|
|
111
172
|
// Without `opts.url`, the function must resolve a real Metro URL.
|
|
112
173
|
// RN 0.83 + new architecture leaves `NativeModules.SourceCode.scriptURL`
|
|
@@ -89,9 +89,50 @@ function fromMetroFrame(m: MetroFrame, fallback: Frame): Frame {
|
|
|
89
89
|
function: m.methodName ?? undefined,
|
|
90
90
|
inApp: !m.collapse && !m.file.includes('node_modules'),
|
|
91
91
|
line: typeof m.lineNumber === 'number' ? m.lineNumber : 0,
|
|
92
|
+
// These ARE real source positions — without the flag the
|
|
93
|
+
// dashboard stamped Metro-resolved dev frames MINIFIED
|
|
94
|
+
// (insight round-4 A5).
|
|
95
|
+
symbolicated: true,
|
|
92
96
|
};
|
|
93
97
|
}
|
|
94
98
|
|
|
99
|
+
/** Metro's `codeFrame.content` is an ANSI-coloured code frame:
|
|
100
|
+
*
|
|
101
|
+
* 140 | return
|
|
102
|
+
* > 142 | const sid = target.session.sessionId
|
|
103
|
+
* | ^
|
|
104
|
+
* 143 | await api.adoptSession(sid)
|
|
105
|
+
*
|
|
106
|
+
* Parse it into the wire's source-window fields so the dev
|
|
107
|
+
* dashboard shows the failing line in context, same as release
|
|
108
|
+
* builds get from the sourcemap's sourcesContent. */
|
|
109
|
+
export function parseCodeFrame(content: string): null | {
|
|
110
|
+
line: number;
|
|
111
|
+
preContext: string[];
|
|
112
|
+
contextLine: string;
|
|
113
|
+
postContext: string[];
|
|
114
|
+
} {
|
|
115
|
+
// eslint-disable-next-line no-control-regex
|
|
116
|
+
const clean = content.replace(/\u001b\[[0-9;]*m/g, '');
|
|
117
|
+
const pre: string[] = [];
|
|
118
|
+
const post: string[] = [];
|
|
119
|
+
let hit: null | { line: number; text: string } = null;
|
|
120
|
+
for (const raw of clean.split('\n')) {
|
|
121
|
+
const m = /^(>?)\s*(\d+)\s\|(.*)$/.exec(raw);
|
|
122
|
+
if (!m) continue; // gutter-only rows (the ^ pointer) carry no source
|
|
123
|
+
const text = m[3] ?? '';
|
|
124
|
+
if (m[1] === '>') {
|
|
125
|
+
hit = { line: Number(m[2]), text };
|
|
126
|
+
} else if (hit) {
|
|
127
|
+
post.push(text);
|
|
128
|
+
} else {
|
|
129
|
+
pre.push(text);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (!hit) return null;
|
|
133
|
+
return { contextLine: hit.text, line: hit.line, postContext: post, preContext: pre };
|
|
134
|
+
}
|
|
135
|
+
|
|
95
136
|
/**
|
|
96
137
|
* POST the frames to Metro's `/symbolicate` and return the mapped-back
|
|
97
138
|
* stack, or `null` if it can't be done (not a dev server, Metro down,
|
|
@@ -118,9 +159,34 @@ export async function symbolicateStackViaMetro(
|
|
|
118
159
|
clearTimeout(timer);
|
|
119
160
|
}
|
|
120
161
|
if (!resp.ok) return null;
|
|
121
|
-
const body = (await resp.json()) as {
|
|
162
|
+
const body = (await resp.json()) as {
|
|
163
|
+
codeFrame?: { content?: string; fileName?: string; location?: { row?: number } };
|
|
164
|
+
stack?: MetroFrame[];
|
|
165
|
+
};
|
|
122
166
|
if (!Array.isArray(body.stack) || body.stack.length !== frames.length) return null;
|
|
123
|
-
|
|
167
|
+
const mapped = body.stack.map((m, i) => fromMetroFrame(m, frames[i]!));
|
|
168
|
+
// Metro sends one codeFrame (for the crashing frame): attach its
|
|
169
|
+
// source window to the frame it belongs to, or the top in-app
|
|
170
|
+
// frame when the location doesn't match any.
|
|
171
|
+
const codeFrame = body.codeFrame;
|
|
172
|
+
if (typeof codeFrame?.content === 'string') {
|
|
173
|
+
const win = parseCodeFrame(codeFrame.content);
|
|
174
|
+
if (win) {
|
|
175
|
+
const exact = mapped.findIndex(
|
|
176
|
+
(f) => f.file === codeFrame.fileName && f.line === codeFrame.location?.row,
|
|
177
|
+
);
|
|
178
|
+
const at = exact >= 0 ? exact : mapped.findIndex((f) => f.inApp);
|
|
179
|
+
if (at >= 0) {
|
|
180
|
+
mapped[at] = {
|
|
181
|
+
...mapped[at]!,
|
|
182
|
+
contextLine: win.contextLine,
|
|
183
|
+
postContext: win.postContext,
|
|
184
|
+
preContext: win.preContext,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return mapped;
|
|
124
190
|
} catch {
|
|
125
191
|
return null;
|
|
126
192
|
}
|
package/src/rage-tap.tsx
CHANGED
|
@@ -40,7 +40,18 @@ export function RageTapCapture({
|
|
|
40
40
|
const target = e.nativeEvent?.target;
|
|
41
41
|
if (typeof target !== 'number') return;
|
|
42
42
|
const tapAt = Date.now();
|
|
43
|
-
|
|
43
|
+
// pageX/pageY (logical pt, same space as the wireframe frames)
|
|
44
|
+
// let the dashboard draw the tap on the replay; `target` is
|
|
45
|
+
// RN's internal node tag and is only kept for the dead-tap
|
|
46
|
+
// bucketing below (insight round-4 A2).
|
|
47
|
+
const px = e.nativeEvent?.pageX;
|
|
48
|
+
const py = e.nativeEvent?.pageY;
|
|
49
|
+
pushSignal('tap', {
|
|
50
|
+
target,
|
|
51
|
+
...(typeof px === 'number' && typeof py === 'number'
|
|
52
|
+
? { x: Math.round(px), y: Math.round(py) }
|
|
53
|
+
: {}),
|
|
54
|
+
});
|
|
44
55
|
|
|
45
56
|
// Responsiveness verdict lands after the window closes: the
|
|
46
57
|
// ring tells us whether the app reacted to this tap at all.
|
package/src/transport.ts
CHANGED
|
@@ -20,7 +20,7 @@ const STORAGE_KEY = '@sentori/pending';
|
|
|
20
20
|
const MAX_PERSISTED = 1000;
|
|
21
21
|
|
|
22
22
|
// Pinned to package.json by a test — bump both together.
|
|
23
|
-
const SDK_VERSION = '5.
|
|
23
|
+
const SDK_VERSION = '5.3.0';
|
|
24
24
|
|
|
25
25
|
let _queue: WireEvent[] = [];
|
|
26
26
|
let _assertStats = new Map<string, AssertStat>();
|