Skip to content

Commit 5d92448

Browse files
committed
Prevent Playback WebGL status events from reentering Unity
Playback status is exposed as a browser event for website integration. If a host page or injected listener synchronously calls THUAI9Unity APIs while handling that status event, Unity can immediately SendMessage back into itself and emit another forced status event on the same JavaScript stack. Dispatching playback status on the next browser task and suppressing identical forced payloads breaks that loop without changing the public website API. Constraint: Keep existing website-facing THUAI9Unity and thuai9-playback-status APIs compatible Rejected: Remove playback-status events entirely | website integrations still need status updates Rejected: Make all Unity events asynchronous | playback-loading must stay ordered before the actual load call Confidence: high Scope-risk: narrow Directive: Do not let identical playback-status payloads bypass de-duplication, even for command responses Tested: Unity Playback WebGL build completed successfully Tested: CDP-injected status listener synchronously calling THUAI9Unity.play no longer triggers RangeError Tested: Query-url load of latest truncated playback reports 11865 loaded frames with incomplete-tail warning Tested: Latest v9 and old v7 playback samples still parse through MessageReader Tested: Unity-Playback-WebGL.zip matches playback directory SHA256 for all 17 files Tested: dotnet format whitespace Unity-Playback scripts --verify-no-changes Tested: WebGL root/live/playback/trial HTTP smoke returned 200 from interface Unity-WebGL root Not-tested: Manual click test in the user's exact browser profile
1 parent 21dfc16 commit 5d92448

6 files changed

Lines changed: 14 additions & 4 deletions

File tree

interface/Unity/Unity-Playback/Assets/Plugins/WebGL/THUAI9WebGLBridge.jslib

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ mergeInto(LibraryManager.library, {
3838
if (typeof window.CustomEvent === 'function') { window.dispatchEvent(new CustomEvent(eventName, { detail: detail })); return; }
3939
var event = document.createEvent('CustomEvent'); event.initCustomEvent(eventName, false, false, detail); window.dispatchEvent(event);
4040
},
41+
dispatchCustomEventLater: function (eventName, detail) {
42+
var dispatch = function () { THUAI9WebGLBridge.dispatchCustomEvent(eventName, detail); };
43+
if (typeof window.setTimeout === 'function') { window.setTimeout(dispatch, 0); return; }
44+
dispatch();
45+
},
4146
revokeActivePlaybackObjectUrl: function () {
4247
if (!THUAI9WebGLBridge.activePlaybackObjectUrl) return;
4348
try { URL.revokeObjectURL(THUAI9WebGLBridge.activePlaybackObjectUrl); } catch (_) {}
@@ -117,8 +122,11 @@ mergeInto(LibraryManager.library, {
117122
THUAI9_DispatchUnityEvent__deps: ['$THUAI9WebGLBridge'],
118123
THUAI9_DispatchUnityEvent: function (eventNamePtr, payloadPtr) {
119124
var eventName = UTF8ToString(eventNamePtr); var payload = UTF8ToString(payloadPtr);
120-
THUAI9WebGLBridge.dispatchCustomEvent('thuai9-unity-event', { eventName: eventName, payload: payload });
121-
THUAI9WebGLBridge.dispatchCustomEvent('thuai9-' + eventName, payload);
125+
var dispatch = eventName === 'playback-status'
126+
? THUAI9WebGLBridge.dispatchCustomEventLater
127+
: THUAI9WebGLBridge.dispatchCustomEvent;
128+
dispatch('thuai9-unity-event', { eventName: eventName, payload: payload });
129+
dispatch('thuai9-' + eventName, payload);
122130
if (eventName === 'playback-error' || (eventName === 'playback-status' && THUAI9WebGLBridge.isTerminalPlaybackStatus(payload))) {
123131
THUAI9WebGLBridge.revokeActivePlaybackObjectUrl();
124132
}

interface/Unity/Unity-Playback/Assets/Scripts/WebGL/WebGLFrameBridge.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,9 @@ private void DispatchPlaybackStatus(bool force)
212212
statusText = playbackController.StatusText
213213
});
214214

215-
if (!force && payload == lastStatusPayload)
215+
// Even forced command responses must not re-emit an identical status.
216+
// Host pages may synchronously call back into Unity from status listeners.
217+
if (payload == lastStatusPayload)
216218
{
217219
return;
218220
}
67 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.

interface/Unity/Unity-WebGL/playback/Build/playback.framework.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
-8 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)