diff --git a/core/webidl.rs b/core/webidl.rs index 7d5b490fd..6efb03702 100644 --- a/core/webidl.rs +++ b/core/webidl.rs @@ -13,55 +13,52 @@ pub struct WebIdlError { pub kind: WebIdlErrorKind, } -type DynContext<'a> = dyn Fn() -> Cow<'static, str> + 'a; +type DynContextFn<'a> = dyn Fn() -> Cow<'static, str> + 'a; -enum MyCow<'a> { - Borrowed(&'a DynContext<'a>), - Owned(Box>), +enum ContextFnInner<'a> { + Borrowed(&'a DynContextFn<'a>), + Owned(Box>), } -pub struct ContextFn<'a>(MyCow<'a>); +/// A function that returns a context string for an error. +/// +/// When possible, prefer to use `ContextFn::new_borrowed` when creating a new context function +/// to avoid unnecessary allocations. +/// +/// To pass a borrow of the context function, use `ContextFn::borrowed`. +pub struct ContextFn<'a>(ContextFnInner<'a>); impl<'a, T> From for ContextFn<'a> where T: Fn() -> Cow<'static, str> + 'a, { fn from(f: T) -> Self { - Self(MyCow::Owned(Box::new(f))) + Self(ContextFnInner::Owned(Box::new(f))) } } impl<'a> ContextFn<'a> { pub fn call(&self) -> Cow<'static, str> { match &self.0 { - MyCow::Borrowed(b) => b(), - MyCow::Owned(b) => b(), + ContextFnInner::Borrowed(b) => b(), + ContextFnInner::Owned(b) => b(), } } pub fn new(f: impl Fn() -> Cow<'static, str> + 'a) -> Self { - Self(MyCow::Owned(Box::new(f))) + Self(ContextFnInner::Owned(Box::new(f))) } - pub fn new_borrowed(b: &'a DynContext<'a>) -> Self { - Self(MyCow::Borrowed(b)) - } -} - -impl<'a> AsRef> for ContextFn<'a> { - fn as_ref(&self) -> &DynContext<'a> { - match &self.0 { - MyCow::Borrowed(b) => *b, - MyCow::Owned(b) => b.as_ref(), - } + pub fn new_borrowed(b: &'a DynContextFn<'a>) -> Self { + Self(ContextFnInner::Borrowed(b)) } } impl<'a> ContextFn<'a> { pub fn borrowed(&'a self) -> ContextFn<'a> { match self { - Self(MyCow::Borrowed(b)) => Self(MyCow::Borrowed(*b)), - Self(MyCow::Owned(b)) => Self(MyCow::Borrowed(&**b)), + Self(ContextFnInner::Borrowed(b)) => Self(ContextFnInner::Borrowed(*b)), + Self(ContextFnInner::Owned(b)) => Self(ContextFnInner::Borrowed(&**b)), } } } @@ -371,8 +368,8 @@ impl<'a, T: WebIdlConverter<'a>> WebIdlConverter<'a> for Vec { scope, iter_val, prefix.clone(), - ContextFn::from(|| { - format!("{}, index {}", (context.as_ref())(), out.len()).into() + ContextFn::new_borrowed(&|| { + format!("{}, index {}", context.call(), out.len()).into() }), options, )?); diff --git a/ops/op2/dispatch_slow.rs b/ops/op2/dispatch_slow.rs index ba600cb1b..a8add3cd1 100644 --- a/ops/op2/dispatch_slow.rs +++ b/ops/op2/dispatch_slow.rs @@ -711,7 +711,7 @@ pub fn from_arg( &mut #scope, #arg_ident, #prefix.into(), - deno_core::webidl::ContextFn::from(|| std::borrow::Cow::Borrowed(#context)), + deno_core::webidl::ContextFn::new_borrowed(&|| std::borrow::Cow::Borrowed(#context)), &#options, ) { Ok(t) => t, diff --git a/ops/op2/test_cases/sync/webidl.out b/ops/op2/test_cases/sync/webidl.out index 525b3d58b..b536d01af 100644 --- a/ops/op2/test_cases/sync/webidl.out +++ b/ops/op2/test_cases/sync/webidl.out @@ -45,7 +45,9 @@ const fn op_webidl() -> ::deno_core::_ops::OpDecl { &mut scope, arg0, "Failed to execute 'UNINIT.call'".into(), - || std::borrow::Cow::Borrowed("Argument 1"), + deno_core::webidl::ContextFn::new_borrowed( + &|| std::borrow::Cow::Borrowed("Argument 1"), + ), &Default::default(), ) { Ok(t) => t, @@ -65,7 +67,9 @@ const fn op_webidl() -> ::deno_core::_ops::OpDecl { &mut scope, arg1, "Failed to execute 'UNINIT.call'".into(), - || std::borrow::Cow::Borrowed("Argument 2"), + deno_core::webidl::ContextFn::new_borrowed( + &|| std::borrow::Cow::Borrowed("Argument 2"), + ), &Default::default(), ) { Ok(t) => t, diff --git a/ops/webidl/enum.rs b/ops/webidl/enum.rs index 056c547d9..2a867122a 100644 --- a/ops/webidl/enum.rs +++ b/ops/webidl/enum.rs @@ -33,14 +33,14 @@ pub fn get_body( let Ok(str) = __value.try_cast::<::deno_core::v8::String>() else { return Err(::deno_core::webidl::WebIdlError::new( __prefix, - &__context, + __context, ::deno_core::webidl::WebIdlErrorKind::ConvertToConverterType("enum"), )); }; match str.to_rust_string_lossy(__scope).as_str() { #(#variants),*, - s => Err(::deno_core::webidl::WebIdlError::new(__prefix, &__context, ::deno_core::webidl::WebIdlErrorKind::InvalidEnumVariant { converter: #ident_string, variant: s.to_string() })) + s => Err(::deno_core::webidl::WebIdlError::new(__prefix, __context, ::deno_core::webidl::WebIdlErrorKind::InvalidEnumVariant { converter: #ident_string, variant: s.to_string() })) } }) } diff --git a/ops/webidl/test_cases/dict.out b/ops/webidl/test_cases/dict.out index 68119d045..6aa0ec4c3 100644 --- a/ops/webidl/test_cases/dict.out +++ b/ops/webidl/test_cases/dict.out @@ -1,15 +1,12 @@ impl<'a> ::deno_core::webidl::WebIdlConverter<'a> for Dict { type Options = (); - fn convert( + fn convert<'b>( __scope: &mut ::deno_core::v8::HandleScope<'a>, __value: ::deno_core::v8::Local<'a, ::deno_core::v8::Value>, __prefix: std::borrow::Cow<'static, str>, - __context: C, + __context: ::deno_core::webidl::ContextFn<'b>, __options: &Self::Options, - ) -> Result - where - C: Fn() -> std::borrow::Cow<'static, str>, - { + ) -> Result { ::deno_core::v8_static_strings! { __v8_static_a = "a", __v8_static_b = "b", __v8_static_c = "c", __v8_static_e = "e", __v8_static_f = "f" @@ -32,7 +29,7 @@ impl<'a> ::deno_core::webidl::WebIdlConverter<'a> for Dict { return Err( ::deno_core::webidl::WebIdlError::new( __prefix, - &__context, + __context.borrowed(), ::deno_core::webidl::WebIdlErrorKind::ConvertToConverterType( "dictionary", ), @@ -50,7 +47,7 @@ impl<'a> ::deno_core::webidl::WebIdlConverter<'a> for Dict { .v8_string(__scope) .map_err(|e| ::deno_core::webidl::WebIdlError::other( __prefix.clone(), - &__context, + __context.borrowed(), e, ))?; __eternal.set(__scope, __key); @@ -66,14 +63,16 @@ impl<'a> ::deno_core::webidl::WebIdlConverter<'a> for Dict { __scope, __value, __prefix.clone(), - || format!("{} ({})", "'a' of 'Dict'", __context()).into(), + ::deno_core::webidl::ContextFn::new_borrowed( + &|| format!("{} ({})", "'a' of 'Dict'", __context.call()).into(), + ), &Default::default(), )? } else { return Err( ::deno_core::webidl::WebIdlError::new( __prefix, - &__context, + __context.borrowed(), ::deno_core::webidl::WebIdlErrorKind::DictionaryCannotConvertKey { converter: "Dict", key: "a", @@ -92,7 +91,7 @@ impl<'a> ::deno_core::webidl::WebIdlConverter<'a> for Dict { .v8_string(__scope) .map_err(|e| ::deno_core::webidl::WebIdlError::other( __prefix.clone(), - &__context, + __context.borrowed(), e, ))?; __eternal.set(__scope, __key); @@ -108,7 +107,9 @@ impl<'a> ::deno_core::webidl::WebIdlConverter<'a> for Dict { __scope, __value, __prefix.clone(), - || format!("{} ({})", "'b' of 'Dict'", __context()).into(), + ::deno_core::webidl::ContextFn::new_borrowed( + &|| format!("{} ({})", "'b' of 'Dict'", __context.call()).into(), + ), &{ type Alias<'a> = ::deno_core::webidl::WebIdlConverter<'a> for Dict { return Err( ::deno_core::webidl::WebIdlError::new( __prefix, - &__context, + __context.borrowed(), ::deno_core::webidl::WebIdlErrorKind::DictionaryCannotConvertKey { converter: "Dict", key: "b", @@ -142,7 +143,7 @@ impl<'a> ::deno_core::webidl::WebIdlConverter<'a> for Dict { .v8_string(__scope) .map_err(|e| ::deno_core::webidl::WebIdlError::other( __prefix.clone(), - &__context, + __context.borrowed(), e, ))?; __eternal.set(__scope, __key); @@ -161,7 +162,9 @@ impl<'a> ::deno_core::webidl::WebIdlConverter<'a> for Dict { __scope, __value, __prefix.clone(), - || format!("{} ({})", "'c' of 'Dict'", __context()).into(), + ::deno_core::webidl::ContextFn::new_borrowed( + &|| format!("{} ({})", "'c' of 'Dict'", __context.call()).into(), + ), &Default::default(), )? } else { @@ -178,7 +181,7 @@ impl<'a> ::deno_core::webidl::WebIdlConverter<'a> for Dict { .v8_string(__scope) .map_err(|e| ::deno_core::webidl::WebIdlError::other( __prefix.clone(), - &__context, + __context.borrowed(), e, ))?; __eternal.set(__scope, __key); @@ -194,14 +197,16 @@ impl<'a> ::deno_core::webidl::WebIdlConverter<'a> for Dict { __scope, __value, __prefix.clone(), - || format!("{} ({})", "'e' of 'Dict'", __context()).into(), + ::deno_core::webidl::ContextFn::new_borrowed( + &|| format!("{} ({})", "'e' of 'Dict'", __context.call()).into(), + ), &Default::default(), )? } else { return Err( ::deno_core::webidl::WebIdlError::new( __prefix, - &__context, + __context.borrowed(), ::deno_core::webidl::WebIdlErrorKind::DictionaryCannotConvertKey { converter: "Dict", key: "e", @@ -220,7 +225,7 @@ impl<'a> ::deno_core::webidl::WebIdlConverter<'a> for Dict { .v8_string(__scope) .map_err(|e| ::deno_core::webidl::WebIdlError::other( __prefix.clone(), - &__context, + __context.borrowed(), e, ))?; __eternal.set(__scope, __key); @@ -236,14 +241,16 @@ impl<'a> ::deno_core::webidl::WebIdlConverter<'a> for Dict { __scope, __value, __prefix.clone(), - || format!("{} ({})", "'f' of 'Dict'", __context()).into(), + ::deno_core::webidl::ContextFn::new_borrowed( + &|| format!("{} ({})", "'f' of 'Dict'", __context.call()).into(), + ), &Default::default(), )? } else { return Err( ::deno_core::webidl::WebIdlError::new( __prefix, - &__context, + __context.borrowed(), ::deno_core::webidl::WebIdlErrorKind::DictionaryCannotConvertKey { converter: "Dict", key: "f", diff --git a/ops/webidl/test_cases/enum.out b/ops/webidl/test_cases/enum.out index dc09959d4..91077e01b 100644 --- a/ops/webidl/test_cases/enum.out +++ b/ops/webidl/test_cases/enum.out @@ -1,20 +1,17 @@ impl<'a> ::deno_core::webidl::WebIdlConverter<'a> for Enumeration { type Options = (); - fn convert( + fn convert<'b>( __scope: &mut ::deno_core::v8::HandleScope<'a>, __value: ::deno_core::v8::Local<'a, ::deno_core::v8::Value>, __prefix: std::borrow::Cow<'static, str>, - __context: C, + __context: ::deno_core::webidl::ContextFn<'b>, __options: &Self::Options, - ) -> Result - where - C: Fn() -> std::borrow::Cow<'static, str>, - { + ) -> Result { let Ok(str) = __value.try_cast::<::deno_core::v8::String>() else { return Err( ::deno_core::webidl::WebIdlError::new( __prefix, - &__context, + __context, ::deno_core::webidl::WebIdlErrorKind::ConvertToConverterType("enum"), ), ); @@ -27,7 +24,7 @@ impl<'a> ::deno_core::webidl::WebIdlConverter<'a> for Enumeration { Err( ::deno_core::webidl::WebIdlError::new( __prefix, - &__context, + __context, ::deno_core::webidl::WebIdlErrorKind::InvalidEnumVariant { converter: "Enumeration", variant: s.to_string(),