@goliapkg/sentori-react-native 5.2.0 → 5.4.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/android/src/main/java/com/sentori/SentoriScreenshotCapture.kt +12 -2
- package/ios/SentoriModule.swift +1 -1
- package/ios/SentoriScreenshotCapture.swift +12 -4
- 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/native.d.ts +2 -0
- package/lib/native.d.ts.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/replay-screens.d.ts.map +1 -1
- package/lib/replay-screens.js +3 -0
- package/lib/replay-screens.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/__tests__/replay-screens.test.ts +10 -2
- package/src/handlers/dev-symbolicate.ts +68 -2
- package/src/native.ts +2 -2
- package/src/rage-tap.tsx +12 -1
- package/src/replay-screens.ts +13 -1
- package/src/transport.ts +1 -1
|
@@ -156,14 +156,24 @@ object SentoriScreenshotCapture {
|
|
|
156
156
|
maskedIds: List<String>,
|
|
157
157
|
longEdgePx: Double,
|
|
158
158
|
quality: Double,
|
|
159
|
-
): Map<String,
|
|
159
|
+
): Map<String, Any>? {
|
|
160
160
|
val activity = SentoriForegroundActivity.current() ?: return null
|
|
161
161
|
val window = activity.window ?: return null
|
|
162
162
|
val pct = (quality * 100).toInt().coerceIn(1, 100)
|
|
163
163
|
val (base64, mediaType) =
|
|
164
164
|
captureScreen(window, maskedIds.toHashSet(), longEdgePx.toFloat(), pct)
|
|
165
165
|
?: return null
|
|
166
|
-
|
|
166
|
+
// v5.4 — the window's logical size (dp), the same space RN's
|
|
167
|
+
// pageX/pageY taps live in: the dashboard maps tap
|
|
168
|
+
// coordinates onto the scaled-down JPEG with it.
|
|
169
|
+
val density = activity.resources.displayMetrics.density
|
|
170
|
+
val view = window.decorView
|
|
171
|
+
return mapOf(
|
|
172
|
+
"base64" to base64,
|
|
173
|
+
"mediaType" to mediaType,
|
|
174
|
+
"w" to (view.width / density).toDouble(),
|
|
175
|
+
"h" to (view.height / density).toDouble(),
|
|
176
|
+
)
|
|
167
177
|
}
|
|
168
178
|
|
|
169
179
|
// ── screenshot ────────────────────────────────────────────────
|
package/ios/SentoriModule.swift
CHANGED
|
@@ -81,7 +81,7 @@ public class SentoriModule: Module {
|
|
|
81
81
|
// quality come from JS so the frame budget is tunable without
|
|
82
82
|
// a native release.
|
|
83
83
|
AsyncFunction("captureReplayFrame") {
|
|
84
|
-
(maskedIds: [String], longEdgePx: Double, quality: Double) -> [String:
|
|
84
|
+
(maskedIds: [String], longEdgePx: Double, quality: Double) -> [String: Any]? in
|
|
85
85
|
return SentoriScreenshotCapture.captureReplayFrame(
|
|
86
86
|
maskedIds: maskedIds,
|
|
87
87
|
longEdgePx: longEdgePx,
|
|
@@ -89,8 +89,8 @@ import UIKit
|
|
|
89
89
|
maskedIds: [String],
|
|
90
90
|
longEdgePx: Double,
|
|
91
91
|
quality: Double
|
|
92
|
-
) -> [String:
|
|
93
|
-
let run: () -> [String:
|
|
92
|
+
) -> [String: Any]? {
|
|
93
|
+
let run: () -> [String: Any]? = {
|
|
94
94
|
guard let window = keyWindowDiag().window else { return nil }
|
|
95
95
|
guard
|
|
96
96
|
let jpeg = renderJpegBase64(
|
|
@@ -100,12 +100,20 @@ import UIKit
|
|
|
100
100
|
quality: CGFloat(quality)
|
|
101
101
|
)
|
|
102
102
|
else { return nil }
|
|
103
|
-
|
|
103
|
+
// v5.4 — the window's logical size (pt), the same space
|
|
104
|
+
// RN's pageX/pageY taps live in: the dashboard maps tap
|
|
105
|
+
// coordinates onto the scaled-down JPEG with it.
|
|
106
|
+
return [
|
|
107
|
+
"base64": jpeg,
|
|
108
|
+
"mediaType": "image/jpeg",
|
|
109
|
+
"w": Double(window.bounds.width),
|
|
110
|
+
"h": Double(window.bounds.height),
|
|
111
|
+
]
|
|
104
112
|
}
|
|
105
113
|
if Thread.isMainThread {
|
|
106
114
|
return run()
|
|
107
115
|
}
|
|
108
|
-
var result: [String:
|
|
116
|
+
var result: [String: Any]?
|
|
109
117
|
DispatchQueue.main.sync { result = run() }
|
|
110
118
|
return result
|
|
111
119
|
}
|
|
@@ -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":"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"}
|
package/lib/native.d.ts
CHANGED
|
@@ -77,6 +77,8 @@ export declare function getRecentNativeException(): null | {
|
|
|
77
77
|
export declare function captureNativeReplayFrame(maskedIds: string[], longEdgePx: number, quality: number): Promise<null | {
|
|
78
78
|
base64: string;
|
|
79
79
|
mediaType: string;
|
|
80
|
+
w?: number;
|
|
81
|
+
h?: number;
|
|
80
82
|
}>;
|
|
81
83
|
export declare function captureNativeScreenshotWithMask(maskedIds: string[]): Promise<null | {
|
|
82
84
|
base64: string;
|
package/lib/native.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../src/native.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkMH,wBAAgB,eAAe,CAAC,MAAM,EAAE;IACtC,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;CACd,GAAG,IAAI,CAMP;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAQ5D;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAMzC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE;IACzC,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,GAAG,IAAI,CAMP;AAID;gEACgE;AAChE,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CAQ5D;AAED;yCACyC;AACzC,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CAQpE;AAED,wBAAgB,YAAY,IAAI,IAAI,CAMnC;AAED,wBAAgB,cAAc,IAAI,IAAI,CAMrC;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IAC7C,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CACrC,CAAA;AAED;8CAC8C;AAC9C,wBAAsB,cAAc,IAAI,OAAO,CAAC,cAAc,CAAC,CAU9D;AAED,wBAAgB,eAAe,IAAI,IAAI,CAMtC;AAED,+DAA+D;AAC/D,wBAAgB,uBAAuB,IAAI,IAAI,CAM9C;AAED,yEAAyE;AACzE,wBAAgB,oBAAoB,IAAI,IAAI,GAAG,MAAM,CAOpD;AAED,oEAAoE;AACpE,wBAAgB,sBAAsB,IAAI,IAAI,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAMhF;AAED,iEAAiE;AACjE,wBAAgB,wBAAwB,IAAI,IAAI,CAM/C;AAED;;yBAEyB;AACzB,wBAAgB,wBAAwB,IAAI,IAAI,GAAG;IACjD,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB,CAMA;AAiBD,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,MAAM,EAAE,EACnB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../src/native.ts"],"names":[],"mappings":"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"}
|
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":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay-screens.d.ts","sourceRoot":"","sources":["../src/replay-screens.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAEpD,KAAK,SAAS,GAAG,OAAO,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"replay-screens.d.ts","sourceRoot":"","sources":["../src/replay-screens.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAEpD,KAAK,SAAS,GAAG,OAAO,wBAAwB,CAAC;AA6BjD;mCACmC;AACnC,eAAO,MAAM,iBAAiB,kBAAmB,MAAM,KAAG,IAOzD,CAAC;AAkBF;;;;4BAI4B;AAC5B,eAAO,MAAM,iBAAiB,QAAO,IAAI,GAAG,MAe3C,CAAC;AAEF,eAAO,MAAM,eAAe,QAAO,IAOlC,CAAC;AAEF,eAAO,MAAM,oBAAoB,OAAQ,SAAS,KAAG,IAEpD,CAAC"}
|
package/lib/replay-screens.js
CHANGED
|
@@ -68,6 +68,9 @@ export const drainScreenReplay = () => {
|
|
|
68
68
|
.map((f) => JSON.stringify({
|
|
69
69
|
t: Number(((f.t - now) / 1000).toFixed(1)),
|
|
70
70
|
mediaType: f.mediaType,
|
|
71
|
+
...(typeof f.w === 'number' && typeof f.h === 'number'
|
|
72
|
+
? { w: f.w, h: f.h }
|
|
73
|
+
: {}),
|
|
71
74
|
base64: f.base64,
|
|
72
75
|
}))
|
|
73
76
|
.join('\n');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay-screens.js","sourceRoot":"","sources":["../src/replay-screens.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,EAAE;AACF,+DAA+D;AAC/D,iEAAiE;AACjE,6DAA6D;AAC7D,gEAAgE;AAChE,6DAA6D;AAC7D,mDAAmD;AACnD,EAAE;AACF,kEAAkE;AAClE,gEAAgE;AAEhE,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAEhD,OAAO,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAGpD,IAAI,QAAQ,GAAc,wBAAwB,CAAC;AAEnD;oDACoD;AACpD,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAC/B;;wCAEwC;AACxC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAC/B,2CAA2C;AAC3C,MAAM,aAAa,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"replay-screens.js","sourceRoot":"","sources":["../src/replay-screens.ts"],"names":[],"mappings":"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"}
|
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.4.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.4.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`
|
|
@@ -42,8 +42,14 @@ describe('screens ring', () => {
|
|
|
42
42
|
|
|
43
43
|
test('drain emits NDJSON with negative relative timestamps', async () => {
|
|
44
44
|
let n = 0;
|
|
45
|
+
// native ≥ 5.4 carries the window's logical size with each frame
|
|
45
46
|
__setCaptureForTests(
|
|
46
|
-
mock(async () => ({
|
|
47
|
+
mock(async () => ({
|
|
48
|
+
base64: `frame${(n += 1)}`,
|
|
49
|
+
h: 852,
|
|
50
|
+
mediaType: 'image/jpeg',
|
|
51
|
+
w: 393,
|
|
52
|
+
})),
|
|
47
53
|
);
|
|
48
54
|
startScreenReplay(60);
|
|
49
55
|
await new Promise((r) => setTimeout(r, 2_600));
|
|
@@ -51,11 +57,13 @@ describe('screens ring', () => {
|
|
|
51
57
|
expect(out).not.toBeNull();
|
|
52
58
|
const lines = (out ?? '')
|
|
53
59
|
.split('\n')
|
|
54
|
-
.map((l) => JSON.parse(l) as { t: number; base64: string });
|
|
60
|
+
.map((l) => JSON.parse(l) as { t: number; base64: string; w?: number; h?: number });
|
|
55
61
|
expect(lines.length).toBeGreaterThanOrEqual(1);
|
|
56
62
|
for (const l of lines) {
|
|
57
63
|
expect(l.t).toBeLessThanOrEqual(0);
|
|
58
64
|
expect(l.base64.startsWith('frame')).toBe(true);
|
|
65
|
+
expect(l.w).toBe(393);
|
|
66
|
+
expect(l.h).toBe(852);
|
|
59
67
|
}
|
|
60
68
|
// drain does not clear: a second error still sees the window
|
|
61
69
|
expect(drainScreenReplay()).not.toBeNull();
|
|
@@ -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/native.ts
CHANGED
|
@@ -75,7 +75,7 @@ type SentoriNativeModule = {
|
|
|
75
75
|
maskedIds: string[],
|
|
76
76
|
longEdgePx: number,
|
|
77
77
|
quality: number,
|
|
78
|
-
) => Promise<null | { base64: string; mediaType: string }>
|
|
78
|
+
) => Promise<null | { base64: string; mediaType: string; w?: number; h?: number }>
|
|
79
79
|
/**
|
|
80
80
|
* v0.9.12 — diagnostic readout for the wireframe path. Cheap
|
|
81
81
|
* synchronous call that returns the path the last `captureWireframe`
|
|
@@ -402,7 +402,7 @@ export async function captureNativeReplayFrame(
|
|
|
402
402
|
maskedIds: string[],
|
|
403
403
|
longEdgePx: number,
|
|
404
404
|
quality: number,
|
|
405
|
-
): Promise<null | { base64: string; mediaType: string }> {
|
|
405
|
+
): Promise<null | { base64: string; mediaType: string; w?: number; h?: number }> {
|
|
406
406
|
const n = native()
|
|
407
407
|
if (!n) return null
|
|
408
408
|
if (!n.captureReplayFrame) {
|
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/replay-screens.ts
CHANGED
|
@@ -28,7 +28,16 @@ const FRAME_LONG_EDGE_PX = 360;
|
|
|
28
28
|
/** JPEG/WebP quality for replay frames. */
|
|
29
29
|
const FRAME_QUALITY = 0.35;
|
|
30
30
|
|
|
31
|
-
type ScreenFrame = {
|
|
31
|
+
type ScreenFrame = {
|
|
32
|
+
t: number;
|
|
33
|
+
base64: string;
|
|
34
|
+
mediaType: string;
|
|
35
|
+
/** Window logical size (pt/dp), same space as tap pageX/pageY —
|
|
36
|
+
* present from native ≥ 5.4; older binaries omit it and the
|
|
37
|
+
* dashboard simply draws no tap markers on pixels. */
|
|
38
|
+
w?: number;
|
|
39
|
+
h?: number;
|
|
40
|
+
};
|
|
32
41
|
|
|
33
42
|
let _ring: ScreenFrame[] = [];
|
|
34
43
|
let _capacity = 0;
|
|
@@ -75,6 +84,9 @@ export const drainScreenReplay = (): null | string => {
|
|
|
75
84
|
JSON.stringify({
|
|
76
85
|
t: Number(((f.t - now) / 1000).toFixed(1)),
|
|
77
86
|
mediaType: f.mediaType,
|
|
87
|
+
...(typeof f.w === 'number' && typeof f.h === 'number'
|
|
88
|
+
? { w: f.w, h: f.h }
|
|
89
|
+
: {}),
|
|
78
90
|
base64: f.base64,
|
|
79
91
|
}),
|
|
80
92
|
)
|
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.4.0';
|
|
24
24
|
|
|
25
25
|
let _queue: WireEvent[] = [];
|
|
26
26
|
let _assertStats = new Map<string, AssertStat>();
|