LCOV - code coverage report
Current view: top level - src/regexp - regexp-utils.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 42 54 77.8 %
Date: 2017-04-26 Functions: 7 8 87.5 %

          Line data    Source code
       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      424558 : Handle<String> RegExpUtils::GenericCaptureGetter(
      16             :     Isolate* isolate, Handle<RegExpMatchInfo> match_info, int capture,
      17             :     bool* ok) {
      18      424558 :   const int index = capture * 2;
      19      424558 :   if (index >= match_info->NumberOfCaptureRegisters()) {
      20        2889 :     if (ok != nullptr) *ok = false;
      21             :     return isolate->factory()->empty_string();
      22             :   }
      23             : 
      24             :   const int match_start = match_info->Capture(index);
      25             :   const int match_end = match_info->Capture(index + 1);
      26      421669 :   if (match_start == -1 || match_end == -1) {
      27         322 :     if (ok != nullptr) *ok = false;
      28             :     return isolate->factory()->empty_string();
      29             :   }
      30             : 
      31      421347 :   if (ok != nullptr) *ok = true;
      32             :   Handle<String> last_subject(match_info->LastSubject());
      33      421347 :   return isolate->factory()->NewSubString(last_subject, match_start, match_end);
      34             : }
      35             : 
      36             : namespace {
      37             : 
      38             : V8_INLINE bool HasInitialRegExpMap(Isolate* isolate, Handle<JSReceiver> recv) {
      39        8738 :   return recv->map() == isolate->regexp_function()->initial_map();
      40             : }
      41             : 
      42             : }  // namespace
      43             : 
      44        4264 : MaybeHandle<Object> RegExpUtils::SetLastIndex(Isolate* isolate,
      45             :                                               Handle<JSReceiver> recv,
      46             :                                               int value) {
      47        4264 :   if (HasInitialRegExpMap(isolate, recv)) {
      48             :     JSRegExp::cast(*recv)->SetLastIndex(value);
      49             :     return recv;
      50             :   } else {
      51             :     return Object::SetProperty(recv, isolate->factory()->lastIndex_string(),
      52         216 :                                handle(Smi::FromInt(value), isolate), STRICT);
      53             :   }
      54             : }
      55             : 
      56         105 : MaybeHandle<Object> RegExpUtils::GetLastIndex(Isolate* isolate,
      57             :                                               Handle<JSReceiver> recv) {
      58         105 :   if (HasInitialRegExpMap(isolate, recv)) {
      59             :     return handle(JSRegExp::cast(*recv)->LastIndex(), isolate);
      60             :   } else {
      61          30 :     return Object::GetProperty(recv, isolate->factory()->lastIndex_string());
      62             :   }
      63             : }
      64             : 
      65             : // ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S )
      66             : // Also takes an optional exec method in case our caller
      67             : // has already fetched exec.
      68        1092 : MaybeHandle<Object> RegExpUtils::RegExpExec(Isolate* isolate,
      69             :                                             Handle<JSReceiver> regexp,
      70             :                                             Handle<String> string,
      71             :                                             Handle<Object> exec) {
      72        1092 :   if (exec->IsUndefined(isolate)) {
      73        2184 :     ASSIGN_RETURN_ON_EXCEPTION(
      74             :         isolate, exec,
      75             :         Object::GetProperty(regexp, isolate->factory()->exec_string()), Object);
      76             :   }
      77             : 
      78        1092 :   if (exec->IsCallable()) {
      79             :     const int argc = 1;
      80             :     ScopedVector<Handle<Object>> argv(argc);
      81        1047 :     argv[0] = string;
      82             : 
      83             :     Handle<Object> result;
      84        2094 :     ASSIGN_RETURN_ON_EXCEPTION(
      85             :         isolate, result,
      86             :         Execution::Call(isolate, exec, regexp, argc, argv.start()), Object);
      87             : 
      88        1494 :     if (!result->IsJSReceiver() && !result->IsNull(isolate)) {
      89           0 :       THROW_NEW_ERROR(isolate,
      90             :                       NewTypeError(MessageTemplate::kInvalidRegExpExecResult),
      91             :                       Object);
      92             :     }
      93             :     return result;
      94             :   }
      95             : 
      96          45 :   if (!regexp->IsJSRegExp()) {
      97           0 :     THROW_NEW_ERROR(isolate,
      98             :                     NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
      99             :                                  isolate->factory()->NewStringFromAsciiChecked(
     100             :                                      "RegExp.prototype.exec"),
     101             :                                  regexp),
     102             :                     Object);
     103             :   }
     104             : 
     105             :   {
     106          45 :     Handle<JSFunction> regexp_exec = isolate->regexp_exec_function();
     107             : 
     108             :     const int argc = 1;
     109             :     ScopedVector<Handle<Object>> argv(argc);
     110          45 :     argv[0] = string;
     111             : 
     112          45 :     return Execution::Call(isolate, regexp_exec, regexp, argc, argv.start());
     113             :   }
     114             : }
     115             : 
     116       22658 : Maybe<bool> RegExpUtils::IsRegExp(Isolate* isolate, Handle<Object> object) {
     117       22658 :   if (!object->IsJSReceiver()) return Just(false);
     118             : 
     119         785 :   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
     120             : 
     121             :   Handle<Object> match;
     122        1570 :   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
     123             :       isolate, match,
     124             :       JSObject::GetProperty(receiver, isolate->factory()->match_symbol()),
     125             :       Nothing<bool>());
     126             : 
     127        1108 :   if (!match->IsUndefined(isolate)) return Just(match->BooleanValue());
     128             :   return Just(object->IsJSRegExp());
     129             : }
     130             : 
     131        9361 : bool RegExpUtils::IsUnmodifiedRegExp(Isolate* isolate, Handle<Object> obj) {
     132             :   // TODO(ishell): Update this check once map changes for constant field
     133             :   // tracking are landing.
     134             : 
     135        9361 :   if (!obj->IsJSReceiver()) return false;
     136             : 
     137             :   JSReceiver* recv = JSReceiver::cast(*obj);
     138             : 
     139             :   // Check the receiver's map.
     140        9361 :   Handle<JSFunction> regexp_function = isolate->regexp_function();
     141        9361 :   if (recv->map() != regexp_function->initial_map()) return false;
     142             : 
     143             :   // Check the receiver's prototype's map.
     144             :   Object* proto = recv->map()->prototype();
     145        9064 :   if (!proto->IsJSReceiver()) return false;
     146             : 
     147        9064 :   Handle<Map> initial_proto_initial_map = isolate->regexp_prototype_map();
     148        9064 :   if (JSReceiver::cast(proto)->map() != *initial_proto_initial_map) {
     149             :     return false;
     150             :   }
     151             : 
     152             :   // The smi check is required to omit ToLength(lastIndex) calls with possible
     153             :   // user-code execution on the fast path.
     154             :   Object* last_index = JSRegExp::cast(recv)->LastIndex();
     155       17830 :   return last_index->IsSmi() && Smi::cast(last_index)->value() >= 0;
     156             : }
     157             : 
     158          75 : int RegExpUtils::AdvanceStringIndex(Isolate* isolate, Handle<String> string,
     159             :                                     int index, bool unicode) {
     160          75 :   if (unicode && index < string->length()) {
     161             :     const uint16_t first = string->Get(index);
     162           0 :     if (first >= 0xD800 && first <= 0xDBFF && string->length() > index + 1) {
     163           0 :       const uint16_t second = string->Get(index + 1);
     164           0 :       if (second >= 0xDC00 && second <= 0xDFFF) {
     165           0 :         return index + 2;
     166             :       }
     167             :     }
     168             :   }
     169             : 
     170          75 :   return index + 1;
     171             : }
     172             : 
     173           0 : MaybeHandle<Object> RegExpUtils::SetAdvancedStringIndex(
     174             :     Isolate* isolate, Handle<JSReceiver> regexp, Handle<String> string,
     175             :     bool unicode) {
     176             :   Handle<Object> last_index_obj;
     177           0 :   ASSIGN_RETURN_ON_EXCEPTION(
     178             :       isolate, last_index_obj,
     179             :       Object::GetProperty(regexp, isolate->factory()->lastIndex_string()),
     180             :       Object);
     181             : 
     182           0 :   ASSIGN_RETURN_ON_EXCEPTION(isolate, last_index_obj,
     183             :                              Object::ToLength(isolate, last_index_obj), Object);
     184           0 :   const int last_index = PositiveNumberToUint32(*last_index_obj);
     185             :   const int new_last_index =
     186           0 :       AdvanceStringIndex(isolate, string, last_index, unicode);
     187             : 
     188           0 :   return SetLastIndex(isolate, regexp, new_last_index);
     189             : }
     190             : 
     191             : }  // namespace internal
     192             : }  // namespace v8

Generated by: LCOV version 1.10