Skip to content

Commit 62d03fb

Browse files
authored
Implement support for reading argc and argv in MINIMAL_RUNTIME. (#25307)
Implement support for reading argc and argv in MINIMAL_RUNTIME. With the help of the existing MAIN_READS_PARAMS machinery (thanks to #9064), this is only-pay-for-what-you-use. Note that unlike the regular runtime that locates `argv[0]` to be the script name, MINIMAL_RUNTIME will place the shell interpreter name in `argv[0]` and the script name in `argv[1]`, to align with Node.js and Python `process.argv` and `sys.argv` behavior. In a browser run, regular runtime has a dummy `"./this.program"` in `argv[0]`. Instead of a hardcoded mock value in `argv[0]`, the current page URL (e.g. `"https://localhost:5932/foo/bar/baz.html"`) is located in `argv[0]` instead, followed by the search query parameters in `argv[1]` onwards.
1 parent 8d9966a commit 62d03fb

File tree

2 files changed

+46
-10
lines changed

2 files changed

+46
-10
lines changed

src/postamble_minimal.js

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,28 +26,64 @@ function exitRuntime(ret) {
2626
}
2727
#endif
2828

29+
{{{ globalThis.argc_argv = function(condition) {
30+
if (!MAIN_READS_PARAMS) return '';
31+
return `argc, ${to64('argv')}`;
32+
}
33+
globalThis.HEAPptr = MEMORY64 ? 'HEAPU64' : 'HEAPU32';
34+
null;
35+
}}}
36+
2937
function run() {
3038
#if MEMORYPROFILER
3139
emscriptenMemoryProfiler.onPreloadComplete();
3240
#endif
3341

3442
<<< ATMAINS >>>
3543

44+
#if MAIN_READS_PARAMS
45+
var args =
46+
#if ENVIRONMENT_MAY_BE_NODE
47+
// Remove Node.js executable name from argc/argv to emulate C/C++ standards.
48+
ENVIRONMENT_IS_NODE ? process.argv.slice(1) :
49+
#endif
50+
[location.href.split('?')[0], ...location.search.slice(1).split('&').map(decodeURIComponent)];
51+
52+
// C standard (C17 §5.1.2.2.1/5): "The parameters argc and argv and the
53+
// strings pointed to by the argv array shall be modifiable by the program,
54+
// and retain their last-stored values between program startup and program
55+
// termination."
56+
// -> in particular this means that the stackAlloc() that we do below shall
57+
// never be undone, and ideally should no longer be considered to be part of
58+
// the stack. Though currently it will be. (TODO: figure if this will ever be
59+
// a problem)
60+
var arg,
61+
argc = args.length,
62+
argv = stackAlloc(argc * {{{ POINTER_SIZE }}} + {{{ POINTER_SIZE }}}),
63+
argvIndex = argv / {{{ POINTER_SIZE }}};
64+
65+
for (arg of args) {{{ HEAPptr }}}[argvIndex++] = {{{ to64('stringToUTF8OnStack(arg)') }}};
66+
67+
// C standard (C17 §5.1.2.2.1/2): "argv[argc] shall be a null pointer."
68+
{{{ HEAPptr }}}[argvIndex] = {{{ to64(0) }}};
69+
70+
#endif
71+
3672
#if PROXY_TO_PTHREAD
3773
// User requested the PROXY_TO_PTHREAD option, so call a stub main which
3874
// pthread_create()s a new thread that will call the user's real main() for
3975
// the application.
40-
__emscripten_proxy_main();
76+
__emscripten_proxy_main({{{ argc_argv() }}});
4177
#elif ASYNCIFY == 2 && EXIT_RUNTIME
4278
// In JSPI-enabled build mode, the main() function will return a Promise,
4379
// which resolves to the process exit code.
44-
_main().then(exitRuntime);
80+
_main({{{ argc_argv() }}}).then(exitRuntime);
4581
#elif EXIT_RUNTIME
4682
// In regular exitRuntime mode, exit with the given return code from main().
47-
exitRuntime(_main());
83+
exitRuntime(_main({{{ argc_argv() }}}));
4884
#else
4985
// Run a persistent (never-exiting) application starting at main().
50-
_main();
86+
_main({{{ argc_argv() }}});
5187
#endif
5288

5389
#if STACK_OVERFLOW_CHECK
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"a.html": 552,
33
"a.html.gz": 373,
4-
"a.js": 112,
5-
"a.js.gz": 121,
6-
"a.wasm": 2678,
7-
"a.wasm.gz": 1648,
8-
"total": 3342,
9-
"total_gz": 2142
4+
"a.js": 849,
5+
"a.js.gz": 506,
6+
"a.wasm": 2715,
7+
"a.wasm.gz": 1674,
8+
"total": 4116,
9+
"total_gz": 2553
1010
}

0 commit comments

Comments
 (0)