fix(core,studio): escape user values in querySelector attribute selectors

Extract cssAttrSelector to packages/core/src/utils/cssSelector.ts and
use it (or CSS.escape for browser-side code) at all 12 sites that
previously interpolated raw user-authored values into querySelector
attribute selectors. A " in a composition ID, script src, or
data-start value would produce a malformed selector that throws.

Node-side (core compiler/parser): uses the shared cssAttrSelector.
Browser-side (runtime, studio): uses native CSS.escape().

Supersedes #1568 which fixed only the 3 bundler sites.
This commit is contained in:
Miguel Ángel
2026-06-19 15:47:28 -04:00
committed by GitHub
parent 758eda995c
commit c0ffdc0fb0
15 changed files with 126 additions and 21 deletions
+2 -1
View File
@@ -13,6 +13,7 @@ import type {
import { validateCompositionGsap } from "./gsapSerialize";
import { ensureHfIds } from "./hfIds.js";
import { parseGsapScriptAcornForWrite } from "./gsapParserAcorn.js";
import { queryByAttr } from "../utils/cssSelector";
import { removeAnimationFromScript } from "./gsapWriterAcorn.js";
import type { ValidationResult } from "../core.types";
@@ -519,7 +520,7 @@ export function updateElementInHtml(
const parser = new DOMParser();
const doc = parser.parseFromString(html, "text/html");
const el = doc.getElementById(elementId) || doc.querySelector(`[data-name="${elementId}"]`);
const el = doc.getElementById(elementId) || queryByAttr(doc, "data-name", elementId);
if (!el) return html;
if (updates.startTime !== undefined) {