@@ -1494,6 +1494,33 @@ describe("HyperframesPlayer srcdoc attribute", () => {
14941494 | undefined ;
14951495 expect ( ctor ) . toBeDefined ( ) ;
14961496 expect ( ctor ! . observedAttributes ) . toContain ( "srcdoc" ) ;
1497+ expect ( ctor ! . observedAttributes ) . toContain ( "runtime-src" ) ;
1498+ } ) ;
1499+
1500+ it ( "uses a configured runtime source for loopback srcdoc" , ( ) => {
1501+ const player = document . createElement ( "hyperframes-player" ) as PlayerInternal ;
1502+ player . setAttribute ( "runtime-src" , "http://127.0.0.1:8900/hyperframe.runtime.iife.js" ) ;
1503+ player . setAttribute ( "srcdoc" , "<!doctype html><html><head></head><body></body></html>" ) ;
1504+ document . body . appendChild ( player ) ;
1505+
1506+ expect ( player . iframe . getAttribute ( "srcdoc" ) ) . toContain (
1507+ '<script src="http://127.0.0.1:8900/hyperframe.runtime.iife.js"></script>' ,
1508+ ) ;
1509+
1510+ player . remove ( ) ;
1511+ } ) ;
1512+
1513+ it ( "falls back to the pinned runtime for an unsafe runtime source" , ( ) => {
1514+ const player = document . createElement ( "hyperframes-player" ) as PlayerInternal ;
1515+ player . setAttribute ( "runtime-src" , 'javascript:alert("no")' ) ;
1516+ player . setAttribute ( "srcdoc" , "<!doctype html><html><head></head><body></body></html>" ) ;
1517+ document . body . appendChild ( player ) ;
1518+
1519+ const srcdoc = player . iframe . getAttribute ( "srcdoc" ) ?? "" ;
1520+ expect ( srcdoc ) . not . toContain ( "javascript:" ) ;
1521+ expect ( srcdoc ) . toContain ( "hyperframe.runtime.iife.js" ) ;
1522+
1523+ player . remove ( ) ;
14971524 } ) ;
14981525
14991526 it ( "forwards an initial srcdoc attribute to the iframe on connect" , ( ) => {
@@ -1961,6 +1988,8 @@ describe("HyperframesPlayer runtime ready handshake", () => {
19611988 paused : boolean ;
19621989 iframe : HTMLIFrameElement ;
19631990 _onMessage : ( event : MessageEvent ) => void ;
1991+ _onIframeLoad : ( ) => void ;
1992+ _runtimeBridgeReady : boolean ;
19641993 }
19651994
19661995 let player : PlayerInternal ;
@@ -2102,6 +2131,15 @@ describe("HyperframesPlayer runtime ready handshake", () => {
21022131 expect ( findControlCalls ( "set-muted" ) ) . toHaveLength ( 2 ) ;
21032132 } ) ;
21042133
2134+ it ( "does not erase a DOMContentLoaded runtime handshake when iframe load follows it" , ( ) => {
2135+ player . _onMessage ( readyMessage ( ) ) ;
2136+ expect ( player . _runtimeBridgeReady ) . toBe ( true ) ;
2137+
2138+ player . _onIframeLoad ( ) ;
2139+
2140+ expect ( player . _runtimeBridgeReady ) . toBe ( true ) ;
2141+ } ) ;
2142+
21052143 it ( "ignores ready events from a different window" , ( ) => {
21062144 postSpy . mockClear ( ) ;
21072145 const otherSource = { } as Window ;
0 commit comments