@@ -20,9 +20,42 @@ function getCode() {
20
20
void ( async ( ) => {
21
21
const code = getCode ( ) ;
22
22
let events = [ ] ;
23
+ let injectionInProgress = false ;
23
24
24
25
async function injectRecording ( frame ) {
26
+ // 防止并发注入
27
+ if ( injectionInProgress ) {
28
+ return ;
29
+ }
30
+
25
31
try {
32
+ injectionInProgress = true ;
33
+
34
+ // 检查 frame 是否仍然有效
35
+ if ( frame . isDetached ( ) ) {
36
+ console . log ( 'Frame is detached, skipping injection' ) ;
37
+ return ;
38
+ }
39
+
40
+ // 等待页面稳定
41
+ await new Promise ( resolve => setTimeout ( resolve , 1000 ) ) ;
42
+
43
+ // 再次检查 frame 状态
44
+ if ( frame . isDetached ( ) ) {
45
+ console . log ( 'Frame became detached while waiting, skipping injection' ) ;
46
+ return ;
47
+ }
48
+
49
+ // 检查是否已经注入过
50
+ const alreadyInjected = await frame . evaluate ( ( ) => {
51
+ return window . __IS_RECORDING__ === true ;
52
+ } ) . catch ( ( ) => false ) ;
53
+
54
+ if ( alreadyInjected ) {
55
+ console . log ( 'Recording script already injected' ) ;
56
+ return ;
57
+ }
58
+
26
59
await frame . evaluate ( ( rrwebCode ) => {
27
60
const win = window ;
28
61
if ( win . __IS_RECORDING__ ) return ;
@@ -38,27 +71,45 @@ void (async () => {
38
71
document . head . append ( s ) ;
39
72
} else {
40
73
requestAnimationFrame ( ( ) => {
41
- document . head . append ( s ) ;
74
+ if ( document . head ) {
75
+ document . head . append ( s ) ;
76
+ }
42
77
} ) ;
43
78
}
44
79
}
45
80
loadScript ( rrwebCode ) ;
46
81
47
82
win . events = [ ] ;
48
- rrweb . record ( {
49
- emit : ( event ) => {
50
- win . events . push ( event ) ;
51
- win . _replLog ( event ) ;
52
- } ,
53
- plugins : [ ] ,
54
- recordCanvas : true ,
55
- recordCrossOriginIframes : true ,
56
- collectFonts : true ,
57
- } ) ;
83
+ // 添加全局错误处理
84
+ try {
85
+ rrweb . record ( {
86
+ emit : ( event ) => {
87
+ win . events . push ( event ) ;
88
+ if ( win . _replLog ) {
89
+ win . _replLog ( event ) ;
90
+ }
91
+ } ,
92
+ plugins : [ ] ,
93
+ recordCanvas : true ,
94
+ recordCrossOriginIframes : true ,
95
+ collectFonts : true ,
96
+ } ) ;
97
+ console . log ( 'rrweb recording started successfully' ) ;
98
+ } catch ( e ) {
99
+ console . error ( 'Failed to start rrweb recording:' , e ) ;
100
+ }
58
101
} ) ( ) ;
59
102
} , code ) ;
103
+
104
+ console . log ( 'Recording script injected successfully' ) ;
60
105
} catch ( e ) {
61
- console . error ( 'failed to inject recording script:' , e ) ;
106
+ // 只在非上下文销毁错误时输出错误信息
107
+ if ( ! e . message . includes ( 'Execution context was destroyed' ) &&
108
+ ! e . message . includes ( 'detached frame' ) ) {
109
+ console . error ( 'Failed to inject recording script:' , e . message ) ;
110
+ }
111
+ } finally {
112
+ injectionInProgress = false ;
62
113
}
63
114
}
64
115
@@ -153,6 +204,8 @@ void (async () => {
153
204
'--start-maximized' ,
154
205
'--ignore-certificate-errors' ,
155
206
'--no-sandbox' ,
207
+ '--disable-web-security' ,
208
+ '--disable-features=VizDisplayCompositor'
156
209
] ,
157
210
} ) ;
158
211
const page = await browser . newPage ( ) ;
@@ -161,15 +214,36 @@ void (async () => {
161
214
events . push ( event ) ;
162
215
} ) ;
163
216
164
- page . on ( 'framenavigated' , async ( frame ) => {
165
- await injectRecording ( frame ) ;
166
- } ) ;
217
+ // 使用去抖动的注入函数
218
+ let injectionTimeout ;
219
+ const debouncedInject = ( frame ) => {
220
+ clearTimeout ( injectionTimeout ) ;
221
+ injectionTimeout = setTimeout ( ( ) => {
222
+ injectRecording ( frame ) ;
223
+ } , 500 ) ;
224
+ } ;
225
+
226
+ page . on ( 'framenavigated' , debouncedInject ) ;
167
227
168
- await page . goto ( url , {
169
- waitUntil : 'domcontentloaded' ,
170
- timeout : 300000 ,
228
+ // 监听页面加载完成事件
229
+ page . on ( 'load' , ( ) => {
230
+ setTimeout ( ( ) => {
231
+ injectRecording ( page . mainFrame ( ) ) ;
232
+ } , 1000 ) ;
171
233
} ) ;
172
234
235
+ try {
236
+ await page . goto ( url , {
237
+ waitUntil : 'domcontentloaded' ,
238
+ timeout : 300000 ,
239
+ } ) ;
240
+
241
+ // 初始注入
242
+ await injectRecording ( page . mainFrame ( ) ) ;
243
+ } catch ( e ) {
244
+ console . error ( 'Failed to navigate to URL:' , e . message ) ;
245
+ }
246
+
173
247
emitter . once ( 'done' , async ( shouldReplay ) => {
174
248
const pages = await browser . pages ( ) ;
175
249
await Promise . all ( pages . map ( ( page ) => page . close ( ) ) ) ;
0 commit comments