LCOV - code coverage report
Current view: top level - test/unittests/api - v8-object-unittest.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 108 110 98.2 %
Date: 2019-04-17 Functions: 16 21 76.2 %

          Line data    Source code
       1             : // Copyright 2017 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 "include/v8.h"
       6             : #include "src/api.h"
       7             : #include "src/objects-inl.h"
       8             : #include "test/unittests/test-utils.h"
       9             : #include "testing/gtest/include/gtest/gtest.h"
      10             : 
      11             : namespace v8 {
      12             : namespace {
      13             : 
      14             : using ObjectTest = TestWithContext;
      15             : 
      16           0 : void accessor_name_getter_callback(Local<Name>,
      17           0 :                                    const PropertyCallbackInfo<Value>&) {}
      18             : 
      19       15444 : TEST_F(ObjectTest, SetAccessorWhenUnconfigurablePropAlreadyDefined) {
      20           2 :   TryCatch try_catch(isolate());
      21             : 
      22           1 :   Local<Object> global = context()->Global();
      23             :   Local<String> property_name =
      24           1 :       String::NewFromUtf8(isolate(), "foo", NewStringType::kNormal)
      25             :           .ToLocalChecked();
      26             : 
      27           2 :   PropertyDescriptor prop_desc;
      28           1 :   prop_desc.set_configurable(false);
      29           2 :   global->DefineProperty(context(), property_name, prop_desc).ToChecked();
      30             : 
      31             :   Maybe<bool> result = global->SetAccessor(context(), property_name,
      32           1 :                                            accessor_name_getter_callback);
      33           1 :   ASSERT_TRUE(result.IsJust());
      34           2 :   ASSERT_FALSE(result.FromJust());
      35           2 :   ASSERT_FALSE(try_catch.HasCaught());
      36             : }
      37             : 
      38             : using LapContextTest = TestWithIsolate;
      39             : 
      40       15443 : TEST_F(LapContextTest, CurrentContextInLazyAccessorOnPrototype) {
      41             :   // The receiver object is created in |receiver_context|, but its prototype
      42             :   // object is created in |prototype_context|, and the property is accessed
      43             :   // from |caller_context|.
      44           1 :   Local<Context> receiver_context = Context::New(isolate());
      45           1 :   Local<Context> prototype_context = Context::New(isolate());
      46           1 :   Local<Context> caller_context = Context::New(isolate());
      47             : 
      48             :   static int call_count;  // The number of calls of the accessor callback.
      49           1 :   call_count = 0;
      50             : 
      51           1 :   Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate());
      52           1 :   Local<Signature> signature = Signature::New(isolate(), function_template);
      53             :   Local<String> property_key =
      54           1 :       String::NewFromUtf8(isolate(), "property", NewStringType::kNormal)
      55             :           .ToLocalChecked();
      56             :   Local<FunctionTemplate> get_or_set = FunctionTemplate::New(
      57             :       isolate(),
      58          16 :       [](const FunctionCallbackInfo<Value>& info) {
      59           8 :         ++call_count;
      60             :         Local<Context> prototype_context = *reinterpret_cast<Local<Context>*>(
      61           8 :             info.Data().As<External>()->Value());
      62          16 :         EXPECT_EQ(prototype_context, info.GetIsolate()->GetCurrentContext());
      63          16 :       },
      64           2 :       External::New(isolate(), &prototype_context), signature);
      65           2 :   function_template->PrototypeTemplate()->SetAccessorProperty(
      66           1 :       property_key, get_or_set, get_or_set);
      67             : 
      68             :   // |object| is created in |receiver_context|, and |prototype| is created
      69             :   // in |prototype_context|.  And then, object.__proto__ = prototype.
      70             :   Local<Function> interface_for_receiver =
      71           1 :       function_template->GetFunction(receiver_context).ToLocalChecked();
      72             :   Local<Function> interface_for_prototype =
      73           1 :       function_template->GetFunction(prototype_context).ToLocalChecked();
      74             :   Local<String> prototype_key =
      75           1 :       String::NewFromUtf8(isolate(), "prototype", NewStringType::kNormal)
      76             :           .ToLocalChecked();
      77             :   Local<Object> prototype =
      78           2 :       interface_for_prototype->Get(caller_context, prototype_key)
      79             :           .ToLocalChecked()
      80             :           .As<Object>();
      81             :   Local<Object> object =
      82             :       interface_for_receiver->NewInstance(receiver_context).ToLocalChecked();
      83           2 :   object->SetPrototype(caller_context, prototype).ToChecked();
      84           2 :   EXPECT_EQ(receiver_context, object->CreationContext());
      85           2 :   EXPECT_EQ(prototype_context, prototype->CreationContext());
      86             : 
      87           2 :   EXPECT_EQ(0, call_count);
      88           2 :   object->Get(caller_context, property_key).ToLocalChecked();
      89           2 :   EXPECT_EQ(1, call_count);
      90           2 :   object->Set(caller_context, property_key, Null(isolate())).ToChecked();
      91           2 :   EXPECT_EQ(2, call_count);
      92             : 
      93             :   // Test with a compiled version.
      94             :   Local<String> object_key =
      95           1 :       String::NewFromUtf8(isolate(), "object", NewStringType::kNormal)
      96             :           .ToLocalChecked();
      97           3 :   caller_context->Global()->Set(caller_context, object_key, object).ToChecked();
      98             :   const char script[] =
      99             :       "function f() { object.property; object.property = 0; } "
     100             :       "f(); f(); "
     101             :       "%OptimizeFunctionOnNextCall(f); "
     102           1 :       "f();";
     103             :   Context::Scope scope(caller_context);
     104           1 :   internal::FLAG_allow_natives_syntax = true;
     105           1 :   Script::Compile(
     106             :       caller_context,
     107           1 :       String::NewFromUtf8(isolate(), script, v8::NewStringType::kNormal)
     108             :           .ToLocalChecked())
     109             :       .ToLocalChecked()
     110           1 :       ->Run(caller_context)
     111             :       .ToLocalChecked();
     112           2 :   EXPECT_EQ(8, call_count);
     113           1 : }
     114             : 
     115       15443 : TEST_F(LapContextTest, CurrentContextInLazyAccessorOnPlatformObject) {
     116           1 :   Local<Context> receiver_context = Context::New(isolate());
     117           1 :   Local<Context> caller_context = Context::New(isolate());
     118             : 
     119             :   static int call_count;  // The number of calls of the accessor callback.
     120           1 :   call_count = 0;
     121             : 
     122           1 :   Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate());
     123           1 :   Local<Signature> signature = Signature::New(isolate(), function_template);
     124             :   Local<String> property_key =
     125           1 :       String::NewFromUtf8(isolate(), "property", NewStringType::kNormal)
     126             :           .ToLocalChecked();
     127             :   Local<FunctionTemplate> get_or_set = FunctionTemplate::New(
     128             :       isolate(),
     129          16 :       [](const FunctionCallbackInfo<Value>& info) {
     130           8 :         ++call_count;
     131             :         Local<Context> receiver_context = *reinterpret_cast<Local<Context>*>(
     132           8 :             info.Data().As<External>()->Value());
     133          16 :         EXPECT_EQ(receiver_context, info.GetIsolate()->GetCurrentContext());
     134          16 :       },
     135           2 :       External::New(isolate(), &receiver_context), signature);
     136           2 :   function_template->InstanceTemplate()->SetAccessorProperty(
     137           1 :       property_key, get_or_set, get_or_set);
     138             : 
     139             :   Local<Function> interface =
     140           1 :       function_template->GetFunction(receiver_context).ToLocalChecked();
     141             :   Local<Object> object =
     142             :       interface->NewInstance(receiver_context).ToLocalChecked();
     143             : 
     144           2 :   EXPECT_EQ(0, call_count);
     145           2 :   object->Get(caller_context, property_key).ToLocalChecked();
     146           2 :   EXPECT_EQ(1, call_count);
     147           2 :   object->Set(caller_context, property_key, Null(isolate())).ToChecked();
     148           2 :   EXPECT_EQ(2, call_count);
     149             : 
     150             :   // Test with a compiled version.
     151             :   Local<String> object_key =
     152           1 :       String::NewFromUtf8(isolate(), "object", NewStringType::kNormal)
     153             :           .ToLocalChecked();
     154           3 :   caller_context->Global()->Set(caller_context, object_key, object).ToChecked();
     155             :   const char script[] =
     156             :       "function f() { object.property; object.property = 0; } "
     157             :       "f(); f(); "
     158             :       "%OptimizeFunctionOnNextCall(f); "
     159           1 :       "f();";
     160             :   Context::Scope scope(caller_context);
     161           1 :   internal::FLAG_allow_natives_syntax = true;
     162           1 :   Script::Compile(
     163             :       caller_context,
     164           1 :       String::NewFromUtf8(isolate(), script, v8::NewStringType::kNormal)
     165             :           .ToLocalChecked())
     166             :       .ToLocalChecked()
     167           1 :       ->Run(caller_context)
     168             :       .ToLocalChecked();
     169           2 :   EXPECT_EQ(8, call_count);
     170           1 : }
     171             : 
     172       15443 : TEST_F(LapContextTest, CurrentContextInLazyAccessorOnInterface) {
     173           1 :   Local<Context> interface_context = Context::New(isolate());
     174           1 :   Local<Context> caller_context = Context::New(isolate());
     175             : 
     176             :   static int call_count;  // The number of calls of the accessor callback.
     177           1 :   call_count = 0;
     178             : 
     179           1 :   Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate());
     180             :   Local<String> property_key =
     181           1 :       String::NewFromUtf8(isolate(), "property", NewStringType::kNormal)
     182             :           .ToLocalChecked();
     183             :   Local<FunctionTemplate> get_or_set = FunctionTemplate::New(
     184             :       isolate(),
     185          16 :       [](const FunctionCallbackInfo<Value>& info) {
     186           8 :         ++call_count;
     187             :         Local<Context> interface_context = *reinterpret_cast<Local<Context>*>(
     188           8 :             info.Data().As<External>()->Value());
     189          16 :         EXPECT_EQ(interface_context, info.GetIsolate()->GetCurrentContext());
     190          16 :       },
     191           2 :       External::New(isolate(), &interface_context), Local<Signature>());
     192           1 :   function_template->SetAccessorProperty(property_key, get_or_set, get_or_set);
     193             : 
     194             :   Local<Function> interface =
     195           1 :       function_template->GetFunction(interface_context).ToLocalChecked();
     196             : 
     197           2 :   EXPECT_EQ(0, call_count);
     198           2 :   interface->Get(caller_context, property_key).ToLocalChecked();
     199           2 :   EXPECT_EQ(1, call_count);
     200           2 :   interface->Set(caller_context, property_key, Null(isolate())).ToChecked();
     201           2 :   EXPECT_EQ(2, call_count);
     202             : 
     203             :   // Test with a compiled version.
     204             :   Local<String> interface_key =
     205           1 :       String::NewFromUtf8(isolate(), "Interface", NewStringType::kNormal)
     206             :           .ToLocalChecked();
     207           1 :   caller_context->Global()
     208           3 :       ->Set(caller_context, interface_key, interface)
     209             :       .ToChecked();
     210             :   const char script[] =
     211             :       "function f() { Interface.property; Interface.property = 0; } "
     212             :       "f(); f(); "
     213             :       "%OptimizeFunctionOnNextCall(f); "
     214           1 :       "f();";
     215             :   Context::Scope scope(caller_context);
     216           1 :   internal::FLAG_allow_natives_syntax = true;
     217           1 :   Script::Compile(
     218             :       caller_context,
     219           1 :       String::NewFromUtf8(isolate(), script, v8::NewStringType::kNormal)
     220             :           .ToLocalChecked())
     221             :       .ToLocalChecked()
     222           1 :       ->Run(caller_context)
     223             :       .ToLocalChecked();
     224           2 :   EXPECT_EQ(8, call_count);
     225           1 : }
     226             : 
     227             : }  // namespace
     228        9264 : }  // namespace v8

Generated by: LCOV version 1.10