Skip to content

Commit e2f7f6a

Browse files
committed
fix: add regression fixtures with golden baselines + address review
- Create sub-comp-t0 and sub-comp-id-selector as proper regression tests under packages/producer/tests/ with golden MP4 baselines - Add both to shard-7 in regression.yml - Add clarifying comment on activateNestedChildTimelines scope - Confirm test fixture network safety in comment
1 parent 0d12a46 commit e2f7f6a

12 files changed

Lines changed: 319 additions & 1 deletion

File tree

.github/workflows/regression.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ jobs:
7272
- shard: shard-6
7373
args: "overlay-montage-prod style-12-prod chat missing-host-comp-id png-sequence"
7474
- shard: shard-7
75-
args: "sub-composition-video style-18-prod raf-ball-render-compat font-variant-numeric"
75+
args: "sub-composition-video style-18-prod raf-ball-render-compat font-variant-numeric sub-comp-t0 sub-comp-id-selector"
7676
- shard: shard-8
7777
args: "style-13-prod style-6-prod vignelli-stacking gsap-letters-render-compat"
7878
steps:

packages/core/src/compiler/inlineSubCompositions.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { describe, expect, it } from "vitest";
22
import { parseHTML } from "linkedom";
33
import { inlineSubCompositions } from "./inlineSubCompositions";
44

5+
// Fixtures reference GSAP CDN but are never loaded in a real browser — resolveHtml is mocked.
6+
57
/**
68
* Minimal sub-composition HTML that uses `#intro` as its CSS and GSAP scope.
79
* This is the pattern that breaks when the producer path strips the inner root.

packages/core/src/runtime/init.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1724,6 +1724,10 @@ export function initSandboxRuntimeModular(): void {
17241724
}
17251725
};
17261726

1727+
// Unpause all non-root timelines. Per GSAP semantics, paused(false) on a
1728+
// child timeline that hasn't been reached by the parent's playhead is a
1729+
// no-op — the child won't fire onStart/onUpdate until the parent seeks
1730+
// past its insertion point. Per-frame visibility is gated by the engine.
17271731
const activateNestedChildTimelines = (masterTimeline: RuntimeTimelineLike) => {
17281732
const timelines = (window.__timelines ?? {}) as Record<string, RuntimeTimelineLike | undefined>;
17291733
for (const tl of Object.values(timelines)) {
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "Sub-composition #ID selector scoping",
3+
"description": "Documents that sub-compositions using #ID selectors may render differently between preview and render due to the producer stripping the inner root element. Workaround: use [data-composition-id] selectors instead of #ID.",
4+
"tags": ["sub-composition", "regression", "selector"],
5+
"minPsnr": 20,
6+
"maxFrameFailures": 10,
7+
"minAudioCorrelation": 0.0,
8+
"maxAudioLagWindows": 120,
9+
"renderConfig": {
10+
"fps": 24
11+
}
12+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:f86791eaf7839adcd9e71ba6d1d56f3d970e6a155e8ac227947540e7a1990229
3+
size 47948
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
6+
<style>
7+
body {
8+
margin: 0;
9+
width: 1920px;
10+
height: 1080px;
11+
overflow: hidden;
12+
background: #000;
13+
}
14+
.scene {
15+
position: absolute;
16+
inset: 0;
17+
overflow: hidden;
18+
}
19+
#scene-intro {
20+
opacity: 1;
21+
}
22+
</style>
23+
</head>
24+
<body>
25+
<div
26+
id="root"
27+
data-composition-id="main"
28+
data-start="0"
29+
data-duration="4"
30+
data-width="1920"
31+
data-height="1080"
32+
>
33+
<div
34+
id="scene-intro"
35+
class="scene"
36+
data-composition-id="intro"
37+
data-composition-src="intro.html"
38+
data-start="0"
39+
data-duration="4"
40+
data-track-index="0"
41+
></div>
42+
</div>
43+
<script>
44+
window.__timelines = window.__timelines || {};
45+
window.__timelines["main"] = gsap.timeline({ paused: true });
46+
</script>
47+
</body>
48+
</html>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<template id="intro-template">
2+
<div id="intro" data-composition-id="intro" data-width="1920" data-height="1080">
3+
<div
4+
class="title"
5+
style="
6+
position: absolute;
7+
top: 50%;
8+
left: 50%;
9+
transform: translate(-50%, -50%);
10+
font-size: 120px;
11+
font-family: Impact, sans-serif;
12+
color: #fff;
13+
opacity: 0;
14+
"
15+
>
16+
HELLO WORLD
17+
</div>
18+
<style>
19+
#intro {
20+
position: relative;
21+
width: 1920px;
22+
height: 1080px;
23+
background: #111;
24+
}
25+
</style>
26+
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
27+
<script>
28+
(function () {
29+
window.__timelines = window.__timelines || {};
30+
var tl = gsap.timeline({ paused: true });
31+
var scope = "#intro";
32+
tl.fromTo(
33+
scope + " .title",
34+
{ opacity: 0, y: 50, scale: 0.8 },
35+
{ opacity: 1, y: 0, scale: 1, duration: 0.5, ease: "power3.out" },
36+
0.2,
37+
);
38+
window.__timelines["intro"] = tl;
39+
})();
40+
</script>
41+
</div>
42+
</template>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "Sub-composition timeline activation at t=0",
3+
"description": "Regression for: sub-composition timelines at data-start near 0 were not activated during renderSeek, causing GSAP-animated elements to stay invisible. The fix activates nested child timelines before every render frame seek.",
4+
"tags": ["sub-composition", "regression", "timeline"],
5+
"minPsnr": 25,
6+
"maxFrameFailures": 5,
7+
"minAudioCorrelation": 0.0,
8+
"maxAudioLagWindows": 120,
9+
"renderConfig": {
10+
"fps": 24
11+
}
12+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:d85ea36a219e5ffbeed672a075a6cfb8ecb71e175753c4f5b8407e67abe29fc9
3+
size 18186
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<template id="hook-template">
2+
<div id="hook" data-composition-id="hook" data-width="1920" data-height="1080">
3+
<div class="hook-title">BREAKING</div>
4+
<div class="hook-subtitle">Transfer confirmed</div>
5+
6+
<style>
7+
#hook {
8+
position: relative;
9+
width: 1920px;
10+
height: 1080px;
11+
overflow: hidden;
12+
background: #07110d;
13+
display: flex;
14+
align-items: center;
15+
justify-content: center;
16+
flex-direction: column;
17+
gap: 20px;
18+
}
19+
#hook .hook-title {
20+
font-family: Impact, system-ui, sans-serif;
21+
font-size: 200px;
22+
font-weight: 900;
23+
color: #ff3b30;
24+
opacity: 0;
25+
}
26+
#hook .hook-subtitle {
27+
font-family: Arial, system-ui, sans-serif;
28+
font-size: 60px;
29+
color: #f7f3e8;
30+
opacity: 0;
31+
}
32+
</style>
33+
34+
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
35+
<script>
36+
(function () {
37+
window.__timelines = window.__timelines || {};
38+
var tl = gsap.timeline({ paused: true });
39+
var scope = "#hook";
40+
41+
// Title slams in at 0.1s
42+
tl.fromTo(
43+
scope + " .hook-title",
44+
{ scale: 3.5, opacity: 0 },
45+
{ scale: 1, opacity: 1, duration: 0.25, ease: "expo.out" },
46+
0.1,
47+
);
48+
49+
// Subtitle fades in at 0.5s
50+
tl.fromTo(
51+
scope + " .hook-subtitle",
52+
{ y: 30, opacity: 0 },
53+
{ y: 0, opacity: 1, duration: 0.4, ease: "power3.out" },
54+
0.5,
55+
);
56+
57+
window.__timelines["hook"] = tl;
58+
})();
59+
</script>
60+
</div>
61+
</template>

0 commit comments

Comments
 (0)