LCOV - code coverage report
Current view: top level - src/inspector - v8-value-copier.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 93 108 86.1 %
Date: 2017-04-26 Functions: 6 6 100.0 %

          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/inspector/v8-value-copier.h"
       6             : 
       7             : namespace v8_inspector {
       8             : 
       9             : namespace {
      10             : 
      11             : static int kMaxDepth = 20;
      12             : static int kMaxCalls = 1000;
      13             : 
      14             : class V8ValueCopier {
      15             :  public:
      16         468 :   v8::MaybeLocal<v8::Value> copy(v8::Local<v8::Value> value, int depth) {
      17         468 :     if (++m_calls > kMaxCalls || depth > kMaxDepth)
      18           0 :       return v8::MaybeLocal<v8::Value>();
      19             : 
      20         468 :     if (value.IsEmpty()) return v8::MaybeLocal<v8::Value>();
      21        1398 :     if (value->IsNull() || value->IsUndefined() || value->IsBoolean() ||
      22         738 :         value->IsString() || value->IsNumber())
      23         216 :       return value;
      24         252 :     if (!value->IsObject()) return v8::MaybeLocal<v8::Value>();
      25             :     v8::Local<v8::Object> object = value.As<v8::Object>();
      26         504 :     if (object->CreationContext() != m_from) return value;
      27             : 
      28         192 :     if (object->IsArray()) {
      29             :       v8::Local<v8::Array> array = object.As<v8::Array>();
      30          60 :       v8::Local<v8::Array> result = v8::Array::New(m_isolate, array->Length());
      31         180 :       if (!result->SetPrototype(m_to, v8::Null(m_isolate)).FromMaybe(false))
      32           0 :         return v8::MaybeLocal<v8::Value>();
      33          96 :       for (uint32_t i = 0; i < array->Length(); ++i) {
      34             :         v8::Local<v8::Value> item;
      35         192 :         if (!array->Get(m_from, i).ToLocal(&item))
      36           0 :           return v8::MaybeLocal<v8::Value>();
      37             :         v8::Local<v8::Value> copied;
      38         192 :         if (!copy(item, depth + 1).ToLocal(&copied))
      39           0 :           return v8::MaybeLocal<v8::Value>();
      40         192 :         if (!createDataProperty(m_to, result, i, copied).FromMaybe(false))
      41           0 :           return v8::MaybeLocal<v8::Value>();
      42             :       }
      43          60 :       return result;
      44             :     }
      45             : 
      46         132 :     v8::Local<v8::Object> result = v8::Object::New(m_isolate);
      47         396 :     if (!result->SetPrototype(m_to, v8::Null(m_isolate)).FromMaybe(false))
      48           0 :       return v8::MaybeLocal<v8::Value>();
      49             :     v8::Local<v8::Array> properties;
      50         264 :     if (!object->GetOwnPropertyNames(m_from).ToLocal(&properties))
      51           0 :       return v8::MaybeLocal<v8::Value>();
      52         312 :     for (uint32_t i = 0; i < properties->Length(); ++i) {
      53             :       v8::Local<v8::Value> name;
      54         936 :       if (!properties->Get(m_from, i).ToLocal(&name) || !name->IsString())
      55           0 :         return v8::MaybeLocal<v8::Value>();
      56             :       v8::Local<v8::Value> property;
      57         624 :       if (!object->Get(m_from, name).ToLocal(&property))
      58           0 :         return v8::MaybeLocal<v8::Value>();
      59             :       v8::Local<v8::Value> copied;
      60         624 :       if (!copy(property, depth + 1).ToLocal(&copied))
      61           0 :         return v8::MaybeLocal<v8::Value>();
      62         312 :       if (!createDataProperty(m_to, result, v8::Local<v8::String>::Cast(name),
      63         312 :                               copied)
      64         624 :                .FromMaybe(false))
      65           0 :         return v8::MaybeLocal<v8::Value>();
      66             :     }
      67         132 :     return result;
      68             :   }
      69             : 
      70             :   v8::Isolate* m_isolate;
      71             :   v8::Local<v8::Context> m_from;
      72             :   v8::Local<v8::Context> m_to;
      73             :   int m_calls;
      74             : };
      75             : 
      76    45912258 : protocol::Response toProtocolValue(v8::Local<v8::Context> context,
      77             :                                    v8::Local<v8::Value> value, int maxDepth,
      78             :                                    std::unique_ptr<protocol::Value>* result) {
      79             :   using protocol::Response;
      80    45912258 :   if (value.IsEmpty()) {
      81           0 :     UNREACHABLE();
      82             :     return Response::InternalError();
      83             :   }
      84             : 
      85    45912258 :   if (!maxDepth) return Response::Error("Object reference chain is too long");
      86    45912258 :   maxDepth--;
      87             : 
      88    91820874 :   if (value->IsNull() || value->IsUndefined()) {
      89             :     *result = protocol::Value::null();
      90        3648 :     return Response::OK();
      91             :   }
      92    45908610 :   if (value->IsBoolean()) {
      93    27796864 :     *result =
      94    13898432 :         protocol::FundamentalValue::create(value.As<v8::Boolean>()->Value());
      95    13898432 :     return Response::OK();
      96             :   }
      97    32010178 :   if (value->IsNumber()) {
      98     1476233 :     double doubleValue = value.As<v8::Number>()->Value();
      99     1476233 :     int intValue = static_cast<int>(doubleValue);
     100     1476233 :     if (intValue == doubleValue) {
     101     2899238 :       *result = protocol::FundamentalValue::create(intValue);
     102     1449619 :       return Response::OK();
     103             :     }
     104       53228 :     *result = protocol::FundamentalValue::create(doubleValue);
     105       26614 :     return Response::OK();
     106             :   }
     107    30533945 :   if (value->IsString()) {
     108    63399639 :     *result =
     109             :         protocol::StringValue::create(toProtocolString(value.As<v8::String>()));
     110    21133213 :     return Response::OK();
     111             :   }
     112     9400732 :   if (value->IsArray()) {
     113             :     v8::Local<v8::Array> array = value.As<v8::Array>();
     114             :     std::unique_ptr<protocol::ListValue> inspectorArray =
     115      375450 :         protocol::ListValue::create();
     116      375450 :     uint32_t length = array->Length();
     117     4532792 :     for (uint32_t i = 0; i < length; i++) {
     118             :       v8::Local<v8::Value> value;
     119     8314684 :       if (!array->Get(context, i).ToLocal(&value))
     120           0 :         return Response::InternalError();
     121     4157342 :       std::unique_ptr<protocol::Value> element;
     122     4157342 :       Response response = toProtocolValue(context, value, maxDepth, &element);
     123     4157342 :       if (!response.isSuccess()) return response;
     124     8314684 :       inspectorArray->pushValue(std::move(element));
     125             :     }
     126             :     *result = std::move(inspectorArray);
     127      375450 :     return Response::OK();
     128             :   }
     129     9025282 :   if (value->IsObject()) {
     130             :     std::unique_ptr<protocol::DictionaryValue> jsonObject =
     131     9025276 :         protocol::DictionaryValue::create();
     132             :     v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value);
     133             :     v8::Local<v8::Array> propertyNames;
     134    18050552 :     if (!object->GetPropertyNames(context).ToLocal(&propertyNames))
     135           0 :       return Response::InternalError();
     136     9025276 :     uint32_t length = propertyNames->Length();
     137    75918042 :     for (uint32_t i = 0; i < length; i++) {
     138             :       v8::Local<v8::Value> name;
     139   133785544 :       if (!propertyNames->Get(context, i).ToLocal(&name))
     140           6 :         return Response::InternalError();
     141             :       // FIXME(yurys): v8::Object should support GetOwnPropertyNames
     142    66892772 :       if (name->IsString()) {
     143             :         v8::Maybe<bool> hasRealNamedProperty = object->HasRealNamedProperty(
     144    66892772 :             context, v8::Local<v8::String>::Cast(name));
     145   133785544 :         if (!hasRealNamedProperty.IsJust() || !hasRealNamedProperty.FromJust())
     146    25353384 :           continue;
     147             :       }
     148             :       v8::Local<v8::String> propertyName;
     149    83078776 :       if (!name->ToString(context).ToLocal(&propertyName)) continue;
     150             :       v8::Local<v8::Value> property;
     151    83078776 :       if (!object->Get(context, name).ToLocal(&property))
     152           0 :         return Response::InternalError();
     153    41539388 :       std::unique_ptr<protocol::Value> propertyValue;
     154             :       Response response =
     155    41539388 :           toProtocolValue(context, property, maxDepth, &propertyValue);
     156    41539388 :       if (!response.isSuccess()) return response;
     157             :       jsonObject->setValue(toProtocolString(propertyName),
     158   166157528 :                            std::move(propertyValue));
     159             :     }
     160             :     *result = std::move(jsonObject);
     161     9025270 :     return Response::OK();
     162             :   }
     163          12 :   return Response::Error("Object couldn't be returned by value");
     164             : }
     165             : 
     166             : }  // namespace
     167             : 
     168          60 : v8::MaybeLocal<v8::Value> copyValueFromDebuggerContext(
     169             :     v8::Isolate* isolate, v8::Local<v8::Context> debuggerContext,
     170             :     v8::Local<v8::Context> toContext, v8::Local<v8::Value> value) {
     171             :   V8ValueCopier copier;
     172          60 :   copier.m_isolate = isolate;
     173          60 :   copier.m_from = debuggerContext;
     174          60 :   copier.m_to = toContext;
     175          60 :   copier.m_calls = 0;
     176          60 :   return copier.copy(value, 0);
     177             : }
     178             : 
     179      278644 : v8::Maybe<bool> createDataProperty(v8::Local<v8::Context> context,
     180             :                                    v8::Local<v8::Object> object,
     181             :                                    v8::Local<v8::Name> key,
     182             :                                    v8::Local<v8::Value> value) {
     183      278644 :   v8::TryCatch tryCatch(context->GetIsolate());
     184             :   v8::Isolate::DisallowJavascriptExecutionScope throwJs(
     185             :       context->GetIsolate(),
     186      557288 :       v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
     187      557288 :   return object->CreateDataProperty(context, key, value);
     188             : }
     189             : 
     190       13690 : v8::Maybe<bool> createDataProperty(v8::Local<v8::Context> context,
     191             :                                    v8::Local<v8::Array> array, int index,
     192             :                                    v8::Local<v8::Value> value) {
     193       13690 :   v8::TryCatch tryCatch(context->GetIsolate());
     194             :   v8::Isolate::DisallowJavascriptExecutionScope throwJs(
     195             :       context->GetIsolate(),
     196       27380 :       v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
     197       41070 :   return array->CreateDataProperty(context, index, value);
     198             : }
     199             : 
     200      215528 : protocol::Response toProtocolValue(v8::Local<v8::Context> context,
     201             :                                    v8::Local<v8::Value> value,
     202             :                                    std::unique_ptr<protocol::Value>* result) {
     203      215528 :   return toProtocolValue(context, value, 1000, result);
     204             : }
     205             : 
     206             : }  // namespace v8_inspector

Generated by: LCOV version 1.10