Skip to content

Commit

Permalink
Add #[this] _: v8::Global<v8::Object> (#1053)
Browse files Browse the repository at this point in the history
Example usage:

```rust
#[op2]
impl UnsafePointerView {
  #[cppgc]
  fn get_context(&self, #[this] this: v8::Global<v8::Object>) -> GPUCanvasContext {
    GPUCanvasContext { view: this }
  }
}

struct GPUCanvasContext {
  view: v8::Global<v8::Object>,
}

#[op2]
impl GPUCanvasContext {
  fn canvas(&self) -> v8::Global<v8::Object> { self.view.clone() }
}
```

`#[this]` works on both slow and fast calls.
  • Loading branch information
littledivy authored Jan 22, 2025
1 parent b92a9a3 commit e97dbb1
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 5 deletions.
9 changes: 5 additions & 4 deletions ops/op2/dispatch_fast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -757,10 +757,10 @@ fn map_v8_fastcall_arg_to_arg(
let #arg_ident = #arg_ident.try_borrow_mut::<#state>();
}
}
Arg::VarArgs => {
quote! {
let #arg_ident = None;
}
Arg::VarArgs => quote!(let #arg_ident = None;),
Arg::This => {
*needs_fast_isolate = true;
quote!(let #arg_ident = deno_core::v8::Global::new(&mut #scope, this);)
}
Arg::String(Strings::RefStr) => {
quote! {
Expand Down Expand Up @@ -886,6 +886,7 @@ fn map_arg_to_v8_fastcall_type(
| Arg::Ref(RefType::Ref, Special::JsRuntimeState)
| Arg::State(..)
| Arg::VarArgs
| Arg::This
| Arg::Special(Special::Isolate)
| Arg::OptionState(..) => V8FastCallType::Virtual,
// Other types + ref types are not handled
Expand Down
6 changes: 6 additions & 0 deletions ops/op2/dispatch_slow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,12 @@ pub fn from_arg(
let #arg_ident = Some(&#fn_args);
})
}
Arg::This => {
*needs_isolate = true;
gs_quote!(generator_state(scope, fn_args) => {
let #arg_ident = deno_core::v8::Global::new(&mut #scope, #fn_args.this());
})
}
Arg::Buffer(buffer_type, mode, source) => {
// Explicit temporary lifetime extension so we can take a reference
let temp = format_ident!("{}_temp", arg_ident);
Expand Down
16 changes: 15 additions & 1 deletion ops/op2/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ pub enum Arg {
ToV8(String),
WebIDL(String, Vec<WebIDLPairs>, Option<WebIDLDefault>),
VarArgs,
This,
}

impl Arg {
Expand Down Expand Up @@ -373,7 +374,7 @@ impl Arg {
| Special::HandleScope,
) => true,
Self::State(..) | Self::OptionState(..) => true,
Self::VarArgs => true,
Self::This | Self::VarArgs => true,
_ => false,
}
}
Expand Down Expand Up @@ -787,6 +788,8 @@ pub enum AttributeModifier {
Ignore,
/// Varaible-length arguments.
VarArgs,
/// The `this` receiver.
This,
}

impl AttributeModifier {
Expand All @@ -806,6 +809,7 @@ impl AttributeModifier {
AttributeModifier::CppGcResource => "cppgc",
AttributeModifier::Ignore => "ignore",
AttributeModifier::VarArgs => "varargs",
AttributeModifier::This => "this",
}
}
}
Expand Down Expand Up @@ -1278,6 +1282,7 @@ fn parse_attribute(
(#[arraybuffer(copy)]) => Some(AttributeModifier::Buffer(BufferMode::Copy, BufferSource::ArrayBuffer)),
(#[arraybuffer(detach)]) => Some(AttributeModifier::Buffer(BufferMode::Detach, BufferSource::ArrayBuffer)),
(#[global]) => Some(AttributeModifier::Global),
(#[this]) => Some(AttributeModifier::This),
(#[cppgc]) => Some(AttributeModifier::CppGcResource),
(#[to_v8]) => Some(AttributeModifier::ToV8),
(#[from_v8]) => Some(AttributeModifier::FromV8),
Expand Down Expand Up @@ -1650,6 +1655,15 @@ pub(crate) fn parse_type(
| AttributeModifier::Global => {
// We handle this as part of the normal parsing process
}
AttributeModifier::This => {
if position == Position::RetVal {
return Err(ArgError::InvalidAttributePosition(
primary.name(),
"argument",
));
}
return Ok(Arg::This);
}
AttributeModifier::Number => match ty {
Type::Path(of) => {
match parse_type_path(
Expand Down
3 changes: 3 additions & 0 deletions testing/checkin/runner/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ impl TestObjectWrap {
#[rename("with_RENAME")]
fn with_rename(&self) {}

#[fast]
fn with_this(&self, #[this] _: v8::Global<v8::Object>) {}

#[async_method]
async fn with_async_fn(&self, #[smi] ms: u32) -> Result<(), JsErrorBox> {
tokio::time::sleep(std::time::Duration::from_millis(ms as u64)).await;
Expand Down
1 change: 1 addition & 0 deletions testing/ops.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export class TestObjectWrap {
withVarargs(...args: any[]): number;
with_RENAME(): void;
withAsyncFn(ms: number): Promise<void>;
withThis(): void;
}

export class TestEnumWrap {}
1 change: 1 addition & 0 deletions testing/unit/resource_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ test(async function testDomPoint() {
assertEquals(wrap.withVarargs(), 0);
assertEquals(wrap.withVarargs(undefined), 1);

wrap.withThis();
wrap.with_RENAME();

const promise = wrap.withAsyncFn(10);
Expand Down

0 comments on commit e97dbb1

Please sign in to comment.