Skip to content

Commit 1a94b58

Browse files
committed
Allow #[cppgc] &mut T in sync ops
Closes #787
1 parent 655d1d7 commit 1a94b58

File tree

8 files changed

+204
-14
lines changed

8 files changed

+204
-14
lines changed

core/cppgc.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,16 @@ pub fn make_cppgc_object<'a, T: 'static>(
4141
obj
4242
}
4343

44+
#[repr(C)]
45+
struct InnerMember {
46+
inner: [usize; 2],
47+
ptr: *mut (),
48+
}
49+
4450
#[allow(clippy::needless_lifetimes)]
4551
pub fn try_unwrap_cppgc_object<'sc, T: 'static>(
4652
val: v8::Local<'sc, v8::Value>,
47-
) -> Option<&'sc T> {
53+
) -> Option<&'sc mut T> {
4854
let Ok(obj): Result<v8::Local<v8::Object>, _> = val.try_into() else {
4955
return None;
5056
};
@@ -60,13 +66,13 @@ pub fn try_unwrap_cppgc_object<'sc, T: 'static>(
6066
// The object can only be created by `make_cppgc_object`.
6167
let member = unsafe {
6268
let ptr = obj.get_aligned_pointer_from_internal_field(SLOT_OFFSET);
63-
let obj = &*(ptr as *const v8::cppgc::InnerMember);
64-
obj.get::<CppGcObject<T>>()
69+
let obj = &*(ptr as *mut InnerMember);
70+
obj.ptr.cast::<CppGcObject<T>>().as_mut().unwrap()
6571
};
6672

6773
if member.tag != TypeId::of::<T>() {
6874
return None;
6975
}
7076

71-
Some(&member.member)
77+
Some(&mut member.member)
7278
}

core/runtime/ops.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,7 @@ mod tests {
608608
op_arraybuffer_slice,
609609
op_test_get_cppgc_resource,
610610
op_test_make_cppgc_resource,
611+
op_test_set_cppgc_resource,
611612
op_external_make,
612613
op_external_process,
613614
op_external_make_ptr,
@@ -1907,14 +1908,24 @@ mod tests {
19071908
resource.value
19081909
}
19091910

1911+
#[op2(fast)]
1912+
pub fn op_test_set_cppgc_resource(
1913+
#[cppgc] resource: &mut TestResource,
1914+
value: u32,
1915+
) {
1916+
resource.value = value;
1917+
}
1918+
19101919
#[test]
19111920
pub fn test_op_cppgc_object() -> Result<(), Box<dyn std::error::Error>> {
19121921
run_test2(
19131922
10,
1914-
"op_test_make_cppgc_resource, op_test_get_cppgc_resource",
1923+
"op_test_make_cppgc_resource, op_test_get_cppgc_resource, op_test_set_cppgc_resource",
19151924
r"
19161925
const resource = op_test_make_cppgc_resource();
1917-
assert(op_test_get_cppgc_resource(resource) == 42);",
1926+
assert(op_test_get_cppgc_resource(resource) == 42);
1927+
op_test_set_cppgc_resource(resource, 43);
1928+
assert(op_test_get_cppgc_resource(resource) == 43);",
19181929
)?;
19191930
Ok(())
19201931
}

ops/op2/dispatch_async.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub(crate) fn generate_dispatch_async(
4747
let mut output = TokenStream::new();
4848

4949
let with_self = if generator_state.needs_self {
50-
with_self(generator_state, &signature.ret_val)
50+
with_self(generator_state, true, &signature.ret_val)
5151
.map_err(V8SignatureMappingError::NoSelfMapping)?
5252
} else {
5353
quote!()

ops/op2/dispatch_slow.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ pub(crate) fn generate_dispatch_slow(
9292
)?);
9393

9494
let with_self = if generator_state.needs_self {
95-
with_self(generator_state, &signature.ret_val)
95+
with_self(generator_state, false, &signature.ret_val)
9696
.map_err(V8SignatureMappingError::NoSelfMapping)?
9797
} else {
9898
quote!()
@@ -246,6 +246,7 @@ pub(crate) fn with_js_runtime_state(
246246

247247
pub(crate) fn with_self(
248248
generator_state: &mut GeneratorState,
249+
is_async: bool,
249250
ret_val: &RetVal,
250251
) -> Result<TokenStream, V8MappingError> {
251252
generator_state.needs_opctx = true;
@@ -254,6 +255,7 @@ pub(crate) fn with_self(
254255
format!("expected {}", &generator_state.self_ty),
255256
)?;
256257
let tokens = if matches!(ret_val, RetVal::Future(_) | RetVal::FutureResult(_))
258+
|| is_async
257259
{
258260
let tokens = gs_quote!(generator_state(self_ty, fn_args, scope) => {
259261
let Some(self_) = deno_core::_ops::CppGcObjectGuard::<#self_ty>::try_new_from_cppgc_object(&mut *#scope, #fn_args.this().into()) else {

ops/op2/signature.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -1470,12 +1470,10 @@ fn parse_type_state(ty: &Type) -> Result<Arg, ArgError> {
14701470

14711471
fn parse_cppgc(position: Position, ty: &Type) -> Result<Arg, ArgError> {
14721472
match (position, ty) {
1473-
(Position::Arg, Type::Reference(of)) if of.mutability.is_none() => {
1474-
match &*of.elem {
1475-
Type::Path(of) => Ok(Arg::CppGcResource(stringify_token(&of.path))),
1476-
_ => Err(ArgError::InvalidCppGcType(stringify_token(ty))),
1477-
}
1478-
}
1473+
(Position::Arg, Type::Reference(of)) => match &*of.elem {
1474+
Type::Path(of) => Ok(Arg::CppGcResource(stringify_token(&of.path))),
1475+
_ => Err(ArgError::InvalidCppGcType(stringify_token(ty))),
1476+
},
14791477
(Position::RetVal, Type::Path(of)) => {
14801478
Ok(Arg::CppGcResource(stringify_token(&of.path)))
14811479
}

ops/op2/test_cases/sync/cppgc_resource.out

+167
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ops/op2/test_cases/sync/cppgc_resource.rs

+3
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,6 @@ fn op_make_cppgc_object() -> Wrap {
1212

1313
#[op2(fast)]
1414
fn op_use_cppgc_object(#[cppgc] _wrap: &Wrap) {}
15+
16+
#[op2(fast)]
17+
fn op_use_cppgc_object_mut(#[cppgc] _wrap: &mut Wrap) {}

ops/op2/test_cases_fail/lifetimes.rs

+3
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,6 @@ fn op_use_cppgc_object(#[cppgc] _wrap: &'static Wrap) {}
1111

1212
#[op2(fast)]
1313
fn op_use_buffer(#[buffer] _buffer: &'static [u8]) {}
14+
15+
#[op2(async)]
16+
async fn op_use_cppgc_object_mut_async(#[cppgc] _wrap: &mut Wrap) {}

0 commit comments

Comments
 (0)