LCOV - code coverage report
Current view: top level - src/regexp - regexp-utils.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 46 58 79.3 %
Date: 2017-10-20 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      284752 : Handle<String> RegExpUtils::GenericCaptureGetter(
      16             :     Isolate* isolate, Handle<RegExpMatchInfo> match_info, int capture,
      17             :     bool* ok) {
      18      284752 :   const int index = capture * 2;
      19      284752 :   if (index >= match_info->NumberOfCaptureRegisters()) {
      20        2004 :     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      282748 :   if (match_start == -1 || match_end == -1) {
      27         212 :     if (ok != nullptr) *ok = false;
      28             :     return isolate->factory()->empty_string();
      29             :   }
      30             : 
      31      282536 :   if (ok != nullptr) *ok = true;
      32             :   Handle<String> last_subject(match_info->LastSubject());
      33      282536 :   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        6284 :   return recv->map() == isolate->regexp_function()->initial_map();
      40             : }
      41             : 
      42             : }  // namespace
      43             : 
      44        3022 : MaybeHandle<Object> RegExpUtils::SetLastIndex(Isolate* isolate,
      45             :                                               Handle<JSReceiver> recv,
      46             :                                               int value) {
      47        3022 :   if (HasInitialRegExpMap(isolate, recv)) {
      48             :     JSRegExp::cast(*recv)->set_last_index(Smi::FromInt(value),
      49        2872 :                                           SKIP_WRITE_BARRIER);
      50        2872 :     return recv;
      51             :   } else {
      52             :     return Object::SetProperty(recv, isolate->factory()->lastIndex_string(),
      53             :                                handle(Smi::FromInt(value), isolate),
      54         150 :                                LanguageMode::kStrict);
      55             :   }
      56             : }
      57             : 
      58         120 : MaybeHandle<Object> RegExpUtils::GetLastIndex(Isolate* isolate,
      59             :                                               Handle<JSReceiver> recv) {
      60         120 :   if (HasInitialRegExpMap(isolate, recv)) {
      61         100 :     return handle(JSRegExp::cast(*recv)->last_index(), isolate);
      62             :   } else {
      63          20 :     return Object::GetProperty(recv, isolate->factory()->lastIndex_string());
      64             :   }
      65             : }
      66             : 
      67             : // ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S )
      68             : // Also takes an optional exec method in case our caller
      69             : // has already fetched exec.
      70         918 : MaybeHandle<Object> RegExpUtils::RegExpExec(Isolate* isolate,
      71             :                                             Handle<JSReceiver> regexp,
      72             :                                             Handle<String> string,
      73             :                                             Handle<Object> exec) {
      74         918 :   if (exec->IsUndefined(isolate)) {
      75        1836 :     ASSIGN_RETURN_ON_EXCEPTION(
      76             :         isolate, exec,
      77             :         Object::GetProperty(regexp, isolate->factory()->exec_string()), Object);
      78             :   }
      79             : 
      80         918 :   if (exec->IsCallable()) {
      81             :     const int argc = 1;
      82             :     ScopedVector<Handle<Object>> argv(argc);
      83         888 :     argv[0] = string;
      84             : 
      85             :     Handle<Object> result;
      86        1776 :     ASSIGN_RETURN_ON_EXCEPTION(
      87             :         isolate, result,
      88             :         Execution::Call(isolate, exec, regexp, argc, argv.start()), Object);
      89             : 
      90        1309 :     if (!result->IsJSReceiver() && !result->IsNull(isolate)) {
      91           0 :       THROW_NEW_ERROR(isolate,
      92             :                       NewTypeError(MessageTemplate::kInvalidRegExpExecResult),
      93             :                       Object);
      94             :     }
      95         878 :     return result;
      96             :   }
      97             : 
      98          30 :   if (!regexp->IsJSRegExp()) {
      99           0 :     THROW_NEW_ERROR(isolate,
     100             :                     NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
     101             :                                  isolate->factory()->NewStringFromAsciiChecked(
     102             :                                      "RegExp.prototype.exec"),
     103             :                                  regexp),
     104             :                     Object);
     105             :   }
     106             : 
     107             :   {
     108          30 :     Handle<JSFunction> regexp_exec = isolate->regexp_exec_function();
     109             : 
     110             :     const int argc = 1;
     111             :     ScopedVector<Handle<Object>> argv(argc);
     112          30 :     argv[0] = string;
     113             : 
     114          30 :     return Execution::Call(isolate, regexp_exec, regexp, argc, argv.start());
     115             :   }
     116             : }
     117             : 
     118       40016 : Maybe<bool> RegExpUtils::IsRegExp(Isolate* isolate, Handle<Object> object) {
     119       40016 :   if (!object->IsJSReceiver()) return Just(false);
     120             : 
     121         515 :   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
     122             : 
     123             :   Handle<Object> match;
     124        1030 :   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
     125             :       isolate, match,
     126             :       JSObject::GetProperty(receiver, isolate->factory()->match_symbol()),
     127             :       Nothing<bool>());
     128             : 
     129         733 :   if (!match->IsUndefined(isolate)) return Just(match->BooleanValue());
     130             :   return Just(object->IsJSRegExp());
     131             : }
     132             : 
     133        6441 : bool RegExpUtils::IsUnmodifiedRegExp(Isolate* isolate, Handle<Object> obj) {
     134             :   // TODO(ishell): Update this check once map changes for constant field
     135             :   // tracking are landing.
     136             : 
     137        6441 :   if (!obj->IsJSReceiver()) return false;
     138             : 
     139             :   JSReceiver* recv = JSReceiver::cast(*obj);
     140             : 
     141             :   // Check the receiver's map.
     142        6441 :   Handle<JSFunction> regexp_function = isolate->regexp_function();
     143        6441 :   if (recv->map() != regexp_function->initial_map()) return false;
     144             : 
     145             :   // Check the receiver's prototype's map.
     146             :   Object* proto = recv->map()->prototype();
     147        6231 :   if (!proto->IsJSReceiver()) return false;
     148             : 
     149        6231 :   Handle<Map> initial_proto_initial_map = isolate->regexp_prototype_map();
     150        6231 :   if (JSReceiver::cast(proto)->map() != *initial_proto_initial_map) {
     151             :     return false;
     152             :   }
     153             : 
     154             :   // The smi check is required to omit ToLength(lastIndex) calls with possible
     155             :   // user-code execution on the fast path.
     156             :   Object* last_index = JSRegExp::cast(recv)->last_index();
     157       12269 :   return last_index->IsSmi() && Smi::ToInt(last_index) >= 0;
     158             : }
     159             : 
     160         170 : int RegExpUtils::AdvanceStringIndex(Isolate* isolate, Handle<String> string,
     161             :                                     int index, bool unicode) {
     162         170 :   if (unicode && index < string->length()) {
     163             :     const uint16_t first = string->Get(index);
     164           0 :     if (first >= 0xD800 && first <= 0xDBFF && string->length() > index + 1) {
     165           0 :       const uint16_t second = string->Get(index + 1);
     166           0 :       if (second >= 0xDC00 && second <= 0xDFFF) {
     167           0 :         return index + 2;
     168             :       }
     169             :     }
     170             :   }
     171             : 
     172         170 :   return index + 1;
     173             : }
     174             : 
     175           0 : MaybeHandle<Object> RegExpUtils::SetAdvancedStringIndex(
     176             :     Isolate* isolate, Handle<JSReceiver> regexp, Handle<String> string,
     177             :     bool unicode) {
     178             :   Handle<Object> last_index_obj;
     179           0 :   ASSIGN_RETURN_ON_EXCEPTION(
     180             :       isolate, last_index_obj,
     181             :       Object::GetProperty(regexp, isolate->factory()->lastIndex_string()),
     182             :       Object);
     183             : 
     184           0 :   ASSIGN_RETURN_ON_EXCEPTION(isolate, last_index_obj,
     185             :                              Object::ToLength(isolate, last_index_obj), Object);
     186           0 :   const int last_index = PositiveNumberToUint32(*last_index_obj);
     187             :   const int new_last_index =
     188           0 :       AdvanceStringIndex(isolate, string, last_index, unicode);
     189             : 
     190           0 :   return SetLastIndex(isolate, regexp, new_last_index);
     191             : }
     192             : 
     193             : }  // namespace internal
     194             : }  // namespace v8

Generated by: LCOV version 1.10