@hyperframes/studio 0.8.165 → 0.8.166
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/assets/{hyperframes-player-9o0UqKMR.js → hyperframes-player-BhRLDR30.js} +1 -1
- package/dist/assets/{index-CIOtrzQ5.js → index-CCRXiiFo.js} +1 -1
- package/dist/assets/{index-DFRwKDBl.js → index-DQ_I6X0d.js} +97 -97
- package/dist/index.html +1 -1
- package/dist/index.js +10 -2
- package/package.json +8 -8
- package/src/player/hooks/useShadowPreviewReload.ts +15 -2
- package/src/player/hooks/useTimelinePlayer.shadowReload.test.ts +70 -0
package/dist/index.html
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
document.documentElement.dataset.theme = "paper";
|
|
15
15
|
}
|
|
16
16
|
</script>
|
|
17
|
-
<script type="module" crossorigin src="/assets/index-
|
|
17
|
+
<script type="module" crossorigin src="/assets/index-DQ_I6X0d.js"></script>
|
|
18
18
|
<link rel="stylesheet" crossorigin href="/assets/index-DkQKsFxx.css">
|
|
19
19
|
</head>
|
|
20
20
|
<body>
|
package/dist/index.js
CHANGED
|
@@ -31510,6 +31510,13 @@ function restoreSeekPainted(iframe) {
|
|
|
31510
31510
|
return win?.__hfWaitForSeekCompletion?.().catch(() => {
|
|
31511
31511
|
});
|
|
31512
31512
|
}
|
|
31513
|
+
function shadowPlayerReachable(iframe) {
|
|
31514
|
+
try {
|
|
31515
|
+
return Boolean(iframe?.contentWindow?.__player);
|
|
31516
|
+
} catch {
|
|
31517
|
+
return false;
|
|
31518
|
+
}
|
|
31519
|
+
}
|
|
31513
31520
|
function isDocumentHidden() {
|
|
31514
31521
|
return typeof document !== "undefined" && document.visibilityState === "hidden";
|
|
31515
31522
|
}
|
|
@@ -31565,6 +31572,7 @@ function useShadowPreviewReload({
|
|
|
31565
31572
|
const failShadow = useCallback39(
|
|
31566
31573
|
(gen, cause) => {
|
|
31567
31574
|
if (gen !== shadowGenRef.current) return;
|
|
31575
|
+
const waitingFor = !shadowPlayerReachable(shadowIframeRef.current) ? "the page and its runtime to load" : pendingCommitRef.current?.gen !== gen ? "its timeline to be ready" : "its loaders to clear";
|
|
31568
31576
|
shadowGenRef.current += 1;
|
|
31569
31577
|
stopPendingShadow();
|
|
31570
31578
|
shadowIframeRef.current = null;
|
|
@@ -31572,8 +31580,8 @@ function useShadowPreviewReload({
|
|
|
31572
31580
|
pendingSeekRef.current = null;
|
|
31573
31581
|
setPreviewSlots(planShadowDiscard);
|
|
31574
31582
|
setPreviewReloading(false);
|
|
31575
|
-
const message = `The preview did not reload (${cause}). The previous preview is still showing.`;
|
|
31576
|
-
logReload("shadow-failed", { cause });
|
|
31583
|
+
const message = `The preview did not reload (${cause}). It was still waiting for ${waitingFor}. The previous preview is still showing.`;
|
|
31584
|
+
logReload("shadow-failed", { cause, waitingFor });
|
|
31577
31585
|
console.error(`[studio] ${message}`);
|
|
31578
31586
|
onReloadFailedRef.current?.(message);
|
|
31579
31587
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/studio",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.166",
|
|
4
4
|
"description": "",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -59,12 +59,12 @@
|
|
|
59
59
|
"dockview-react": "8.3.1",
|
|
60
60
|
"gsap": "^3.13.0",
|
|
61
61
|
"mediabunny": "^1.45.3",
|
|
62
|
-
"@hyperframes/core": "0.8.
|
|
63
|
-
"@hyperframes/
|
|
64
|
-
"@hyperframes/
|
|
65
|
-
"@hyperframes/
|
|
66
|
-
"@hyperframes/
|
|
67
|
-
"@hyperframes/
|
|
62
|
+
"@hyperframes/core": "0.8.166",
|
|
63
|
+
"@hyperframes/parsers": "0.8.166",
|
|
64
|
+
"@hyperframes/sdk": "0.8.166",
|
|
65
|
+
"@hyperframes/player": "0.8.166",
|
|
66
|
+
"@hyperframes/shader-transitions": "0.8.166",
|
|
67
|
+
"@hyperframes/studio-server": "0.8.166"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
70
|
"@tailwindcss/vite": "^4.3.3",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"vite": "^6.4.2",
|
|
82
82
|
"vitest": "^4.1.11",
|
|
83
83
|
"zustand": "^5.0.0",
|
|
84
|
-
"@hyperframes/producer": "0.8.
|
|
84
|
+
"@hyperframes/producer": "0.8.166"
|
|
85
85
|
},
|
|
86
86
|
"peerDependencies": {
|
|
87
87
|
"react": "19",
|
|
@@ -35,6 +35,14 @@ function restoreSeekPainted(iframe: HTMLIFrameElement | null): Promise<void> | u
|
|
|
35
35
|
return win?.__hfWaitForSeekCompletion?.().catch(() => {});
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
function shadowPlayerReachable(iframe: HTMLIFrameElement | null): boolean {
|
|
39
|
+
try {
|
|
40
|
+
return Boolean((iframe?.contentWindow as IframeWindow | null | undefined)?.__player);
|
|
41
|
+
} catch {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
38
46
|
function isDocumentHidden(): boolean {
|
|
39
47
|
return typeof document !== "undefined" && document.visibilityState === "hidden";
|
|
40
48
|
}
|
|
@@ -104,6 +112,11 @@ export function useShadowPreviewReload({
|
|
|
104
112
|
const failShadow = useCallback(
|
|
105
113
|
(gen: number, cause: string) => {
|
|
106
114
|
if (gen !== shadowGenRef.current) return;
|
|
115
|
+
const waitingFor = !shadowPlayerReachable(shadowIframeRef.current)
|
|
116
|
+
? "the page and its runtime to load"
|
|
117
|
+
: pendingCommitRef.current?.gen !== gen
|
|
118
|
+
? "its timeline to be ready"
|
|
119
|
+
: "its loaders to clear";
|
|
107
120
|
shadowGenRef.current += 1;
|
|
108
121
|
stopPendingShadow();
|
|
109
122
|
shadowIframeRef.current = null;
|
|
@@ -111,8 +124,8 @@ export function useShadowPreviewReload({
|
|
|
111
124
|
pendingSeekRef.current = null;
|
|
112
125
|
setPreviewSlots(planShadowDiscard);
|
|
113
126
|
setPreviewReloading(false);
|
|
114
|
-
const message = `The preview did not reload (${cause}). The previous preview is still showing.`;
|
|
115
|
-
logReload("shadow-failed", { cause });
|
|
127
|
+
const message = `The preview did not reload (${cause}). It was still waiting for ${waitingFor}. The previous preview is still showing.`;
|
|
128
|
+
logReload("shadow-failed", { cause, waitingFor });
|
|
116
129
|
console.error(`[studio] ${message}`);
|
|
117
130
|
onReloadFailedRef.current?.(message);
|
|
118
131
|
},
|
|
@@ -371,6 +371,9 @@ describe("shadow reload readiness and failure", () => {
|
|
|
371
371
|
expect(getApi().iframeRef.current).toBe(live);
|
|
372
372
|
expect(live.style.visibility).toBe("");
|
|
373
373
|
expect(onPreviewReloadFailed).toHaveBeenCalledWith(expect.stringContaining("too long"));
|
|
374
|
+
expect(onPreviewReloadFailed).toHaveBeenCalledWith(
|
|
375
|
+
expect.stringContaining("still waiting for the page and its runtime to load"),
|
|
376
|
+
);
|
|
374
377
|
expect(consoleError).toHaveBeenCalled();
|
|
375
378
|
unmount(root);
|
|
376
379
|
});
|
|
@@ -395,6 +398,48 @@ describe("shadow reload readiness and failure", () => {
|
|
|
395
398
|
act(() => void vi.advanceTimersByTime(1));
|
|
396
399
|
expect(getApi().previewSlots).toEqual([{ gen: 0, role: "live" }]);
|
|
397
400
|
expect(onPreviewReloadFailed).toHaveBeenCalledWith(expect.stringContaining("too long"));
|
|
401
|
+
expect(onPreviewReloadFailed).toHaveBeenCalledWith(
|
|
402
|
+
expect.stringContaining("still waiting for the page and its runtime to load"),
|
|
403
|
+
);
|
|
404
|
+
unmount(root);
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
it("names the timeline when a shadow's runtime runs but never reports a length", () => {
|
|
408
|
+
vi.useFakeTimers();
|
|
409
|
+
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
410
|
+
const onPreviewReloadFailed = vi.fn();
|
|
411
|
+
const { getApi, gen, root } = beginReload({ onPreviewReloadFailed });
|
|
412
|
+
const lengthless = makeFakeIframe(makeAdapterWindow({ duration: 0 }).win);
|
|
413
|
+
act(() => {
|
|
414
|
+
getApi().setShadowIframeNode(lengthless);
|
|
415
|
+
getApi().onShadowIframeLoad(gen);
|
|
416
|
+
getApi().onShadowReadyChange(gen, true);
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
act(() => void vi.advanceTimersByTime(FULL_WAIT_MS));
|
|
420
|
+
|
|
421
|
+
expect(onPreviewReloadFailed).toHaveBeenCalledWith(
|
|
422
|
+
expect.stringContaining("still waiting for its timeline to be ready"),
|
|
423
|
+
);
|
|
424
|
+
unmount(root);
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
it("names the loaders when a shadow with a ready timeline never clears them", () => {
|
|
428
|
+
vi.useFakeTimers();
|
|
429
|
+
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
430
|
+
const onPreviewReloadFailed = vi.fn();
|
|
431
|
+
const { getApi, gen, root } = beginReload({ onPreviewReloadFailed });
|
|
432
|
+
const shadow = makeShadowWithSpies();
|
|
433
|
+
act(() => {
|
|
434
|
+
getApi().setShadowIframeNode(shadow.iframe);
|
|
435
|
+
getApi().onShadowIframeLoad(gen);
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
act(() => void vi.advanceTimersByTime(FULL_WAIT_MS));
|
|
439
|
+
|
|
440
|
+
expect(onPreviewReloadFailed).toHaveBeenCalledWith(
|
|
441
|
+
expect.stringContaining("still waiting for its loaders to clear"),
|
|
442
|
+
);
|
|
398
443
|
unmount(root);
|
|
399
444
|
});
|
|
400
445
|
|
|
@@ -475,6 +520,31 @@ describe("shadow reload readiness and failure", () => {
|
|
|
475
520
|
unmount(root);
|
|
476
521
|
});
|
|
477
522
|
|
|
523
|
+
it("still drops and reports a shadow whose window throws on access", () => {
|
|
524
|
+
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
525
|
+
const onPreviewReloadFailed = vi.fn();
|
|
526
|
+
const { getApi, live, gen, root } = beginReload({ onPreviewReloadFailed });
|
|
527
|
+
const crossOrigin = makeFakeIframe(
|
|
528
|
+
Object.defineProperty({}, "__player", {
|
|
529
|
+
get: () => {
|
|
530
|
+
throw new DOMException("Blocked a frame", "SecurityError");
|
|
531
|
+
},
|
|
532
|
+
}),
|
|
533
|
+
);
|
|
534
|
+
act(() => getApi().setShadowIframeNode(crossOrigin));
|
|
535
|
+
|
|
536
|
+
act(() => getApi().onShadowError(gen, "Composition timeline not found after 8s"));
|
|
537
|
+
|
|
538
|
+
expect(getApi().previewSlots).toEqual([{ gen: 0, role: "live" }]);
|
|
539
|
+
expect(getApi().iframeRef.current).toBe(live);
|
|
540
|
+
expect(isPreviewChanging()).toBe(false);
|
|
541
|
+
expect(onPreviewReloadFailed).toHaveBeenCalledTimes(1);
|
|
542
|
+
expect(onPreviewReloadFailed).toHaveBeenCalledWith(
|
|
543
|
+
expect.stringContaining("still waiting for the page and its runtime to load"),
|
|
544
|
+
);
|
|
545
|
+
unmount(root);
|
|
546
|
+
});
|
|
547
|
+
|
|
478
548
|
it("drops a shadow whose document reports an error and reports the cause", () => {
|
|
479
549
|
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
480
550
|
const onPreviewReloadFailed = vi.fn();
|