Skip to content

Commit b9c27b9

Browse files
committed
Update all non-mutable slices into Rust to use AllocCopy
This commit migrates all non-mutable slices incoming into Rust to use the standard `AllocCopy` binding instead of using a custom `Slice` binding defined by `wasm-bindgen`. This is done by freeing the memory from Rust rather than freeing the memory from JS. We can't do this for mutable slices yet but otherwise this should be working well!
1 parent e16dd15 commit b9c27b9

File tree

3 files changed

+65
-65
lines changed

3 files changed

+65
-65
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ impl<'a, 'b> Incoming<'a, 'b> {
153153

154154
// Similar to `AllocCopy`, except that we deallocate in a finally
155155
// block.
156-
NonstandardIncoming::Slice { kind, val, mutable } => {
156+
NonstandardIncoming::MutableSlice { kind, val } => {
157157
let (expr, ty) = self.standard_typed(val)?;
158158
assert_eq!(ty, ast::WebidlScalarType::Any.into());
159159
let func = self.cx.pass_to_wasm_function(*kind)?;
@@ -162,7 +162,7 @@ impl<'a, 'b> Incoming<'a, 'b> {
162162
.prelude(&format!("const ptr{} = {}({});", i, func, expr));
163163
self.js
164164
.prelude(&format!("const len{} = WASM_VECTOR_LEN;", i));
165-
self.finally_free_slice(&expr, i, *kind, *mutable)?;
165+
self.finally_free_slice(&expr, i, *kind, true)?;
166166
self.js.typescript_required(kind.js_ty());
167167
return Ok(vec![format!("ptr{}", i), format!("len{}", i)]);
168168
}

crates/cli-support/src/webidl/incoming.rs

Lines changed: 58 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,11 @@ pub enum NonstandardIncoming {
4747
expr: Box<ast::IncomingBindingExpression>,
4848
},
4949

50-
/// JS is passing a typed slice of data into Rust. Currently this is
51-
/// implemented with a deallocation in the JS shim, hence a custom binding.
52-
///
53-
/// TODO: we should move deallocation into Rust so we can use a vanilla and
54-
/// standard webidl binding here.
55-
Slice {
50+
/// A mutable slice of values going from JS to Rust, and after Rust finishes
51+
/// the JS slice is updated with the current value of the slice.
52+
MutableSlice {
5653
kind: VectorKind,
5754
val: ast::IncomingBindingExpression,
58-
mutable: bool,
5955
},
6056

6157
/// This is either a slice or `undefined` being passed into Rust.
@@ -216,52 +212,11 @@ impl IncomingBuilder {
216212
Descriptor::Option(d) => self.process_option(d)?,
217213

218214
Descriptor::String | Descriptor::Vector(_) => {
219-
use wasm_webidl_bindings::ast::WebidlScalarType::*;
220-
221215
let kind = arg.vector_kind().ok_or_else(|| {
222216
format_err!("unsupported argument type for calling Rust function from JS {:?}", arg)
223217
})? ;
224218
self.wasm.extend(&[ValType::I32; 2]);
225-
match kind {
226-
VectorKind::I8 => self.alloc_copy(Int8Array),
227-
VectorKind::U8 => self.alloc_copy(Uint8Array),
228-
VectorKind::ClampedU8 => self.alloc_copy(Uint8ClampedArray),
229-
VectorKind::I16 => self.alloc_copy(Int16Array),
230-
VectorKind::U16 => self.alloc_copy(Uint16Array),
231-
VectorKind::I32 => self.alloc_copy(Int32Array),
232-
VectorKind::U32 => self.alloc_copy(Uint32Array),
233-
VectorKind::F32 => self.alloc_copy(Float32Array),
234-
VectorKind::F64 => self.alloc_copy(Float64Array),
235-
VectorKind::String => {
236-
let expr = ast::IncomingBindingExpressionAllocUtf8Str {
237-
alloc_func_name: self.alloc_func_name(),
238-
expr: Box::new(self.expr_get()),
239-
};
240-
self.webidl.push(DomString);
241-
self.bindings
242-
.push(NonstandardIncoming::Standard(expr.into()));
243-
}
244-
VectorKind::I64 | VectorKind::U64 => {
245-
let signed = match kind {
246-
VectorKind::I64 => true,
247-
_ => false,
248-
};
249-
self.bindings.push(NonstandardIncoming::AllocCopyInt64 {
250-
alloc_func_name: self.alloc_func_name(),
251-
expr: Box::new(self.expr_get()),
252-
signed,
253-
});
254-
self.webidl.push(Any);
255-
}
256-
VectorKind::Anyref => {
257-
self.bindings
258-
.push(NonstandardIncoming::AllocCopyAnyrefArray {
259-
alloc_func_name: self.alloc_func_name(),
260-
expr: Box::new(self.expr_get()),
261-
});
262-
self.webidl.push(Any);
263-
}
264-
}
219+
self.alloc_copy_kind(kind)
265220
}
266221

267222
// Can't be passed from JS to Rust yet
@@ -309,12 +264,15 @@ impl IncomingBuilder {
309264
)
310265
})?;
311266
self.wasm.extend(&[ValType::I32; 2]);
312-
self.bindings.push(NonstandardIncoming::Slice {
313-
kind,
314-
val: self.expr_get(),
315-
mutable,
316-
});
317-
self.webidl.push(ast::WebidlScalarType::Any);
267+
if mutable {
268+
self.bindings.push(NonstandardIncoming::MutableSlice {
269+
kind,
270+
val: self.expr_get(),
271+
});
272+
self.webidl.push(ast::WebidlScalarType::Any);
273+
} else {
274+
self.alloc_copy_kind(kind)
275+
}
318276
}
319277
_ => bail!(
320278
"unsupported reference argument type for calling Rust function from JS: {:?}",
@@ -445,6 +403,51 @@ impl IncomingBuilder {
445403
"__wbindgen_malloc".to_string()
446404
}
447405

406+
fn alloc_copy_kind(&mut self, kind: VectorKind) {
407+
use wasm_webidl_bindings::ast::WebidlScalarType::*;
408+
409+
match kind {
410+
VectorKind::I8 => self.alloc_copy(Int8Array),
411+
VectorKind::U8 => self.alloc_copy(Uint8Array),
412+
VectorKind::ClampedU8 => self.alloc_copy(Uint8ClampedArray),
413+
VectorKind::I16 => self.alloc_copy(Int16Array),
414+
VectorKind::U16 => self.alloc_copy(Uint16Array),
415+
VectorKind::I32 => self.alloc_copy(Int32Array),
416+
VectorKind::U32 => self.alloc_copy(Uint32Array),
417+
VectorKind::F32 => self.alloc_copy(Float32Array),
418+
VectorKind::F64 => self.alloc_copy(Float64Array),
419+
VectorKind::String => {
420+
let expr = ast::IncomingBindingExpressionAllocUtf8Str {
421+
alloc_func_name: self.alloc_func_name(),
422+
expr: Box::new(self.expr_get()),
423+
};
424+
self.webidl.push(DomString);
425+
self.bindings
426+
.push(NonstandardIncoming::Standard(expr.into()));
427+
}
428+
VectorKind::I64 | VectorKind::U64 => {
429+
let signed = match kind {
430+
VectorKind::I64 => true,
431+
_ => false,
432+
};
433+
self.bindings.push(NonstandardIncoming::AllocCopyInt64 {
434+
alloc_func_name: self.alloc_func_name(),
435+
expr: Box::new(self.expr_get()),
436+
signed,
437+
});
438+
self.webidl.push(Any);
439+
}
440+
VectorKind::Anyref => {
441+
self.bindings
442+
.push(NonstandardIncoming::AllocCopyAnyrefArray {
443+
alloc_func_name: self.alloc_func_name(),
444+
expr: Box::new(self.expr_get()),
445+
});
446+
self.webidl.push(Any);
447+
}
448+
}
449+
}
450+
448451
fn alloc_copy(&mut self, webidl: ast::WebidlScalarType) {
449452
let expr = ast::IncomingBindingExpressionAllocCopy {
450453
alloc_func_name: self.alloc_func_name(),

src/convert/slices.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,11 @@ macro_rules! vectors {
9494

9595
impl RefFromWasmAbi for [$t] {
9696
type Abi = WasmSlice;
97-
type Anchor = &'static [$t];
97+
type Anchor = Box<[$t]>;
9898

9999
#[inline]
100-
unsafe fn ref_from_abi(js: WasmSlice) -> &'static [$t] {
101-
slice::from_raw_parts(
102-
<*const $t>::from_abi(js.ptr),
103-
js.len as usize,
104-
)
100+
unsafe fn ref_from_abi(js: WasmSlice) -> Box<[$t]> {
101+
<Box<[$t]>>::from_abi(js)
105102
}
106103
}
107104

@@ -195,11 +192,11 @@ impl<'a> OptionIntoWasmAbi for &'a str {
195192

196193
impl RefFromWasmAbi for str {
197194
type Abi = <[u8] as RefFromWasmAbi>::Abi;
198-
type Anchor = &'static str;
195+
type Anchor = Box<str>;
199196

200197
#[inline]
201198
unsafe fn ref_from_abi(js: Self::Abi) -> Self::Anchor {
202-
str::from_utf8_unchecked(<[u8]>::ref_from_abi(js))
199+
mem::transmute::<Box<[u8]>, Box<str>>(<Box<[u8]>>::from_abi(js))
203200
}
204201
}
205202

0 commit comments

Comments
 (0)