@aura3d/debug 4.1.0 → 4.1.2
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/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/safety/blackFrame.d.ts +86 -9
- package/dist/safety/blackFrame.d.ts.map +1 -1
- package/dist/safety/blackFrame.js +244 -27
- package/dist/safety/blackFrame.js.map +1 -1
- package/dist/safety/diagnosticsPanel.d.ts +17 -0
- package/dist/safety/diagnosticsPanel.d.ts.map +1 -1
- package/dist/safety/diagnosticsPanel.js +6 -0
- package/dist/safety/diagnosticsPanel.js.map +1 -1
- package/dist/safety/frameTap.d.ts +23 -0
- package/dist/safety/frameTap.d.ts.map +1 -0
- package/dist/safety/frameTap.js +125 -0
- package/dist/safety/frameTap.js.map +1 -0
- package/dist/safety/guard.d.ts +63 -0
- package/dist/safety/guard.d.ts.map +1 -0
- package/dist/safety/guard.js +79 -0
- package/dist/safety/guard.js.map +1 -0
- package/dist/safety/index.d.ts +6 -2
- package/dist/safety/index.d.ts.map +1 -1
- package/dist/safety/index.js +13 -2
- package/dist/safety/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -28,6 +28,6 @@ export { buildAxesHelper, buildBoundsHelper, buildCameraFrustumHelper, buildDire
|
|
|
28
28
|
export type { AxesHelperOptions, BoundsHelperOptions, CameraFrustumHelperOptions, DebugColor, DebugVec3, DirectionalLightHelperOptions, GridHelperOptions, SkeletonHelperJoint } from "./SceneHelpers.js";
|
|
29
29
|
export { ReportExporter } from "./ReportExporter.js";
|
|
30
30
|
export type { DebugReport } from "./ReportExporter.js";
|
|
31
|
-
export { DEFAULT_HEAL_LADDER, DEFAULT_HEAL_STORAGE_KEY, createBlackFrameWatch, formatEngineSection, formatGpuProbe, healParams, healRungName, healStage, installDiagnosticsPanel, installSafetyNet, isBlackFrame, probeGpu, resolveQualitySwitches } from "./safety/index.js";
|
|
32
|
-
export type { BlackFrameWatch, BlackFrameWatchOptions, DiagnosticsAppLike, DiagnosticsPanelHandle, DiagnosticsPanelOptions, GpuProbe, HealRung, QualitySwitches, ResolveQualitySwitchesOptions, SafetyNet, SafetyNetOptions, SafetyReport, SafetySettings } from "./safety/index.js";
|
|
31
|
+
export { DEFAULT_HEAL_LADDER, DEFAULT_HEAL_STORAGE_KEY, QR_HEAL_LADDER, createBlackFrameWatch, formatEngineSection, formatGpuProbe, healParams, healRungName, healStage, installBlackFrameGuard, installDiagnosticsPanel, installFrameTap, installSafetyNet, isBlackFrame, probeGpu, qrHealRungName, qrHealStage, qrHealUrl, resolveQualitySwitches } from "./safety/index.js";
|
|
32
|
+
export type { BlackFrameGuardOptions, BlackFrameWatch, BlackFrameWatchOptions, DiagnosticsAppLike, DiagnosticsPanelHandle, DiagnosticsPanelOptions, FrameTap, FrameTapOptions, GpuProbe, HealGlobal, HealRung, QualitySwitches, ResolveQualitySwitchesOptions, SafetyNet, SafetyNetOptions, SafetyReport, SafetySettings } from "./safety/index.js";
|
|
33
33
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../packages/debug/src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../packages/debug/src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -13,5 +13,5 @@ export { DebugOverlay } from "./DebugOverlay.js";
|
|
|
13
13
|
export { DebugLineCanvasRenderer } from "./DebugLineCanvasRenderer.js";
|
|
14
14
|
export { buildAxesHelper, buildBoundsHelper, buildCameraFrustumHelper, buildDirectionalLightHelper, buildGridHelper, buildSkeletonHelper } from "./SceneHelpers.js";
|
|
15
15
|
export { ReportExporter } from "./ReportExporter.js";
|
|
16
|
-
export { DEFAULT_HEAL_LADDER, DEFAULT_HEAL_STORAGE_KEY, createBlackFrameWatch, formatEngineSection, formatGpuProbe, healParams, healRungName, healStage, installDiagnosticsPanel, installSafetyNet, isBlackFrame, probeGpu, resolveQualitySwitches } from "./safety/index.js";
|
|
16
|
+
export { DEFAULT_HEAL_LADDER, DEFAULT_HEAL_STORAGE_KEY, QR_HEAL_LADDER, createBlackFrameWatch, formatEngineSection, formatGpuProbe, healParams, healRungName, healStage, installBlackFrameGuard, installDiagnosticsPanel, installFrameTap, installSafetyNet, isBlackFrame, probeGpu, qrHealRungName, qrHealStage, qrHealUrl, resolveQualitySwitches } from "./safety/index.js";
|
|
17
17
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/debug/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEvF,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAElF,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAExF,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE1E,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAEvE,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,wBAAwB,EACxB,2BAA2B,EAC3B,eAAe,EACf,mBAAmB,EACpB,MAAM,mBAAmB,CAAC;AAW3B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,UAAU,EACV,YAAY,EACZ,SAAS,EACT,uBAAuB,EACvB,gBAAgB,EAChB,YAAY,EACZ,QAAQ,EACR,sBAAsB,EACvB,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/debug/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEvF,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAElF,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAExF,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE1E,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAEvE,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,wBAAwB,EACxB,2BAA2B,EAC3B,eAAe,EACf,mBAAmB,EACpB,MAAM,mBAAmB,CAAC;AAW3B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,cAAc,EACd,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,UAAU,EACV,YAAY,EACZ,SAAS,EACT,sBAAsB,EACtB,uBAAuB,EACvB,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,QAAQ,EACR,cAAc,EACd,WAAW,EACX,SAAS,EACT,sBAAsB,EACvB,MAAM,mBAAmB,CAAC"}
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Black-frame self-heal. Some GPU/driver combinations present a frame that is entirely black while the engine reports
|
|
3
3
|
* draw calls. When that persists the page reloads itself one rung down a compatibility ladder (each rung switches off
|
|
4
|
-
* one more optional stage) and records the rung, so a player still gets a picture and the diagnostics panel
|
|
5
|
-
* rung fixed it. Opt-in only: nothing here runs unless `installSafetyNet
|
|
4
|
+
* one more optional stage) and records the rung and why, so a player still gets a picture and the diagnostics panel
|
|
5
|
+
* shows which rung fixed it. Opt-in only: nothing here runs unless `installSafetyNet`, `installBlackFrameGuard` or
|
|
6
|
+
* `createBlackFrameWatch` is called.
|
|
7
|
+
*
|
|
8
|
+
* The watch is deliberately conservative. A frame counts as broken only when (almost) every sampled texel of the world
|
|
9
|
+
* canvas is the clear colour, the app is ready (document loaded, no loading overlay, no asset fetches in flight, the
|
|
10
|
+
* engine drew something), it has rendered a minimum number of frames since becoming ready, and the canvas stayed that
|
|
11
|
+
* way for several consecutive samples over a time budget that grows with the measured frame time. A dark but valid
|
|
12
|
+
* scene, a slow first frame on a CPU renderer or a page that is still loading never trips it.
|
|
6
13
|
*/
|
|
7
14
|
export interface HealRung {
|
|
8
15
|
readonly name: string;
|
|
@@ -16,30 +23,100 @@ export declare function healStage(storage?: Pick<Storage, "getItem"> | undefined
|
|
|
16
23
|
/** Query parameters implied by rung `stage` (cumulative); callers merge them under the author's explicit parameters. */
|
|
17
24
|
export declare function healParams(stage: number, ladder?: readonly HealRung[]): Record<string, string>;
|
|
18
25
|
export declare function healRungName(stage: number, ladder?: readonly HealRung[]): string;
|
|
19
|
-
|
|
20
|
-
|
|
26
|
+
export interface FrameStats {
|
|
27
|
+
readonly samples: number;
|
|
28
|
+
/** Samples with any colour channel above the black threshold. */
|
|
29
|
+
readonly lit: number;
|
|
30
|
+
readonly litFraction: number;
|
|
31
|
+
/** Largest colour channel seen (0..255). */
|
|
32
|
+
readonly max: number;
|
|
33
|
+
/** Mean of the RGB channels (0..255). */
|
|
34
|
+
readonly mean: number;
|
|
35
|
+
}
|
|
36
|
+
/** Statistics of a downscaled RGBA probe of the canvas. */
|
|
37
|
+
export declare function analyseFrame(rgba: ArrayLike<number>, maxChannel?: number): FrameStats;
|
|
38
|
+
/**
|
|
39
|
+
* True when the sampled frame is black: every texel by default; pass a small `maxLitFraction` to tolerate a few stray lit
|
|
40
|
+
* texels (for example a HUD drawn into the same canvas). Empty input is never black.
|
|
41
|
+
*/
|
|
42
|
+
export declare function isBlackFrame(rgba: ArrayLike<number>, maxLitFraction?: number): boolean;
|
|
43
|
+
/** True while a visible loading overlay is on the page (`#boot`, `#loading`, `.loading`, `[aria-busy=true]` ...). */
|
|
44
|
+
export declare function hasVisibleLoadingOverlay(root?: Pick<Document, "querySelectorAll"> | undefined): boolean;
|
|
45
|
+
/** Default readiness: document fully loaded, no asset fetches in flight, no visible loading overlay. */
|
|
46
|
+
export declare function defaultIsReady(): boolean;
|
|
47
|
+
/** Largest canvas big enough to be the world view, ignoring minimap/HUD/overlay canvases. */
|
|
48
|
+
export declare function findWorldCanvas(root?: Pick<Document, "querySelectorAll"> | undefined): HTMLCanvasElement | null;
|
|
49
|
+
export interface WatchObservation {
|
|
50
|
+
/** `sample()` calls so far (frames the app drew while the watch was installed). */
|
|
51
|
+
readonly calls: number;
|
|
52
|
+
/** Call index at which the app first counted as ready, or null while it is not. */
|
|
53
|
+
readonly readyAtCall: number | null;
|
|
54
|
+
readonly framesSinceReady: number;
|
|
55
|
+
readonly samples: number;
|
|
56
|
+
readonly blackSamples: number;
|
|
57
|
+
readonly consecutiveBlack: number;
|
|
58
|
+
/** True once lit frames were seen for long enough that the watch relaxed to occasional sampling. */
|
|
59
|
+
readonly healthy: boolean;
|
|
60
|
+
readonly lastStats: FrameStats | undefined;
|
|
61
|
+
readonly medianFrameMs: number;
|
|
62
|
+
/** How long the canvas has stayed black (ms), 0 when it is not. */
|
|
63
|
+
readonly blackMs: number;
|
|
64
|
+
readonly skipped: {
|
|
65
|
+
readonly notReady: number;
|
|
66
|
+
readonly noDrawCalls: number;
|
|
67
|
+
readonly hidden: number;
|
|
68
|
+
};
|
|
69
|
+
readonly escalated: boolean;
|
|
70
|
+
/** Why the watch reloaded this page (set on escalation) or why the previous page did (from session storage). */
|
|
71
|
+
readonly reason: string | undefined;
|
|
72
|
+
}
|
|
21
73
|
export interface BlackFrameWatchOptions {
|
|
22
74
|
readonly enabled: boolean;
|
|
23
75
|
readonly ladder?: readonly HealRung[];
|
|
24
76
|
readonly storageKey?: string;
|
|
25
|
-
/** Shortens
|
|
77
|
+
/** Shortens every window (tests only): minimum frames after ready, no minimum black time, samples needed = half of it. */
|
|
26
78
|
readonly fastFrames?: number;
|
|
27
|
-
/** Reads a downscaled RGBA probe of the canvas. Defaults to a
|
|
79
|
+
/** Reads a downscaled RGBA probe of the canvas. Defaults to a nearest-neighbour 2D canvas copy. */
|
|
28
80
|
readonly readProbe?: (canvas: HTMLCanvasElement) => ArrayLike<number> | undefined;
|
|
29
81
|
readonly storage?: StorageLike;
|
|
30
82
|
readonly currentUrl?: () => string;
|
|
31
83
|
/** Navigates to the next rung. Defaults to `location.replace`. */
|
|
32
84
|
readonly navigate?: (url: string) => void;
|
|
33
85
|
readonly log?: (code: string, message: string) => void;
|
|
86
|
+
/** Extra readiness signal (for example the app's own `ready` flag). The default checks overlays, load state and fetches. */
|
|
87
|
+
readonly isReady?: () => boolean;
|
|
88
|
+
/** Engine draw calls for the current frame; when given and not > 0 the frame is not judged (nothing was drawn). */
|
|
89
|
+
readonly getDrawCalls?: () => number | undefined;
|
|
90
|
+
/** Builds the reload URL for rung `stage`, or null to stop. Default merges the rung parameters under the existing query. */
|
|
91
|
+
readonly buildUrl?: (stage: number, currentUrl: string) => string | null;
|
|
92
|
+
/** Clock in ms (tests). Defaults to `performance.now()`. */
|
|
93
|
+
readonly now?: () => number;
|
|
94
|
+
/** Treat the page as hidden (tests). Defaults to `document.hidden`. */
|
|
95
|
+
readonly isHidden?: () => boolean;
|
|
96
|
+
/** Minimum black duration in ms; the effective window is `max(minBlackMs, medianFrameMs * blackFramesBudget)`. Default 4000. */
|
|
97
|
+
readonly minBlackMs?: number;
|
|
98
|
+
/** Frames' worth of measured frame time black must persist for. Default 40. */
|
|
99
|
+
readonly blackFramesBudget?: number;
|
|
100
|
+
/** Rendered frames required after becoming ready before judging. Default 30. */
|
|
101
|
+
readonly minFramesAfterReady?: number;
|
|
102
|
+
/** Judge every Nth frame. Default 4. */
|
|
103
|
+
readonly sampleEvery?: number;
|
|
104
|
+
/** Consecutive black samples required. Default 12. */
|
|
105
|
+
readonly samplesNeeded?: number;
|
|
34
106
|
}
|
|
35
107
|
export interface BlackFrameWatch {
|
|
36
|
-
/**
|
|
37
|
-
|
|
108
|
+
/**
|
|
109
|
+
* Call right after a frame was drawn, in the same task (before the browser composites it). Pass the canvas that was just
|
|
110
|
+
* drawn when it is known (the frame tap does); a number (a frame counter) is accepted and ignored for compatibility.
|
|
111
|
+
*/
|
|
112
|
+
sample(drawn?: HTMLCanvasElement | number): void;
|
|
38
113
|
readonly stage: number;
|
|
39
114
|
readonly rung: string;
|
|
40
115
|
/** True once the watch decided to reload one rung down. */
|
|
41
116
|
readonly escalated: boolean;
|
|
117
|
+
/** What the watch has seen so far (also why the previous page reloaded, if it did). */
|
|
118
|
+
observation(): WatchObservation;
|
|
42
119
|
}
|
|
43
|
-
export declare function createBlackFrameWatch(canvas: HTMLCanvasElement, options: BlackFrameWatchOptions): BlackFrameWatch;
|
|
120
|
+
export declare function createBlackFrameWatch(canvas: HTMLCanvasElement | (() => HTMLCanvasElement | null | undefined), options: BlackFrameWatchOptions): BlackFrameWatch;
|
|
44
121
|
export {};
|
|
45
122
|
//# sourceMappingURL=blackFrame.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blackFrame.d.ts","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/blackFrame.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"blackFrame.d.ts","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/blackFrame.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,9 +7,14 @@ export const DEFAULT_HEAL_LADDER = [
|
|
|
7
7
|
{ name: "low-quality", params: { quality: "low", sky: "1" } }
|
|
8
8
|
];
|
|
9
9
|
export const DEFAULT_HEAL_STORAGE_KEY = "aura3d-safety-heal-stage";
|
|
10
|
-
const DEFAULT_FRAMES_NEEDED = 45;
|
|
11
10
|
const BLACK_MAX_CHANNEL = 4;
|
|
12
|
-
|
|
11
|
+
/** Nearest-neighbour probe grid: one texel per block, so thin bright features are not averaged away. */
|
|
12
|
+
const PROBE_WIDTH = 48;
|
|
13
|
+
const PROBE_HEIGHT = 32;
|
|
14
|
+
/** "Nearly all" black: at most this fraction of grid samples may be lit (a few stray texels of a HUD drawn into the canvas). */
|
|
15
|
+
const MAX_LIT_FRACTION = 0.002;
|
|
16
|
+
const LOADING_SELECTOR = '#boot, .boot, #loading, #loader, #loading-screen, .loading, .loader, [data-loading="true"], [aria-busy="true"], [id*="loading" i], [class*="loading" i]';
|
|
17
|
+
const HIDDEN_CLASSES = ["hidden", "done", "is-hidden", "loaded", "ready", "fade-out"];
|
|
13
18
|
function safeStorage() {
|
|
14
19
|
try {
|
|
15
20
|
return globalThis.sessionStorage;
|
|
@@ -33,76 +38,288 @@ export function healParams(stage, ladder = DEFAULT_HEAL_LADDER) {
|
|
|
33
38
|
export function healRungName(stage, ladder = DEFAULT_HEAL_LADDER) {
|
|
34
39
|
return stage <= 0 ? "full" : ladder[Math.min(stage, ladder.length) - 1].name;
|
|
35
40
|
}
|
|
36
|
-
/**
|
|
37
|
-
export function
|
|
41
|
+
/** Statistics of a downscaled RGBA probe of the canvas. */
|
|
42
|
+
export function analyseFrame(rgba, maxChannel = BLACK_MAX_CHANNEL) {
|
|
43
|
+
let samples = 0;
|
|
44
|
+
let lit = 0;
|
|
45
|
+
let max = 0;
|
|
46
|
+
let sum = 0;
|
|
47
|
+
for (let i = 0; i + 2 < rgba.length; i += 4) {
|
|
48
|
+
const r = rgba[i];
|
|
49
|
+
const g = rgba[i + 1];
|
|
50
|
+
const b = rgba[i + 2];
|
|
51
|
+
samples += 1;
|
|
52
|
+
sum += r + g + b;
|
|
53
|
+
const peak = Math.max(r, g, b);
|
|
54
|
+
if (peak > max)
|
|
55
|
+
max = peak;
|
|
56
|
+
if (peak > maxChannel)
|
|
57
|
+
lit += 1;
|
|
58
|
+
}
|
|
59
|
+
return { samples, lit, litFraction: samples === 0 ? 1 : lit / samples, max, mean: samples === 0 ? 0 : sum / (samples * 3) };
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* True when the sampled frame is black: every texel by default; pass a small `maxLitFraction` to tolerate a few stray lit
|
|
63
|
+
* texels (for example a HUD drawn into the same canvas). Empty input is never black.
|
|
64
|
+
*/
|
|
65
|
+
export function isBlackFrame(rgba, maxLitFraction = 0) {
|
|
38
66
|
if (rgba.length < 4)
|
|
39
67
|
return false;
|
|
40
|
-
|
|
41
|
-
|
|
68
|
+
return analyseFrame(rgba).litFraction <= maxLitFraction;
|
|
69
|
+
}
|
|
70
|
+
function elementVisible(element) {
|
|
71
|
+
const node = element;
|
|
72
|
+
if (node.hidden === true)
|
|
73
|
+
return false;
|
|
74
|
+
const classes = node.classList;
|
|
75
|
+
if (classes && HIDDEN_CLASSES.some((name) => classes.contains(name)))
|
|
76
|
+
return false;
|
|
77
|
+
if (typeof getComputedStyle === "function") {
|
|
78
|
+
try {
|
|
79
|
+
const style = getComputedStyle(node);
|
|
80
|
+
if (style.display === "none" || style.visibility === "hidden" || Number(style.opacity) < 0.02)
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
/* detached or stubbed element: treat as visible */
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (typeof node.getBoundingClientRect === "function") {
|
|
88
|
+
const box = node.getBoundingClientRect();
|
|
89
|
+
if (box.width <= 0 || box.height <= 0)
|
|
42
90
|
return false;
|
|
43
91
|
}
|
|
44
92
|
return true;
|
|
45
93
|
}
|
|
94
|
+
/** True while a visible loading overlay is on the page (`#boot`, `#loading`, `.loading`, `[aria-busy=true]` ...). */
|
|
95
|
+
export function hasVisibleLoadingOverlay(root = typeof document === "undefined" ? undefined : document) {
|
|
96
|
+
if (!root || typeof root.querySelectorAll !== "function")
|
|
97
|
+
return false;
|
|
98
|
+
try {
|
|
99
|
+
return Array.from(root.querySelectorAll(LOADING_SELECTOR)).some(elementVisible);
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/** Default readiness: document fully loaded, no asset fetches in flight, no visible loading overlay. */
|
|
106
|
+
export function defaultIsReady() {
|
|
107
|
+
if (typeof document !== "undefined" && document.readyState && document.readyState !== "complete")
|
|
108
|
+
return false;
|
|
109
|
+
const inflight = globalThis.__aura3dInFlightByteFetches;
|
|
110
|
+
if (typeof inflight === "number" && inflight > 0)
|
|
111
|
+
return false;
|
|
112
|
+
return !hasVisibleLoadingOverlay();
|
|
113
|
+
}
|
|
114
|
+
/** Largest canvas big enough to be the world view, ignoring minimap/HUD/overlay canvases. */
|
|
115
|
+
export function findWorldCanvas(root = typeof document === "undefined" ? undefined : document) {
|
|
116
|
+
if (!root || typeof root.querySelectorAll !== "function")
|
|
117
|
+
return null;
|
|
118
|
+
let best = null;
|
|
119
|
+
let area = 0;
|
|
120
|
+
for (const canvas of Array.from(root.querySelectorAll("canvas"))) {
|
|
121
|
+
const label = `${canvas.id ?? ""} ${canvas.className ?? ""}`;
|
|
122
|
+
if (/minimap|mini-map|hud|overlay|compass|radar|(^|[\s_-])ui([\s_-]|$)/i.test(label))
|
|
123
|
+
continue;
|
|
124
|
+
const a = canvas.width * canvas.height;
|
|
125
|
+
if (canvas.width >= 128 && canvas.height >= 96 && a > area) {
|
|
126
|
+
best = canvas;
|
|
127
|
+
area = a;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return best;
|
|
131
|
+
}
|
|
46
132
|
function defaultProbe() {
|
|
47
133
|
let ctx;
|
|
48
134
|
return (canvas) => {
|
|
49
135
|
if (ctx === undefined) {
|
|
50
136
|
const probe = document.createElement("canvas");
|
|
51
|
-
probe.width =
|
|
52
|
-
probe.height =
|
|
137
|
+
probe.width = PROBE_WIDTH;
|
|
138
|
+
probe.height = PROBE_HEIGHT;
|
|
53
139
|
ctx = probe.getContext("2d", { willReadFrequently: true });
|
|
140
|
+
if (ctx)
|
|
141
|
+
ctx.imageSmoothingEnabled = false;
|
|
54
142
|
}
|
|
55
143
|
if (!ctx)
|
|
56
144
|
return undefined;
|
|
57
|
-
ctx.drawImage(canvas, 0, 0,
|
|
58
|
-
return ctx.getImageData(0, 0,
|
|
145
|
+
ctx.drawImage(canvas, 0, 0, PROBE_WIDTH, PROBE_HEIGHT);
|
|
146
|
+
return ctx.getImageData(0, 0, PROBE_WIDTH, PROBE_HEIGHT).data;
|
|
59
147
|
};
|
|
60
148
|
}
|
|
149
|
+
function median(values) {
|
|
150
|
+
if (values.length === 0)
|
|
151
|
+
return 0;
|
|
152
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
153
|
+
return sorted[Math.floor(sorted.length / 2)];
|
|
154
|
+
}
|
|
61
155
|
export function createBlackFrameWatch(canvas, options) {
|
|
62
156
|
const ladder = options.ladder ?? DEFAULT_HEAL_LADDER;
|
|
63
157
|
const storageKey = options.storageKey ?? DEFAULT_HEAL_STORAGE_KEY;
|
|
158
|
+
const reasonKey = `${storageKey}:reason`;
|
|
64
159
|
const storage = options.storage ?? safeStorage();
|
|
65
|
-
const
|
|
66
|
-
const
|
|
160
|
+
const fast = options.fastFrames !== undefined;
|
|
161
|
+
const minFramesAfterReady = options.minFramesAfterReady ?? options.fastFrames ?? 30;
|
|
162
|
+
const sampleEvery = Math.max(1, options.sampleEvery ?? (fast ? 2 : 4));
|
|
163
|
+
const samplesNeeded = Math.max(2, options.samplesNeeded ?? (fast ? Math.ceil(options.fastFrames / 2) : 12));
|
|
164
|
+
const minBlackMs = options.minBlackMs ?? (fast ? 0 : 4000);
|
|
165
|
+
const blackFramesBudget = options.blackFramesBudget ?? (fast ? 0 : 40);
|
|
67
166
|
const stage = healStage(storage, ladder, storageKey);
|
|
68
167
|
const readProbe = options.readProbe ?? defaultProbe();
|
|
69
168
|
const log = options.log ?? ((code, message) => console.warn(`${code}: ${message}`));
|
|
70
169
|
const currentUrl = options.currentUrl ?? (() => location.href);
|
|
71
170
|
const navigate = options.navigate ?? ((url) => location.replace(url));
|
|
171
|
+
const now = options.now ?? (() => performance.now());
|
|
172
|
+
const isHidden = options.isHidden ?? (() => typeof document !== "undefined" && (document.hidden === true || document.visibilityState === "hidden"));
|
|
173
|
+
const appReady = options.isReady;
|
|
174
|
+
const previousReason = (() => {
|
|
175
|
+
try {
|
|
176
|
+
return storage?.getItem(reasonKey) ?? undefined;
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
return undefined;
|
|
180
|
+
}
|
|
181
|
+
})();
|
|
182
|
+
let calls = 0;
|
|
183
|
+
let readyAtCall = null;
|
|
184
|
+
let samples = 0;
|
|
185
|
+
let blackSamples = 0;
|
|
72
186
|
let consecutive = 0;
|
|
187
|
+
let litStreak = 0;
|
|
188
|
+
let healthy = false;
|
|
189
|
+
let blackSince = 0;
|
|
73
190
|
let escalated = false;
|
|
191
|
+
let lastStats;
|
|
192
|
+
let lastTime;
|
|
193
|
+
let reason = previousReason;
|
|
194
|
+
const deltas = [];
|
|
195
|
+
const skipped = { notReady: 0, noDrawCalls: 0, hidden: 0 };
|
|
74
196
|
if (stage > 0)
|
|
75
|
-
log("SAFETY_COMPAT_MODE", `rung ${stage} (${healRungName(stage, ladder)}) after a black frame was detected`);
|
|
197
|
+
log("SAFETY_COMPAT_MODE", `rung ${stage} (${healRungName(stage, ladder)}) after a black frame was detected${previousReason ? `: ${previousReason}` : ""}`);
|
|
198
|
+
const resetStreak = () => {
|
|
199
|
+
consecutive = 0;
|
|
200
|
+
blackSince = 0;
|
|
201
|
+
};
|
|
76
202
|
return {
|
|
77
203
|
stage,
|
|
78
204
|
rung: healRungName(stage, ladder),
|
|
79
205
|
get escalated() {
|
|
80
206
|
return escalated;
|
|
81
207
|
},
|
|
82
|
-
|
|
83
|
-
|
|
208
|
+
observation() {
|
|
209
|
+
const t = lastTime ?? 0;
|
|
210
|
+
return {
|
|
211
|
+
calls,
|
|
212
|
+
readyAtCall,
|
|
213
|
+
framesSinceReady: readyAtCall === null ? 0 : calls - readyAtCall + 1,
|
|
214
|
+
samples,
|
|
215
|
+
blackSamples,
|
|
216
|
+
consecutiveBlack: consecutive,
|
|
217
|
+
healthy,
|
|
218
|
+
lastStats,
|
|
219
|
+
medianFrameMs: median(deltas),
|
|
220
|
+
blackMs: blackSince ? Math.max(0, t - blackSince) : 0,
|
|
221
|
+
skipped: { ...skipped },
|
|
222
|
+
escalated,
|
|
223
|
+
reason
|
|
224
|
+
};
|
|
225
|
+
},
|
|
226
|
+
sample(drawn) {
|
|
227
|
+
const t = now();
|
|
228
|
+
if (lastTime !== undefined && t >= lastTime) {
|
|
229
|
+
deltas.push(t - lastTime);
|
|
230
|
+
if (deltas.length > 31)
|
|
231
|
+
deltas.shift();
|
|
232
|
+
}
|
|
233
|
+
lastTime = t;
|
|
234
|
+
calls += 1;
|
|
235
|
+
if (!options.enabled || escalated)
|
|
236
|
+
return;
|
|
237
|
+
if (isHidden()) {
|
|
238
|
+
skipped.hidden += 1;
|
|
239
|
+
resetStreak();
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
let ready = (appReady ? appReady() : true) && defaultIsReady();
|
|
243
|
+
if (!ready) {
|
|
244
|
+
skipped.notReady += 1;
|
|
245
|
+
readyAtCall = null;
|
|
246
|
+
healthy = false;
|
|
247
|
+
litStreak = 0;
|
|
248
|
+
resetStreak();
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
if (readyAtCall === null)
|
|
252
|
+
readyAtCall = calls;
|
|
253
|
+
ready = true;
|
|
254
|
+
const since = calls - readyAtCall + 1;
|
|
255
|
+
const every = healthy ? sampleEvery * 8 : sampleEvery;
|
|
256
|
+
if (since < minFramesAfterReady || since % every !== 0)
|
|
257
|
+
return;
|
|
258
|
+
const drawCalls = options.getDrawCalls?.();
|
|
259
|
+
if (drawCalls !== undefined && !(drawCalls > 0)) {
|
|
260
|
+
skipped.noDrawCalls += 1;
|
|
261
|
+
resetStreak();
|
|
84
262
|
return;
|
|
85
|
-
|
|
263
|
+
}
|
|
264
|
+
const target = drawn !== undefined && typeof drawn === "object" ? drawn : typeof canvas === "function" ? canvas() : canvas;
|
|
265
|
+
if (!target)
|
|
266
|
+
return;
|
|
267
|
+
let stats;
|
|
86
268
|
try {
|
|
87
|
-
const data = readProbe(
|
|
269
|
+
const data = readProbe(target);
|
|
88
270
|
if (!data)
|
|
89
271
|
return;
|
|
90
|
-
|
|
272
|
+
stats = analyseFrame(data);
|
|
91
273
|
}
|
|
92
274
|
catch {
|
|
93
275
|
return;
|
|
94
276
|
}
|
|
95
|
-
|
|
96
|
-
|
|
277
|
+
lastStats = stats;
|
|
278
|
+
samples += 1;
|
|
279
|
+
const black = stats.samples > 0 && stats.litFraction <= MAX_LIT_FRACTION;
|
|
280
|
+
if (!black) {
|
|
281
|
+
litStreak += 1;
|
|
282
|
+
resetStreak();
|
|
283
|
+
if (litStreak >= 3)
|
|
284
|
+
healthy = true;
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
litStreak = 0;
|
|
288
|
+
blackSamples += 1;
|
|
289
|
+
consecutive += 1;
|
|
290
|
+
if (blackSince === 0)
|
|
291
|
+
blackSince = t;
|
|
292
|
+
const medianFrameMs = median(deltas);
|
|
293
|
+
const windowMs = Math.max(minBlackMs, medianFrameMs * blackFramesBudget);
|
|
294
|
+
if (consecutive < samplesNeeded || t - blackSince < windowMs || stage >= ladder.length)
|
|
97
295
|
return;
|
|
98
296
|
escalated = true;
|
|
99
|
-
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
297
|
+
reason = `black for ${consecutive} samples / ${Math.round(t - blackSince)} ms after ${since} ready frames (lit ${stats.lit}/${stats.samples}, max channel ${stats.max}, median frame ${Math.round(medianFrameMs)} ms, drawCalls ${drawCalls ?? "n/a"})`;
|
|
298
|
+
const href = currentUrl();
|
|
299
|
+
let next;
|
|
300
|
+
if (options.buildUrl) {
|
|
301
|
+
next = options.buildUrl(stage + 1, href);
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
const url = new URL(href);
|
|
305
|
+
for (const [key, value] of Object.entries(healParams(stage + 1, ladder)))
|
|
306
|
+
if (!url.searchParams.has(key))
|
|
307
|
+
url.searchParams.set(key, value);
|
|
308
|
+
next = url.toString();
|
|
309
|
+
}
|
|
310
|
+
if (!next) {
|
|
311
|
+
escalated = false;
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
try {
|
|
315
|
+
storage?.setItem(storageKey, String(stage + 1));
|
|
316
|
+
storage?.setItem(reasonKey, reason);
|
|
317
|
+
}
|
|
318
|
+
catch {
|
|
319
|
+
/* storage unavailable: the reload still happens, the rung just cannot continue */
|
|
320
|
+
}
|
|
321
|
+
log("SAFETY_BLACK_FRAME", `reloading at rung ${stage + 1} (${healRungName(stage + 1, ladder)}): ${reason}`);
|
|
322
|
+
navigate(next);
|
|
106
323
|
}
|
|
107
324
|
};
|
|
108
325
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blackFrame.js","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/blackFrame.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,MAAM,mBAAmB,GAAwB;IACtD,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE;IACtC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;IAC1C,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE;IAC7C,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IACxC,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE;IAC9C,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;CAC9D,CAAC;AAEF,MAAM,CAAC,MAAM,wBAAwB,GAAG,0BAA0B,CAAC;AACnE,MAAM,qBAAqB,GAAG,EAAE,CAAC;AACjC,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAC5B,MAAM,UAAU,GAAG,EAAE,CAAC;AAItB,SAAS,WAAW;IAClB,IAAI,CAAC;QACH,OAAO,UAAU,CAAC,cAAc,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,SAAS,CACvB,UAAgD,WAAW,EAAE,EAC7D,SAA8B,mBAAmB,EACjD,aAAqB,wBAAwB;IAE7C,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,IAAI,GAAG,CAAC,CAAC;IACxD,OAAO,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7E,CAAC;AAED,wHAAwH;AACxH,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,SAA8B,mBAAmB;IACzF,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3F,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAa,EAAE,SAA8B,mBAAmB;IAC3F,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAE,CAAC,IAAI,CAAC;AAChF,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,YAAY,CAAC,IAAuB;IAClD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5C,IAAI,IAAI,CAAC,CAAC,CAAE,GAAG,iBAAiB,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAE,GAAG,iBAAiB,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAE,GAAG,iBAAiB;YAAE,OAAO,KAAK,CAAC;IACzH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AA0BD,SAAS,YAAY;IACnB,IAAI,GAAgD,CAAC;IACrD,OAAO,CAAC,MAAM,EAAE,EAAE;QAChB,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YAC/C,KAAK,CAAC,KAAK,GAAG,UAAU,CAAC;YACzB,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC;YAC1B,GAAG,GAAG,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,CAAC;QACD,IAAI,CAAC,GAAG;YAAE,OAAO,SAAS,CAAC;QAC3B,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;QACpD,OAAO,GAAG,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC;IAC7D,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,MAAyB,EAAE,OAA+B;IAC9F,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,mBAAmB,CAAC;IACrD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,wBAAwB,CAAC;IAClE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,WAAW,EAAE,CAAC;IACjD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC;IAC3C,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,UAAU,IAAI,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAChG,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;IACrD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,YAAY,EAAE,CAAC;IACtD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC;IACpF,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC/D,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9E,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,IAAI,KAAK,GAAG,CAAC;QAAE,GAAG,CAAC,oBAAoB,EAAE,QAAQ,KAAK,KAAK,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,oCAAoC,CAAC,CAAC;IAC5H,OAAO;QACL,KAAK;QACL,IAAI,EAAE,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC;QACjC,IAAI,SAAS;YACX,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,CAAC,WAAmB;YACxB,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,SAAS,IAAI,WAAW,GAAG,SAAS,IAAI,WAAW,GAAG,CAAC,KAAK,CAAC;gBAAE,OAAO;YAC9F,IAAI,KAAc,CAAC;YACnB,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;gBAC/B,IAAI,CAAC,IAAI;oBAAE,OAAO;gBAClB,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;YAC7B,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO;YACT,CAAC;YACD,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1C,IAAI,WAAW,GAAG,aAAa,IAAI,KAAK,IAAI,MAAM,CAAC,MAAM;gBAAE,OAAO;YAClE,SAAS,GAAG,IAAI,CAAC;YACjB,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;YAChD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;YAClC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;gBAAE,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC;oBAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YAC3I,GAAG,CAAC,oBAAoB,EAAE,qBAAqB,KAAK,GAAG,CAAC,KAAK,YAAY,CAAC,KAAK,GAAG,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;YACjG,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC3B,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"blackFrame.js","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/blackFrame.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,6 +4,22 @@
|
|
|
4
4
|
* bug reports ("open the page with ?diag=1 and send a screenshot"). Nothing is installed until the function is called,
|
|
5
5
|
* and `dispose()` restores every patched browser prototype and console method.
|
|
6
6
|
*/
|
|
7
|
+
/** Subset of the engine's `diagnostics().shaderFailures` records the panel prints. */
|
|
8
|
+
export interface ShaderFailureLike {
|
|
9
|
+
readonly code?: string;
|
|
10
|
+
readonly material?: string;
|
|
11
|
+
readonly stage?: string;
|
|
12
|
+
readonly message?: string;
|
|
13
|
+
readonly locations?: readonly {
|
|
14
|
+
readonly line?: number;
|
|
15
|
+
readonly authoredLine?: number;
|
|
16
|
+
readonly message?: string;
|
|
17
|
+
readonly window?: readonly {
|
|
18
|
+
readonly text?: string;
|
|
19
|
+
readonly error?: boolean;
|
|
20
|
+
}[];
|
|
21
|
+
}[];
|
|
22
|
+
}
|
|
7
23
|
export interface DiagnosticsAppLike {
|
|
8
24
|
/** `AuraApp.diagnostics()` shape; only these members are read. */
|
|
9
25
|
diagnostics?(): {
|
|
@@ -12,6 +28,7 @@ export interface DiagnosticsAppLike {
|
|
|
12
28
|
readonly fps?: unknown;
|
|
13
29
|
readonly warnings?: readonly string[];
|
|
14
30
|
readonly errors?: readonly string[];
|
|
31
|
+
readonly shaderFailures?: readonly ShaderFailureLike[];
|
|
15
32
|
} | undefined;
|
|
16
33
|
}
|
|
17
34
|
export interface DiagnosticsPanelOptions {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnosticsPanel.d.ts","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/diagnosticsPanel.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,kEAAkE;IAClE,WAAW,CAAC,IAAI;QAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"diagnosticsPanel.d.ts","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/diagnosticsPanel.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,sFAAsF;AACtF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS;YAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;SAAE,EAAE,CAAA;KAAE,EAAE,CAAC;CAC1M;AAED,MAAM,WAAW,kBAAkB;IACjC,kEAAkE;IAClE,WAAW,CAAC,IAAI;QAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAA;KAAE,GAAG,SAAS,CAAC;CACtP;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,GAAG,CAAC,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,mGAAmG;IACnG,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,SAAS,MAAM,EAAE,CAAC;IAC9C,2BAA2B;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,OAAO,IAAI,IAAI,CAAC;IAChB,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAID,wBAAgB,QAAQ,IAAI,QAAQ,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAehE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,QAAQ,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAGnF;AAED,wFAAwF;AACxF,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,kBAAkB,GAAG,SAAS,EAAE,QAAQ,EAAE,aAAa,CAAC;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,MAAM,CAsBnM;AAED,wBAAgB,uBAAuB,CAAC,OAAO,GAAE,uBAA4B,GAAG,sBAAsB,CAsErG"}
|
|
@@ -38,6 +38,12 @@ export function formatEngineSection(app, canvases) {
|
|
|
38
38
|
parts.push(`warn:${String(warning).slice(0, 80)}`);
|
|
39
39
|
for (const error of (report.errors ?? []).slice(0, 3))
|
|
40
40
|
parts.push(`error:${String(error).slice(0, 80)}`);
|
|
41
|
+
for (const failure of (report.shaderFailures ?? []).slice(0, 2)) {
|
|
42
|
+
const first = failure.locations?.[0];
|
|
43
|
+
const offending = first?.window?.find((row) => row.error)?.text?.trim();
|
|
44
|
+
const where = first ? ` ${failure.stage ?? ""} line ${first.line}${first.authoredLine !== undefined ? ` (source line ${first.authoredLine})` : ""}` : ` ${failure.stage ?? ""}`;
|
|
45
|
+
parts.push(`\nSHADER ${failure.code ?? "FAILED"} "${failure.material ?? "?"}"${where}: ${String(first?.message ?? failure.message ?? "").slice(0, 100)}${offending ? ` >> ${offending.slice(0, 100)}` : ""}`);
|
|
46
|
+
}
|
|
41
47
|
}
|
|
42
48
|
}
|
|
43
49
|
catch {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnosticsPanel.js","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/diagnosticsPanel.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"diagnosticsPanel.js","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/diagnosticsPanel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface FrameTapOptions {
|
|
2
|
+
/** Called once per task in which the default framebuffer of a sufficiently large canvas was drawn, after the draw code returned. */
|
|
3
|
+
readonly onFrame: (canvas: HTMLCanvasElement) => void;
|
|
4
|
+
/** Prototypes to wrap. Defaults to `WebGL2RenderingContext.prototype` and `WebGLRenderingContext.prototype`. */
|
|
5
|
+
readonly prototypes?: readonly object[];
|
|
6
|
+
/** Schedules `fn` after the current call stack unwinds and before compositing. Defaults to `queueMicrotask`. */
|
|
7
|
+
readonly enqueue?: (fn: () => void) => void;
|
|
8
|
+
/** Canvases smaller than this are never reported (minimaps, HUD widgets, probe canvases). Defaults 128 x 96. */
|
|
9
|
+
readonly minWidth?: number;
|
|
10
|
+
readonly minHeight?: number;
|
|
11
|
+
}
|
|
12
|
+
export interface FrameTap {
|
|
13
|
+
/** Draw calls to the default framebuffer seen so far, summed over every canvas. */
|
|
14
|
+
drawCalls(): number;
|
|
15
|
+
/** Tasks that were reported through `onFrame` so far. */
|
|
16
|
+
frames(): number;
|
|
17
|
+
/** The reported canvas with the largest area (the world view), or undefined before any frame. */
|
|
18
|
+
worldCanvas(): HTMLCanvasElement | undefined;
|
|
19
|
+
/** Restores every wrapped method. */
|
|
20
|
+
dispose(): void;
|
|
21
|
+
}
|
|
22
|
+
export declare function installFrameTap(options: FrameTapOptions): FrameTap;
|
|
23
|
+
//# sourceMappingURL=frameTap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frameTap.d.ts","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/frameTap.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,eAAe;IAC9B,oIAAoI;IACpI,QAAQ,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACtD,gHAAgH;IAChH,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,gHAAgH;IAChH,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IAC5C,gHAAgH;IAChH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,QAAQ;IACvB,mFAAmF;IACnF,SAAS,IAAI,MAAM,CAAC;IACpB,yDAAyD;IACzD,MAAM,IAAI,MAAM,CAAC;IACjB,iGAAiG;IACjG,WAAW,IAAI,iBAAiB,GAAG,SAAS,CAAC;IAC7C,qCAAqC;IACrC,OAAO,IAAI,IAAI,CAAC;CACjB;AAUD,wBAAgB,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,QAAQ,CAkGlE"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frame tap: tells the black-frame guard when a WebGL canvas has just been drawn to, in the same task as the draw.
|
|
3
|
+
*
|
|
4
|
+
* A WebGL canvas created without `preserveDrawingBuffer` only holds its pixels until the browser composites the frame; read
|
|
5
|
+
* it from a different task (for example an unrelated `requestAnimationFrame` callback that runs before the app draws) and it
|
|
6
|
+
* returns zeros, so a healthy game looks black. The tap wraps the GL draw calls (`drawArrays`, `drawElements`, the instanced
|
|
7
|
+
* and multi-draw forms) and, for the first draw to the default framebuffer in a task, queues a microtask. The microtask runs
|
|
8
|
+
* after the drawing code returns and before the browser composites, so a read in `onFrame` sees the finished frame. Draws to
|
|
9
|
+
* an offscreen framebuffer do not count, so a render-to-texture pass never triggers a read of an empty canvas.
|
|
10
|
+
*
|
|
11
|
+
* The tap never renders, never changes context attributes and adds one array lookup per draw call.
|
|
12
|
+
*/
|
|
13
|
+
const DRAW_METHODS = ["drawArrays", "drawElements", "drawArraysInstanced", "drawElementsInstanced", "drawRangeElements"];
|
|
14
|
+
const MULTI_DRAW_METHODS = ["multiDrawArraysWEBGL", "multiDrawElementsWEBGL", "multiDrawArraysInstancedWEBGL", "multiDrawElementsInstancedWEBGL"];
|
|
15
|
+
const GL_FRAMEBUFFER = 0x8d40;
|
|
16
|
+
const GL_DRAW_FRAMEBUFFER = 0x8ca9;
|
|
17
|
+
function isElementCanvas(value) {
|
|
18
|
+
return typeof HTMLCanvasElement !== "undefined" ? value instanceof HTMLCanvasElement : typeof value === "object" && value !== null && typeof value.width === "number";
|
|
19
|
+
}
|
|
20
|
+
export function installFrameTap(options) {
|
|
21
|
+
const prototypes = options.prototypes ??
|
|
22
|
+
[typeof WebGL2RenderingContext !== "undefined" ? WebGL2RenderingContext.prototype : undefined, typeof WebGLRenderingContext !== "undefined" ? WebGLRenderingContext.prototype : undefined].filter(Boolean);
|
|
23
|
+
const enqueue = options.enqueue ?? ((fn) => queueMicrotask(fn));
|
|
24
|
+
const minWidth = options.minWidth ?? 128;
|
|
25
|
+
const minHeight = options.minHeight ?? 96;
|
|
26
|
+
const restores = [];
|
|
27
|
+
const drawFramebuffer = new WeakMap();
|
|
28
|
+
const states = new WeakMap();
|
|
29
|
+
const wrappedExtensions = new WeakSet();
|
|
30
|
+
let draws = 0;
|
|
31
|
+
let frames = 0;
|
|
32
|
+
let world;
|
|
33
|
+
const noteDraw = (gl) => {
|
|
34
|
+
if (drawFramebuffer.get(gl) != null)
|
|
35
|
+
return;
|
|
36
|
+
const canvas = gl.canvas;
|
|
37
|
+
if (!isElementCanvas(canvas))
|
|
38
|
+
return;
|
|
39
|
+
draws += 1;
|
|
40
|
+
let state = states.get(canvas);
|
|
41
|
+
if (!state) {
|
|
42
|
+
state = { pending: false };
|
|
43
|
+
states.set(canvas, state);
|
|
44
|
+
}
|
|
45
|
+
if (state.pending)
|
|
46
|
+
return;
|
|
47
|
+
state.pending = true;
|
|
48
|
+
const st = state;
|
|
49
|
+
enqueue(() => {
|
|
50
|
+
st.pending = false;
|
|
51
|
+
if (canvas.width < minWidth || canvas.height < minHeight)
|
|
52
|
+
return;
|
|
53
|
+
if (!world || canvas.width * canvas.height >= world.width * world.height)
|
|
54
|
+
world = canvas;
|
|
55
|
+
frames += 1;
|
|
56
|
+
try {
|
|
57
|
+
options.onFrame(canvas);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
/* a failing observer must never break the page */
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
for (const proto of prototypes) {
|
|
65
|
+
const target = proto;
|
|
66
|
+
for (const name of DRAW_METHODS) {
|
|
67
|
+
const original = target[name];
|
|
68
|
+
if (typeof original !== "function")
|
|
69
|
+
continue;
|
|
70
|
+
target[name] = function (...args) {
|
|
71
|
+
const result = original.apply(this, args);
|
|
72
|
+
noteDraw(this);
|
|
73
|
+
return result;
|
|
74
|
+
};
|
|
75
|
+
restores.push(() => {
|
|
76
|
+
target[name] = original;
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
const bind = target.bindFramebuffer;
|
|
80
|
+
if (typeof bind === "function") {
|
|
81
|
+
target.bindFramebuffer = function (glTarget, framebuffer) {
|
|
82
|
+
if (glTarget === GL_FRAMEBUFFER || glTarget === GL_DRAW_FRAMEBUFFER)
|
|
83
|
+
drawFramebuffer.set(this, framebuffer);
|
|
84
|
+
return bind.call(this, glTarget, framebuffer);
|
|
85
|
+
};
|
|
86
|
+
restores.push(() => {
|
|
87
|
+
target.bindFramebuffer = bind;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
const getExtension = target.getExtension;
|
|
91
|
+
if (typeof getExtension === "function") {
|
|
92
|
+
target.getExtension = function (name) {
|
|
93
|
+
const extension = getExtension.call(this, name);
|
|
94
|
+
if (extension && typeof name === "string" && /multi_draw/i.test(name) && !wrappedExtensions.has(extension)) {
|
|
95
|
+
wrappedExtensions.add(extension);
|
|
96
|
+
const gl = this;
|
|
97
|
+
for (const method of MULTI_DRAW_METHODS) {
|
|
98
|
+
const original = extension[method];
|
|
99
|
+
if (typeof original !== "function")
|
|
100
|
+
continue;
|
|
101
|
+
extension[method] = function (...args) {
|
|
102
|
+
const result = original.apply(this, args);
|
|
103
|
+
noteDraw(gl);
|
|
104
|
+
return result;
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return extension;
|
|
109
|
+
};
|
|
110
|
+
restores.push(() => {
|
|
111
|
+
target.getExtension = getExtension;
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
drawCalls: () => draws,
|
|
117
|
+
frames: () => frames,
|
|
118
|
+
worldCanvas: () => world,
|
|
119
|
+
dispose() {
|
|
120
|
+
for (const restore of restores.splice(0))
|
|
121
|
+
restore();
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=frameTap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frameTap.js","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/frameTap.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { createBlackFrameWatch, type BlackFrameWatch, type WatchObservation } from "./blackFrame.js";
|
|
2
|
+
/**
|
|
3
|
+
* Black-frame guard for pages that run on the engine's `a3d-qr` URL flag list (the showcase games). It installs once,
|
|
4
|
+
* before the app starts drawing. By default it taps the WebGL draw calls (`installFrameTap`) so the world canvas is
|
|
5
|
+
* sampled in the same task that drew it, before the browser composites: a canvas without `preserveDrawingBuffer` reads as
|
|
6
|
+
* zeros anywhere else, which is how an earlier version reloaded healthy games. It reloads one rung down when the canvas
|
|
7
|
+
* stays black. It is a thin shell around `createBlackFrameWatch`: readiness gating, black-versus-dark detection,
|
|
8
|
+
* once-per-load stepping and the recorded reason all live there.
|
|
9
|
+
*
|
|
10
|
+
* `?heal=0` disables it; an `a3d-qr` supplied in the URL by the author or player is never rewritten.
|
|
11
|
+
*/
|
|
12
|
+
export declare const QR_HEAL_LADDER: ReadonlyArray<{
|
|
13
|
+
readonly name: string;
|
|
14
|
+
readonly qr: string;
|
|
15
|
+
}>;
|
|
16
|
+
/** Rung currently applied (0 = full quality) from the stored value. */
|
|
17
|
+
export declare function qrHealStage(raw: string | null | undefined): number;
|
|
18
|
+
export declare const qrHealRungName: (stage: number) => string;
|
|
19
|
+
/**
|
|
20
|
+
* URL for rung `stage`, or `null` when the ladder is exhausted or an author/player supplied their own `a3d-qr`.
|
|
21
|
+
* `ownsQr` is true when the `a3d-qr` already in the URL was written by an earlier rung of this guard.
|
|
22
|
+
*/
|
|
23
|
+
export declare function qrHealUrl(href: string, stage: number, ownsQr?: boolean): string | null;
|
|
24
|
+
export interface HealGlobal {
|
|
25
|
+
rung: number;
|
|
26
|
+
name: string;
|
|
27
|
+
enabled: boolean;
|
|
28
|
+
/** Live view of what the watch has seen (frames, samples, last probe stats, skips) and why a reload happened. */
|
|
29
|
+
observation?: () => WatchObservation;
|
|
30
|
+
}
|
|
31
|
+
declare global {
|
|
32
|
+
interface Window {
|
|
33
|
+
__AURA3D_HEAL__?: HealGlobal;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export interface BlackFrameGuardOptions {
|
|
37
|
+
/** Defaults to true unless the URL has `heal=0`. */
|
|
38
|
+
readonly enabled?: boolean;
|
|
39
|
+
/** Tests only: shorter detection window. */
|
|
40
|
+
readonly fast?: boolean;
|
|
41
|
+
/** Extra readiness signal, for example the app's own `ready` flag. Combined with the built-in overlay/load/fetch checks. */
|
|
42
|
+
readonly isReady?: () => boolean;
|
|
43
|
+
/** Engine draw calls for the current frame; when given and not > 0 the frame is not judged. */
|
|
44
|
+
readonly getDrawCalls?: () => number | undefined;
|
|
45
|
+
/** Which canvas to judge. Defaults to the largest canvas that was drawn to (never a minimap or HUD canvas). */
|
|
46
|
+
readonly canvas?: () => HTMLCanvasElement | null | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* How frames are observed. `draw` (default) samples in the task of each GL draw to the default framebuffer.
|
|
49
|
+
* `raf` samples after every animation-frame callback (non-WebGL pages and tests; unreliable for WebGL canvases
|
|
50
|
+
* created without `preserveDrawingBuffer`).
|
|
51
|
+
*/
|
|
52
|
+
readonly sampling?: "draw" | "raf";
|
|
53
|
+
/** Tests only: forwarded to `installFrameTap` (fake GL prototypes, a fake microtask queue). */
|
|
54
|
+
readonly tap?: {
|
|
55
|
+
readonly prototypes?: readonly object[];
|
|
56
|
+
readonly enqueue?: (fn: () => void) => void;
|
|
57
|
+
};
|
|
58
|
+
/** Test hooks forwarded to the watch (clock, probe, storage, navigation, logging). */
|
|
59
|
+
readonly watch?: Partial<Pick<Parameters<typeof createBlackFrameWatch>[1], "now" | "readProbe" | "storage" | "navigate" | "log" | "isHidden" | "currentUrl" | "minBlackMs" | "blackFramesBudget" | "minFramesAfterReady" | "sampleEvery" | "samplesNeeded">>;
|
|
60
|
+
}
|
|
61
|
+
/** Returns the watch (or undefined when disabled/unavailable) so callers and tests can read its observation. */
|
|
62
|
+
export declare function installBlackFrameGuard(options?: BlackFrameGuardOptions): BlackFrameWatch | undefined;
|
|
63
|
+
//# sourceMappingURL=guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAiC,KAAK,eAAe,EAAiB,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGnJ;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,EAAE,aAAa,CAAC;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAIxF,CAAC;AAIF,uEAAuE;AACvE,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAGlE;AAED,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,KAAG,MAAuC,CAAC;AAEvF;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,UAAQ,GAAG,MAAM,GAAG,IAAI,CAMpF;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,iHAAiH;IACjH,WAAW,CAAC,EAAE,MAAM,gBAAgB,CAAC;CACtC;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,eAAe,CAAC,EAAE,UAAU,CAAC;KAC9B;CACF;AAED,MAAM,WAAW,sBAAsB;IACrC,oDAAoD;IACpD,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,4CAA4C;IAC5C,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,4HAA4H;IAC5H,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC;IACjC,+FAA+F;IAC/F,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IACjD,+GAA+G;IAC/G,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,iBAAiB,GAAG,IAAI,GAAG,SAAS,CAAC;IAC7D;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IACnC,+FAA+F;IAC/F,QAAQ,CAAC,GAAG,CAAC,EAAE;QAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,KAAK,IAAI,CAAA;KAAE,CAAC;IACxG,sFAAsF;IACtF,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,WAAW,GAAG,SAAS,GAAG,UAAU,GAAG,KAAK,GAAG,UAAU,GAAG,YAAY,GAAG,YAAY,GAAG,mBAAmB,GAAG,qBAAqB,GAAG,aAAa,GAAG,eAAe,CAAC,CAAC,CAAC;CAC9P;AAED,gHAAgH;AAChH,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,sBAA2B,GAAG,eAAe,GAAG,SAAS,CAqCxG"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { createBlackFrameWatch, findWorldCanvas, healRungName } from "./blackFrame.js";
|
|
2
|
+
import { installFrameTap } from "./frameTap.js";
|
|
3
|
+
/**
|
|
4
|
+
* Black-frame guard for pages that run on the engine's `a3d-qr` URL flag list (the showcase games). It installs once,
|
|
5
|
+
* before the app starts drawing. By default it taps the WebGL draw calls (`installFrameTap`) so the world canvas is
|
|
6
|
+
* sampled in the same task that drew it, before the browser composites: a canvas without `preserveDrawingBuffer` reads as
|
|
7
|
+
* zeros anywhere else, which is how an earlier version reloaded healthy games. It reloads one rung down when the canvas
|
|
8
|
+
* stays black. It is a thin shell around `createBlackFrameWatch`: readiness gating, black-versus-dark detection,
|
|
9
|
+
* once-per-load stepping and the recorded reason all live there.
|
|
10
|
+
*
|
|
11
|
+
* `?heal=0` disables it; an `a3d-qr` supplied in the URL by the author or player is never rewritten.
|
|
12
|
+
*/
|
|
13
|
+
export const QR_HEAL_LADDER = [
|
|
14
|
+
{ name: "no-vfx-fog", qr: "-vfxFog" },
|
|
15
|
+
{ name: "no-post", qr: "-vfxFog,-post" },
|
|
16
|
+
{ name: "legacy-compile", qr: "-vfxFog,-post,-compiler" }
|
|
17
|
+
];
|
|
18
|
+
const QR_RUNGS = QR_HEAL_LADDER.map((rung) => ({ name: rung.name, params: { "a3d-qr": `game,${rung.qr}` } }));
|
|
19
|
+
/** Rung currently applied (0 = full quality) from the stored value. */
|
|
20
|
+
export function qrHealStage(raw) {
|
|
21
|
+
const n = Number(raw ?? "0");
|
|
22
|
+
return Number.isInteger(n) && n >= 0 && n <= QR_HEAL_LADDER.length ? n : 0;
|
|
23
|
+
}
|
|
24
|
+
export const qrHealRungName = (stage) => healRungName(stage, QR_RUNGS);
|
|
25
|
+
/**
|
|
26
|
+
* URL for rung `stage`, or `null` when the ladder is exhausted or an author/player supplied their own `a3d-qr`.
|
|
27
|
+
* `ownsQr` is true when the `a3d-qr` already in the URL was written by an earlier rung of this guard.
|
|
28
|
+
*/
|
|
29
|
+
export function qrHealUrl(href, stage, ownsQr = false) {
|
|
30
|
+
if (stage < 1 || stage > QR_HEAL_LADDER.length)
|
|
31
|
+
return null;
|
|
32
|
+
const url = new URL(href);
|
|
33
|
+
if (url.searchParams.has("a3d-qr") && !ownsQr)
|
|
34
|
+
return null;
|
|
35
|
+
url.searchParams.set("a3d-qr", `game,${QR_HEAL_LADDER[stage - 1].qr}`);
|
|
36
|
+
return url.toString();
|
|
37
|
+
}
|
|
38
|
+
/** Returns the watch (or undefined when disabled/unavailable) so callers and tests can read its observation. */
|
|
39
|
+
export function installBlackFrameGuard(options = {}) {
|
|
40
|
+
if (typeof window === "undefined" || window.__AURA3D_HEAL_INSTALLED__)
|
|
41
|
+
return undefined;
|
|
42
|
+
window.__AURA3D_HEAL_INSTALLED__ = true;
|
|
43
|
+
const params = new URLSearchParams(location.search);
|
|
44
|
+
const enabled = options.enabled ?? params.get("heal") !== "0";
|
|
45
|
+
const key = `aura3d-heal:${location.pathname}`;
|
|
46
|
+
let worldCanvas = () => undefined;
|
|
47
|
+
const watch = createBlackFrameWatch(options.canvas ?? (() => worldCanvas() ?? findWorldCanvas()), {
|
|
48
|
+
enabled,
|
|
49
|
+
ladder: QR_RUNGS,
|
|
50
|
+
storageKey: key,
|
|
51
|
+
...(options.fast ? { fastFrames: 6 } : {}),
|
|
52
|
+
...(options.isReady ? { isReady: options.isReady } : {}),
|
|
53
|
+
...(options.getDrawCalls ? { getDrawCalls: options.getDrawCalls } : {}),
|
|
54
|
+
buildUrl: (next, href) => qrHealUrl(href, next, next > 1),
|
|
55
|
+
...(options.watch ?? {})
|
|
56
|
+
});
|
|
57
|
+
window.__AURA3D_HEAL__ = { rung: watch.stage, name: qrHealRungName(watch.stage), enabled, observation: () => watch.observation() };
|
|
58
|
+
if (!enabled)
|
|
59
|
+
return watch;
|
|
60
|
+
if ((options.sampling ?? "draw") === "draw") {
|
|
61
|
+
const tap = installFrameTap({
|
|
62
|
+
...(options.tap ?? {}),
|
|
63
|
+
onFrame: (canvas) => {
|
|
64
|
+
const target = options.canvas?.() ?? tap.worldCanvas();
|
|
65
|
+
if (target && canvas === target)
|
|
66
|
+
watch.sample(canvas);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
worldCanvas = () => tap.worldCanvas();
|
|
70
|
+
return watch;
|
|
71
|
+
}
|
|
72
|
+
const originalRaf = window.requestAnimationFrame.bind(window);
|
|
73
|
+
window.requestAnimationFrame = (callback) => originalRaf((time) => {
|
|
74
|
+
callback(time);
|
|
75
|
+
watch.sample();
|
|
76
|
+
});
|
|
77
|
+
return watch;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/guard.ts"],"names":[],"mappings":"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"}
|
package/dist/safety/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { type BlackFrameWatchOptions, type HealRung } from "./blackFrame.js";
|
|
1
|
+
import { type BlackFrameWatchOptions, type HealRung, type WatchObservation } from "./blackFrame.js";
|
|
2
2
|
import { type DiagnosticsAppLike } from "./diagnosticsPanel.js";
|
|
3
3
|
import { type QualitySwitches } from "./switches.js";
|
|
4
4
|
export * from "./blackFrame.js";
|
|
5
|
+
export * from "./guard.js";
|
|
6
|
+
export * from "./frameTap.js";
|
|
5
7
|
export * from "./diagnosticsPanel.js";
|
|
6
8
|
export * from "./switches.js";
|
|
7
9
|
export interface SafetyNetOptions {
|
|
@@ -18,7 +20,7 @@ export interface SafetySettings {
|
|
|
18
20
|
/** Show the diagnostics panel. Default: only when the URL has `?diag=1`. */
|
|
19
21
|
readonly panel?: boolean | "query";
|
|
20
22
|
readonly ladder?: readonly HealRung[];
|
|
21
|
-
readonly watch?: Pick<BlackFrameWatchOptions, "fastFrames" | "readProbe" | "storage" | "currentUrl" | "navigate" | "storageKey" | "log">;
|
|
23
|
+
readonly watch?: Pick<BlackFrameWatchOptions, "fastFrames" | "readProbe" | "storage" | "currentUrl" | "navigate" | "storageKey" | "log" | "isReady" | "getDrawCalls" | "now" | "isHidden" | "minBlackMs" | "blackFramesBudget" | "minFramesAfterReady" | "sampleEvery" | "samplesNeeded">;
|
|
22
24
|
}
|
|
23
25
|
export interface SafetyReport {
|
|
24
26
|
readonly enabled: boolean;
|
|
@@ -27,6 +29,8 @@ export interface SafetyReport {
|
|
|
27
29
|
readonly escalated: boolean;
|
|
28
30
|
readonly switches: QualitySwitches;
|
|
29
31
|
readonly panel: boolean;
|
|
32
|
+
/** What the black-frame watch has seen (frames, probe stats, skips) and why a reload happened; undefined without a watch. */
|
|
33
|
+
readonly observed?: WatchObservation;
|
|
30
34
|
}
|
|
31
35
|
export interface SafetyNet {
|
|
32
36
|
/** Switches in force (explicit URL parameters, then the black-frame rung's parameters). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6F,KAAK,sBAAsB,EAAE,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6F,KAAK,sBAAsB,EAAE,KAAK,QAAQ,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC/L,OAAO,EAA2B,KAAK,kBAAkB,EAA+B,MAAM,uBAAuB,CAAC;AACtH,OAAO,EAA0B,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAE7E,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAE9B,MAAM,WAAW,gBAAgB;IAC/B,sGAAsG;IACtG,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,cAAc,CAAC;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,iBAAiB,CAAC;IACpC,QAAQ,CAAC,GAAG,CAAC,EAAE,kBAAkB,CAAC;IAClC,yEAAyE;IACzE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;CAC5C;AAED,MAAM,WAAW,cAAc;IAC7B,4FAA4F;IAC5F,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,sBAAsB,EAAE,YAAY,GAAG,WAAW,GAAG,SAAS,GAAG,YAAY,GAAG,UAAU,GAAG,YAAY,GAAG,KAAK,GAAG,SAAS,GAAG,cAAc,GAAG,KAAK,GAAG,UAAU,GAAG,YAAY,GAAG,mBAAmB,GAAG,qBAAqB,GAAG,aAAa,GAAG,eAAe,CAAC,CAAC;CAC3R;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,6HAA6H;IAC7H,QAAQ,CAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAC;CACtC;AAED,MAAM,WAAW,SAAS;IACxB,2FAA2F;IAC3F,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,qEAAqE;IACrE,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,6FAA6F;IAC7F,MAAM,IAAI,YAAY,CAAC;IACvB,OAAO,IAAI,IAAI,CAAC;CACjB;AAID;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,GAAG,SAAS,CAsDrE"}
|
package/dist/safety/index.js
CHANGED
|
@@ -2,6 +2,8 @@ import { createBlackFrameWatch, DEFAULT_HEAL_LADDER, healRungName, healStage } f
|
|
|
2
2
|
import { installDiagnosticsPanel } from "./diagnosticsPanel.js";
|
|
3
3
|
import { resolveQualitySwitches } from "./switches.js";
|
|
4
4
|
export * from "./blackFrame.js";
|
|
5
|
+
export * from "./guard.js";
|
|
6
|
+
export * from "./frameTap.js";
|
|
5
7
|
export * from "./diagnosticsPanel.js";
|
|
6
8
|
export * from "./switches.js";
|
|
7
9
|
const NOOP_REPORT = (switches) => ({ enabled: false, stage: 0, rung: "full", escalated: false, switches, panel: false });
|
|
@@ -31,7 +33,8 @@ export function installSafetyNet(options) {
|
|
|
31
33
|
rung: watch?.rung ?? healRungName(stage, ladder),
|
|
32
34
|
escalated: watch?.escalated ?? false,
|
|
33
35
|
switches,
|
|
34
|
-
panel: showPanel
|
|
36
|
+
panel: showPanel,
|
|
37
|
+
...(watch ? { observed: watch.observation() } : {})
|
|
35
38
|
});
|
|
36
39
|
let panel;
|
|
37
40
|
if (showPanel && typeof document !== "undefined") {
|
|
@@ -41,7 +44,15 @@ export function installSafetyNet(options) {
|
|
|
41
44
|
extraLines: () => {
|
|
42
45
|
const r = report();
|
|
43
46
|
const off = ["post", "shadow", "env", "sky", "aa"].filter((key) => !switches[key]);
|
|
44
|
-
|
|
47
|
+
const lines = [`safety: rung ${r.stage} (${r.rung})${r.escalated ? " reloading" : ""} off:[${off.join(",")}] quality:${switches.quality} tm:${switches.toneMapping} heal:${switches.heal ? "on" : "off"}`];
|
|
48
|
+
const seen = r.observed ?? globalThis.__AURA3D_HEAL__?.observation?.();
|
|
49
|
+
if (seen) {
|
|
50
|
+
const s = seen.lastStats;
|
|
51
|
+
lines.push(`heal watch: frames ${seen.calls} ready@${seen.readyAtCall ?? "no"} samples ${seen.samples} black ${seen.blackSamples} lit ${s ? `${s.lit}/${s.samples} max ${s.max}` : "n/a"} frame ${Math.round(seen.medianFrameMs)}ms skipped notReady ${seen.skipped.notReady} noDraw ${seen.skipped.noDrawCalls}${seen.healthy ? " healthy" : ""}`);
|
|
52
|
+
if (seen.reason)
|
|
53
|
+
lines.push(`heal reason: ${seen.reason}`);
|
|
54
|
+
}
|
|
55
|
+
return lines;
|
|
45
56
|
}
|
|
46
57
|
});
|
|
47
58
|
}
|
package/dist/safety/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,YAAY,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aura3d/debug",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@aura3d/animation": "4.1.
|
|
7
|
-
"@aura3d/physics": "4.1.
|
|
8
|
-
"@aura3d/rendering": "4.1.
|
|
6
|
+
"@aura3d/animation": "4.1.2",
|
|
7
|
+
"@aura3d/physics": "4.1.2",
|
|
8
|
+
"@aura3d/rendering": "4.1.2"
|
|
9
9
|
},
|
|
10
10
|
"exports": {
|
|
11
11
|
".": {
|