| Index: src/builtins/builtins-regexp.cc
|
| diff --git a/src/builtins/builtins-regexp.cc b/src/builtins/builtins-regexp.cc
|
| index 2dbfb0c3e6d805b574ce405ece694409007491fb..f1e458860c7e96487ad9e79cf19ff0785d820e48 100644
|
| --- a/src/builtins/builtins-regexp.cc
|
| +++ b/src/builtins/builtins-regexp.cc
|
| @@ -148,249 +148,5 @@
|
| RegExpInitialize(isolate, regexp, pattern, flags));
|
| }
|
|
|
| -#define APPEND_CHAR_FOR_FLAG(flag, c) \
|
| - do { \
|
| - Handle<Object> property; \
|
| - Handle<Name> name = isolate->factory()->flag##_string(); \
|
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, property, \
|
| - JSReceiver::GetProperty(recv, name)); \
|
| - if (property->BooleanValue()) { \
|
| - builder.AppendCharacter(c); \
|
| - } \
|
| - } while (false);
|
| -
|
| -// ES6 21.2.5.3.
|
| -BUILTIN(RegExpPrototypeFlagsGetter) {
|
| - HandleScope scope(isolate);
|
| - CHECK_RECEIVER(JSReceiver, recv, "get RegExp.prototype.flags");
|
| -
|
| - IncrementalStringBuilder builder(isolate);
|
| -
|
| - APPEND_CHAR_FOR_FLAG(global, 'g');
|
| - APPEND_CHAR_FOR_FLAG(ignoreCase, 'i');
|
| - APPEND_CHAR_FOR_FLAG(multiline, 'm');
|
| - APPEND_CHAR_FOR_FLAG(unicode, 'u');
|
| - APPEND_CHAR_FOR_FLAG(sticky, 'y');
|
| -
|
| - RETURN_RESULT_OR_FAILURE(isolate, builder.Finish());
|
| -}
|
| -
|
| -#undef APPEND_CHAR_FOR_FLAG
|
| -
|
| -// ES6 21.2.5.10.
|
| -BUILTIN(RegExpPrototypeSourceGetter) {
|
| - HandleScope scope(isolate);
|
| -
|
| - Handle<Object> recv = args.receiver();
|
| - if (!recv->IsJSRegExp()) {
|
| - // TODO(littledan): Remove this RegExp compat workaround
|
| - Handle<JSFunction> regexp_fun = isolate->regexp_function();
|
| - if (*recv == regexp_fun->prototype()) {
|
| - isolate->CountUsage(v8::Isolate::kRegExpPrototypeSourceGetter);
|
| - return *isolate->factory()->NewStringFromAsciiChecked("(?:)");
|
| - }
|
| - THROW_NEW_ERROR_RETURN_FAILURE(
|
| - isolate, NewTypeError(MessageTemplate::kRegExpNonRegExp,
|
| - isolate->factory()->NewStringFromAsciiChecked(
|
| - "RegExp.prototype.source")));
|
| - }
|
| -
|
| - Handle<JSRegExp> regexp = Handle<JSRegExp>::cast(recv);
|
| - return regexp->source();
|
| -}
|
| -
|
| -// ES6 21.2.4.2.
|
| -BUILTIN(RegExpPrototypeSpeciesGetter) {
|
| - HandleScope scope(isolate);
|
| - return *args.receiver();
|
| -}
|
| -
|
| -#define REGEXP_FLAG_GETTER(name, counter, getter) \
|
| - BUILTIN(RegExpPrototype##name##Getter) { \
|
| - HandleScope scope(isolate); \
|
| - Handle<Object> recv = args.receiver(); \
|
| - if (!recv->IsJSRegExp()) { \
|
| - /* TODO(littledan): Remove this RegExp compat workaround */ \
|
| - Handle<JSFunction> regexp_fun = isolate->regexp_function(); \
|
| - if (*recv == regexp_fun->prototype()) { \
|
| - isolate->CountUsage(v8::Isolate::kRegExpPrototype##counter##Getter); \
|
| - return isolate->heap()->undefined_value(); \
|
| - } \
|
| - THROW_NEW_ERROR_RETURN_FAILURE( \
|
| - isolate, NewTypeError(MessageTemplate::kRegExpNonRegExp, \
|
| - isolate->factory()->NewStringFromAsciiChecked( \
|
| - getter))); \
|
| - } \
|
| - Handle<JSRegExp> regexp = Handle<JSRegExp>::cast(recv); \
|
| - const bool ret = (regexp->GetFlags() & JSRegExp::k##name) != 0; \
|
| - return *isolate->factory()->ToBoolean(ret); \
|
| - }
|
| -
|
| -// ES6 21.2.5.4.
|
| -REGEXP_FLAG_GETTER(Global, OldFlag, "RegExp.prototype.global")
|
| -
|
| -// ES6 21.2.5.5.
|
| -REGEXP_FLAG_GETTER(IgnoreCase, OldFlag, "RegExp.prototype.ignoreCase")
|
| -
|
| -// ES6 21.2.5.7.
|
| -REGEXP_FLAG_GETTER(Multiline, OldFlag, "RegExp.prototype.multiline")
|
| -
|
| -// ES6 21.2.5.12.
|
| -REGEXP_FLAG_GETTER(Sticky, Sticky, "RegExp.prototype.sticky")
|
| -
|
| -// ES6 21.2.5.15.
|
| -REGEXP_FLAG_GETTER(Unicode, Unicode, "RegExp.prototype.unicode")
|
| -
|
| -#undef REGEXP_FLAG_GETTER
|
| -
|
| -namespace {
|
| -
|
| -// Constants for accessing RegExpLastMatchInfo.
|
| -// TODO(jgruber): Currently, RegExpLastMatchInfo is still a JSObject maintained
|
| -// and accessed from JS. This is a crutch until all RegExp logic is ported, then
|
| -// we can take care of RegExpLastMatchInfo.
|
| -const int kNumberOfCapturesIndex = 0;
|
| -const int kLastSubjectIndex = 1;
|
| -const int kLastInputIndex = 2;
|
| -const int kFirstCaptureIndex = 3;
|
| -
|
| -Handle<Object> GetLastMatchField(Isolate* isolate, int index) {
|
| - Handle<JSFunction> global_regexp = isolate->regexp_function();
|
| - Handle<Object> last_match_info_obj = JSReceiver::GetDataProperty(
|
| - global_regexp, isolate->factory()->regexp_last_match_info_symbol());
|
| -
|
| - Handle<JSReceiver> last_match_info =
|
| - Handle<JSReceiver>::cast(last_match_info_obj);
|
| - return JSReceiver::GetElement(isolate, last_match_info, index)
|
| - .ToHandleChecked();
|
| -}
|
| -
|
| -void SetLastMatchField(Isolate* isolate, int index, Handle<Object> value) {
|
| - Handle<JSFunction> global_regexp = isolate->regexp_function();
|
| - Handle<Object> last_match_info_obj = JSReceiver::GetDataProperty(
|
| - global_regexp, isolate->factory()->regexp_last_match_info_symbol());
|
| -
|
| - Handle<JSReceiver> last_match_info =
|
| - Handle<JSReceiver>::cast(last_match_info_obj);
|
| - JSReceiver::SetElement(isolate, last_match_info, index, value, SLOPPY)
|
| - .ToHandleChecked();
|
| -}
|
| -
|
| -int GetLastMatchNumberOfCaptures(Isolate* isolate) {
|
| - Handle<Object> obj = GetLastMatchField(isolate, kNumberOfCapturesIndex);
|
| - return Handle<Smi>::cast(obj)->value();
|
| -}
|
| -
|
| -Handle<String> GetLastMatchSubject(Isolate* isolate) {
|
| - return Handle<String>::cast(GetLastMatchField(isolate, kLastSubjectIndex));
|
| -}
|
| -
|
| -Handle<Object> GetLastMatchInput(Isolate* isolate) {
|
| - return GetLastMatchField(isolate, kLastInputIndex);
|
| -}
|
| -
|
| -int GetLastMatchCapture(Isolate* isolate, int i) {
|
| - Handle<Object> obj = GetLastMatchField(isolate, kFirstCaptureIndex + i);
|
| - return Handle<Smi>::cast(obj)->value();
|
| -}
|
| -
|
| -Object* GenericCaptureGetter(Isolate* isolate, int capture) {
|
| - HandleScope scope(isolate);
|
| - const int index = capture * 2;
|
| - if (index >= GetLastMatchNumberOfCaptures(isolate)) {
|
| - return isolate->heap()->empty_string();
|
| - }
|
| -
|
| - const int match_start = GetLastMatchCapture(isolate, index);
|
| - const int match_end = GetLastMatchCapture(isolate, index + 1);
|
| - if (match_start == -1 || match_end == -1) {
|
| - return isolate->heap()->empty_string();
|
| - }
|
| -
|
| - Handle<String> last_subject = GetLastMatchSubject(isolate);
|
| - return *isolate->factory()->NewSubString(last_subject, match_start,
|
| - match_end);
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -// The properties $1..$9 are the first nine capturing substrings of the last
|
| -// successful match, or ''. The function RegExpMakeCaptureGetter will be
|
| -// called with indices from 1 to 9.
|
| -#define DEFINE_CAPTURE_GETTER(i) \
|
| - BUILTIN(RegExpPrototypeCapture##i##Getter) { \
|
| - HandleScope scope(isolate); \
|
| - return GenericCaptureGetter(isolate, i); \
|
| - }
|
| -DEFINE_CAPTURE_GETTER(1)
|
| -DEFINE_CAPTURE_GETTER(2)
|
| -DEFINE_CAPTURE_GETTER(3)
|
| -DEFINE_CAPTURE_GETTER(4)
|
| -DEFINE_CAPTURE_GETTER(5)
|
| -DEFINE_CAPTURE_GETTER(6)
|
| -DEFINE_CAPTURE_GETTER(7)
|
| -DEFINE_CAPTURE_GETTER(8)
|
| -DEFINE_CAPTURE_GETTER(9)
|
| -#undef DEFINE_CAPTURE_GETTER
|
| -
|
| -// The properties `input` and `$_` are aliases for each other. When this
|
| -// value is set the value it is set to is coerced to a string.
|
| -// Getter and setter for the input.
|
| -
|
| -BUILTIN(RegExpPrototypeInputGetter) {
|
| - HandleScope scope(isolate);
|
| - Handle<Object> obj = GetLastMatchInput(isolate);
|
| - return obj->IsUndefined(isolate) ? isolate->heap()->empty_string()
|
| - : String::cast(*obj);
|
| -}
|
| -
|
| -BUILTIN(RegExpPrototypeInputSetter) {
|
| - HandleScope scope(isolate);
|
| - Handle<Object> value = args.atOrUndefined(isolate, 1);
|
| - Handle<String> str;
|
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, str,
|
| - Object::ToString(isolate, value));
|
| - SetLastMatchField(isolate, kLastInputIndex, str);
|
| - return isolate->heap()->undefined_value();
|
| -}
|
| -
|
| -// Getters for the static properties lastMatch, lastParen, leftContext, and
|
| -// rightContext of the RegExp constructor. The properties are computed based
|
| -// on the captures array of the last successful match and the subject string
|
| -// of the last successful match.
|
| -BUILTIN(RegExpPrototypeLastMatchGetter) {
|
| - HandleScope scope(isolate);
|
| - return GenericCaptureGetter(isolate, 0);
|
| -}
|
| -
|
| -BUILTIN(RegExpPrototypeLastParenGetter) {
|
| - HandleScope scope(isolate);
|
| - const int length = GetLastMatchNumberOfCaptures(isolate);
|
| - if (length <= 2) return isolate->heap()->empty_string(); // No captures.
|
| -
|
| - DCHECK_EQ(0, length % 2);
|
| - const int last_capture = (length / 2) - 1;
|
| -
|
| - // We match the SpiderMonkey behavior: return the substring defined by the
|
| - // last pair (after the first pair) of elements of the capture array even if
|
| - // it is empty.
|
| - return GenericCaptureGetter(isolate, last_capture);
|
| -}
|
| -
|
| -BUILTIN(RegExpPrototypeLeftContextGetter) {
|
| - HandleScope scope(isolate);
|
| - const int start_index = GetLastMatchCapture(isolate, 0);
|
| - Handle<String> last_subject = GetLastMatchSubject(isolate);
|
| - return *isolate->factory()->NewSubString(last_subject, 0, start_index);
|
| -}
|
| -
|
| -BUILTIN(RegExpPrototypeRightContextGetter) {
|
| - HandleScope scope(isolate);
|
| - const int start_index = GetLastMatchCapture(isolate, 1);
|
| - Handle<String> last_subject = GetLastMatchSubject(isolate);
|
| - const int len = last_subject->length();
|
| - return *isolate->factory()->NewSubString(last_subject, start_index, len);
|
| -}
|
| -
|
| } // namespace internal
|
| } // namespace v8
|
|
|