-
Notifications
You must be signed in to change notification settings - Fork 9
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
RefFromWasmAbi causes panic in dev builds but not in prod #32
Comments
Okay, when I looked at the implementation of the generated impl RefFromWasmAbi for JsType {
type Abi = <JsValue as RefFromWasmAbi>::Abi;
type Anchor = core::mem::ManuallyDrop<JsType>;
#[inline]
unsafe fn ref_from_abi(js: Self::Abi) -> Self::Anchor {
let tmp = <JsValue as RefFromWasmAbi>::ref_from_abi(js);
core::mem::ManuallyDrop::new(JsType {
obj: core::mem::ManuallyDrop::into_inner(tmp).into(),
})
}
}
} But the generated RefFromWasmAbi for the derived types just calls See the following difference in the generated js: module.exports.take_foo = function(blubs) {
wasm.take_foo(addHeapObject(blubs));
};
module.exports.take_foo_ref = function(blubs) {
try {
wasm.take_foo_ref(addBorrowedObject(blubs));
} finally {
heap[stack_pointer++] = undefined;
}
}; In the reference case, js is responsible for the heap and in the other case, rust is responsible. impl Drop for JsValue {
#[inline]
fn drop(&mut self) {
unsafe {
// We definitely should never drop anything in the stack area
debug_assert!(self.idx >= JSIDX_OFFSET, "free of stack slot {}", self.idx);
// Otherwise if we're not dropping one of our reserved values,
// actually call the intrinsic. See #1054 for eventually removing
// this branch.
if self.idx >= JSIDX_RESERVED {
__wbindgen_object_drop_ref(self.idx);
}
}
}
} My proposed fix would be implementing diff --git a/tsify-next-macros/src/wasm_bindgen.rs b/tsify-next-macros/src/wasm_bindgen.rs
index d179d34..45dd823 100644
--- a/tsify-next-macros/src/wasm_bindgen.rs
+++ b/tsify-next-macros/src/wasm_bindgen.rs
@@ -171,7 +171,11 @@ fn expand_from_wasm_abi(cont: &Container) -> TokenStream {
type Anchor = SelfOwner<Self>;
unsafe fn ref_from_abi(js: Self::Abi) -> Self::Anchor {
+ let result = Self::from_js(&*JsType::ref_from_abi(js));
+ if let Err(err) = result {
+ wasm_bindgen::throw_str(err.to_string().as_ref());
+ }
+ SelfOwner(result.unwrap_throw())
- SelfOwner(Self::from_abi(js))
}
}
} Edit: the diff was in the wrong order. |
Really interesting issue, I learn a lot by reading your very well-written report of it ! Is the Maybe @cwfitzgerald could be interested by this :) |
Yes the Edit: Now that I looked at it again I realized that it checks two different indeces. I am not sure whether the stack is corrupted in release mode when passing tsify references, I might try this out later. |
Alright, so my first intuition was right, in release mode the drop does nothing in this case as the indeces are defined like this: const JSIDX_OFFSET: u32 = 128; // keep in sync with js/mod.rs
const JSIDX_UNDEFINED: u32 = JSIDX_OFFSET;
const JSIDX_NULL: u32 = JSIDX_OFFSET + 1;
const JSIDX_TRUE: u32 = JSIDX_OFFSET + 2;
const JSIDX_FALSE: u32 = JSIDX_OFFSET + 3;
const JSIDX_RESERVED: u32 = JSIDX_OFFSET + 4; |
Ok at least there is that, no double free ! Your proposal makes a lot of sense to me but it would be great to have the input of @cwfitzgerald to be sure. I guess the worst that could happen if the reasoning is wrong is a memory leak 😌 |
By the way: It seems that the current implementation of impl RefFromWasmAbi for JsValue {
type Abi = u32;
type Anchor = ManuallyDrop<JsValue>;
#[inline]
unsafe fn ref_from_abi(js: u32) -> Self::Anchor {
ManuallyDrop::new(JsValue::_new(js))
}
}
impl LongRefFromWasmAbi for JsValue {
type Abi = u32;
type Anchor = JsValue;
#[inline]
unsafe fn long_ref_from_abi(js: u32) -> Self::Anchor {
Self::from_abi(js)
}
} |
Since it causes a runtime error, let's leave this open for now. It seems like more than a missing feature. |
I fixed this RuntimeError in #33 or did I miss something? |
Fixed by #33 My mistake. I assumed this issue would be auto-closed by github! |
When compiling the wasm code via wasm-back (
wasm-pack build --target nodejs --dev
), passing a reference of atsify
derived type results in a panic:Note that compiling without
--dev
option results in working code.Minimal rust code to reproduce my issue:
with the following js snippet:
I tested with both stable (rustc 1.75.0) and nightly (rustc 1.78.0-nightly).
The text was updated successfully, but these errors were encountered: