5 #include "src/regexp/regexp-utils.h" 7 #include "src/heap/factory.h" 8 #include "src/isolate.h" 9 #include "src/objects-inl.h" 10 #include "src/objects/js-regexp-inl.h" 11 #include "src/regexp/jsregexp.h" 16 Handle<String> RegExpUtils::GenericCaptureGetter(
17 Isolate* isolate, Handle<RegExpMatchInfo> match_info,
int capture,
19 const int index = capture * 2;
20 if (index >= match_info->NumberOfCaptureRegisters()) {
21 if (ok !=
nullptr) *ok =
false;
22 return isolate->factory()->empty_string();
25 const int match_start = match_info->Capture(index);
26 const int match_end = match_info->Capture(index + 1);
27 if (match_start == -1 || match_end == -1) {
28 if (ok !=
nullptr) *ok =
false;
29 return isolate->factory()->empty_string();
32 if (ok !=
nullptr) *ok =
true;
33 Handle<String> last_subject(match_info->LastSubject(), isolate);
34 return isolate->factory()->NewSubString(last_subject, match_start, match_end);
39 V8_INLINE
bool HasInitialRegExpMap(Isolate* isolate, Handle<JSReceiver> recv) {
40 return recv->map() == isolate->regexp_function()->initial_map();
45 MaybeHandle<Object> RegExpUtils::SetLastIndex(Isolate* isolate,
46 Handle<JSReceiver> recv,
48 Handle<Object> value_as_object =
49 isolate->factory()->NewNumberFromInt64(value);
50 if (HasInitialRegExpMap(isolate, recv)) {
51 JSRegExp::cast(*recv)->set_last_index(*value_as_object, SKIP_WRITE_BARRIER);
54 return Object::SetProperty(isolate, recv,
55 isolate->factory()->lastIndex_string(),
56 value_as_object, LanguageMode::kStrict);
60 MaybeHandle<Object> RegExpUtils::GetLastIndex(Isolate* isolate,
61 Handle<JSReceiver> recv) {
62 if (HasInitialRegExpMap(isolate, recv)) {
63 return handle(JSRegExp::cast(*recv)->last_index(), isolate);
65 return Object::GetProperty(isolate, recv,
66 isolate->factory()->lastIndex_string());
73 MaybeHandle<Object> RegExpUtils::RegExpExec(Isolate* isolate,
74 Handle<JSReceiver> regexp,
75 Handle<String>
string,
76 Handle<Object> exec) {
77 if (exec->IsUndefined(isolate)) {
78 ASSIGN_RETURN_ON_EXCEPTION(
80 Object::GetProperty(isolate, regexp, isolate->factory()->exec_string()),
84 if (exec->IsCallable()) {
86 ScopedVector<Handle<Object>> argv(argc);
89 Handle<Object> result;
90 ASSIGN_RETURN_ON_EXCEPTION(
92 Execution::Call(isolate, exec, regexp, argc, argv.start()), Object);
94 if (!result->IsJSReceiver() && !result->IsNull(isolate)) {
95 THROW_NEW_ERROR(isolate,
96 NewTypeError(MessageTemplate::kInvalidRegExpExecResult),
102 if (!regexp->IsJSRegExp()) {
103 THROW_NEW_ERROR(isolate,
104 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
105 isolate->factory()->NewStringFromAsciiChecked(
106 "RegExp.prototype.exec"),
112 Handle<JSFunction> regexp_exec = isolate->regexp_exec_function();
115 ScopedVector<Handle<Object>> argv(argc);
118 return Execution::Call(isolate, regexp_exec, regexp, argc, argv.start());
122 Maybe<bool> RegExpUtils::IsRegExp(Isolate* isolate, Handle<Object>
object) {
123 if (!object->IsJSReceiver())
return Just(
false);
125 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(
object);
127 Handle<Object> match;
128 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
130 JSObject::GetProperty(isolate, receiver,
131 isolate->factory()->match_symbol()),
134 if (!match->IsUndefined(isolate))
return Just(match->BooleanValue(isolate));
135 return Just(object->IsJSRegExp());
138 bool RegExpUtils::IsUnmodifiedRegExp(Isolate* isolate, Handle<Object> obj) {
139 #ifdef V8_ENABLE_FORCE_SLOW_PATH 140 if (isolate->force_slow_path())
return false;
143 if (!obj->IsJSReceiver())
return false;
145 JSReceiver* recv = JSReceiver::cast(*obj);
148 Handle<JSFunction> regexp_function = isolate->regexp_function();
149 if (recv->map() != regexp_function->initial_map())
return false;
152 Object* proto = recv->map()->prototype();
153 if (!proto->IsJSReceiver())
return false;
155 Handle<Map> initial_proto_initial_map = isolate->regexp_prototype_map();
156 Map proto_map = JSReceiver::cast(proto)->map();
157 if (proto_map != *initial_proto_initial_map) {
162 if (FLAG_track_constant_fields) {
165 DCHECK_EQ(*(isolate->factory()->exec_string()),
166 proto_map->instance_descriptors()->GetKey(
167 JSRegExp::kExecFunctionDescriptorIndex));
168 if (proto_map->instance_descriptors()
169 ->GetDetails(JSRegExp::kExecFunctionDescriptorIndex)
170 .constness() != PropertyConstness::kConst) {
175 if (!isolate->IsRegExpSpeciesLookupChainIntact())
return false;
179 Object* last_index = JSRegExp::cast(recv)->last_index();
180 return last_index->IsSmi() && Smi::ToInt(last_index) >= 0;
183 uint64_t RegExpUtils::AdvanceStringIndex(Handle<String>
string, uint64_t index,
185 DCHECK_LE(static_cast<double>(index), kMaxSafeInteger);
186 const uint64_t string_length =
static_cast<uint64_t
>(
string->length());
187 if (unicode && index < string_length) {
188 const uint16_t first =
string->Get(static_cast<uint32_t>(index));
189 if (first >= 0xD800 && first <= 0xDBFF && index + 1 < string_length) {
190 DCHECK_LT(index, std::numeric_limits<uint64_t>::max());
191 const uint16_t second =
string->Get(static_cast<uint32_t>(index + 1));
192 if (second >= 0xDC00 && second <= 0xDFFF) {
201 MaybeHandle<Object> RegExpUtils::SetAdvancedStringIndex(
202 Isolate* isolate, Handle<JSReceiver> regexp, Handle<String>
string,
204 Handle<Object> last_index_obj;
205 ASSIGN_RETURN_ON_EXCEPTION(
206 isolate, last_index_obj,
207 Object::GetProperty(isolate, regexp,
208 isolate->factory()->lastIndex_string()),
211 ASSIGN_RETURN_ON_EXCEPTION(isolate, last_index_obj,
212 Object::ToLength(isolate, last_index_obj), Object);
213 const uint64_t last_index = PositiveNumberToUint64(*last_index_obj);
214 const uint64_t new_last_index =
215 AdvanceStringIndex(
string, last_index, unicode);
217 return SetLastIndex(isolate, regexp, new_last_index);