Commit b1c1a81f authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[regexp] Expose RegExp::Exec through the API

Previously, embedders had to fetch the 'exec' property off the RegExp
prototype in order to call exec (and such calls involve two
transitions between C++ and JS).

This CL exposes a convenient RegExp::Exec method through the API.

Bug: v8:9695
Change-Id: I57a9174626143d26f2ea34676b8e55fef64932cf
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1864940
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64508}
parent 5e7de6aa
......@@ -5748,6 +5748,20 @@ class V8_EXPORT RegExp : public Object {
Local<Context> context, Local<String> pattern, Flags flags,
uint32_t backtrack_limit);
/**
* Executes the current RegExp instance on the given subject string.
* Equivalent to RegExp.prototype.exec as described in
*
* https://tc39.es/ecma262/#sec-regexp.prototype.exec
*
* On success, an Array containing the matched strings is returned. On
* failure, returns Null.
*
* Note: modifies global context state, accessible e.g. through RegExp.input.
*/
V8_WARN_UNUSED_RESULT MaybeLocal<Object> Exec(Local<Context> context,
Local<String> subject);
/**
* Returns the value of the source property: a string representing
* the regular expression.
......
......@@ -91,6 +91,7 @@
#include "src/profiler/heap-snapshot-generator-inl.h"
#include "src/profiler/profile-generator-inl.h"
#include "src/profiler/tick-sample.h"
#include "src/regexp/regexp-utils.h"
#include "src/runtime/runtime.h"
#include "src/snapshot/code-serializer.h"
#include "src/snapshot/partial-serializer.h"
......@@ -6655,6 +6656,27 @@ v8::RegExp::Flags v8::RegExp::GetFlags() const {
return RegExp::Flags(static_cast<int>(obj->GetFlags()));
}
MaybeLocal<v8::Object> v8::RegExp::Exec(Local<Context> context,
Local<v8::String> subject) {
PREPARE_FOR_EXECUTION(context, RegExp, Exec, Object);
i::Handle<i::JSRegExp> regexp = Utils::OpenHandle(this);
i::Handle<i::String> subject_string = Utils::OpenHandle(*subject);
// TODO(jgruber): RegExpUtils::RegExpExec was not written with efficiency in
// mind. It fetches the 'exec' property and then calls it through JSEntry.
// Unfortunately, this is currently the only full implementation of
// RegExp.prototype.exec available in C++.
Local<v8::Object> result;
has_pending_exception = !ToLocal<Object>(
i::RegExpUtils::RegExpExec(isolate, regexp, subject_string,
isolate->factory()->undefined_value()),
&result);
RETURN_ON_FAILED_EXECUTION(Object);
RETURN_ESCAPED(result);
}
Local<v8::Array> v8::Array::New(Isolate* isolate, int length) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
LOG_API(i_isolate, Array, New);
......
......@@ -840,6 +840,7 @@ class RuntimeCallTimer final {
V(Proxy_New) \
V(RangeError_New) \
V(ReferenceError_New) \
V(RegExp_Exec) \
V(RegExp_New) \
V(ScriptCompiler_Compile) \
V(ScriptCompiler_CompileFunctionInContext) \
......
......@@ -18811,14 +18811,28 @@ TEST(RegExp) {
v8::Local<v8::Value> value(CompileRun("re.property"));
CHECK_EQ(32, value->Int32Value(context.local()).FromJust());
v8::TryCatch try_catch(context->GetIsolate());
CHECK(v8::RegExp::New(context.local(), v8_str("foo["), v8::RegExp::kNone)
.IsEmpty());
CHECK(try_catch.HasCaught());
CHECK(context->Global()
->Set(context.local(), v8_str("ex"), try_catch.Exception())
.FromJust());
ExpectTrue("ex instanceof SyntaxError");
{
v8::TryCatch try_catch(context->GetIsolate());
CHECK(v8::RegExp::New(context.local(), v8_str("foo["), v8::RegExp::kNone)
.IsEmpty());
CHECK(try_catch.HasCaught());
CHECK(context->Global()
->Set(context.local(), v8_str("ex"), try_catch.Exception())
.FromJust());
ExpectTrue("ex instanceof SyntaxError");
}
// RegExp::Exec.
{
v8::Local<v8::RegExp> regexp =
v8::RegExp::New(context.local(), v8_str("a.c"), {}).ToLocalChecked();
v8::Local<v8::Object> result0 =
regexp->Exec(context.local(), v8_str("abc")).ToLocalChecked();
CHECK(result0->IsArray());
v8::Local<v8::Object> result1 =
regexp->Exec(context.local(), v8_str("abd")).ToLocalChecked();
CHECK(result1->IsNull());
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment