diff --git a/ops/op2/dispatch_fast.rs b/ops/op2/dispatch_fast.rs index cb477f308..d804e142f 100644 --- a/ops/op2/dispatch_fast.rs +++ b/ops/op2/dispatch_fast.rs @@ -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! { @@ -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 diff --git a/ops/op2/dispatch_slow.rs b/ops/op2/dispatch_slow.rs index feb7bfb02..f545899a4 100644 --- a/ops/op2/dispatch_slow.rs +++ b/ops/op2/dispatch_slow.rs @@ -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); diff --git a/ops/op2/signature.rs b/ops/op2/signature.rs index 3e09841e2..13cfc340b 100644 --- a/ops/op2/signature.rs +++ b/ops/op2/signature.rs @@ -300,6 +300,7 @@ pub enum Arg { ToV8(String), WebIDL(String, Vec, Option), VarArgs, + This, } impl Arg { @@ -373,7 +374,7 @@ impl Arg { | Special::HandleScope, ) => true, Self::State(..) | Self::OptionState(..) => true, - Self::VarArgs => true, + Self::This | Self::VarArgs => true, _ => false, } } @@ -787,6 +788,8 @@ pub enum AttributeModifier { Ignore, /// Varaible-length arguments. VarArgs, + /// The `this` receiver. + This, } impl AttributeModifier { @@ -806,6 +809,7 @@ impl AttributeModifier { AttributeModifier::CppGcResource => "cppgc", AttributeModifier::Ignore => "ignore", AttributeModifier::VarArgs => "varargs", + AttributeModifier::This => "this", } } } @@ -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), @@ -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( diff --git a/testing/checkin/runner/ops.rs b/testing/checkin/runner/ops.rs index 83b7c5bf9..a8cab08d1 100644 --- a/testing/checkin/runner/ops.rs +++ b/testing/checkin/runner/ops.rs @@ -96,6 +96,9 @@ impl TestObjectWrap { #[rename("with_RENAME")] fn with_rename(&self) {} + #[fast] + fn with_this(&self, #[this] _: v8::Global) {} + #[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; diff --git a/testing/ops.d.ts b/testing/ops.d.ts index e603d0b03..008d83789 100644 --- a/testing/ops.d.ts +++ b/testing/ops.d.ts @@ -41,6 +41,7 @@ export class TestObjectWrap { withVarargs(...args: any[]): number; with_RENAME(): void; withAsyncFn(ms: number): Promise; + withThis(): void; } export class TestEnumWrap {} diff --git a/testing/unit/resource_test.ts b/testing/unit/resource_test.ts index 3819239f2..0214f91a7 100644 --- a/testing/unit/resource_test.ts +++ b/testing/unit/resource_test.ts @@ -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);