-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
In MODULARIZE mode avoid modifying the incoming moduleArg. NFC #21775
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// In MODULARIZE mode we wrap the generated code in a factory function | ||
// and return either the Module itself, or a promise of the module. | ||
// | ||
// We assign to the `moduleRtn` global here and configure closure to see | ||
// this as and extern so it won't get minified. | ||
|
||
#if WASM_ASYNC_COMPILATION | ||
|
||
#if USE_READY_PROMISE | ||
moduleRtn = readyPromise; | ||
#else | ||
moduleRtn = {}; | ||
#endif | ||
|
||
#else // WASM_ASYNC_COMPILATION | ||
|
||
moduleRtn = Module; | ||
|
||
#endif // WASM_ASYNC_COMPILATION | ||
|
||
#if ASSERTIONS | ||
// Assertion for attempting to access module properties on the incoming | ||
// moduleArg. In the past we used this object as the prototype of the module | ||
// and assigned properties to it, but now we return a distinct object. This | ||
// keeps the instance private until it is ready (i.e the promise has been | ||
// resolved). | ||
for (const prop of Object.keys(Module)) { | ||
if (!(prop in moduleArg)) { | ||
Object.defineProperty(moduleArg, prop, { | ||
configurable: true, | ||
get() { | ||
#if WASM_ASYNC_COMPILATION | ||
abort(`Access to module property ('${prop}') is no longer possible via the incoming module contructor argument; Instead, use the result of the module promise.`) | ||
#else | ||
abort(`Access to module property ('${prop}') is no longer possible via the module input argument; Instead, use the module constructor return value.`) | ||
#endif | ||
} | ||
}); | ||
} | ||
} | ||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
55580 | ||
55579 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
31465 | ||
31464 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
54468 | ||
54467 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6416,11 +6416,11 @@ def test_modularize_sync_compilation(self): | |
console.log('before'); | ||
var result = Module(); | ||
// It should be an object. | ||
console.log(typeof result); | ||
console.log('typeof result: ' + typeof result); | ||
// And it should have the exports that Module has, showing it is Module in fact. | ||
console.log(typeof result._main); | ||
console.log('typeof _main: ' + typeof result._main); | ||
// And it should not be a Promise. | ||
console.log(typeof result.then); | ||
console.log('typeof result.then: ' + typeof result.then); | ||
console.log('after'); | ||
''') | ||
self.run_process([EMCC, test_file('hello_world.c'), | ||
|
@@ -6430,12 +6430,25 @@ def test_modularize_sync_compilation(self): | |
self.assertContained('''\ | ||
before | ||
hello, world! | ||
object | ||
function | ||
undefined | ||
typeof result: object | ||
typeof _main: function | ||
typeof result.then: undefined | ||
after | ||
''', self.run_js('a.out.js')) | ||
|
||
def test_modularize_argument_misuse(self): | ||
create_file('test.c', ''' | ||
#include <emscripten.h> | ||
EMSCRIPTEN_KEEPALIVE int foo() { return 42; }''') | ||
|
||
create_file('post.js', r''' | ||
var arg = { bar: 1 }; | ||
var promise = Module(arg); | ||
arg._foo();''') | ||
|
||
expected = "Aborted(Access to module property ('_foo') is no longer possible via the incoming module contructor argument; Instead, use the result of the module promise" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I read this comment a few times and I'm not actually sure what the user is expected to do to fix it? This is post-js code so it is inside the emitted JS, how can the module Promise be accessed? Also, this seems like a breaking change that should be mentioned in the changelog? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, thanks, I missed the |
||
self.do_runf('test.c', expected, assert_returncode=NON_ZERO, emcc_args=['--no-entry', '-sMODULARIZE', '--extern-post-js=post.js']) | ||
|
||
def test_export_all_3142(self): | ||
create_file('src.cpp', r''' | ||
typedef unsigned int Bit32u; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think we could take this further and fully separate the arguments and return value at some point too (i.e. not put all the module arg inputs on the module return value)? It would be a bigger breaking change, but IIRC it doesn't seem like many people rely on that behavior when using modularize?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see what you mean, yes. I think it might be possible yes.