Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d486dc1
Add pthreads support to MINIMAL_RUNTIME.
juj Dec 6, 2019
4a787fe
Multithreaded MINIMAL_RUNTIME builds working with MODULARIZE.
juj Dec 29, 2019
4b8db00
Fix up MINIMAL_RUNTIME pthreads
juj Feb 5, 2020
f8e47fe
Pthreads fixes in MINIMAL_RUNTIME.
juj Feb 5, 2020
fa9759a
MINIMAL_RUNTIME fixes to pthreads.
juj Feb 5, 2020
ae6f617
Add threading related closure externs
juj Feb 5, 2020
8a215be
Remove 'establishStackSpace' variable.
juj Feb 6, 2020
b532545
Rename establishStackSpaceInJsModule to establishStackSpace.
juj Feb 6, 2020
8713949
flake
juj Feb 9, 2020
405d731
pthread_cleanup_push needs ATEXIT registration only if EXIT_RUNTIME=1.
juj Feb 9, 2020
e91ee95
Offset Converter loading for MINIMAL_RUNTIME pthreads
juj Feb 9, 2020
cbb28db
Add note about MODULARIZE_INSTANCE with MINIMAL_RUNTIME=1
juj Feb 9, 2020
8c7e3d3
MODULARIZE_INSTANCE working with MINIMAL_RUNTIME.
juj Feb 10, 2020
1a0d4e2
Fix Closure error
juj Feb 11, 2020
ddd2ff8
Separate MINIMAL_RUNTIME + USE_PTHREADS + !MODULARIZE externs to its …
juj Feb 11, 2020
ef424d9
Remove unused function makeAsmImportsAccessInPthread
juj Feb 11, 2020
e09448f
Remove unused STREAMING_WASM_COMPILATION
juj Feb 11, 2020
46e4e03
More closure externs
juj Feb 11, 2020
374ab6d
Update call_sync_on_main_thread test
juj Feb 12, 2020
a2dd850
Fix emscripten_check_blocking_allowed
juj Feb 12, 2020
4b8e4c5
Restore asm.js specific function for setting the stack frame
juj Feb 12, 2020
26395c7
Add phread exports to MINIMAL_RUNTIME
juj Feb 12, 2020
eac77f1
Remove removeEmptyElements(x) as redundant
juj Feb 12, 2020
9188ac7
Remove duplicate MINIMAL_RUNTIME pthread test
juj Feb 12, 2020
ad9e79c
Add deduplication of JS library files
juj Feb 14, 2020
eea85f6
makeAsmImportsAccessInPthread('wasm')
juj Feb 14, 2020
61d0ea0
Address review
juj Feb 14, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 19 additions & 13 deletions emcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -1294,6 +1294,7 @@ def is_supported_link_flag(f):
if shared.Settings.STACK_OVERFLOW_CHECK:
if shared.Settings.MINIMAL_RUNTIME:
shared.Settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$abortStackOverflow']
shared.Settings.EXPORTED_RUNTIME_METHODS += ['writeStackCookie', 'checkStackCookie']
else:
shared.Settings.EXPORTED_RUNTIME_METHODS += ['writeStackCookie', 'checkStackCookie', 'abortStackOverflow']

Expand Down Expand Up @@ -1528,16 +1529,17 @@ def is_supported_link_flag(f):
]

if shared.Settings.USE_PTHREADS:
shared.Settings.EXPORTED_RUNTIME_METHODS += ['establishStackSpace']

# memalign is used to ensure allocated thread stacks are aligned.
shared.Settings.EXPORTED_FUNCTIONS += ['_memalign']
shared.Settings.EXPORTED_FUNCTIONS += ['_memalign', '_malloc']

# dynCall_ii is used to call pthread entry points in worker.js (as
# metadce does not consider worker.js, which is external, we must
# consider it a user export, i.e., one which can never be removed).
shared.Building.user_requested_exports += ['dynCall_ii']

if shared.Settings.MINIMAL_RUNTIME:
shared.Building.user_requested_exports += ['exit']

if shared.Settings.PROXY_TO_PTHREAD:
shared.Settings.EXPORTED_FUNCTIONS += ['_proxy_main']

Expand All @@ -1546,15 +1548,22 @@ def include_and_export(name):
shared.Settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$' + name]
shared.Settings.EXPORTED_FUNCTIONS += [name]

include_and_export('establishStackSpaceInJsModule')
include_and_export('getNoExitRuntime')
include_and_export('establishStackSpace')
if not shared.Settings.MINIMAL_RUNTIME:
# noExitRuntime does not apply to MINIMAL_RUNTIME.
include_and_export('getNoExitRuntime')

if shared.Settings.MODULARIZE:
# MODULARIZE+USE_PTHREADS mode requires extra exports out to Module so that worker.js
# can access them:

# general threading variables:
shared.Settings.EXPORTED_RUNTIME_METHODS += ['PThread', 'ExitStatus']
shared.Settings.EXPORTED_RUNTIME_METHODS += ['PThread']

# To keep code size to minimum, MINIMAL_RUNTIME does not utilize the global ExitStatus
# object, only regular runtime has it.
if not shared.Settings.MINIMAL_RUNTIME:
shared.Settings.EXPORTED_RUNTIME_METHODS += ['ExitStatus']

# stack check:
if shared.Settings.STACK_OVERFLOW_CHECK:
Expand Down Expand Up @@ -1921,9 +1930,6 @@ def check_human_readable_list(items):
if shared.Settings.EMTERPRETIFY:
exit_with_error('-s EMTERPRETIFY=1 is not supported with -s MINIMAL_RUNTIME=1')

if shared.Settings.USE_PTHREADS:
exit_with_error('-s USE_PTHREADS=1 is not yet supported with -s MINIMAL_RUNTIME=1')

if shared.Settings.PRECISE_F32 == 2:
exit_with_error('-s PRECISE_F32=2 is not supported with -s MINIMAL_RUNTIME=1')

Expand Down Expand Up @@ -3327,8 +3333,9 @@ def modularize():
logger.debug('Modularizing, assigning to var ' + shared.Settings.EXPORT_NAME)
src = open(final).read()

# TODO: exports object generation for MINIMAL_RUNTIME
exports_object = '{}' if shared.Settings.MINIMAL_RUNTIME else shared.Settings.EXPORT_NAME
# TODO: exports object generation for MINIMAL_RUNTIME. As a temp measure, multithreaded MINIMAL_RUNTIME builds export like regular
# runtime does, so that worker.js can see the JS module contents.
exports_object = '{}' if shared.Settings.MINIMAL_RUNTIME and not shared.Settings.USE_PTHREADS else shared.Settings.EXPORT_NAME

src = '''
function(%(EXPORT_NAME)s) {
Expand Down Expand Up @@ -3424,8 +3431,7 @@ def module_export_name_substitution():
src = src.replace(shared.JS.module_export_name_substitution_pattern, replacement)
# For Node.js and other shell environments, create an unminified Module object so that
# loading external .asm.js file that assigns to Module['asm'] works even when Closure is used.
if shared.Settings.MINIMAL_RUNTIME and (shared.Settings.target_environment_may_be('node') or
shared.Settings.target_environment_may_be('shell')):
if shared.Settings.MINIMAL_RUNTIME and not shared.Settings.MODULARIZE_INSTANCE and (shared.Settings.target_environment_may_be('node') or shared.Settings.target_environment_may_be('shell')):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why does modularize_instance matter here? (and, why not modularize?)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MODULARIZE_INSTANCE creates the Module on the next line, emitting

if(typeof Module==="undefined"){var Module={};}
var Module = (

would be redundant for code size.

src = 'if(typeof Module==="undefined"){var Module={};}' + src
f.write(src)
save_intermediate('module_export_name_substitution')
Expand Down
24 changes: 14 additions & 10 deletions emscripten.py
Original file line number Diff line number Diff line change
Expand Up @@ -943,8 +943,8 @@ def get_exported_implemented_functions(all_exported_functions, all_implemented,
funcs.append('_emscripten_replace_memory')
if not shared.Settings.SIDE_MODULE and not shared.Settings.MINIMAL_RUNTIME:
funcs += ['stackAlloc', 'stackSave', 'stackRestore']
if shared.Settings.USE_PTHREADS:
funcs += ['establishStackSpace']
if shared.Settings.USE_PTHREADS:
funcs += ['asmJsEstablishStackFrame']

if shared.Settings.EMTERPRETIFY:
funcs += ['emterpret']
Expand Down Expand Up @@ -1675,8 +1675,6 @@ def create_asm_runtime_funcs():
funcs = []
if not (shared.Settings.WASM and shared.Settings.SIDE_MODULE) and not shared.Settings.MINIMAL_RUNTIME:
funcs += ['stackAlloc', 'stackSave', 'stackRestore']
if shared.Settings.USE_PTHREADS:
funcs += ['establishStackSpace']
return funcs


Expand Down Expand Up @@ -1887,9 +1885,13 @@ def create_runtime_funcs_asmjs(exports, metadata):
}
''' % stack_check]

if shared.Settings.MINIMAL_RUNTIME:
# MINIMAL_RUNTIME moves stack functions to library.
funcs = []

if shared.Settings.USE_PTHREADS:
funcs.append('''
function establishStackSpace(stackBase, stackMax) {
function asmJsEstablishStackFrame(stackBase, stackMax) {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed this to highlight the fact that this functionality is only needed for old fastcomp threading support.

stackBase = stackBase|0;
stackMax = stackMax|0;
STACKTOP = stackBase;
Expand All @@ -1899,10 +1901,6 @@ def create_runtime_funcs_asmjs(exports, metadata):
}
''')

if shared.Settings.MINIMAL_RUNTIME:
# MINIMAL_RUNTIME moves stack functions to library.
funcs = []

if shared.Settings.EMTERPRETIFY:
funcs.append('''
function emterpret(pc) { // this will be replaced when the emterpreter code is generated; adding it here allows validation until then
Expand Down Expand Up @@ -2645,7 +2643,13 @@ def create_receiving_wasm(exports, initializers):
# In wasm2js exports can be directly processed at top level, i.e.
# var asm = Module["asm"](asmGlobalArg, asmLibraryArg, buffer);
# var _main = asm["_main"];
receiving += ['var ' + asmjs_mangle(s) + ' = asm["' + asmjs_mangle(s) + '"];' for s in exports_that_are_not_initializers]
if shared.Settings.USE_PTHREADS and shared.Settings.MODULARIZE:
# TODO: As a temp solution, multithreaded MODULARIZEd MINIMAL_RUNTIME builds export all symbols like regular runtime does.
# Fix this by migrating worker.js code to reside inside the Module so it is in the same scope as the rest of the JS code, or
# by defining an export syntax to MINIMAL_RUNTIME that multithreaded MODULARIZEd builds can export on.
receiving += [asmjs_mangle(s) + ' = Module["' + asmjs_mangle(s) + '"] = asm["' + s + '"];' for s in exports_that_are_not_initializers]
else:
receiving += ['var ' + asmjs_mangle(s) + ' = asm["' + asmjs_mangle(s) + '"];' for s in exports_that_are_not_initializers]
else:
receiving += ['var ' + asmjs_mangle(s) + ' = Module["' + asmjs_mangle(s) + '"] = asm["' + s + '"];' for s in exports]
else:
Expand Down
12 changes: 12 additions & 0 deletions src/closure-externs.js
Original file line number Diff line number Diff line change
Expand Up @@ -975,3 +975,15 @@ var outerWidth;
var outerHeight;
var event;
var devicePixelRatio;

// TODO: Use Closure's multifile support and/or migrate worker.js onmessage handler to inside the MODULARIZEd block
// to be able to remove all the variables below:

// Variables that are present in both output runtime .js file/JS lib files, and worker.js, so cannot be minified because
// the names need to match:
/** @suppress {duplicate} */
var threadInfoStruct;
/** @suppress {duplicate} */
var selfThreadId;
/** @suppress {duplicate} */
var noExitRuntime;
17 changes: 6 additions & 11 deletions src/library.js
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,12 @@ LibraryManager.library = {
_Exit__sig: 'vi',
_Exit: 'exit',

#if MINIMAL_RUNTIME
$exit: function(status) {
throw 'exit(' + status + ')';
},
#endif

fork__deps: ['__setErrNo'],
fork: function() {
// pid_t fork(void);
Expand Down Expand Up @@ -1353,17 +1359,6 @@ LibraryManager.library = {
},
#endif

#if USE_PTHREADS
$establishStackSpace__asm: true,
$establishStackSpace__sig: 'vii',
$establishStackSpace: function(stackBase, stackMax) {
stackBase = stackBase|0;
stackMax = stackMax|0;
STACKTOP = stackBase;
STACK_MAX = stackMax;
},
#endif

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This deletion is not strictly related to MINIMAL_RUNTIME multithreading support, but while doing this PR I realized this whole function is redundant, so simplified the code.

#if WASM_BACKEND == 0
$setThrew__asm: true,
$setThrew__sig: 'vii',
Expand Down
68 changes: 56 additions & 12 deletions src/library_pthread.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ var LibraryPThread = {
_emscripten_register_main_browser_thread_id(PThread.mainThreadBlock);
},
initMainThreadBlock: function() {
if (ENVIRONMENT_IS_PTHREAD) return;
#if ASSERTIONS
assert(!ENVIRONMENT_IS_PTHREAD);
#endif

#if PTHREAD_POOL_SIZE
var pthreadPoolSize = {{{ PTHREAD_POOL_SIZE }}};
Expand Down Expand Up @@ -374,8 +376,8 @@ var LibraryPThread = {
#endif

#if ASSERTIONS && WASM
assert(wasmMemory, 'WebAssembly memory should have been loaded by now!');
assert(wasmModule, 'WebAssembly Module should have been loaded by now!');
assert(wasmMemory instanceof WebAssembly.Memory, 'WebAssembly memory should have been loaded by now!');
assert(wasmModule instanceof WebAssembly.Module, 'WebAssembly Module should have been loaded by now!');
#endif

// Ask the new worker to load up the Emscripten-compiled page. This is a heavy operation.
Expand All @@ -400,17 +402,23 @@ var LibraryPThread = {
'buffer': HEAPU8.buffer,
'asmJsUrlOrBlob': Module["asmJsUrlOrBlob"],
#endif
#if !MINIMAL_RUNTIME
'DYNAMIC_BASE': DYNAMIC_BASE,
#endif

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In MINIMAL_RUNTIME the DYNAMIC_BASE variable is not a thing.

'DYNAMICTOP_PTR': DYNAMICTOP_PTR
});
},

// Creates a new web Worker and places it in the unused worker pool to wait for its use.
allocateUnusedWorker: function() {
#if MINIMAL_RUNTIME
var pthreadMainJs = Module['worker'];

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This use of Module['worker'] is probably temporary/internal, and will go away later as the src/worker.js refactor happens.

#else
// Allow HTML module to configure the location where the 'worker.js' file will be loaded from,
// via Module.locateFile() function. If not specified, then the default URL 'worker.js' relative
// to the main html file is loaded.
var pthreadMainJs = locateFile('{{{ PTHREAD_WORKER_FILE }}}');
#endif
#if PTHREADS_DEBUG
out('Allocating a new web worker from ' + pthreadMainJs);
#endif
Expand Down Expand Up @@ -550,7 +558,7 @@ var LibraryPThread = {
return navigator['hardwareConcurrency'];
},

{{{ USE_LSAN || USE_ASAN ? 'emscripten_builtin_' : '' }}}pthread_create__deps: ['_spawn_thread', 'pthread_getschedparam', 'pthread_self', 'memalign'],
{{{ USE_LSAN || USE_ASAN ? 'emscripten_builtin_' : '' }}}pthread_create__deps: ['_spawn_thread', 'pthread_getschedparam', 'pthread_self', 'memalign', '$resetPrototype'],
{{{ USE_LSAN || USE_ASAN ? 'emscripten_builtin_' : '' }}}pthread_create: function(pthread_ptr, attr, start_routine, arg) {
if (typeof SharedArrayBuffer === 'undefined') {
err('Current environment does not support SharedArrayBuffer, pthreads are not available!');
Expand Down Expand Up @@ -769,17 +777,30 @@ var LibraryPThread = {
if (canceled == 2) throw 'Canceled!';
},

#if MINIMAL_RUNTIME
emscripten_check_blocking_allowed__deps: ['$warnOnce'],
#endif
emscripten_check_blocking_allowed: function() {
#if ASSERTIONS
assert(ENVIRONMENT_IS_WEB);
warnOnce('Blocking on the main thread is very dangerous, see https://emscripten.org/docs/porting/pthreads.html#blocking-on-the-main-browser-thread');
#if ASSERTIONS || IN_TEST_HARNESS || !MINIMAL_RUNTIME || !ALLOW_BLOCKING_ON_MAIN_THREAD

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why !MINIMAL_RUNTIME is here? This code is already behind ASSERTIONS, so it won't be in an optimized build with the minimal runtime or not? I think it's useful in assertion builds to have maximal checks, regardless of runtime.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, that is a || !MINIMAL_RUNTIME statement and not a && !MINIMAL_RUNTIME statement. The || !MINIMAL_RUNTIME statement is here so that regular runtime will get the non-assertion release builds also to contain the allow blocking checks.

#if ENVIRONMENT_MAY_BE_NODE
if (ENVIRONMENT_IS_NODE) return;
#endif

if (ENVIRONMENT_IS_PTHREAD) return; // Blocking in a pthread is fine.

warnOnce('Blocking on the main thread is very dangerous, see https://emscripten.org/docs/porting/pthreads.html#blocking-on-the-main-browser-thread');
#if !ALLOW_BLOCKING_ON_MAIN_THREAD
abort('Blocking on the main thread is not allowed by default. See https://emscripten.org/docs/porting/pthreads.html#blocking-on-the-main-browser-thread');
#endif

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In MINIMAL_RUNTIME we do not want to pay code size for emscripten_check_blocking_allowed type of checks, so this is not generated there.

#endif
},

_emscripten_do_pthread_join__deps: ['_cleanup_thread', '_pthread_testcancel_js', 'emscripten_main_thread_process_queued_calls', 'emscripten_futex_wait', 'emscripten_check_blocking_allowed'],
_emscripten_do_pthread_join__deps: ['_cleanup_thread', '_pthread_testcancel_js', 'emscripten_main_thread_process_queued_calls', 'emscripten_futex_wait',
#if ASSERTIONS || IN_TEST_HARNESS || !MINIMAL_RUNTIME || !ALLOW_BLOCKING_ON_MAIN_THREAD
'emscripten_check_blocking_allowed'
#endif
],
_emscripten_do_pthread_join: function(thread, status, block) {
if (!thread) {
err('pthread_join attempted on a null thread pointer!');
Expand All @@ -805,9 +826,11 @@ var LibraryPThread = {
return ERRNO_CODES.EINVAL; // The thread is already detached, can no longer join it!
}

if (block && ENVIRONMENT_IS_WEB) {
#if ASSERTIONS || IN_TEST_HARNESS || !MINIMAL_RUNTIME || !ALLOW_BLOCKING_ON_MAIN_THREAD
if (block) {
_emscripten_check_blocking_allowed();
}
#endif

for (;;) {
var threadStatus = Atomics.load(HEAPU32, (thread + {{{ C_STRUCTS.pthread.threadStatus }}} ) >> 2);
Expand Down Expand Up @@ -1057,9 +1080,11 @@ var LibraryPThread = {
pthread_cleanup_push: function(routine, arg) {
if (PThread.exitHandlers === null) {
PThread.exitHandlers = [];
#if EXIT_RUNTIME
if (!ENVIRONMENT_IS_PTHREAD) {
__ATEXIT__.push(function() { PThread.runExitHandlers(); });
}
#endif
}
PThread.exitHandlers.push(function() { {{{ makeDynCall('vi') }}}(routine, arg) });
},
Expand Down Expand Up @@ -1297,7 +1322,7 @@ var LibraryPThread = {
return func.apply(null, _emscripten_receive_on_main_thread_js_callArgs);
},

$establishStackSpaceInJsModule: function(stackTop, stackMax) {
$establishStackSpace: function(stackTop, stackMax) {
STACK_BASE = STACKTOP = stackTop;
STACK_MAX = stackMax;

Expand All @@ -1318,15 +1343,34 @@ var LibraryPThread = {
#if STACK_OVERFLOW_CHECK
writeStackCookie();
#endif
// Call inside asm.js/wasm module to set up the stack frame for this pthread in asm.js/wasm module scope
establishStackSpace(stackTop, stackMax);

#if WASM_BACKEND
// Call inside wasm module to set up the stack frame for this pthread in asm.js/wasm module scope
stackRestore(stackTop);
#else
// In old asm.js backend, use a dedicated function to establish the stack frame.
asmJsEstablishStackFrame(stackTop, stackMax);
#endif
},

// allow pthreads to check if noExitRuntime from worker.js
$getNoExitRuntime: function() {
return noExitRuntime;
},

// When using postMessage to send an object, it is processed by the structured clone algorithm.
// The prototype, and hence methods, on that object is then lost. This function adds back the lost prototype.
// This does not work with nested objects that has prototypes, but it suffices for WasmSourceMap and WasmOffsetConverter.
$resetPrototype: function(constructor, attrs) {
var object = Object.create(constructor.prototype);
for (var key in attrs) {
if (attrs.hasOwnProperty(key)) {
object[key] = attrs[key];
}
}
return object;
},

// This function is called internally to notify target thread ID that it has messages it needs to
// process in its message queue inside the Wasm heap. As a helper, the caller must also pass the
// ID of the main browser thread to this function, to avoid needlessly ping-ponging between JS and
Expand Down
4 changes: 4 additions & 0 deletions src/library_syscall.js
Original file line number Diff line number Diff line change
Expand Up @@ -1153,6 +1153,10 @@ var SyscallsLibrary = {
}
#endif // SYSCALLS_REQUIRE_FILESYSTEM
},

#if MINIMAL_RUNTIME
__syscall252__deps: ['$exit'],
#endif
__syscall252: function(which, varargs) { // exit_group
var status = SYSCALLS.get();
exit(status);
Expand Down
4 changes: 4 additions & 0 deletions src/memoryprofiler.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#if MEMORYPROFILER

// Copyright 2015 The Emscripten Authors. All rights reserved.
// Emscripten is available under two separate licenses, the MIT license and the
// University of Illinois/NCSA Open Source License. Both these licenses can be
Expand Down Expand Up @@ -597,3 +599,5 @@ var emscriptenMemoryProfiler = {
function memoryprofiler_add_hooks() { emscriptenMemoryProfiler.initialize(); }

if (typeof Module !== 'undefined' && typeof document !== 'undefined' && typeof window !== 'undefined' && typeof process === 'undefined') emscriptenMemoryProfiler.initialize();

#endif

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving this #ifdef was done to be more idiomatic with include guards (the file itself guards, rather than the includer of that file)

6 changes: 6 additions & 0 deletions src/minimal_runtime_worker_externs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// These externs are needed for MINIMAL_RUNTIME + USE_PTHREADS + !MODULARIZE
// This file should go away in the future when worker.js is refactored to live inside the JS module.

var ENVIRONMENT_IS_PTHREAD;
/** @suppress {duplicate} */
var wasmMemory;
Loading