@@ -36,12 +36,57 @@ pub fn attribute_gdextension(decl: Declaration) -> ParseResult<TokenStream> {
3636 Ok ( quote ! {
3737 #impl_decl
3838
39+ // This cfg cannot be checked from the outer proc-macro since its 'target' is the build
40+ // host. See: https://github.com/rust-lang/rust/issues/42587
41+ #[ cfg( target_os = "emscripten" ) ]
42+ fn emscripten_preregistration( ) {
43+ // Module is documented here[1] by emscripten so perhaps we can consider it a part
44+ // of its public API? In any case for now we mutate global state directly in order
45+ // to get things working.
46+ // [1] https://emscripten.org/docs/api_reference/module.html
47+ //
48+ // Warning: It may be possible that in the process of executing the code leading up
49+ // to `emscripten_run_script` that we might trigger usage of one of the symbols we
50+ // wish to monkey patch? It seems fairly unlikely, especially as long as no i64 are
51+ // involved, but I don't know what guarantees we have here.
52+ //
53+ // We should keep an eye out for these sorts of failures!
54+ let script = std:: ffi:: CString :: new( concat!(
55+ "var pkgName = '" , env!( "CARGO_PKG_NAME" ) , "';" , r#"
56+ var libName = pkgName.replaceAll('-', '_') + '.wasm';
57+ var dso = LDSO.loadedLibsByName[libName]["module"];
58+ var registrants = [];
59+ for (sym in dso) {
60+ if (sym.startsWith("dynCall_")) {
61+ if (!(sym in Module)) {
62+ console.log(`Patching Module with ${sym}`);
63+ Module[sym] = dso[sym];
64+ }
65+ } else if (sym.startsWith("rust_gdext_registrant_")) {
66+ registrants.push(sym);
67+ }
68+ }
69+ for (sym of registrants) {
70+ console.log(`Running registrant ${sym}`);
71+ dso[sym]();
72+ }
73+ console.log("Added", registrants.length, "plugins to registry!");
74+ "# ) ) . expect( "Unable to create CString from script" ) ;
75+
76+ extern "C" { fn emscripten_run_script( script: * const std:: ffi:: c_char) ; }
77+ unsafe { emscripten_run_script( script. as_ptr( ) ) ; }
78+ }
79+
3980 #[ no_mangle]
4081 unsafe extern "C" fn #entry_point(
4182 interface_or_get_proc_address: :: godot:: sys:: InitCompat ,
4283 library: :: godot:: sys:: GDExtensionClassLibraryPtr ,
4384 init: * mut :: godot:: sys:: GDExtensionInitialization ,
4485 ) -> :: godot:: sys:: GDExtensionBool {
86+ // Required due to the lack of a constructor facility such as .init_array in rust wasm
87+ #[ cfg( target_os = "emscripten" ) ]
88+ emscripten_preregistration( ) ;
89+
4590 :: godot:: init:: __gdext_load_library:: <#impl_ty>(
4691 interface_or_get_proc_address,
4792 library,
0 commit comments