From 0de17a1f669419b926311f93148d64f842df01aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20=C3=81ngel?= Date: Mon, 25 May 2026 19:41:14 +0000 Subject: [PATCH] fix(core): restore IIFE with escaping for composition scripts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Function constructor (3bb0d1ef) was a security hardening to prevent injection, but it broke sub-composition DOM proxy scoping. This restores the inline IIFE (preserving closure scope) while adding → <\/script> escaping to maintain the injection prevention. Updates tests to match the new IIFE output shape. Closes #1074 --- packages/core/src/compiler/compositionScoping.test.ts | 7 ++++--- packages/core/src/compiler/compositionScoping.ts | 2 +- packages/core/src/compiler/htmlBundler.test.ts | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/core/src/compiler/compositionScoping.test.ts b/packages/core/src/compiler/compositionScoping.test.ts index 5a0a0cd3a..5d806ccdc 100644 --- a/packages/core/src/compiler/compositionScoping.test.ts +++ b/packages/core/src/compiler/compositionScoping.test.ts @@ -572,14 +572,15 @@ window.__afterTimeline = window.__timelines.scene; expect(scoped).toContain('[data-composition-id="chrome-overlay"] .child-element'); }); - it("wraps scoped composition script source as a string literal", () => { + it("escapes in scoped composition script source to prevent injection", () => { const wrapped = wrapScopedCompositionScript( 'window.payload = "";', "scene", ); - expect(wrapped).toContain('Function("document", "gsap", "window", "__hyperframes", '); - expect(wrapped).toContain('\\"\\"'); + expect(wrapped).toContain("(function(document, gsap, window, __hyperframes)"); + expect(wrapped).not.toContain("