Skip to content

Commit 3e1cffc

Browse files
authored
Automatically enable worker ENVIRONMENT when needed (#24525)
- Similar to #14151 but for more combos. - Fixes #14162.
1 parent 659aad1 commit 3e1cffc

File tree

5 files changed

+29
-29
lines changed

5 files changed

+29
-29
lines changed

ChangeLog.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ See docs/process.md for more on how version tagging works.
2020

2121
4.0.11 (in development)
2222
-----------------------
23-
23+
- The `ENVIRONMENT` setting will now be automatically updated to include
24+
`worker` if multi-threading is enabled. (#24525)
2425

2526
4.0.10 - 06/07/25
2627
-----------------

test/test_browser.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3923,7 +3923,7 @@ def test_pthread_once(self):
39233923

39243924
# Test against a certain thread exit time handling bug by spawning tons of threads.
39253925
def test_pthread_spawns(self):
3926-
self.btest_exit('pthread/test_pthread_spawns.cpp', emcc_args=['-O3', '-pthread', '-sPTHREAD_POOL_SIZE=8', '--closure=1', '-sENVIRONMENT=web,worker'])
3926+
self.btest_exit('pthread/test_pthread_spawns.cpp', emcc_args=['-O3', '-pthread', '-sPTHREAD_POOL_SIZE=8', '--closure=1', '-sENVIRONMENT=web'])
39273927

39283928
# It is common for code to flip volatile global vars for thread control. This is a bit lax, but nevertheless, test whether that
39293929
# kind of scheme will work with Emscripten as well.
@@ -5115,7 +5115,7 @@ def test_system(self):
51155115
# Tests the hello_wasm_worker.c documentation example code.
51165116
@also_with_minimal_runtime
51175117
def test_wasm_worker_hello(self):
5118-
self.btest_exit('wasm_worker/hello_wasm_worker.c', emcc_args=['-sWASM_WORKERS', '-sENVIRONMENT=web,worker'])
5118+
self.btest_exit('wasm_worker/hello_wasm_worker.c', emcc_args=['-sWASM_WORKERS', '-sENVIRONMENT=web'])
51195119

51205120
def test_wasm_worker_hello_minimal_runtime_2(self):
51215121
self.btest_exit('wasm_worker/hello_wasm_worker.c', emcc_args=['-sWASM_WORKERS', '-sMINIMAL_RUNTIME=2'])
@@ -5583,7 +5583,7 @@ def test_webpack(self, es6):
55835583
else:
55845584
copytree(test_file('webpack'), '.')
55855585
outfile = 'src/hello.js'
5586-
self.compile_btest('hello_world.c', ['-sEXIT_RUNTIME', '-sMODULARIZE', '-sENVIRONMENT=web,worker', '-o', outfile])
5586+
self.compile_btest('hello_world.c', ['-sEXIT_RUNTIME', '-sMODULARIZE', '-sENVIRONMENT=web', '-o', outfile])
55875587
self.run_process(shared.get_npm_cmd('webpack') + ['--mode=development', '--no-devtool'])
55885588
# Webpack doesn't bundle the wasm file by default so we need to copy it
55895589
# TODO(sbc): Look into plugins that do bundling.
@@ -5593,14 +5593,14 @@ def test_webpack(self, es6):
55935593
@also_with_threads
55945594
def test_vite(self):
55955595
copytree(test_file('vite'), '.')
5596-
self.compile_btest('hello_world.c', ['-sEXIT_RUNTIME', '-sENVIRONMENT=web,worker', '-o', 'hello.mjs'])
5596+
self.compile_btest('hello_world.c', ['-sEXIT_RUNTIME', '-sENVIRONMENT=web', '-o', 'hello.mjs'])
55975597
self.run_process(shared.get_npm_cmd('vite') + ['build'])
55985598
self.run_browser('dist/index.html', '/report_result?exit:0')
55995599

56005600
@also_with_threads
56015601
def test_rollup(self):
56025602
copytree(test_file('rollup'), '.')
5603-
self.compile_btest('hello_world.c', ['-sEXIT_RUNTIME', '-o', 'hello.mjs'])
5603+
self.compile_btest('hello_world.c', ['-sEXIT_RUNTIME', '-sENVIRONMENT=web', '-o', 'hello.mjs'])
56045604
self.run_process(shared.get_npm_cmd('rollup') + ['--config'])
56055605
# Rollup doesn't bundle the wasm file by default so we need to copy it
56065606
# TODO(sbc): Look into plugins that do bundling.

test/test_core.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9176,8 +9176,6 @@ def test_fpic_static(self):
91769176
# @also_with_standalone_wasm(impure=True)
91779177
@node_pthreads
91789178
def test_pthread_create(self):
9179-
# test that the node environment can be specified by itself, and that still
9180-
# works with pthreads (even though we did not specify 'node,worker')
91819179
self.set_setting('ENVIRONMENT', 'node')
91829180
self.set_setting('STRICT')
91839181
self.do_run_in_out_file_test('core/pthread/create.c')
@@ -9194,8 +9192,7 @@ def test_pthread_c11_threads(self, args):
91949192
self.set_setting('PTHREADS_DEBUG')
91959193
if not self.has_changed_setting('INITIAL_MEMORY'):
91969194
self.set_setting('INITIAL_MEMORY', '64mb')
9197-
# test that the node and worker environments can be specified
9198-
self.set_setting('ENVIRONMENT', 'node,worker')
9195+
self.set_setting('ENVIRONMENT', 'node')
91999196
self.do_run_in_out_file_test('pthread/test_pthread_c11_threads.c')
92009197

92019198
@node_pthreads

test/test_other.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11844,8 +11844,8 @@ def test_minimal_runtime_code_size(self, test_name, wasm2js, compare_js_output=F
1184411844
'-lGL',
1184511845
'-sMODULARIZE']
1184611846
hello_webgl2_sources = hello_webgl_sources + ['-sMAX_WEBGL_VERSION=2']
11847-
hello_wasm_worker_sources = [test_file('wasm_worker/wasm_worker_code_size.c'), '-sWASM_WORKERS', '-sENVIRONMENT=web,worker']
11848-
audio_worklet_sources = [test_file('webaudio/audioworklet.c'), '-sWASM_WORKERS', '-sAUDIO_WORKLET', '-sENVIRONMENT=web,worker', '-sTEXTDECODER=1']
11847+
hello_wasm_worker_sources = [test_file('wasm_worker/wasm_worker_code_size.c'), '-sWASM_WORKERS', '-sENVIRONMENT=web']
11848+
audio_worklet_sources = [test_file('webaudio/audioworklet.c'), '-sWASM_WORKERS', '-sAUDIO_WORKLET', '-sENVIRONMENT=web', '-sTEXTDECODER=1']
1184911849
embind_hello_sources = [test_file('code_size/embind_hello_world.cpp'), '-lembind']
1185011850
embind_val_sources = [test_file('code_size/embind_val_hello_world.cpp'),
1185111851
'-lembind',
@@ -16208,3 +16208,14 @@ def test_unsupported_min_version_when_unsupported_env(self, env):
1620816208
self.assertContainedIf(f'var MIN_CHROME_VERSION = {unsupported};', src, env == 'node')
1620916209
self.assertContainedIf(f'var MIN_SAFARI_VERSION = {unsupported};', src, env == 'node')
1621016210
self.assertContainedIf(f'var MIN_FIREFOX_VERSION = {unsupported};', src, env == 'node')
16211+
16212+
@parameterized({
16213+
'web': ('web',),
16214+
'node': ('node',),
16215+
})
16216+
@parameterized({
16217+
'pthread': (['-pthread'],),
16218+
'wasm_workers': (['-sWASM_WORKERS'],),
16219+
})
16220+
def test_automatic_env_worker(self, env, emcc_args):
16221+
self.emcc(test_file('hello_world.c'), [f'-sENVIRONMENT={env}'] + emcc_args)

tools/link.py

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,12 @@ def will_metadce():
162162

163163

164164
def setup_environment_settings():
165+
# The worker environment is automatically added if any of the pthread or Worker features are used.
166+
# Note: we need to actually modify ENVIRONMENTS variable here before the parsing,
167+
# because some JS code reads it back so modifying parsed info alone is not sufficient.
168+
if settings.SHARED_MEMORY and settings.ENVIRONMENT:
169+
settings.ENVIRONMENT += ',worker'
170+
165171
# Environment setting based on user input
166172
environments = settings.ENVIRONMENT.split(',')
167173
if any(x for x in environments if x not in VALID_ENVIRONMENTS):
@@ -171,6 +177,7 @@ def setup_environment_settings():
171177
settings.ENVIRONMENT_MAY_BE_WEBVIEW = not settings.ENVIRONMENT or 'webview' in environments
172178
settings.ENVIRONMENT_MAY_BE_NODE = not settings.ENVIRONMENT or 'node' in environments
173179
settings.ENVIRONMENT_MAY_BE_SHELL = not settings.ENVIRONMENT or 'shell' in environments
180+
settings.ENVIRONMENT_MAY_BE_WORKER = not settings.ENVIRONMENT or 'worker' in environments
174181

175182
if not settings.ENVIRONMENT_MAY_BE_NODE:
176183
if 'MIN_NODE_VERSION' in user_settings:
@@ -184,21 +191,6 @@ def setup_environment_settings():
184191
diagnostics.warning('unused-command-line-argument', 'ignoring %s because `web` and `webview` environments are not enabled', key)
185192
settings[key] = feature_matrix.UNSUPPORTED
186193

187-
# The worker case also includes Node.js workers when pthreads are
188-
# enabled and Node.js is one of the supported environments for the build to
189-
# run on. Node.js workers are detected as a combination of
190-
# ENVIRONMENT_IS_WORKER and ENVIRONMENT_IS_NODE.
191-
settings.ENVIRONMENT_MAY_BE_WORKER = \
192-
not settings.ENVIRONMENT or \
193-
'worker' in environments or \
194-
(settings.ENVIRONMENT_MAY_BE_NODE and settings.PTHREADS)
195-
196-
if not settings.ENVIRONMENT_MAY_BE_WORKER and settings.PROXY_TO_WORKER:
197-
exit_with_error('if you specify --proxy-to-worker and specify a "-sENVIRONMENT=" directive, it must include "worker" as a target! (Try e.g. -sENVIRONMENT=web,worker)')
198-
199-
if not settings.ENVIRONMENT_MAY_BE_WORKER and settings.SHARED_MEMORY:
200-
exit_with_error('when building with multithreading enabled and a "-sENVIRONMENT=" directive is specified, it must include "worker" as a target! (Try e.g. -sENVIRONMENT=web,worker)')
201-
202194

203195
def generate_js_sym_info():
204196
"""Runs the js compiler to generate a list of all symbols available in the JS
@@ -2016,8 +2008,7 @@ def run_embind_gen(options, wasm_target, js_syms, extra_settings):
20162008
settings.PRE_JS_FILES = []
20172009
settings.POST_JS_FILES = []
20182010
# Force node since that is where the tool runs.
2019-
# When SHARED_MEMORY or PROXY_TO_WORKER are enabled, add the required 'worker' environment.
2020-
settings.ENVIRONMENT = 'node' + (',worker' if settings.SHARED_MEMORY or settings.PROXY_TO_WORKER else '')
2011+
settings.ENVIRONMENT = 'node'
20212012
settings.MINIMAL_RUNTIME = 0
20222013
# Required function to trigger TS generation.
20232014
settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$callRuntimeCallbacks']

0 commit comments

Comments
 (0)