Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(649)

Side by Side Diff: src/regexp/regexp-utils.cc

Issue 2398413002: [regexp] Extract code to regexp-utils.{h,cc} (Closed)
Patch Set: Move IsRegExp to RegExpUtils as well Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/regexp/regexp-utils.h ('k') | src/v8.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/regexp/regexp-utils.h"
6
7 #include "src/factory.h"
8 #include "src/isolate.h"
9 #include "src/objects-inl.h"
10 #include "src/regexp/jsregexp.h"
11
12 namespace v8 {
13 namespace internal {
14
15 // Constants for accessing RegExpLastMatchInfo.
16 // TODO(jgruber): Currently, RegExpLastMatchInfo is still a JSObject maintained
17 // and accessed from JS. This is a crutch until all RegExp logic is ported, then
18 // we can take care of RegExpLastMatchInfo.
19
20 Handle<Object> RegExpUtils::GetLastMatchField(Isolate* isolate,
21 Handle<JSObject> match_info,
22 int index) {
23 return JSReceiver::GetElement(isolate, match_info, index).ToHandleChecked();
24 }
25
26 void RegExpUtils::SetLastMatchField(Isolate* isolate,
27 Handle<JSObject> match_info, int index,
28 Handle<Object> value) {
29 JSReceiver::SetElement(isolate, match_info, index, value, SLOPPY)
30 .ToHandleChecked();
31 }
32
33 int RegExpUtils::GetLastMatchNumberOfCaptures(Isolate* isolate,
34 Handle<JSObject> match_info) {
35 Handle<Object> obj =
36 GetLastMatchField(isolate, match_info, RegExpImpl::kLastCaptureCount);
37 return Handle<Smi>::cast(obj)->value();
38 }
39
40 Handle<String> RegExpUtils::GetLastMatchSubject(Isolate* isolate,
41 Handle<JSObject> match_info) {
42 return Handle<String>::cast(
43 GetLastMatchField(isolate, match_info, RegExpImpl::kLastSubject));
44 }
45
46 Handle<Object> RegExpUtils::GetLastMatchInput(Isolate* isolate,
47 Handle<JSObject> match_info) {
48 return GetLastMatchField(isolate, match_info, RegExpImpl::kLastInput);
49 }
50
51 int RegExpUtils::GetLastMatchCapture(Isolate* isolate,
52 Handle<JSObject> match_info, int i) {
53 Handle<Object> obj =
54 GetLastMatchField(isolate, match_info, RegExpImpl::kFirstCapture + i);
55 return Handle<Smi>::cast(obj)->value();
56 }
57
58 Handle<String> RegExpUtils::GenericCaptureGetter(Isolate* isolate,
59 Handle<JSObject> match_info,
60 int capture, bool* ok) {
61 const int index = capture * 2;
62 if (index >= GetLastMatchNumberOfCaptures(isolate, match_info)) {
63 if (ok != nullptr) *ok = false;
64 return isolate->factory()->empty_string();
65 }
66
67 const int match_start = GetLastMatchCapture(isolate, match_info, index);
68 const int match_end = GetLastMatchCapture(isolate, match_info, index + 1);
69 if (match_start == -1 || match_end == -1) {
70 if (ok != nullptr) *ok = false;
71 return isolate->factory()->empty_string();
72 }
73
74 if (ok != nullptr) *ok = true;
75 Handle<String> last_subject = GetLastMatchSubject(isolate, match_info);
76 return isolate->factory()->NewSubString(last_subject, match_start, match_end);
77 }
78
79 namespace {
80
81 V8_INLINE bool HasInitialRegExpMap(Isolate* isolate, Handle<JSReceiver> recv) {
82 return recv->map() == isolate->regexp_function()->initial_map();
83 }
84
85 } // namespace
86
87 MaybeHandle<Object> RegExpUtils::SetLastIndex(Isolate* isolate,
88 Handle<JSReceiver> recv,
89 int value) {
90 if (HasInitialRegExpMap(isolate, recv)) {
91 JSRegExp::cast(*recv)->SetLastIndex(value);
92 return recv;
93 } else {
94 return Object::SetProperty(recv, isolate->factory()->lastIndex_string(),
95 handle(Smi::FromInt(value), isolate), STRICT);
96 }
97 }
98
99 MaybeHandle<Object> RegExpUtils::GetLastIndex(Isolate* isolate,
100 Handle<JSReceiver> recv) {
101 if (HasInitialRegExpMap(isolate, recv)) {
102 return handle(JSRegExp::cast(*recv)->LastIndex(), isolate);
103 } else {
104 return Object::GetProperty(recv, isolate->factory()->lastIndex_string());
105 }
106 }
107
108 // ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S )
109 // Also takes an optional exec method in case our caller
110 // has already fetched exec.
111 MaybeHandle<Object> RegExpUtils::RegExpExec(Isolate* isolate,
112 Handle<JSReceiver> regexp,
113 Handle<String> string,
114 Handle<Object> exec) {
115 if (exec->IsUndefined(isolate)) {
116 ASSIGN_RETURN_ON_EXCEPTION(
117 isolate, exec,
118 Object::GetProperty(
119 regexp, isolate->factory()->NewStringFromAsciiChecked("exec")),
120 Object);
121 }
122
123 if (exec->IsCallable()) {
124 const int argc = 1;
125 ScopedVector<Handle<Object>> argv(argc);
126 argv[0] = string;
127
128 Handle<Object> result;
129 ASSIGN_RETURN_ON_EXCEPTION(
130 isolate, result,
131 Execution::Call(isolate, exec, regexp, argc, argv.start()), Object);
132
133 if (!result->IsJSReceiver() && !result->IsNull(isolate)) {
134 THROW_NEW_ERROR(isolate,
135 NewTypeError(MessageTemplate::kInvalidRegExpExecResult),
136 Object);
137 }
138 return result;
139 }
140
141 if (!regexp->IsJSRegExp()) {
142 THROW_NEW_ERROR(isolate,
143 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
144 isolate->factory()->NewStringFromAsciiChecked(
145 "RegExp.prototype.exec"),
146 regexp),
147 Object);
148 }
149
150 {
151 Handle<JSFunction> regexp_exec = isolate->regexp_exec_function();
152
153 const int argc = 1;
154 ScopedVector<Handle<Object>> argv(argc);
155 argv[0] = string;
156
157 return Execution::Call(isolate, exec, regexp_exec, argc, argv.start());
158 }
159 }
160
161 Maybe<bool> RegExpUtils::IsRegExp(Isolate* isolate, Handle<Object> object) {
162 if (!object->IsJSReceiver()) return Just(false);
163
164 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
165
166 if (isolate->regexp_function()->initial_map() == receiver->map()) {
167 // Fast-path for unmodified JSRegExp instances.
168 // TODO(ishell): Adapt for new fast-path logic.
169 return Just(true);
170 }
171
172 Handle<Object> match;
173 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
174 isolate, match,
175 JSObject::GetProperty(receiver, isolate->factory()->match_symbol()),
176 Nothing<bool>());
177
178 if (!match->IsUndefined(isolate)) return Just(match->BooleanValue());
179 return Just(object->IsJSRegExp());
180 }
181
182 bool RegExpUtils::IsBuiltinExec(Handle<Object> exec) {
183 if (!exec->IsJSFunction()) return false;
184
185 Code* code = Handle<JSFunction>::cast(exec)->code();
186 if (code == nullptr) return false;
187
188 return (code->builtin_index() == Builtins::kRegExpPrototypeExec);
189 }
190
191 // ES#sec-advancestringindex
192 // AdvanceStringIndex ( S, index, unicode )
193 int RegExpUtils::AdvanceStringIndex(Isolate* isolate, Handle<String> string,
194 int index, bool unicode) {
195 int increment = 1;
196
197 if (unicode && index < string->length()) {
198 const uint16_t first = string->Get(index);
199 if (first >= 0xD800 && first <= 0xDBFF && string->length() > index + 1) {
200 const uint16_t second = string->Get(index + 1);
201 if (second >= 0xDC00 && second <= 0xDFFF) {
202 increment = 2;
203 }
204 }
205 }
206
207 return increment;
208 }
209
210 MaybeHandle<Object> RegExpUtils::SetAdvancedStringIndex(
211 Isolate* isolate, Handle<JSReceiver> regexp, Handle<String> string,
212 bool unicode) {
213 Handle<Object> last_index_obj;
214 ASSIGN_RETURN_ON_EXCEPTION(
215 isolate, last_index_obj,
216 Object::GetProperty(regexp, isolate->factory()->lastIndex_string()),
217 Object);
218
219 ASSIGN_RETURN_ON_EXCEPTION(isolate, last_index_obj,
220 Object::ToLength(isolate, last_index_obj), Object);
221
222 const int last_index = Handle<Smi>::cast(last_index_obj)->value();
223 const int new_last_index =
224 last_index + AdvanceStringIndex(isolate, string, last_index, unicode);
225
226 return SetLastIndex(isolate, regexp, new_last_index);
227 }
228
229 } // namespace internal
230 } // namespace v8
OLDNEW
« no previous file with comments | « src/regexp/regexp-utils.h ('k') | src/v8.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698