11cb0ef41Sopenharmony_ci// Copyright 2016 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/inspector/v8-regex.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include <limits.h>
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ci#include "include/v8-container.h"
101cb0ef41Sopenharmony_ci#include "include/v8-context.h"
111cb0ef41Sopenharmony_ci#include "include/v8-function.h"
121cb0ef41Sopenharmony_ci#include "include/v8-inspector.h"
131cb0ef41Sopenharmony_ci#include "include/v8-microtask-queue.h"
141cb0ef41Sopenharmony_ci#include "include/v8-regexp.h"
151cb0ef41Sopenharmony_ci#include "src/inspector/string-util.h"
161cb0ef41Sopenharmony_ci#include "src/inspector/v8-inspector-impl.h"
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_cinamespace v8_inspector {
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ciV8Regex::V8Regex(V8InspectorImpl* inspector, const String16& pattern,
211cb0ef41Sopenharmony_ci                 bool caseSensitive, bool multiline)
221cb0ef41Sopenharmony_ci    : m_inspector(inspector) {
231cb0ef41Sopenharmony_ci  v8::Isolate* isolate = m_inspector->isolate();
241cb0ef41Sopenharmony_ci  v8::HandleScope handleScope(isolate);
251cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context;
261cb0ef41Sopenharmony_ci  if (!m_inspector->regexContext().ToLocal(&context)) {
271cb0ef41Sopenharmony_ci    DCHECK(isolate->IsExecutionTerminating());
281cb0ef41Sopenharmony_ci    m_errorMessage = "terminated";
291cb0ef41Sopenharmony_ci    return;
301cb0ef41Sopenharmony_ci  }
311cb0ef41Sopenharmony_ci  v8::Context::Scope contextScope(context);
321cb0ef41Sopenharmony_ci  v8::TryCatch tryCatch(isolate);
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci  unsigned flags = v8::RegExp::kNone;
351cb0ef41Sopenharmony_ci  if (!caseSensitive) flags |= v8::RegExp::kIgnoreCase;
361cb0ef41Sopenharmony_ci  if (multiline) flags |= v8::RegExp::kMultiline;
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci  v8::Local<v8::RegExp> regex;
391cb0ef41Sopenharmony_ci  if (v8::RegExp::New(context, toV8String(isolate, pattern),
401cb0ef41Sopenharmony_ci                      static_cast<v8::RegExp::Flags>(flags))
411cb0ef41Sopenharmony_ci          .ToLocal(&regex))
421cb0ef41Sopenharmony_ci    m_regex.Reset(isolate, regex);
431cb0ef41Sopenharmony_ci  else if (tryCatch.HasCaught())
441cb0ef41Sopenharmony_ci    m_errorMessage = toProtocolString(isolate, tryCatch.Message()->Get());
451cb0ef41Sopenharmony_ci  else
461cb0ef41Sopenharmony_ci    m_errorMessage = "Internal error";
471cb0ef41Sopenharmony_ci}
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ciint V8Regex::match(const String16& string, int startFrom,
501cb0ef41Sopenharmony_ci                   int* matchLength) const {
511cb0ef41Sopenharmony_ci  if (matchLength) *matchLength = 0;
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci  if (m_regex.IsEmpty() || string.isEmpty()) return -1;
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ci  // v8 strings are limited to int.
561cb0ef41Sopenharmony_ci  if (string.length() > INT_MAX) return -1;
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci  v8::Isolate* isolate = m_inspector->isolate();
591cb0ef41Sopenharmony_ci  v8::HandleScope handleScope(isolate);
601cb0ef41Sopenharmony_ci  v8::Local<v8::Context> context;
611cb0ef41Sopenharmony_ci  if (!m_inspector->regexContext().ToLocal(&context)) {
621cb0ef41Sopenharmony_ci    DCHECK(isolate->IsExecutionTerminating());
631cb0ef41Sopenharmony_ci    return -1;
641cb0ef41Sopenharmony_ci  }
651cb0ef41Sopenharmony_ci  v8::Context::Scope contextScope(context);
661cb0ef41Sopenharmony_ci  v8::MicrotasksScope microtasks(isolate,
671cb0ef41Sopenharmony_ci                                 v8::MicrotasksScope::kDoNotRunMicrotasks);
681cb0ef41Sopenharmony_ci  v8::TryCatch tryCatch(isolate);
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci  v8::Local<v8::RegExp> regex = m_regex.Get(isolate);
711cb0ef41Sopenharmony_ci  v8::Local<v8::Value> exec;
721cb0ef41Sopenharmony_ci  if (!regex->Get(context, toV8StringInternalized(isolate, "exec"))
731cb0ef41Sopenharmony_ci           .ToLocal(&exec))
741cb0ef41Sopenharmony_ci    return -1;
751cb0ef41Sopenharmony_ci  v8::Local<v8::Value> argv[] = {
761cb0ef41Sopenharmony_ci      toV8String(isolate, string.substring(startFrom))};
771cb0ef41Sopenharmony_ci  v8::Local<v8::Value> returnValue;
781cb0ef41Sopenharmony_ci  if (!exec.As<v8::Function>()
791cb0ef41Sopenharmony_ci           ->Call(context, regex, arraysize(argv), argv)
801cb0ef41Sopenharmony_ci           .ToLocal(&returnValue))
811cb0ef41Sopenharmony_ci    return -1;
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci  // RegExp#exec returns null if there's no match, otherwise it returns an
841cb0ef41Sopenharmony_ci  // Array of strings with the first being the whole match string and others
851cb0ef41Sopenharmony_ci  // being subgroups. The Array also has some random properties tacked on like
861cb0ef41Sopenharmony_ci  // "index" which is the offset of the match.
871cb0ef41Sopenharmony_ci  //
881cb0ef41Sopenharmony_ci  // https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/RegExp/exec
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci  DCHECK(!returnValue.IsEmpty());
911cb0ef41Sopenharmony_ci  if (!returnValue->IsArray()) return -1;
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci  v8::Local<v8::Array> result = returnValue.As<v8::Array>();
941cb0ef41Sopenharmony_ci  v8::Local<v8::Value> matchOffset;
951cb0ef41Sopenharmony_ci  if (!result->Get(context, toV8StringInternalized(isolate, "index"))
961cb0ef41Sopenharmony_ci           .ToLocal(&matchOffset))
971cb0ef41Sopenharmony_ci    return -1;
981cb0ef41Sopenharmony_ci  if (matchLength) {
991cb0ef41Sopenharmony_ci    v8::Local<v8::Value> match;
1001cb0ef41Sopenharmony_ci    if (!result->Get(context, 0).ToLocal(&match)) return -1;
1011cb0ef41Sopenharmony_ci    *matchLength = match.As<v8::String>()->Length();
1021cb0ef41Sopenharmony_ci  }
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci  return matchOffset.As<v8::Int32>()->Value() + startFrom;
1051cb0ef41Sopenharmony_ci}
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci}  // namespace v8_inspector
108