Skip to content

Commit

Permalink
Allow #[cppgc] &mut T in sync ops
Browse files Browse the repository at this point in the history
Closes #787
  • Loading branch information
littledivy committed Jun 20, 2024
1 parent 655d1d7 commit 1a94b58
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 14 deletions.
14 changes: 10 additions & 4 deletions core/cppgc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,16 @@ pub fn make_cppgc_object<'a, T: 'static>(
obj
}

#[repr(C)]
struct InnerMember {
inner: [usize; 2],
ptr: *mut (),
}

#[allow(clippy::needless_lifetimes)]
pub fn try_unwrap_cppgc_object<'sc, T: 'static>(
val: v8::Local<'sc, v8::Value>,
) -> Option<&'sc T> {
) -> Option<&'sc mut T> {
let Ok(obj): Result<v8::Local<v8::Object>, _> = val.try_into() else {
return None;
};
Expand All @@ -60,13 +66,13 @@ pub fn try_unwrap_cppgc_object<'sc, T: 'static>(
// The object can only be created by `make_cppgc_object`.
let member = unsafe {
let ptr = obj.get_aligned_pointer_from_internal_field(SLOT_OFFSET);
let obj = &*(ptr as *const v8::cppgc::InnerMember);
obj.get::<CppGcObject<T>>()
let obj = &*(ptr as *mut InnerMember);
obj.ptr.cast::<CppGcObject<T>>().as_mut().unwrap()
};

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

Some(&member.member)
Some(&mut member.member)
}
15 changes: 13 additions & 2 deletions core/runtime/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,7 @@ mod tests {
op_arraybuffer_slice,
op_test_get_cppgc_resource,
op_test_make_cppgc_resource,
op_test_set_cppgc_resource,
op_external_make,
op_external_process,
op_external_make_ptr,
Expand Down Expand Up @@ -1907,14 +1908,24 @@ mod tests {
resource.value
}

#[op2(fast)]
pub fn op_test_set_cppgc_resource(
#[cppgc] resource: &mut TestResource,
value: u32,
) {
resource.value = value;
}

#[test]
pub fn test_op_cppgc_object() -> Result<(), Box<dyn std::error::Error>> {
run_test2(
10,
"op_test_make_cppgc_resource, op_test_get_cppgc_resource",
"op_test_make_cppgc_resource, op_test_get_cppgc_resource, op_test_set_cppgc_resource",
r"
const resource = op_test_make_cppgc_resource();
assert(op_test_get_cppgc_resource(resource) == 42);",
assert(op_test_get_cppgc_resource(resource) == 42);
op_test_set_cppgc_resource(resource, 43);
assert(op_test_get_cppgc_resource(resource) == 43);",
)?;
Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion ops/op2/dispatch_async.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub(crate) fn generate_dispatch_async(
let mut output = TokenStream::new();

let with_self = if generator_state.needs_self {
with_self(generator_state, &signature.ret_val)
with_self(generator_state, true, &signature.ret_val)
.map_err(V8SignatureMappingError::NoSelfMapping)?
} else {
quote!()
Expand Down
4 changes: 3 additions & 1 deletion ops/op2/dispatch_slow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ pub(crate) fn generate_dispatch_slow(
)?);

let with_self = if generator_state.needs_self {
with_self(generator_state, &signature.ret_val)
with_self(generator_state, false, &signature.ret_val)
.map_err(V8SignatureMappingError::NoSelfMapping)?
} else {
quote!()
Expand Down Expand Up @@ -246,6 +246,7 @@ pub(crate) fn with_js_runtime_state(

pub(crate) fn with_self(
generator_state: &mut GeneratorState,
is_async: bool,
ret_val: &RetVal,
) -> Result<TokenStream, V8MappingError> {
generator_state.needs_opctx = true;
Expand All @@ -254,6 +255,7 @@ pub(crate) fn with_self(
format!("expected {}", &generator_state.self_ty),
)?;
let tokens = if matches!(ret_val, RetVal::Future(_) | RetVal::FutureResult(_))
|| is_async
{
let tokens = gs_quote!(generator_state(self_ty, fn_args, scope) => {
let Some(self_) = deno_core::_ops::CppGcObjectGuard::<#self_ty>::try_new_from_cppgc_object(&mut *#scope, #fn_args.this().into()) else {
Expand Down
10 changes: 4 additions & 6 deletions ops/op2/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1470,12 +1470,10 @@ fn parse_type_state(ty: &Type) -> Result<Arg, ArgError> {

fn parse_cppgc(position: Position, ty: &Type) -> Result<Arg, ArgError> {
match (position, ty) {
(Position::Arg, Type::Reference(of)) if of.mutability.is_none() => {
match &*of.elem {
Type::Path(of) => Ok(Arg::CppGcResource(stringify_token(&of.path))),
_ => Err(ArgError::InvalidCppGcType(stringify_token(ty))),
}
}
(Position::Arg, Type::Reference(of)) => match &*of.elem {
Type::Path(of) => Ok(Arg::CppGcResource(stringify_token(&of.path))),
_ => Err(ArgError::InvalidCppGcType(stringify_token(ty))),
},
(Position::RetVal, Type::Path(of)) => {
Ok(Arg::CppGcResource(stringify_token(&of.path)))
}
Expand Down
167 changes: 167 additions & 0 deletions ops/op2/test_cases/sync/cppgc_resource.out

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions ops/op2/test_cases/sync/cppgc_resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ fn op_make_cppgc_object() -> Wrap {

#[op2(fast)]
fn op_use_cppgc_object(#[cppgc] _wrap: &Wrap) {}

#[op2(fast)]
fn op_use_cppgc_object_mut(#[cppgc] _wrap: &mut Wrap) {}
3 changes: 3 additions & 0 deletions ops/op2/test_cases_fail/lifetimes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ fn op_use_cppgc_object(#[cppgc] _wrap: &'static Wrap) {}

#[op2(fast)]
fn op_use_buffer(#[buffer] _buffer: &'static [u8]) {}

#[op2(async)]
async fn op_use_cppgc_object_mut_async(#[cppgc] _wrap: &mut Wrap) {}

0 comments on commit 1a94b58

Please sign in to comment.