Skip to content

Commit

Permalink
Re-enable preprocessing of pre/post JS file. NFC
Browse files Browse the repository at this point in the history
This change got reverted in emscripten-core#19006 so this time we make the
preprocessing optional.

This is useful as it allows things like `{{{ POINTER_SIZE }}}`
and `{{{ makeGetValue(..) }}}` to be used in pre/post JS files, just
like they can be in JS library files.

This change allows threadprofiler.js to be fixed such that it works
under wasm64.

Fixes: emscripten-core#21226
  • Loading branch information
sbc100 committed Feb 2, 2024
1 parent 81fe157 commit 8f5ac8d
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 31 deletions.
21 changes: 13 additions & 8 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,16 @@ See docs/process.md for more on how version tagging works.

3.1.54 (in development)
-----------------------
- Added `--use-port` option to `emcc`. This option allows ports to be enabled
by name and is designed to replace all existing `-sUSE_XXX` settings for
ports. You can use `--show-ports` to get the list of available ports that
- Added `--use-port` option to `emcc`. This option allows ports to be enabled
by name and is designed to replace all existing `-sUSE_XXX` settings for
ports. You can use `--show-ports` to get the list of available ports that
can be used with this new option. (#21214)

- `--pre-js` and `--post-js` files can now opt into being run through the JS
preprocessor. This change was originally landed in #18525, but it got
reverted in #19006. Now it requires explicit opt-in by adding `#preprocess` to
the top of the JS file. This is useful as it allows things like `{{{
POINTER_SIZE }}}` and `{{{ makeGetValue(..) }}}` to be used in pre/post JS
files, just like they can be in JS library files. (#21227)

3.1.53 - 01/29/24
-----------------
Expand Down Expand Up @@ -68,7 +73,7 @@ See docs/process.md for more on how version tagging works.
is intending to target them today. (#20924)
- C++ objects passed into embind's val via constructors, methods, and call
function will not be automatically destroyed after the function call. This
makes the behavior consistent for invocations.
makes the behavior consistent for invocations.
- The `SUPPORT_ERRNO` setting is now deprecated as it only controlled setting
errno from JS library functions and emscripten no longer requires this.
(#21074)
Expand Down Expand Up @@ -140,7 +145,7 @@ See docs/process.md for more on how version tagging works.
- The `glfwSetWindowSize` function no longer switches to fullscreen when the
width/height provided as parameters match the screen size. This behavior
now matches the behavior of SDL and glut. In order to switch to fullscreen,
the client code should invoke `Module.requestFullscreen(...)` from a user
the client code should invoke `Module.requestFullscreen(...)` from a user
triggered event otherwise the browser raises an error. (#20600)

3.1.48 - 11/05/23
Expand Down Expand Up @@ -375,7 +380,7 @@ See docs/process.md for more on how version tagging works.
- When targeting node, and using `-sMODULARIZE`, we no longer internally catch
unhandled promise rejections or exit status code. That is to say the,
`NODEJS_CATCH_REJECTION` and `NODEJS_CATCH_EXIT` are no longer compatible
with `-sMODULARIZE`.
with `-sMODULARIZE`.

3.1.33 - 03/08/23
-----------------
Expand All @@ -396,7 +401,7 @@ See docs/process.md for more on how version tagging works.
(#18861)
- The `emscripten_proxy_async_with_callback` API was replaced with a simpler
`emscripten_proxy_callback` API that takes a second callback to be called if
the worker thread dies before completing the proxied work.
the worker thread dies before completing the proxied work.

3.1.32 - 02/17/23
-----------------
Expand Down
1 change: 1 addition & 0 deletions src/generated_struct_info32.json
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@
"EM_PROMISE_MATCH": 1,
"EM_PROMISE_MATCH_RELEASE": 2,
"EM_PROMISE_REJECT": 3,
"EM_THREAD_STATUS_NUMFIELDS": 7,
"EM_TIMING_RAF": 1,
"EM_TIMING_SETIMMEDIATE": 2,
"EM_TIMING_SETTIMEOUT": 0,
Expand Down
1 change: 1 addition & 0 deletions src/generated_struct_info64.json
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@
"EM_PROMISE_MATCH": 1,
"EM_PROMISE_MATCH_RELEASE": 2,
"EM_PROMISE_REJECT": 3,
"EM_THREAD_STATUS_NUMFIELDS": 7,
"EM_TIMING_RAF": 1,
"EM_TIMING_SETIMMEDIATE": 2,
"EM_TIMING_SETTIMEOUT": 0,
Expand Down
32 changes: 23 additions & 9 deletions src/jsifier.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,22 @@ function getTransitiveDeps(symbol) {
return Array.from(transitiveDeps);
}

function shouldPreprocess(fileName) {
return read(fileName).trim().startsWith('#preprocess\n');
}

function preJS() {
let result = '';
for (const fileName of PRE_JS_FILES) {
if (shouldPreprocess(fileName)) {
result += processMacros(preprocess(fileName));
} else {
result += read(fileName);
}
}
return result;
}

function runJSify() {
const libraryItems = [];
const symbolDeps = {};
Expand Down Expand Up @@ -583,15 +599,13 @@ function(${args}) {
libraryItems.push(JS);
}

function includeFile(fileName) {
function includeFile(fileName, needsPreprocess = true) {
print(`// include: ${fileName}`);
print(processMacros(preprocess(fileName)));
print(`// end include: ${fileName}`);
}

function includeFileRaw(fileName) {
print(`// include: ${fileName}`);
print(read(fileName));
if (needsPreprocess) {
print(processMacros(preprocess(fileName)));
} else {
print(read(fileName));
}
print(`// end include: ${fileName}`);
}

Expand Down Expand Up @@ -653,7 +667,7 @@ var proxiedFunctionTable = [
includeFile(postFile);

for (const fileName of POST_JS_FILES) {
includeFileRaw(fileName);
includeFile(fileName, shouldPreprocess(fileName));
}

print('//FORWARDED_DATA:' + JSON.stringify({
Expand Down
10 changes: 2 additions & 8 deletions src/parseTools.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ function preprocess(filename) {
if (showCurrentLine()) {
error(`${filename}:${i + 1}: #error ${trimmed.substring(trimmed.indexOf(' ')).trim()}`);
}
} else if (first === '#preprocess') {
// Do nothing
} else {
error(`${filename}:${i + 1}: Unknown preprocessor directive ${first}`);
}
Expand Down Expand Up @@ -1022,14 +1024,6 @@ function getEntryFunction() {
return `_${entryFunction}`;
}

function preJS() {
let result = '';
for (const fileName of PRE_JS_FILES) {
result += read(fileName);
}
return result;
}

function formattedMinNodeVersion() {
var major = MIN_NODE_VERSION / 10000
var minor = (MIN_NODE_VERSION / 100) % 100
Expand Down
6 changes: 6 additions & 0 deletions src/struct_info_internal.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
"SIGCANCEL"
]
},
{
"file": "threading_internal.h",
"defines": [
"EM_THREAD_STATUS_NUMFIELDS"
]
},
{
"file": "dynlink.h",
"structs": {
Expand Down
13 changes: 7 additions & 6 deletions src/threadprofiler.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#preprocess

/**
* @license
* Copyright 2015 The Emscripten Authors
Expand Down Expand Up @@ -41,7 +43,6 @@ var emscriptenThreadProfiler = {
}
for (var i = 0; i < threads.length; ++i) {
var threadPtr = threads[i];
var profilerBlock = Atomics.load(HEAPU32, (threadPtr + 8 /* {{{ C_STRUCTS.pthread.profilerBlock }}}*/) >> 2);
var threadName = PThread.getThreadName(threadPtr);
if (threadName) {
threadName = `"${threadName}" (${ptrToString(threadPtr)})`;
Expand Down Expand Up @@ -69,7 +70,7 @@ var emscriptenThreadProfiler = {

for (var i = 0; i < threads.length; ++i) {
var threadPtr = threads[i];
var profilerBlock = Atomics.load(HEAPU32, (threadPtr + 8 /* {{{ C_STRUCTS.pthread.profilerBlock }}}*/) >> 2);
var profilerBlock = Atomics.load({{{ getHeapForType('*') }}}, {{{ getHeapOffset('threadPtr + ' + C_STRUCTS.pthread.profilerBlock, '*') }}});
var threadName = PThread.getThreadName(threadPtr);
if (threadName) {
threadName = `"${threadName}" (${ptrToString(threadPtr)})`;
Expand All @@ -81,11 +82,11 @@ var emscriptenThreadProfiler = {

var threadTimesInStatus = [];
var totalTime = 0;
var offset = profilerBlock + 16/*C_STRUCTS.thread_profiler_block.timeSpentInStatus*/;
for (var j = 0; j < 7/*EM_THREAD_STATUS_NUMFIELDS*/; ++j, offset += 8) {
threadTimesInStatus.push(Number(getValue(offset, 'double')));
var offset = profilerBlock + {{{ C_STRUCTS.thread_profiler_block.timeSpentInStatus }}};
for (var j = 0; j < {{{ cDefs.EM_THREAD_STATUS_NUMFIELDS }}}; ++j, offset += 8) {
threadTimesInStatus.push({{{ makeGetValue('offset', 0, 'double') }}});
totalTime += threadTimesInStatus[j];
setValue(offset, 0, 'double');
{{{ makeSetValue('offset', 0, 0, 'double') }}};
}
var recent = '';
if (threadTimesInStatus[1] > 0) recent += (threadTimesInStatus[1] / totalTime * 100.0).toFixed(1) + '% running. ';
Expand Down
18 changes: 18 additions & 0 deletions test/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -14463,3 +14463,21 @@ def test_uuid(self):
def test_wasm64_no_asan(self):
err = self.expect_fail([EMCC, test_file('hello_world.c'), '-sMEMORY64', '-fsanitize=address'])
self.assertContained('error: MEMORY64 does not yet work with ASAN', err)

def test_js_preprocess_pre_post(self):
create_file('pre.js', '''
#preprocess
#if ASSERTIONS
console.log('assertions enabled')
#else
console.log('assertions disabled')
#endif
''')
create_file('post.js', '''
#preprocess
console.log({{{ POINTER_SIZE }}});
''')
self.emcc_args += ['--pre-js', 'pre.js', '--post-js', 'post.js']
self.do_runf(test_file('hello_world.c'), 'assertions enabled\n4', emcc_args=['-sASSERTIONS=1'])
self.do_runf(test_file('hello_world.c'), 'assertions disabled\n4', emcc_args=['-sASSERTIONS=0'])
self.assertNotContained('#preprocess', read_file('hello_world.js'))

0 comments on commit 8f5ac8d

Please sign in to comment.