gm-plugkit 2.0.1921 → 2.0.1922
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/package.json +1 -1
- package/plugkit-wasm-wrapper.js +61 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-plugkit",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1922",
|
|
4
4
|
"description": "Bootstrap and daemon-spawn tool for gm plugkit binary. Downloads the correct platform binary, verifies SHA256, and starts the spool watcher daemon. Includes plugkit-wasm-wrapper for WASM-based spool watching.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
package/plugkit-wasm-wrapper.js
CHANGED
|
@@ -682,7 +682,7 @@ function writeJsonFile(fp, value) {
|
|
|
682
682
|
try { atomicWriteJson(fp, value); } catch (_) {}
|
|
683
683
|
}
|
|
684
684
|
|
|
685
|
-
const AGGREGATE_CPU_PROFILE_SRC = `function aggregateCpuProfile(profile, topN) {
|
|
685
|
+
const AGGREGATE_CPU_PROFILE_SRC = `function aggregateCpuProfile(profile, topN, isBrowserCtx) {
|
|
686
686
|
const N = topN || 20;
|
|
687
687
|
if (!profile || !Array.isArray(profile.nodes) || !Array.isArray(profile.samples)) {
|
|
688
688
|
return { timeframe: null, culprits: [] };
|
|
@@ -712,6 +712,21 @@ const AGGREGATE_CPU_PROFILE_SRC = `function aggregateCpuProfile(profile, topN) {
|
|
|
712
712
|
.sort((a, b) => b.self_us - a.self_us)
|
|
713
713
|
.slice(0, N)
|
|
714
714
|
.map(c => ({ location: c.location, function: c.function, self_us: c.self_us, self_pct: total ? Math.round((c.self_us / total) * 1000) / 10 : 0, hits: c.hits }));
|
|
715
|
+
// gpu_hint: when the TOP culprit is the unattributed '(program)'/'(native)' bucket at a dominant
|
|
716
|
+
// share of total self-time, the CPU sampler is telling you it is BLIND here -- that time is real
|
|
717
|
+
// wall-clock cost the JS/V8 sampler cannot see into (GPU driver submission, shader execution,
|
|
718
|
+
// compositor/raster work), not "nothing is happening". Proactively naming the follow-up (the
|
|
719
|
+
// browser verb's own 'trace\\n<script>' CDP-tracing prefix, which returns real gpu_us/viz_us/cc_us
|
|
720
|
+
// wall-clock GPU-process activity) saves a full extra dispatch+re-read round trip every time a
|
|
721
|
+
// caller has to rediscover this on their own -- a real, repeated cost hit debugging a live FPS
|
|
722
|
+
// regression where the top culprit was '(program)' at 84% self-time with nothing further to go on
|
|
723
|
+
// until a SEPARATE trace-mode dispatch was manually reasoned into existence.
|
|
724
|
+
const topC = culprits[0];
|
|
725
|
+
const gpu_hint = (topC && (topC.location === '(native):0' || topC.location === '(program):0') && topC.self_pct >= 40)
|
|
726
|
+
? (isBrowserCtx
|
|
727
|
+
? \`Top culprit is the unattributed \${topC.function === '(program)' ? '(program)' : '(native)'} bucket at \${topC.self_pct}% self-time -- the CPU sampler cannot see GPU-side work (driver submission, shader execution, compositor/raster). Re-run this dispatch with the 'trace\\n<script>' prefix instead of 'profile' to get real gpu_us/viz_us/cc_us wall-clock GPU-process activity via CDP Tracing.\`
|
|
728
|
+
: \`Top culprit is the unattributed \${topC.function === '(program)' ? '(program)' : '(native)'} bucket at \${topC.self_pct}% self-time -- the CPU sampler cannot see into native/C++ addon calls, syscalls, or (on the node exec_js surface) any work happening off the main JS thread. No GPU-tracing follow-up applies here (that is browser-only); consider opts.mem:true or narrowing the profiled span if this bucket needs further attribution.\`)
|
|
729
|
+
: null;
|
|
715
730
|
return {
|
|
716
731
|
timeframe: {
|
|
717
732
|
start_us: typeof profile.startTime === 'number' ? profile.startTime : 0,
|
|
@@ -720,6 +735,7 @@ const AGGREGATE_CPU_PROFILE_SRC = `function aggregateCpuProfile(profile, topN) {
|
|
|
720
735
|
sample_count: sampleCount,
|
|
721
736
|
},
|
|
722
737
|
culprits,
|
|
738
|
+
gpu_hint,
|
|
723
739
|
};
|
|
724
740
|
}`;
|
|
725
741
|
|
|
@@ -737,11 +753,11 @@ function sweepStaleProfileTmp() {
|
|
|
737
753
|
}
|
|
738
754
|
try { sweepStaleProfileTmp(); } catch (_) {}
|
|
739
755
|
let _aggregateCpuProfileFn = null;
|
|
740
|
-
function aggregateCpuProfile(profile, topN) {
|
|
756
|
+
function aggregateCpuProfile(profile, topN, isBrowserCtx) {
|
|
741
757
|
if (!_aggregateCpuProfileFn) {
|
|
742
758
|
_aggregateCpuProfileFn = new Function(AGGREGATE_CPU_PROFILE_SRC + '\nreturn aggregateCpuProfile;')();
|
|
743
759
|
}
|
|
744
|
-
return _aggregateCpuProfileFn(profile, topN);
|
|
760
|
+
return _aggregateCpuProfileFn(profile, topN, isBrowserCtx);
|
|
745
761
|
}
|
|
746
762
|
|
|
747
763
|
const BROWSER_RUNNER_BIN = process.env.GM_BROWSER_RUNNER_BIN || 'playwriter';
|
|
@@ -2821,7 +2837,7 @@ function makeHostFunctions(instanceRef) {
|
|
|
2821
2837
|
+ ` __profile = __r && __r.profile || null;\n`
|
|
2822
2838
|
+ ` } catch (pe) { __profileError = String(pe && pe.message || pe); }\n`
|
|
2823
2839
|
+ ` const __memAfter = process.memoryUsage();\n`
|
|
2824
|
-
+ ` const __agg = __profile ? aggregateCpuProfile(__profile, ${profileTopN}) : { timeframe: null, culprits: [] };\n`
|
|
2840
|
+
+ ` const __agg = __profile ? aggregateCpuProfile(__profile, ${profileTopN}, false) : { timeframe: null, culprits: [] };\n`
|
|
2825
2841
|
+ ` const __userFile = ${JSON.stringify('file:///' + profileUserFile.replace(/\\/g, '/'))};\n`
|
|
2826
2842
|
+ ` const __cpuTotalUs = __agg.timeframe ? __agg.timeframe.total_us : 0;\n`
|
|
2827
2843
|
+ ` const __cpuUserUs = (__agg.culprits || []).filter(c => c.location && c.location.indexOf(__userFile) === 0).reduce((a, c) => a + c.self_us, 0);\n`
|
|
@@ -3155,8 +3171,25 @@ function makeHostFunctions(instanceRef) {
|
|
|
3155
3171
|
// window.__gmGlErrors accumulates {fn,mode,count,offset,type,error,errorName,ctxLabel} for
|
|
3156
3172
|
// up to 40 distinct GL errors per page load (capped to bound memory on a runaway-error page);
|
|
3157
3173
|
// window.__gmGlDrawCalls is a running total per draw-fn name for volume context.
|
|
3174
|
+
// DESIGN NOTES (2026-07-17, fixing two real gaps hit live debugging a session-reported FPS
|
|
3175
|
+
// regression): (1) the original cap was "first 40 occurrences, ever, per page load, then
|
|
3176
|
+
// silently stop recording" -- on a bug that fires every frame, the array fills in <1s and
|
|
3177
|
+
// every subsequent browser dispatch for the rest of a long debugging session reads the exact
|
|
3178
|
+
// same stale 9-or-so entries, making it look like the error stopped recurring or is capped/
|
|
3179
|
+
// dead when it is actually still firing every frame. Fixed to a per-SIGNATURE (fn+error+mode+
|
|
3180
|
+
// count+instanceCount) dedup table with an occurrence COUNTER and lastSeenDrawCallIndex, so a
|
|
3181
|
+
// recurring error updates its own entry's count/lastSeen instead of being dropped once 40 raw
|
|
3182
|
+
// occurrences have ever been logged -- growth is now bounded by DISTINCT error shapes (a
|
|
3183
|
+
// realistic page has a handful, not thousands), not raw occurrence volume, and a caller can
|
|
3184
|
+
// tell "still happening, N times so far, most recently at draw #X" instead of a dead list.
|
|
3185
|
+
// (2) no error entry carried a JS stack trace, forcing the exact same
|
|
3186
|
+
// gl.drawX=function(){...new Error().stack...} monkeypatch to be hand-rolled from scratch in
|
|
3187
|
+
// every debugging session that needed to know WHICH call site triggered a given GL error --
|
|
3188
|
+
// captured here once, for free, on first occurrence of each distinct signature (capturing on
|
|
3189
|
+
// EVERY occurrence would be wasteful once a hot per-frame error has fired thousands of times;
|
|
3190
|
+
// the call site for a given signature does not change across occurrences in practice).
|
|
3158
3191
|
+ `await page.addInitScript(()=>{`
|
|
3159
|
-
+ `window.__gmGlErrors=[];window.__gmGlDrawCalls={};`
|
|
3192
|
+
+ `window.__gmGlErrors=[];window.__gmGlDrawCalls={};window.__gmGlErrorTotalCount=0;`
|
|
3160
3193
|
+ `const __glErrName=(gl,code)=>{for(const k of ['NO_ERROR','INVALID_ENUM','INVALID_VALUE','INVALID_OPERATION','INVALID_FRAMEBUFFER_OPERATION','OUT_OF_MEMORY','CONTEXT_LOST_WEBGL']){try{if(gl[k]===code)return k;}catch(_){}}return 'UNKNOWN_'+code;};`
|
|
3161
3194
|
+ `const __wrapDraw=(gl,ctxLabel)=>{`
|
|
3162
3195
|
+ `['drawArrays','drawElements','drawArraysInstanced','drawElementsInstanced'].forEach(fn=>{`
|
|
@@ -3166,9 +3199,17 @@ function makeHostFunctions(instanceRef) {
|
|
|
3166
3199
|
+ `const __res=__orig(...args);`
|
|
3167
3200
|
+ `window.__gmGlDrawCalls[fn]=(window.__gmGlDrawCalls[fn]||0)+1;`
|
|
3168
3201
|
+ `const __err=gl.getError();`
|
|
3169
|
-
+ `
|
|
3202
|
+
+ `window.__gmGlLastDrainedError={fn,error:__err,errorName:__glErrName(gl,__err),drawCallIndex:window.__gmGlDrawCalls[fn]};` // last-drained-code accessor: a user script's OWN post-draw gl.getError() call always reads NO_ERROR (this wrapper already drained the single-slot GL error queue first) -- read this instead of calling gl.getError() again in user code.
|
|
3203
|
+
+ `if(__err!==gl.NO_ERROR){`
|
|
3204
|
+
+ `window.__gmGlErrorTotalCount++;`
|
|
3170
3205
|
+ `let __bufSize=-1;try{__bufSize=gl.getBufferParameter(gl.ELEMENT_ARRAY_BUFFER,gl.BUFFER_SIZE);}catch(_){}`
|
|
3171
|
-
+ `
|
|
3206
|
+
+ `const __sig=fn+'|'+__err+'|'+args[0]+'|'+args[1]+'|'+(fn.indexOf('Instanced')>=0?args[args.length-1]:'');`
|
|
3207
|
+
+ `let __rec=window.__gmGlErrors.find(e=>e.__sig===__sig);`
|
|
3208
|
+
+ `if(__rec){__rec.occurrenceCount++;__rec.lastDrawCallIndex=window.__gmGlDrawCalls[fn];}`
|
|
3209
|
+
+ `else if(window.__gmGlErrors.length<40){`
|
|
3210
|
+
+ `let __stack='';try{__stack=new Error().stack.split('\\n').slice(1,9).join(' | ');}catch(_){}`
|
|
3211
|
+
+ `window.__gmGlErrors.push({__sig,fn,ctxLabel,mode:args[0],count:args[1],offset:fn.indexOf('Elements')>=0?args[3]:undefined,type:fn.indexOf('Elements')>=0?args[2]:undefined,instanceCount:fn.indexOf('Instanced')>=0?args[args.length-1]:undefined,error:__err,errorName:__glErrName(gl,__err),elementArrayBufferSize:__bufSize,firstDrawCallIndex:window.__gmGlDrawCalls[fn],lastDrawCallIndex:window.__gmGlDrawCalls[fn],occurrenceCount:1,stack:__stack});`
|
|
3212
|
+
+ `}`
|
|
3172
3213
|
+ `}`
|
|
3173
3214
|
+ `return __res;`
|
|
3174
3215
|
+ `};`
|
|
@@ -3210,13 +3251,14 @@ function makeHostFunctions(instanceRef) {
|
|
|
3210
3251
|
+ `const __wmErrors=await page.evaluate(()=>window.__gmErrors||[]);\n`
|
|
3211
3252
|
+ `const __glErrors=await page.evaluate(()=>window.__gmGlErrors||[]).catch(()=>[]);\n`
|
|
3212
3253
|
+ `const __glDrawCalls=await page.evaluate(()=>window.__gmGlDrawCalls||{}).catch(()=>({}));\n`
|
|
3254
|
+
+ `const __glErrorTotalCount=await page.evaluate(()=>window.__gmGlErrorTotalCount||0).catch(()=>0);\n`
|
|
3213
3255
|
+ perfRead
|
|
3214
3256
|
+ AGGREGATE_CPU_PROFILE_SRC + `\n`
|
|
3215
|
-
+ `const __agg = __profile ? aggregateCpuProfile(__profile, ${profileTopNBrowser}) : {timeframe:null,culprits:[]};\n`
|
|
3257
|
+
+ `const __agg = __profile ? aggregateCpuProfile(__profile, ${profileTopNBrowser}, true) : {timeframe:null,culprits:[]};\n`
|
|
3216
3258
|
+ `const __cpuUs=__agg.timeframe?__agg.timeframe.total_us:0;\n`
|
|
3217
3259
|
+ `const __wallVsCpu={wall_us:__wallUs,cpu_self_us:__cpuUs,offcpu_us:Math.max(0,__wallUs-__cpuUs),note:'offcpu_us = wall minus on-CPU JS self time = GPU/compositor/raster/IO/idle the CPU sampler is blind to; use trace mode to attribute GPU activity'};\n`
|
|
3218
3260
|
+ `const __allErrors=[...__errs,...__wmErrors];\n`
|
|
3219
|
-
+ `const __RET={result:__result,profile:__agg,profile_error:__profileError,wall_vs_cpu:__wallVsCpu,debug:{console:${consoleFmt},pageErrors:__allErrors,network:${netFmt},performance:__perf,gl:{errors:__glErrors,drawCalls:__glDrawCalls}}};\n`
|
|
3261
|
+
+ `const __RET={result:__result,profile:__agg,profile_error:__profileError,wall_vs_cpu:__wallVsCpu,debug:{console:${consoleFmt},pageErrors:__allErrors,network:${netFmt},performance:__perf,gl:{errors:__glErrors,drawCalls:__glDrawCalls,errorTotalCount:__glErrorTotalCount}}};\n`
|
|
3220
3262
|
+ emitResult + `return __RET;`;
|
|
3221
3263
|
} else if (modeMatch && modeMatch[1] === 'trace') {
|
|
3222
3264
|
const userScript = modeMatch[3];
|
|
@@ -3231,6 +3273,7 @@ function makeHostFunctions(instanceRef) {
|
|
|
3231
3273
|
+ `const __wmErrors=await page.evaluate(()=>window.__gmErrors||[]);\n`
|
|
3232
3274
|
+ `const __glErrors=await page.evaluate(()=>window.__gmGlErrors||[]).catch(()=>[]);\n`
|
|
3233
3275
|
+ `const __glDrawCalls=await page.evaluate(()=>window.__gmGlDrawCalls||{}).catch(()=>({}));\n`
|
|
3276
|
+
+ `const __glErrorTotalCount=await page.evaluate(()=>window.__gmGlErrorTotalCount||0).catch(()=>0);\n`
|
|
3234
3277
|
+ perfRead
|
|
3235
3278
|
+ `const __byCat={};let __minTs=Infinity,__maxTs=-Infinity;for(const ev of __traceEvents){if(typeof ev.ts==='number'){__minTs=Math.min(__minTs,ev.ts);if(typeof ev.dur==='number')__maxTs=Math.max(__maxTs,ev.ts+ev.dur);}if(typeof ev.dur==='number'&&ev.dur>0){const c=ev.cat||'?';__byCat[c]=(__byCat[c]||0)+ev.dur;}}\n`
|
|
3236
3279
|
+ `const __sum=(re)=>Object.entries(__byCat).filter(([k])=>re.test(k)).reduce((a,[,v])=>a+v,0);\n`
|
|
@@ -3238,7 +3281,7 @@ function makeHostFunctions(instanceRef) {
|
|
|
3238
3281
|
+ `const __topCats=Object.entries(__byCat).sort((a,b)=>b[1]-a[1]).slice(0,15).map(([cat,us])=>({cat,wall_us:us}));\n`
|
|
3239
3282
|
+ `const __spanUs=(isFinite(__minTs)&&__maxTs>0)?(__maxTs-__minTs):0;\n`
|
|
3240
3283
|
+ `const __allErrors=[...__errs,...__wmErrors];\n`
|
|
3241
|
-
+ `const __RET={result:__result,trace:{wall_us:__wallUs,trace_span_us:__spanUs,event_count:__traceEvents.length,complete:__traceComplete,gpu_us:__gpuUs,viz_us:__vizUs,cc_us:__ccUs,raster_us:__rasterUs,offcpu_note:'gpu_us/viz_us/cc_us are wall-clock GPU-process activity (compositor/raster/draw) captured via CDP Tracing -- the CPU sampler cannot see these',by_category:__topCats},trace_error:__traceError,debug:{console:${consoleFmt},pageErrors:__allErrors,network:${netFmt},performance:__perf,gl:{errors:__glErrors,drawCalls:__glDrawCalls}}};\n`
|
|
3284
|
+
+ `const __RET={result:__result,trace:{wall_us:__wallUs,trace_span_us:__spanUs,event_count:__traceEvents.length,complete:__traceComplete,gpu_us:__gpuUs,viz_us:__vizUs,cc_us:__ccUs,raster_us:__rasterUs,offcpu_note:'gpu_us/viz_us/cc_us are wall-clock GPU-process activity (compositor/raster/draw) captured via CDP Tracing -- the CPU sampler cannot see these',by_category:__topCats},trace_error:__traceError,debug:{console:${consoleFmt},pageErrors:__allErrors,network:${netFmt},performance:__perf,gl:{errors:__glErrors,drawCalls:__glDrawCalls,errorTotalCount:__glErrorTotalCount}}};\n`
|
|
3242
3285
|
+ emitResult + `return __RET;`;
|
|
3243
3286
|
} else if (modeMatch && modeMatch[1] === 'capture') {
|
|
3244
3287
|
const userScript = modeMatch[3];
|
|
@@ -3247,9 +3290,10 @@ function makeHostFunctions(instanceRef) {
|
|
|
3247
3290
|
+ `const __wmErrors=await page.evaluate(()=>window.__gmErrors||[]);\n`
|
|
3248
3291
|
+ `const __glErrors=await page.evaluate(()=>window.__gmGlErrors||[]).catch(()=>[]);\n`
|
|
3249
3292
|
+ `const __glDrawCalls=await page.evaluate(()=>window.__gmGlDrawCalls||{}).catch(()=>({}));\n`
|
|
3293
|
+
+ `const __glErrorTotalCount=await page.evaluate(()=>window.__gmGlErrorTotalCount||0).catch(()=>0);\n`
|
|
3250
3294
|
+ perfRead
|
|
3251
3295
|
+ `const __allErrors=[...__errs,...__wmErrors];\n`
|
|
3252
|
-
+ `const __RET={result:__result,debug:{console:${consoleFmt},pageErrors:__allErrors,network:${netFmt},performance:__perf,gl:{errors:__glErrors,drawCalls:__glDrawCalls}}};\n`
|
|
3296
|
+
+ `const __RET={result:__result,debug:{console:${consoleFmt},pageErrors:__allErrors,network:${netFmt},performance:__perf,gl:{errors:__glErrors,drawCalls:__glDrawCalls,errorTotalCount:__glErrorTotalCount}}};\n`
|
|
3253
3297
|
+ emitResult + `return __RET;`;
|
|
3254
3298
|
} else if (screenshotPath) {
|
|
3255
3299
|
// Every path below (screenshot, DOM query, plain URL/eval, bare eval) now attaches the SAME
|
|
@@ -3265,9 +3309,10 @@ function makeHostFunctions(instanceRef) {
|
|
|
3265
3309
|
+ `const __wmErrors=await page.evaluate(()=>window.__gmErrors||[]);\n`
|
|
3266
3310
|
+ `const __glErrors=await page.evaluate(()=>window.__gmGlErrors||[]).catch(()=>[]);\n`
|
|
3267
3311
|
+ `const __glDrawCalls=await page.evaluate(()=>window.__gmGlDrawCalls||{}).catch(()=>({}));\n`
|
|
3312
|
+
+ `const __glErrorTotalCount=await page.evaluate(()=>window.__gmGlErrorTotalCount||0).catch(()=>0);\n`
|
|
3268
3313
|
+ perfRead
|
|
3269
3314
|
+ `const __allErrors=[...__errs,...__wmErrors];\n`
|
|
3270
|
-
+ `const __RET={result:__result,screenshot_path:${JSON.stringify(screenshotPath)},screenshot_error:__shotErr,debug:{console:${consoleFmt},pageErrors:__allErrors,network:${netFmt},performance:__perf,gl:{errors:__glErrors,drawCalls:__glDrawCalls}}};\n`
|
|
3315
|
+
+ `const __RET={result:__result,screenshot_path:${JSON.stringify(screenshotPath)},screenshot_error:__shotErr,debug:{console:${consoleFmt},pageErrors:__allErrors,network:${netFmt},performance:__perf,gl:{errors:__glErrors,drawCalls:__glDrawCalls,errorTotalCount:__glErrorTotalCount}}};\n`
|
|
3271
3316
|
+ emitResult + `return __RET;`;
|
|
3272
3317
|
} else if (domSelector) {
|
|
3273
3318
|
evalBody = debugSetup
|
|
@@ -3275,9 +3320,10 @@ function makeHostFunctions(instanceRef) {
|
|
|
3275
3320
|
+ `const __wmErrors=await page.evaluate(()=>window.__gmErrors||[]);\n`
|
|
3276
3321
|
+ `const __glErrors=await page.evaluate(()=>window.__gmGlErrors||[]).catch(()=>[]);\n`
|
|
3277
3322
|
+ `const __glDrawCalls=await page.evaluate(()=>window.__gmGlDrawCalls||{}).catch(()=>({}));\n`
|
|
3323
|
+
+ `const __glErrorTotalCount=await page.evaluate(()=>window.__gmGlErrorTotalCount||0).catch(()=>0);\n`
|
|
3278
3324
|
+ perfRead
|
|
3279
3325
|
+ `const __allErrors=[...__errs,...__wmErrors];\n`
|
|
3280
|
-
+ `__RET={...__RET,debug:{console:${consoleFmt},pageErrors:__allErrors,network:${netFmt},performance:__perf,gl:{errors:__glErrors,drawCalls:__glDrawCalls}}};\n`
|
|
3326
|
+
+ `__RET={...__RET,debug:{console:${consoleFmt},pageErrors:__allErrors,network:${netFmt},performance:__perf,gl:{errors:__glErrors,drawCalls:__glDrawCalls,errorTotalCount:__glErrorTotalCount}}};\n`
|
|
3281
3327
|
+ emitResult + `return __RET;`;
|
|
3282
3328
|
} else {
|
|
3283
3329
|
// startUrl and/or blankProbe and/or bare-eval all collapse into this single branch now --
|
|
@@ -3287,9 +3333,10 @@ function makeHostFunctions(instanceRef) {
|
|
|
3287
3333
|
+ `const __wmErrors=await page.evaluate(()=>window.__gmErrors||[]);\n`
|
|
3288
3334
|
+ `const __glErrors=await page.evaluate(()=>window.__gmGlErrors||[]).catch(()=>[]);\n`
|
|
3289
3335
|
+ `const __glDrawCalls=await page.evaluate(()=>window.__gmGlDrawCalls||{}).catch(()=>({}));\n`
|
|
3336
|
+
+ `const __glErrorTotalCount=await page.evaluate(()=>window.__gmGlErrorTotalCount||0).catch(()=>0);\n`
|
|
3290
3337
|
+ perfRead
|
|
3291
3338
|
+ `const __allErrors=[...__errs,...__wmErrors];\n`
|
|
3292
|
-
+ `const __RET={result:__result,debug:{console:${consoleFmt},pageErrors:__allErrors,network:${netFmt},performance:__perf,gl:{errors:__glErrors,drawCalls:__glDrawCalls}}};\n`
|
|
3339
|
+
+ `const __RET={result:__result,debug:{console:${consoleFmt},pageErrors:__allErrors,network:${netFmt},performance:__perf,gl:{errors:__glErrors,drawCalls:__glDrawCalls,errorTotalCount:__glErrorTotalCount}}};\n`
|
|
3293
3340
|
+ emitResult + `return __RET;`;
|
|
3294
3341
|
}
|
|
3295
3342
|
const outerTimeoutMs = Math.min(timeoutMs + 6000, 126000);
|