Skip to content

Commit ccf25eb

Browse files
committed
Break out SafeTimers as well
Fix test_no_browser to check for MainLoop instead
1 parent 1fe9dc3 commit ccf25eb

File tree

9 files changed

+130
-111
lines changed

9 files changed

+130
-111
lines changed

src/library_async.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,9 +287,10 @@ mergeInto(LibraryManager.library, {
287287
},
288288
},
289289

290+
emscripten_sleep__deps: ['$SafeTimers'],
290291
emscripten_sleep: function(ms) {
291292
Asyncify.handleSleep(function(wakeUp) {
292-
MainLoop.safeSetTimeout(wakeUp, ms);
293+
SafeTimers.safeSetTimeout(wakeUp, ms);
293294
});
294295
},
295296

src/library_browser.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
// Utilities for browser environments
88
var LibraryBrowser = {
9-
$Browser__deps: ['$MainLoop'],
9+
$Browser__deps: ['$SafeTimers'],
1010
$Browser__postset: 'Module["requestFullscreen"] = function Module_requestFullscreen(lockPointer, resizeCanvas) { Browser.requestFullscreen(lockPointer, resizeCanvas) };\n' + // exports
1111
#if ASSERTIONS
1212
'Module["requestFullScreen"] = function Module_requestFullScreen() { Browser.requestFullScreen() };\n' +
@@ -156,7 +156,7 @@ var LibraryBrowser = {
156156
};
157157
audio.src = url;
158158
// workaround for chrome bug 124926 - we do not always get oncanplaythrough or onerror
159-
MainLoop.safeSetTimeout(function() {
159+
SafeTimers.safeSetTimeout(function() {
160160
finish(audio); // try to use it even though it is not necessarily ready to play
161161
}, 10000);
162162
} else {
@@ -940,12 +940,12 @@ var LibraryBrowser = {
940940
},
941941

942942
// Callable from pthread, executes in pthread context.
943-
emscripten_async_run_script__deps: ['emscripten_run_script', '$MainLoop'],
943+
emscripten_async_run_script__deps: ['emscripten_run_script', '$SafeTimers'],
944944
emscripten_async_run_script: function(script, millis) {
945945
noExitRuntime = true;
946946

947947
// TODO: cache these to avoid generating garbage
948-
MainLoop.safeSetTimeout(function() {
948+
SafeTimers.safeSetTimeout(function() {
949949
_emscripten_run_script(script);
950950
}, millis);
951951
},

src/library_glut.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -421,27 +421,27 @@ var LibraryGLUT = {
421421
}
422422
},
423423

424-
glutIdleFunc__deps: ['$MainLoop'],
424+
glutIdleFunc__deps: ['$SafeTimers'],
425425
glutIdleFunc__proxy: 'sync',
426426
glutIdleFunc__sig: 'vi',
427427
glutIdleFunc: function(func) {
428428
function callback() {
429429
if (GLUT.idleFunc) {
430430
{{{ makeDynCall('v', 'GLUT.idleFunc') }}}();
431-
MainLoop.safeSetTimeout(callback, 4); // HTML spec specifies a 4ms minimum delay on the main thread; workers might get more, but we standardize here
431+
SafeTimers.safeSetTimeout(callback, 4); // HTML spec specifies a 4ms minimum delay on the main thread; workers might get more, but we standardize here
432432
}
433433
}
434434
if (!GLUT.idleFunc) {
435-
MainLoop.safeSetTimeout(callback, 0);
435+
SafeTimers.safeSetTimeout(callback, 0);
436436
}
437437
GLUT.idleFunc = func;
438438
},
439439

440-
glutTimerFunc__deps: ['$MainLoop'],
440+
glutTimerFunc__deps: ['$SafeTimers'],
441441
glutTimerFunc__proxy: 'sync',
442442
glutTimerFunc__sig: 'viii',
443443
glutTimerFunc: function(msec, func, value) {
444-
MainLoop.safeSetTimeout(function() { {{{ makeDynCall('vi', 'func') }}}(value); }, msec);
444+
SafeTimers.safeSetTimeout(function() { {{{ makeDynCall('vi', 'func') }}}(value); }, msec);
445445
},
446446

447447
glutDisplayFunc__proxy: 'sync',
@@ -647,13 +647,13 @@ var LibraryGLUT = {
647647
glutSwapBuffers__sig: 'v',
648648
glutSwapBuffers: function() {},
649649

650-
glutPostRedisplay__deps: ['$MainLoop'],
650+
glutPostRedisplay__deps: ['$MainLoop', '$SafeTimers'],
651651
glutPostRedisplay__proxy: 'sync',
652652
glutPostRedisplay__sig: 'v',
653653
glutPostRedisplay: function() {
654654
if (GLUT.displayFunc && !GLUT.requestedAnimationFrame) {
655655
GLUT.requestedAnimationFrame = true;
656-
MainLoop.requestAnimationFrame(function() {
656+
SafeTimers.requestAnimationFrame(function() {
657657
GLUT.requestedAnimationFrame = false;
658658
MainLoop.runIter(function() {
659659
{{{ makeDynCall('v', 'GLUT.displayFunc') }}}();

src/library_mainloop.js

Lines changed: 5 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
var LibraryMainLoop = {
99
$MainLoop__deps: ['$setMainLoop', 'emscripten_set_main_loop_timing'],
1010
$MainLoop__postset: 'Module["pauseMainLoop"] = function Module_pauseMainLoop() { MainLoop.pause() };\n' +
11-
'Module["requestAnimationFrame"] = function Module_requestAnimationFrame(func) { MainLoop.requestAnimationFrame(func) };\n' +
1211
'Module["resumeMainLoop"] = function Module_resumeMainLoop() { MainLoop.resume() };\n',
1312

1413
$MainLoop: {
@@ -76,91 +75,6 @@ var LibraryMainLoop = {
7675
}
7776
if (Module['postMainLoop']) Module['postMainLoop']();
7877
},
79-
80-
nextRAF: 0,
81-
82-
fakeRequestAnimationFrame: function(func) {
83-
// try to keep 60fps between calls to here
84-
var now = Date.now();
85-
if (MainLoop.nextRAF === 0) {
86-
MainLoop.nextRAF = now + 1000/60;
87-
} else {
88-
while (now + 2 >= MainLoop.nextRAF) { // fudge a little, to avoid timer jitter causing us to do lots of delay:0
89-
MainLoop.nextRAF += 1000/60;
90-
}
91-
}
92-
var delay = Math.max(MainLoop.nextRAF - now, 0);
93-
setTimeout(func, delay);
94-
},
95-
96-
requestAnimationFrame: function(func) {
97-
if (typeof requestAnimationFrame === 'function') {
98-
requestAnimationFrame(func);
99-
return;
100-
}
101-
var RAF = MainLoop.fakeRequestAnimationFrame;
102-
#if LEGACY_VM_SUPPORT
103-
if (typeof window !== 'undefined') {
104-
RAF = window['requestAnimationFrame'] ||
105-
window['mozRequestAnimationFrame'] ||
106-
window['webkitRequestAnimationFrame'] ||
107-
window['msRequestAnimationFrame'] ||
108-
window['oRequestAnimationFrame'] ||
109-
RAF;
110-
}
111-
#endif
112-
RAF(func);
113-
},
114-
115-
// abort and pause-aware versions TODO: build main loop on top of this?
116-
117-
allowAsyncCallbacks: true,
118-
queuedAsyncCallbacks: [],
119-
120-
pauseAsyncCallbacks: function() {
121-
MainLoop.allowAsyncCallbacks = false;
122-
},
123-
resumeAsyncCallbacks: function() { // marks future callbacks as ok to execute, and synchronously runs any remaining ones right now
124-
MainLoop.allowAsyncCallbacks = true;
125-
if (MainLoop.queuedAsyncCallbacks.length > 0) {
126-
var callbacks = MainLoop.queuedAsyncCallbacks;
127-
MainLoop.queuedAsyncCallbacks = [];
128-
callbacks.forEach(function(func) {
129-
func();
130-
});
131-
}
132-
},
133-
134-
safeRequestAnimationFrame: function(func) {
135-
return MainLoop.requestAnimationFrame(function() {
136-
if (ABORT) return;
137-
if (MainLoop.allowAsyncCallbacks) {
138-
func();
139-
} else {
140-
MainLoop.queuedAsyncCallbacks.push(func);
141-
}
142-
});
143-
},
144-
safeSetTimeout: function(func, timeout) {
145-
noExitRuntime = true;
146-
return setTimeout(function() {
147-
if (ABORT) return;
148-
if (MainLoop.allowAsyncCallbacks) {
149-
func();
150-
} else {
151-
MainLoop.queuedAsyncCallbacks.push(func);
152-
}
153-
}, timeout);
154-
},
155-
safeSetInterval: function(func, timeout) {
156-
noExitRuntime = true;
157-
return setInterval(function() {
158-
if (ABORT) return;
159-
if (MainLoop.allowAsyncCallbacks) {
160-
func();
161-
} // drop it on the floor otherwise, next interval will kick in
162-
}, timeout);
163-
},
16478
},
16579

16680
// Runs natively in pthread, no __proxy needed.
@@ -170,6 +84,7 @@ var LibraryMainLoop = {
17084
},
17185

17286
// Runs natively in pthread, no __proxy needed.
87+
emscripten_set_main_loop_timing__deps: ['$SafeTimers'],
17388
emscripten_set_main_loop_timing: function(mode, value) {
17489
MainLoop.timingMode = mode;
17590
MainLoop.timingValue = value;
@@ -189,7 +104,7 @@ var LibraryMainLoop = {
189104
MainLoop.method = 'timeout';
190105
} else if (mode == 1 /*EM_TIMING_RAF*/) {
191106
MainLoop.scheduler = function MainLoop_scheduler_rAF() {
192-
MainLoop.requestAnimationFrame(MainLoop.runner);
107+
SafeTimers.requestAnimationFrame(MainLoop.runner);
193108
};
194109
MainLoop.method = 'rAF';
195110
} else if (mode == 2 /*EM_TIMING_SETIMMEDIATE*/) {
@@ -405,6 +320,7 @@ var LibraryMainLoop = {
405320
},
406321

407322
// Runs natively in pthread, no __proxy needed.
323+
emscripten_async_call__deps: ['$SafeTimers'],
408324
emscripten_async_call: function(func, arg, millis) {
409325
noExitRuntime = true;
410326

@@ -413,9 +329,9 @@ var LibraryMainLoop = {
413329
}
414330

415331
if (millis >= 0) {
416-
MainLoop.safeSetTimeout(wrapper, millis);
332+
SafeTimers.safeSetTimeout(wrapper, millis);
417333
} else {
418-
MainLoop.safeRequestAnimationFrame(wrapper);
334+
SafeTimers.safeRequestAnimationFrame(wrapper);
419335
}
420336
},
421337
};

src/library_safetimers.js

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/**
2+
* @license
3+
* Copyright 2020 The Emscripten Authors
4+
* SPDX-License-Identifier: MIT
5+
*/
6+
7+
// Safe timers
8+
var LibrarySafeTimers = {
9+
$SafeTimers__postset: 'Module["requestAnimationFrame"] = function Module_requestAnimationFrame(func) { SafeTimers.requestAnimationFrame(func) };\n',
10+
$SafeTimers: {
11+
// abort and pause-aware versions TODO: build main loop on top of this?
12+
13+
allowAsyncCallbacks: true,
14+
queuedAsyncCallbacks: [],
15+
16+
pauseAsyncCallbacks: function() {
17+
SafeTimers.allowAsyncCallbacks = false;
18+
},
19+
20+
resumeAsyncCallbacks: function() { // marks future callbacks as ok to execute, and synchronously runs any remaining ones right now
21+
SafeTimers.allowAsyncCallbacks = true;
22+
if (SafeTimers.queuedAsyncCallbacks.length > 0) {
23+
var callbacks = SafeTimers.queuedAsyncCallbacks;
24+
SafeTimers.queuedAsyncCallbacks = [];
25+
callbacks.forEach(function(func) {
26+
func();
27+
});
28+
}
29+
},
30+
31+
safeRequestAnimationFrame: function(func) {
32+
return SafeTimers.requestAnimationFrame(function() {
33+
if (ABORT) return;
34+
if (SafeTimers.allowAsyncCallbacks) {
35+
func();
36+
} else {
37+
SafeTimers.queuedAsyncCallbacks.push(func);
38+
}
39+
});
40+
},
41+
42+
safeSetTimeout: function(func, timeout) {
43+
noExitRuntime = true;
44+
return setTimeout(function() {
45+
if (ABORT) return;
46+
if (SafeTimers.allowAsyncCallbacks) {
47+
func();
48+
} else {
49+
SafeTimers.queuedAsyncCallbacks.push(func);
50+
}
51+
}, timeout);
52+
},
53+
54+
safeSetInterval: function(func, timeout) {
55+
noExitRuntime = true;
56+
return setInterval(function() {
57+
if (ABORT) return;
58+
if (SafeTimers.allowAsyncCallbacks) {
59+
func();
60+
} // drop it on the floor otherwise, next interval will kick in
61+
}, timeout);
62+
},
63+
64+
nextRAF: 0,
65+
66+
fakeRequestAnimationFrame: function(func) {
67+
// try to keep 60fps between calls to here
68+
var now = Date.now();
69+
if (SafeTimers.nextRAF === 0) {
70+
SafeTimers.nextRAF = now + 1000/60;
71+
} else {
72+
while (now + 2 >= SafeTimers.nextRAF) { // fudge a little, to avoid timer jitter causing us to do lots of delay:0
73+
SafeTimers.nextRAF += 1000/60;
74+
}
75+
}
76+
var delay = Math.max(SafeTimers.nextRAF - now, 0);
77+
setTimeout(func, delay);
78+
},
79+
80+
requestAnimationFrame: function(func) {
81+
if (typeof requestAnimationFrame === 'function') {
82+
requestAnimationFrame(func);
83+
return;
84+
}
85+
var RAF = SafeTimers.fakeRequestAnimationFrame;
86+
#if LEGACY_VM_SUPPORT
87+
if (typeof window !== 'undefined') {
88+
RAF = window['requestAnimationFrame'] ||
89+
window['mozRequestAnimationFrame'] ||
90+
window['webkitRequestAnimationFrame'] ||
91+
window['msRequestAnimationFrame'] ||
92+
window['oRequestAnimationFrame'] ||
93+
RAF;
94+
}
95+
#endif
96+
RAF(func);
97+
},
98+
},
99+
};
100+
101+
mergeInto(LibraryManager.library, LibrarySafeTimers);

src/library_sdl.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ var LibrarySDL = {
3030
'$FS',
3131
#endif
3232
'$PATH', '$Browser', 'SDL_GetTicks', 'SDL_LockSurface',
33-
'$SDL_unicode', '$SDL_ttfContext', '$SDL_audio', '$MainLoop'
33+
'$SDL_unicode', '$SDL_ttfContext', '$SDL_audio', '$MainLoop', '$SafeTimers'
3434
],
3535
$SDL: {
3636
defaults: {
@@ -2532,12 +2532,12 @@ var LibrarySDL = {
25322532

25332533
if (SDL.audio.numAudioTimersPending < SDL.audio.numSimultaneouslyQueuedBuffers) {
25342534
++SDL.audio.numAudioTimersPending;
2535-
SDL.audio.timer = MainLoop.safeSetTimeout(SDL.audio.caller, Math.max(0.0, 1000.0*(secsUntilNextPlayStart-preemptBufferFeedSecs)));
2535+
SDL.audio.timer = SafeTimers.safeSetTimeout(SDL.audio.caller, Math.max(0.0, 1000.0*(secsUntilNextPlayStart-preemptBufferFeedSecs)));
25362536

25372537
// If we are risking starving, immediately queue an extra buffer.
25382538
if (SDL.audio.numAudioTimersPending < SDL.audio.numSimultaneouslyQueuedBuffers) {
25392539
++SDL.audio.numAudioTimersPending;
2540-
MainLoop.safeSetTimeout(SDL.audio.caller, 1.0);
2540+
SafeTimers.safeSetTimeout(SDL.audio.caller, 1.0);
25412541
}
25422542
}
25432543
};
@@ -2648,7 +2648,7 @@ var LibrarySDL = {
26482648
} else if (!SDL.audio.timer) {
26492649
// Start the audio playback timer callback loop.
26502650
SDL.audio.numAudioTimersPending = 1;
2651-
SDL.audio.timer = MainLoop.safeSetTimeout(SDL.audio.caller, 1);
2651+
SDL.audio.timer = SafeTimers.safeSetTimeout(SDL.audio.caller, 1);
26522652
}
26532653
SDL.audio.paused = pauseOn;
26542654
},

src/modules.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ var LibraryManager = {
9292
} else {
9393
libraries.push('library_browser.js');
9494
libraries.push('library_mainloop.js');
95+
libraries.push('library_safetimers.js');
9596
}
9697

9798
if (USE_PTHREADS) { // TODO: Currently WebGL proxying makes pthreads library depend on WebGL.

src/proxyWorker.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ window.scrollX = window.scrollY = 0; // TODO: proxy these
143143
window.WebGLRenderingContext = WebGLWorker;
144144

145145
window.requestAnimationFrame = (function() {
146-
// similar to MainLoop.requestAnimationFrame
146+
// similar to SafeTimers.requestAnimationFrame
147147
var nextRAF = 0;
148148
return function(func) {
149149
// try to keep 60fps between calls to here

0 commit comments

Comments
 (0)