fix(sdk): code-review follow-ups (WS-B/C/3.C, #1569/#1570/#1572) (#1588)

Addresses the still-outstanding review concerns from merged PRs #1569 / #1570 /
#1572 not already hoisted into #1573.

WS-B (#1569):
- validateVariables requires discriminant fields for object-valued font/image
  ({name,source} / {url}); a {name:42} font or {foo:42} image previously passed
  runtime validation and surfaced as a bogus font-family / missing image.
- Dropped ImageValue's [key:string]:unknown index signature (let any {url}-shaped
  object through, swallowed typos); explicit alt?/fit? instead.
- Documented the OverrideSet widening for SDK consumers.

WS-C (#1570):
- getElementTimings caches parsed GSAP labels by exact script text (avoids a full
  acorn re-parse per read; content-key invalidates on edit).
- Documented end-inclusive label window + best-effort extractGsapLabels catch.

WS-3.C (#1572):
- Added typed Composition.addWithKeyframes / replaceWithKeyframes (was asymmetric
  with addGsapTween; Studio had to use raw dispatch).
- Extracted shared KeyframeSpec type; documented position as seconds/number-only.

Gates: build + core 18/18 + sdk 19/19 + oxlint + oxfmt + fallow + typecheck all green.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Vance Ingalls
2026-06-19 00:07:53 -07:00
committed by GitHub
co-authored by Claude Opus 4.8
parent 418f198b33
commit dd6fad6bb2
6 changed files with 227 additions and 24 deletions
+24 -2
View File
@@ -87,7 +87,8 @@ function checkType(value: unknown, decl: CompositionVariable): VariableValidatio
}
case "font": {
// Font value is an object {name: string, source: string} OR a fallback string.
if (!isPlainObject(value) && typeof value !== "string") {
if (typeof value === "string") return null;
if (!isPlainObject(value)) {
return {
kind: "type-mismatch",
variableId: decl.id,
@@ -95,11 +96,23 @@ function checkType(value: unknown, decl: CompositionVariable): VariableValidatio
actual: jsTypeOf(value),
};
}
// Object form: require the discriminant fields so a malformed brand-kit
// value ({name: 42} / {}) is caught here rather than surfacing as a bogus
// font-family at render time.
if (typeof value.name !== "string" || typeof value.source !== "string") {
return {
kind: "type-mismatch",
variableId: decl.id,
expected: "font object {name: string, source: string}",
actual: "object missing string name/source",
};
}
return null;
}
case "image": {
// Image value is an object {url: string} OR a fallback string.
if (!isPlainObject(value) && typeof value !== "string") {
if (typeof value === "string") return null;
if (!isPlainObject(value)) {
return {
kind: "type-mismatch",
variableId: decl.id,
@@ -107,6 +120,15 @@ function checkType(value: unknown, decl: CompositionVariable): VariableValidatio
actual: jsTypeOf(value),
};
}
// Object form: require the discriminant field.
if (typeof value.url !== "string") {
return {
kind: "type-mismatch",
variableId: decl.id,
expected: "image object {url: string}",
actual: "object missing string url",
};
}
return null;
}
}