Skip to content

Commit 1f739b6

Browse files
Fixed imports with late binding and this (#4225)
1 parent dcf2566 commit 1f739b6

File tree

8 files changed

+147
-66
lines changed

8 files changed

+147
-66
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@
6666
* Fixed calls to `JsCast::instanceof()` not respecting JavaScript namespaces.
6767
[#4241](https://github.com/rustwasm/wasm-bindgen/pull/4241)
6868

69+
* Fixed imports for functions using `this` and late binding.
70+
[#4225](https://github.com/rustwasm/wasm-bindgen/pull/4225)
71+
6972
--------------------------------------------------------------------------------
7073

7174
## [0.2.95](https://github.com/rustwasm/wasm-bindgen/compare/0.2.94...0.2.95)

crates/cli-support/src/js/mod.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3062,6 +3062,21 @@ __wbg_set_wasm(wasm);"
30623062
}
30633063
}
30643064

3065+
if let JsImportName::Global { .. } | JsImportName::VendorPrefixed { .. } = js.name {
3066+
// We generally cannot import globals directly, because users can
3067+
// change most globals at runtime.
3068+
//
3069+
// An obvious example of this when the object literally changes
3070+
// (e.g. binding `foo.bar`), but polyfills can also change the
3071+
// object or fundtion.
3072+
//
3073+
// Late binding is another issue. The function might not even be
3074+
// defined when the Wasm module is instantiated. In such cases,
3075+
// there is an observable difference between a direct import and a
3076+
// JS shim calling the function.
3077+
return Ok(false);
3078+
}
3079+
30653080
self.expose_not_defined();
30663081
let name = self.import_name(js)?;
30673082
let js = format!(

crates/cli/tests/reference/import-catch.js

Lines changed: 0 additions & 54 deletions
This file was deleted.

crates/cli/tests/reference/import-catch.rs

Lines changed: 0 additions & 12 deletions
This file was deleted.

crates/cli/tests/reference/import.js

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
let wasm;
2+
export function __wbg_set_wasm(val) {
3+
wasm = val;
4+
}
5+
6+
7+
const heap = new Array(128).fill(undefined);
8+
9+
heap.push(undefined, null, true, false);
10+
11+
let heap_next = heap.length;
12+
13+
function addHeapObject(obj) {
14+
if (heap_next === heap.length) heap.push(heap.length + 1);
15+
const idx = heap_next;
16+
heap_next = heap[idx];
17+
18+
heap[idx] = obj;
19+
return idx;
20+
}
21+
22+
function handleError(f, args) {
23+
try {
24+
return f.apply(this, args);
25+
} catch (e) {
26+
wasm.__wbindgen_exn_store(addHeapObject(e));
27+
}
28+
}
29+
30+
const lTextDecoder = typeof TextDecoder === 'undefined' ? (0, module.require)('util').TextDecoder : TextDecoder;
31+
32+
let cachedTextDecoder = new lTextDecoder('utf-8', { ignoreBOM: true, fatal: true });
33+
34+
cachedTextDecoder.decode();
35+
36+
let cachedUint8ArrayMemory0 = null;
37+
38+
function getUint8ArrayMemory0() {
39+
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
40+
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
41+
}
42+
return cachedUint8ArrayMemory0;
43+
}
44+
45+
function getStringFromWasm0(ptr, len) {
46+
ptr = ptr >>> 0;
47+
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
48+
}
49+
50+
function getObject(idx) { return heap[idx]; }
51+
52+
function dropObject(idx) {
53+
if (idx < 132) return;
54+
heap[idx] = heap_next;
55+
heap_next = idx;
56+
}
57+
58+
function takeObject(idx) {
59+
const ret = getObject(idx);
60+
dropObject(idx);
61+
return ret;
62+
}
63+
64+
export function exported() {
65+
const ret = wasm.exported();
66+
if (ret[1]) {
67+
throw takeObject(ret[0]);
68+
}
69+
}
70+
71+
export function __wbg_add_dd5307a7ca6818d5(arg0, arg1) {
72+
const ret = add(arg0, arg1);
73+
return ret;
74+
};
75+
76+
export function __wbg_barfromfoo_d097f3ec35aab47c() {
77+
bar_from_foo();
78+
};
79+
80+
export function __wbg_catchme_a7bca7f3d5a5f319() { return handleError(function () {
81+
catch_me();
82+
}, arguments) };
83+
84+
export function __wbg_nocatch_62552fa42a58590b() {
85+
no_catch();
86+
};
87+
88+
export function __wbg_reload_90d82b22b83c1d99() {
89+
window.location.reload();
90+
};
91+
92+
export function __wbg_write_d258674ff6f0ea8d(arg0, arg1) {
93+
window.document.write(getStringFromWasm0(arg0, arg1));
94+
};
95+

crates/cli/tests/reference/import.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
use wasm_bindgen::prelude::*;
2+
3+
#[wasm_bindgen]
4+
extern "C" {
5+
// Both `catch_me` and `no_catch` should be defined in the JS and invoke
6+
// their respective JS function inside a JS shim function. This is
7+
// important, because these 2 function may not be defined when the WASM
8+
// module is instantiated.
9+
#[wasm_bindgen(catch)]
10+
fn catch_me() -> Result<(), JsValue>;
11+
fn no_catch();
12+
13+
// Reload needs to be passed the right `this` parameter in JS.
14+
#[wasm_bindgen(js_namespace = ["window", "location"])]
15+
fn reload();
16+
#[wasm_bindgen(js_namespace = ["window", "document"])]
17+
fn write(s: &str);
18+
19+
// module import
20+
#[wasm_bindgen(module = "./foo.js")]
21+
fn bar_from_foo();
22+
#[wasm_bindgen(inline_js = "export function add(a,b) { return a + b; }")]
23+
fn add(a: f64, b: f64) -> f64;
24+
}
25+
26+
#[wasm_bindgen]
27+
pub fn exported() -> Result<(), JsValue> {
28+
bar_from_foo();
29+
let _ = add(1.0, 2.0);
30+
reload();
31+
write("");
32+
no_catch();
33+
catch_me()
34+
}

0 commit comments

Comments
 (0)