diff --git a/src/binding.cc b/src/binding.cc index cad27ec22c..15b7cced6c 100644 --- a/src/binding.cc +++ b/src/binding.cc @@ -2367,6 +2367,23 @@ bool v8__PropertyCallbackInfo__ShouldThrowOnError( return self.ShouldThrowOnError(); } +const v8::RegExp* v8__RegExp__New(const v8::Context& context, + const v8::String& pattern, + v8::RegExp::Flags flags) { + return maybe_local_to_ptr( + v8::RegExp::New(ptr_to_local(&context), ptr_to_local(&pattern), flags)); +} + +const v8::Object* v8__RegExp__Exec(v8::RegExp& self, const v8::Context& context, + const v8::String& subject) { + return maybe_local_to_ptr( + self.Exec(ptr_to_local(&context), ptr_to_local(&subject))); +} + +const v8::String* v8__RegExp__GetSource(const v8::RegExp& self) { + return local_to_ptr(self.GetSource()); +} + void v8__ReturnValue__Value__Set(v8::ReturnValue* self, const v8::Value& value) { self->Set(ptr_to_local(&value)); diff --git a/src/lib.rs b/src/lib.rs index bf875f3c9c..f83a791433 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -63,6 +63,7 @@ mod property_descriptor; mod property_filter; mod property_handler_flags; mod proxy; +mod regexp; mod scope; mod script; mod script_or_module; @@ -138,6 +139,7 @@ pub use property_attribute::*; pub use property_descriptor::*; pub use property_filter::*; pub use property_handler_flags::*; +pub use regexp::RegExpCreationFlags; pub use scope::AllowJavascriptExecutionScope; pub use scope::CallbackScope; pub use scope::ContextScope; diff --git a/src/regexp.rs b/src/regexp.rs new file mode 100644 index 0000000000..cd978d7080 --- /dev/null +++ b/src/regexp.rs @@ -0,0 +1,73 @@ +use crate::support::int; +use crate::Context; +use crate::HandleScope; +use crate::Local; +use crate::Object; +use crate::RegExp; +use crate::String; + +bitflags! { + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(transparent)] + pub struct RegExpCreationFlags: int { + const GLOBAL = 1 << 0; + const IGNORE_CASE = 1 << 1; + const MULTILINE = 1 << 2; + const STICKY = 1 << 3; + const UNICODE = 1 << 4; + const DOT_ALL = 1 << 5; + const LINEAR = 1 << 6; + const HAS_INDICES = 1 << 7; + const UNICODE_SETS = 1 << 8; + } +} + +extern "C" { + fn v8__RegExp__New( + context: *const Context, + pattern: *const String, + flags: RegExpCreationFlags, + ) -> *const RegExp; + fn v8__RegExp__Exec( + this: *const RegExp, + context: *const Context, + subject: *const String, + ) -> *const Object; + fn v8__RegExp__GetSource(this: *const RegExp) -> *const String; +} + +impl RegExp { + #[inline(always)] + pub fn new<'s>( + scope: &mut HandleScope<'s>, + pattern: Local, + flags: RegExpCreationFlags, + ) -> Option> { + unsafe { + scope.cast_local(|sd| { + v8__RegExp__New(sd.get_current_context(), &*pattern, flags) + }) + } + } + + #[inline(always)] + pub fn exec<'s>( + &self, + scope: &mut HandleScope<'s>, + subject: Local, + ) -> Option> { + unsafe { + scope.cast_local(|sd| { + v8__RegExp__Exec(self, sd.get_current_context(), &*subject) + }) + } + } + + #[inline(always)] + pub fn get_source<'s>( + &self, + scope: &mut HandleScope<'s>, + ) -> Local<'s, String> { + unsafe { scope.cast_local(|_| v8__RegExp__GetSource(self)) }.unwrap() + } +} diff --git a/tests/test_api.rs b/tests/test_api.rs index 06f4d493db..20f6c22236 100644 --- a/tests/test_api.rs +++ b/tests/test_api.rs @@ -12006,3 +12006,36 @@ fn test_eternals() { assert!(eternal1.is_empty()); eternal1.clear(); } + +#[test] +fn test_regexp() { + let _setup_guard = setup::parallel_test(); + + let mut isolate = v8::Isolate::new(Default::default()); + let mut scope = v8::HandleScope::new(&mut isolate); + let context = v8::Context::new(&mut scope, Default::default()); + let scope = &mut v8::ContextScope::new(&mut scope, context); + + let pattern = v8::String::new(scope, "ab+c").unwrap(); + let regexp = + v8::RegExp::new(scope, pattern, v8::RegExpCreationFlags::empty()).unwrap(); + assert_eq!(regexp.get_source(scope).to_rust_string_lossy(scope), "ab+c"); + + let subject = v8::String::new(scope, "abbbc").unwrap(); + let result = regexp.exec(scope, subject).unwrap(); + + let full = result.get_index(scope, 0).unwrap(); + assert_eq!(full.to_rust_string_lossy(scope), "abbbc"); + + let index_key = v8::String::new(scope, "index").unwrap(); + let index = result.get(scope, index_key.into()).unwrap(); + assert_eq!(index.number_value(scope).unwrap(), 0.0); + + let input_key = v8::String::new(scope, "input").unwrap(); + let input = result.get(scope, input_key.into()).unwrap(); + assert_eq!(input.to_rust_string_lossy(scope), "abbbc"); + + let groups_key = v8::String::new(scope, "groups").unwrap(); + let groups = result.get(scope, groups_key.into()).unwrap(); + assert!(groups.is_undefined()); +}