Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add bindings for RegExp #1674

Merged
merged 9 commits into from
Jan 3, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/binding.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2367,6 +2367,24 @@ bool v8__PropertyCallbackInfo__ShouldThrowOnError(
return self.ShouldThrowOnError();
}

const v8::RegExp* v8__RegExp__new(const v8::Context& context,
const v8::String& pattern,
int options) {
return maybe_local_to_ptr(v8::RegExp::New(
ptr_to_local(&context), ptr_to_local(&pattern), options));
}

const v8::Object* v8__RegExp__Exec(const 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.get_source());
}

void v8__ReturnValue__Value__Set(v8::ReturnValue<v8::Value>* self,
const v8::Value& value) {
self->Set(ptr_to_local(&value));
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
littledivy marked this conversation as resolved.
Show resolved Hide resolved
pub use scope::AllowJavascriptExecutionScope;
pub use scope::CallbackScope;
pub use scope::ContextScope;
Expand Down
73 changes: 73 additions & 0 deletions src/regexp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use crate::support::int;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing copyright header

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

none of the other files i looked at have it 🤔

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<String>,
flags: RegExpCreationFlags,
) -> Option<Local<'s, RegExp>> {
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<String>,
) -> Option<Local<'s, Object>> {
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()
}
}
33 changes: 33 additions & 0 deletions tests/test_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
Loading