Skip to content
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

Fixed imports with late binding and this #4225

Merged
merged 6 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@
* Fixed calls to `JsCast::instanceof()` not respecting JavaScript namespaces.
[#4241](https://github.com/rustwasm/wasm-bindgen/pull/4241)

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

--------------------------------------------------------------------------------

## [0.2.95](https://github.com/rustwasm/wasm-bindgen/compare/0.2.94...0.2.95)
Expand Down
15 changes: 15 additions & 0 deletions crates/cli-support/src/js/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3062,6 +3062,21 @@ __wbg_set_wasm(wasm);"
}
}

if let JsImportName::Global { .. } | JsImportName::VendorPrefixed { .. } = js.name {
// We generally cannot import globals directly, because users can
// change most globals at runtime.
//
// An obvious example of this when the object literally changes
// (e.g. binding `foo.bar`), but polyfills can also change the
// object or fundtion.
//
// Late binding is another issue. The function might not even be
// defined when the Wasm module is instantiated. In such cases,
// there is an observable difference between a direct import and a
// JS shim calling the function.
return Ok(false);
}

self.expose_not_defined();
let name = self.import_name(js)?;
let js = format!(
Expand Down
54 changes: 0 additions & 54 deletions crates/cli/tests/reference/import-catch.js

This file was deleted.

12 changes: 0 additions & 12 deletions crates/cli/tests/reference/import-catch.rs

This file was deleted.

95 changes: 95 additions & 0 deletions crates/cli/tests/reference/import.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
let wasm;
export function __wbg_set_wasm(val) {
wasm = val;
}


const heap = new Array(128).fill(undefined);

heap.push(undefined, null, true, false);

let heap_next = heap.length;

function addHeapObject(obj) {
if (heap_next === heap.length) heap.push(heap.length + 1);
const idx = heap_next;
heap_next = heap[idx];

heap[idx] = obj;
return idx;
}

function handleError(f, args) {
try {
return f.apply(this, args);
} catch (e) {
wasm.__wbindgen_exn_store(addHeapObject(e));
}
}

const lTextDecoder = typeof TextDecoder === 'undefined' ? (0, module.require)('util').TextDecoder : TextDecoder;

let cachedTextDecoder = new lTextDecoder('utf-8', { ignoreBOM: true, fatal: true });

cachedTextDecoder.decode();

let cachedUint8ArrayMemory0 = null;

function getUint8ArrayMemory0() {
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
}
return cachedUint8ArrayMemory0;
}

function getStringFromWasm0(ptr, len) {
ptr = ptr >>> 0;
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
}

function getObject(idx) { return heap[idx]; }

function dropObject(idx) {
if (idx < 132) return;
heap[idx] = heap_next;
heap_next = idx;
}

function takeObject(idx) {
const ret = getObject(idx);
dropObject(idx);
return ret;
}

export function exported() {
const ret = wasm.exported();
if (ret[1]) {
throw takeObject(ret[0]);
}
}

export function __wbg_add_dd5307a7ca6818d5(arg0, arg1) {
const ret = add(arg0, arg1);
return ret;
};

export function __wbg_barfromfoo_d097f3ec35aab47c() {
bar_from_foo();
};

export function __wbg_catchme_a7bca7f3d5a5f319() { return handleError(function () {
catch_me();
}, arguments) };

export function __wbg_nocatch_62552fa42a58590b() {
no_catch();
};

export function __wbg_reload_90d82b22b83c1d99() {
window.location.reload();
};

export function __wbg_write_d258674ff6f0ea8d(arg0, arg1) {
window.document.write(getStringFromWasm0(arg0, arg1));
};

34 changes: 34 additions & 0 deletions crates/cli/tests/reference/import.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern "C" {
// Both `catch_me` and `no_catch` should be defined in the JS and invoke
// their respective JS function inside a JS shim function. This is
// important, because these 2 function may not be defined when the WASM
// module is instantiated.
#[wasm_bindgen(catch)]
fn catch_me() -> Result<(), JsValue>;
fn no_catch();

// Reload needs to be passed the right `this` parameter in JS.
#[wasm_bindgen(js_namespace = ["window", "location"])]
fn reload();
#[wasm_bindgen(js_namespace = ["window", "document"])]
fn write(s: &str);

// module import
#[wasm_bindgen(module = "./foo.js")]
fn bar_from_foo();
#[wasm_bindgen(inline_js = "export function add(a,b) { return a + b; }")]
fn add(a: f64, b: f64) -> f64;
}

#[wasm_bindgen]
pub fn exported() -> Result<(), JsValue> {
bar_from_foo();
let _ = add(1.0, 2.0);
reload();
write("");
no_catch();
catch_me()
}