LCOV - code coverage report
Current view: top level - test/cctest - test-api-accessors.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 219 221 99.1 %
Date: 2019-04-17 Functions: 18 19 94.7 %

          Line data    Source code
       1             : // Copyright 2015 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 "test/cctest/cctest.h"
       6             : 
       7             : #include "include/v8.h"
       8             : #include "src/api.h"
       9             : #include "src/objects-inl.h"
      10             : 
      11             : namespace i = v8::internal;
      12             : 
      13             : // The goal is to avoid the callback.
      14           0 : static void UnreachableCallback(
      15             :     const v8::FunctionCallbackInfo<v8::Value>& info) {
      16           0 :   UNREACHABLE();
      17             : }
      18             : 
      19       26644 : TEST(CachedAccessor) {
      20             :   // TurboFan support for fast accessors is not implemented; turbofanned
      21             :   // code uses the slow accessor which breaks this test's expectations.
      22           5 :   v8::internal::FLAG_always_opt = false;
      23           5 :   LocalContext env;
      24           5 :   v8::Isolate* isolate = env->GetIsolate();
      25          10 :   v8::HandleScope scope(isolate);
      26             : 
      27             :   // Create 'foo' class, with a hidden property.
      28           5 :   v8::Local<v8::ObjectTemplate> foo = v8::ObjectTemplate::New(isolate);
      29             : 
      30             :   v8::Local<v8::Private> priv =
      31           5 :       v8::Private::ForApi(isolate, v8_str("Foo#draft"));
      32             : 
      33          10 :   foo->SetAccessorProperty(v8_str("draft"), v8::FunctionTemplate::NewWithCache(
      34             :                                                 isolate, UnreachableCallback,
      35           5 :                                                 priv, v8::Local<v8::Value>()));
      36             : 
      37             :   // Create 'obj', instance of 'foo'.
      38           5 :   v8::Local<v8::Object> obj = foo->NewInstance(env.local()).ToLocalChecked();
      39             : 
      40             :   // Install the private property on the instance.
      41          10 :   CHECK(obj->SetPrivate(isolate->GetCurrentContext(), priv,
      42             :                         v8::Undefined(isolate))
      43             :             .FromJust());
      44             : 
      45          20 :   CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
      46             : 
      47             :   // Access cached accessor.
      48           5 :   ExpectUndefined("obj.draft");
      49             : 
      50             :   // Set hidden property.
      51          15 :   CHECK(obj->SetPrivate(isolate->GetCurrentContext(), priv,
      52             :                         v8_str("Shhh, I'm private!"))
      53             :             .FromJust());
      54             : 
      55           5 :   ExpectString("obj.draft", "Shhh, I'm private!");
      56             : 
      57             :   // Stress the accessor to use the IC.
      58             :   ExpectString(
      59             :       "var result = '';"
      60             :       "for (var i = 0; i < 10; ++i) { "
      61             :       "  result = obj.draft; "
      62             :       "} "
      63             :       "result; ",
      64           5 :       "Shhh, I'm private!");
      65           5 : }
      66             : 
      67       26644 : TEST(CachedAccessorTurboFan) {
      68           5 :   i::FLAG_allow_natives_syntax = true;
      69             :   // v8::internal::FLAG_always_opt = false;
      70           5 :   LocalContext env;
      71           5 :   v8::Isolate* isolate = env->GetIsolate();
      72          10 :   v8::HandleScope scope(isolate);
      73             : 
      74             :   // Create 'foo' class, with a hidden property.
      75           5 :   v8::Local<v8::ObjectTemplate> foo = v8::ObjectTemplate::New(isolate);
      76             :   v8::Local<v8::Private> priv =
      77           5 :       v8::Private::ForApi(isolate, v8_str("Foo#draft"));
      78             : 
      79             :   // Install the private property on the template.
      80             :   // foo->SetPrivate(priv, v8::Undefined(isolate));
      81             : 
      82          10 :   foo->SetAccessorProperty(v8_str("draft"), v8::FunctionTemplate::NewWithCache(
      83             :                                                 isolate, UnreachableCallback,
      84           5 :                                                 priv, v8::Local<v8::Value>()));
      85             : 
      86             :   // Create 'obj', instance of 'foo'.
      87           5 :   v8::Local<v8::Object> obj = foo->NewInstance(env.local()).ToLocalChecked();
      88             : 
      89             :   // Install the private property on the instance.
      90          10 :   CHECK(obj->SetPrivate(isolate->GetCurrentContext(), priv,
      91             :                         v8::Undefined(isolate))
      92             :             .FromJust());
      93             : 
      94          20 :   CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
      95             : 
      96             :   // Access surrogate accessor.
      97           5 :   ExpectUndefined("obj.draft");
      98             : 
      99             :   // Set hidden property.
     100          15 :   CHECK(obj->SetPrivate(env.local(), priv, v8::Integer::New(isolate, 123))
     101             :             .FromJust());
     102             : 
     103             :   // Test ICs.
     104             :   CompileRun(
     105             :       "function f() {"
     106             :       "  var x;"
     107             :       "  for (var i = 0; i < 100; i++) {"
     108             :       "    x = obj.draft;"
     109             :       "  }"
     110             :       "  return x;"
     111             :       "}");
     112             : 
     113           5 :   ExpectInt32("f()", 123);
     114             : 
     115             :   // Reset hidden property.
     116          15 :   CHECK(obj->SetPrivate(env.local(), priv, v8::Integer::New(isolate, 456))
     117             :             .FromJust());
     118             : 
     119             :   // Test TurboFan.
     120             :   CompileRun("%OptimizeFunctionOnNextCall(f);");
     121             : 
     122           5 :   ExpectInt32("f()", 456);
     123             : 
     124          15 :   CHECK(obj->SetPrivate(env.local(), priv, v8::Integer::New(isolate, 456))
     125             :             .FromJust());
     126             :   // Test non-global ICs.
     127             :   CompileRun(
     128             :       "function g() {"
     129             :       "  var x = obj;"
     130             :       "  var r = 0;"
     131             :       "  for (var i = 0; i < 100; i++) {"
     132             :       "    r = x.draft;"
     133             :       "  }"
     134             :       "  return r;"
     135             :       "}");
     136             : 
     137           5 :   ExpectInt32("g()", 456);
     138             : 
     139             :   // Reset hidden property.
     140          15 :   CHECK(obj->SetPrivate(env.local(), priv, v8::Integer::New(isolate, 789))
     141             :             .FromJust());
     142             : 
     143             :   // Test non-global access in TurboFan.
     144             :   CompileRun("%OptimizeFunctionOnNextCall(g);");
     145             : 
     146           5 :   ExpectInt32("g()", 789);
     147           5 : }
     148             : 
     149       26644 : TEST(CachedAccessorOnGlobalObject) {
     150           5 :   i::FLAG_allow_natives_syntax = true;
     151           5 :   LocalContext env;
     152           5 :   v8::Isolate* isolate = env->GetIsolate();
     153          10 :   v8::HandleScope scope(isolate);
     154             : 
     155             :   v8::Local<v8::FunctionTemplate> templ =
     156           5 :       v8::FunctionTemplate::New(CcTest::isolate());
     157           5 :   v8::Local<v8::ObjectTemplate> object_template = templ->InstanceTemplate();
     158             :   v8::Local<v8::Private> priv =
     159           5 :       v8::Private::ForApi(isolate, v8_str("Foo#draft"));
     160             : 
     161          10 :   object_template->SetAccessorProperty(
     162             :       v8_str("draft"),
     163             :       v8::FunctionTemplate::NewWithCache(isolate, UnreachableCallback, priv,
     164           5 :                                          v8::Local<v8::Value>()));
     165             : 
     166             :   v8::Local<v8::Context> ctx =
     167           5 :       v8::Context::New(CcTest::isolate(), nullptr, object_template);
     168           5 :   v8::Local<v8::Object> obj = ctx->Global();
     169             : 
     170             :   // Install the private property on the instance.
     171          10 :   CHECK(obj->SetPrivate(isolate->GetCurrentContext(), priv,
     172             :                         v8::Undefined(isolate))
     173             :             .FromJust());
     174             : 
     175             :   {
     176             :     v8::Context::Scope context_scope(ctx);
     177             : 
     178             :     // Access surrogate accessor.
     179           5 :     ExpectUndefined("draft");
     180             : 
     181             :     // Set hidden property.
     182          15 :     CHECK(obj->SetPrivate(env.local(), priv, v8::Integer::New(isolate, 123))
     183             :               .FromJust());
     184             : 
     185             :     // Test ICs.
     186             :     CompileRun(
     187             :         "function f() {"
     188             :         "  var x;"
     189             :         "  for (var i = 0; i < 100; i++) {"
     190             :         "    x = draft;"
     191             :         "  }"
     192             :         "  return x;"
     193             :         "}");
     194             : 
     195           5 :     ExpectInt32("f()", 123);
     196             : 
     197             :     // Reset hidden property.
     198          15 :     CHECK(obj->SetPrivate(env.local(), priv, v8::Integer::New(isolate, 456))
     199             :               .FromJust());
     200             : 
     201             :     // Test TurboFan.
     202             :     CompileRun("%OptimizeFunctionOnNextCall(f);");
     203             : 
     204           5 :     ExpectInt32("f()", 456);
     205             : 
     206          15 :     CHECK(obj->SetPrivate(env.local(), priv, v8::Integer::New(isolate, 456))
     207             :               .FromJust());
     208             :     // Test non-global ICs.
     209             :     CompileRun(
     210             :         "var x = this;"
     211             :         "function g() {"
     212             :         "  var r = 0;"
     213             :         "  for (var i = 0; i < 100; i++) {"
     214             :         "    r = x.draft;"
     215             :         "  }"
     216             :         "  return r;"
     217             :         "}");
     218             : 
     219           5 :     ExpectInt32("g()", 456);
     220             : 
     221             :     // Reset hidden property.
     222          15 :     CHECK(obj->SetPrivate(env.local(), priv, v8::Integer::New(isolate, 789))
     223             :               .FromJust());
     224             : 
     225             :     // Test non-global access in TurboFan.
     226             :     CompileRun("%OptimizeFunctionOnNextCall(g);");
     227             : 
     228           5 :     ExpectInt32("g()", 789);
     229             :   }
     230           5 : }
     231             : 
     232             : namespace {
     233             : 
     234             : // Getter return value should be non-null to trigger lazy property paths.
     235          50 : static void Getter(v8::Local<v8::Name> name,
     236             :                    const v8::PropertyCallbackInfo<v8::Value>& info) {
     237          50 :   info.GetReturnValue().Set(v8_str("return value"));
     238          50 : }
     239             : 
     240          10 : static void StringGetter(v8::Local<v8::String> name,
     241          10 :                          const v8::PropertyCallbackInfo<v8::Value>& info) {}
     242             : 
     243             : static int set_accessor_call_count = 0;
     244             : 
     245           5 : static void Setter(v8::Local<v8::Name> name, v8::Local<v8::Value> value,
     246             :                    const v8::PropertyCallbackInfo<void>& info) {
     247           5 :   set_accessor_call_count++;
     248           5 : }
     249             : }  // namespace
     250             : 
     251             : // Re-declaration of non-configurable accessors should throw.
     252       26644 : TEST(RedeclareAccessor) {
     253          10 :   v8::HandleScope scope(CcTest::isolate());
     254           5 :   LocalContext env;
     255             : 
     256             :   v8::Local<v8::FunctionTemplate> templ =
     257           5 :       v8::FunctionTemplate::New(CcTest::isolate());
     258             : 
     259           5 :   v8::Local<v8::ObjectTemplate> object_template = templ->InstanceTemplate();
     260          10 :   object_template->SetAccessor(
     261             :       v8_str("foo"), nullptr, Setter, v8::Local<v8::Value>(),
     262           5 :       v8::AccessControl::DEFAULT, v8::PropertyAttribute::DontDelete);
     263             : 
     264             :   v8::Local<v8::Context> ctx =
     265           5 :       v8::Context::New(CcTest::isolate(), nullptr, object_template);
     266             : 
     267             :   // Declare function.
     268           5 :   v8::Local<v8::String> code = v8_str("function foo() {};");
     269             : 
     270          10 :   v8::TryCatch try_catch(CcTest::isolate());
     271          10 :   v8::Script::Compile(ctx, code).ToLocalChecked()->Run(ctx).IsEmpty();
     272           5 :   CHECK(try_catch.HasCaught());
     273           5 : }
     274             : 
     275             : // Accessors can be whitelisted as side-effect-free via SetAccessor.
     276       26644 : TEST(AccessorSetHasNoSideEffect) {
     277           5 :   LocalContext env;
     278           5 :   v8::Isolate* isolate = env->GetIsolate();
     279          10 :   v8::HandleScope scope(isolate);
     280           5 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
     281             : 
     282           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
     283           5 :   v8::Local<v8::Object> obj = templ->NewInstance(env.local()).ToLocalChecked();
     284          20 :   CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
     285          15 :   obj->SetAccessor(context, v8_str("foo"), Getter).ToChecked();
     286          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo"), true).IsEmpty());
     287             : 
     288          10 :   obj->SetAccessor(context, v8_str("foo"), Getter, nullptr,
     289             :                    v8::MaybeLocal<v8::Value>(), v8::AccessControl::DEFAULT,
     290             :                    v8::PropertyAttribute::None,
     291          10 :                    v8::SideEffectType::kHasNoSideEffect)
     292             :       .ToChecked();
     293           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo"), true).ToLocalChecked();
     294             : 
     295             :   // Check that setter is not whitelisted.
     296          10 :   v8::TryCatch try_catch(isolate);
     297          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo = 1"), true)
     298             :             .IsEmpty());
     299           5 :   CHECK(try_catch.HasCaught());
     300          15 :   CHECK_NE(1, v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo"), false)
     301             :                   .ToLocalChecked()
     302             :                   ->Int32Value(env.local())
     303             :                   .FromJust());
     304           5 :   CHECK_EQ(0, set_accessor_call_count);
     305           5 : }
     306             : 
     307             : // Set accessors can be whitelisted as side-effect-free via SetAccessor.
     308       26644 : TEST(SetAccessorSetSideEffectReceiverCheck1) {
     309           5 :   LocalContext env;
     310           5 :   v8::Isolate* isolate = env->GetIsolate();
     311          10 :   v8::HandleScope scope(isolate);
     312             : 
     313           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
     314           5 :   v8::Local<v8::Object> obj = templ->NewInstance(env.local()).ToLocalChecked();
     315          20 :   CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
     316          10 :   obj->SetAccessor(env.local(), v8_str("foo"), Getter, Setter,
     317             :                    v8::MaybeLocal<v8::Value>(), v8::AccessControl::DEFAULT,
     318             :                    v8::PropertyAttribute::None,
     319             :                    v8::SideEffectType::kHasNoSideEffect,
     320          10 :                    v8::SideEffectType::kHasSideEffectToReceiver)
     321             :       .ToChecked();
     322          20 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo"), true)
     323             :             .ToLocalChecked()
     324             :             ->Equals(env.local(), v8_str("return value"))
     325             :             .FromJust());
     326          10 :   v8::TryCatch try_catch(isolate);
     327          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo = 1"), true)
     328             :             .IsEmpty());
     329           5 :   CHECK(try_catch.HasCaught());
     330           5 :   CHECK_EQ(0, set_accessor_call_count);
     331           5 : }
     332             : 
     333          10 : static void ConstructCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
     334          10 : }
     335             : 
     336       26644 : TEST(SetAccessorSetSideEffectReceiverCheck2) {
     337           5 :   LocalContext env;
     338           5 :   v8::Isolate* isolate = env->GetIsolate();
     339          10 :   v8::HandleScope scope(isolate);
     340           5 :   i::FLAG_enable_one_shot_optimization = false;
     341             : 
     342             :   v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(
     343             :       isolate, ConstructCallback, v8::Local<v8::Value>(),
     344             :       v8::Local<v8::Signature>(), 0, v8::ConstructorBehavior::kAllow,
     345           5 :       v8::SideEffectType::kHasNoSideEffect);
     346          15 :   templ->InstanceTemplate()->SetAccessor(
     347             :       v8_str("bar"), Getter, Setter, v8::Local<v8::Value>(),
     348             :       v8::AccessControl::DEFAULT, v8::PropertyAttribute::None,
     349             :       v8::Local<v8::AccessorSignature>(),
     350             :       v8::SideEffectType::kHasSideEffectToReceiver,
     351           5 :       v8::SideEffectType::kHasSideEffectToReceiver);
     352          25 :   CHECK(env->Global()
     353             :             ->Set(env.local(), v8_str("f"),
     354             :                   templ->GetFunction(env.local()).ToLocalChecked())
     355             :             .FromJust());
     356          20 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("new f().bar"), true)
     357             :             .ToLocalChecked()
     358             :             ->Equals(env.local(), v8_str("return value"))
     359             :             .FromJust());
     360           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("new f().bar = 1"), true)
     361             :       .ToLocalChecked();
     362           5 :   CHECK_EQ(1, set_accessor_call_count);
     363           5 : }
     364             : 
     365             : // Accessors can be whitelisted as side-effect-free via SetNativeDataProperty.
     366       26644 : TEST(AccessorSetNativeDataPropertyHasNoSideEffect) {
     367           5 :   LocalContext env;
     368           5 :   v8::Isolate* isolate = env->GetIsolate();
     369          10 :   v8::HandleScope scope(isolate);
     370           5 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
     371             : 
     372           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
     373           5 :   v8::Local<v8::Object> obj = templ->NewInstance(env.local()).ToLocalChecked();
     374          20 :   CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
     375          15 :   obj->SetNativeDataProperty(context, v8_str("foo"), Getter).ToChecked();
     376          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo"), true).IsEmpty());
     377             : 
     378          10 :   obj->SetNativeDataProperty(
     379             :          context, v8_str("foo"), Getter, nullptr, v8::Local<v8::Value>(),
     380          10 :          v8::PropertyAttribute::None, v8::SideEffectType::kHasNoSideEffect)
     381             :       .ToChecked();
     382           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo"), true).ToLocalChecked();
     383             : 
     384             :   // Check that setter is not whitelisted.
     385          10 :   v8::TryCatch try_catch(isolate);
     386          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo = 1"), true)
     387             :             .IsEmpty());
     388           5 :   CHECK(try_catch.HasCaught());
     389          15 :   CHECK_NE(1, v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo"), false)
     390             :                   .ToLocalChecked()
     391             :                   ->Int32Value(env.local())
     392             :                   .FromJust());
     393           5 : }
     394             : 
     395             : // Accessors can be whitelisted as side-effect-free via SetLazyDataProperty.
     396       26644 : TEST(AccessorSetLazyDataPropertyHasNoSideEffect) {
     397           5 :   LocalContext env;
     398           5 :   v8::Isolate* isolate = env->GetIsolate();
     399          10 :   v8::HandleScope scope(isolate);
     400           5 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
     401             : 
     402           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
     403           5 :   v8::Local<v8::Object> obj = templ->NewInstance(env.local()).ToLocalChecked();
     404          20 :   CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
     405          15 :   obj->SetLazyDataProperty(context, v8_str("foo"), Getter).ToChecked();
     406          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo"), true).IsEmpty());
     407             : 
     408          10 :   obj->SetLazyDataProperty(context, v8_str("foo"), Getter,
     409             :                            v8::Local<v8::Value>(), v8::PropertyAttribute::None,
     410          10 :                            v8::SideEffectType::kHasNoSideEffect)
     411             :       .ToChecked();
     412           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo"), true).ToLocalChecked();
     413             : 
     414             :   // Check that setter is not whitelisted.
     415          10 :   v8::TryCatch try_catch(isolate);
     416          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo = 1"), true)
     417             :             .IsEmpty());
     418           5 :   CHECK(try_catch.HasCaught());
     419          15 :   CHECK_NE(1, v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo"), false)
     420             :                   .ToLocalChecked()
     421             :                   ->Int32Value(env.local())
     422             :                   .FromJust());
     423           5 : }
     424             : 
     425       26644 : TEST(ObjectTemplateSetAccessorHasNoSideEffect) {
     426           5 :   LocalContext env;
     427           5 :   v8::Isolate* isolate = env->GetIsolate();
     428          10 :   v8::HandleScope scope(isolate);
     429             : 
     430           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
     431           5 :   templ->SetAccessor(v8_str("foo"), StringGetter);
     432          10 :   templ->SetAccessor(
     433             :       v8_str("foo2"), StringGetter, nullptr, v8::Local<v8::Value>(),
     434             :       v8::AccessControl::DEFAULT, v8::PropertyAttribute::None,
     435           5 :       v8::Local<v8::AccessorSignature>(), v8::SideEffectType::kHasNoSideEffect);
     436           5 :   v8::Local<v8::Object> obj = templ->NewInstance(env.local()).ToLocalChecked();
     437          20 :   CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
     438             : 
     439          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo"), true).IsEmpty());
     440           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo2"), true).ToLocalChecked();
     441             : 
     442             :   // Check that setter is not whitelisted.
     443          10 :   v8::TryCatch try_catch(isolate);
     444          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo2 = 1"), true)
     445             :             .IsEmpty());
     446           5 :   CHECK(try_catch.HasCaught());
     447          15 :   CHECK_NE(1, v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo2"), false)
     448             :                   .ToLocalChecked()
     449             :                   ->Int32Value(env.local())
     450             :                   .FromJust());
     451           5 : }
     452             : 
     453       26644 : TEST(ObjectTemplateSetNativePropertyHasNoSideEffect) {
     454           5 :   LocalContext env;
     455           5 :   v8::Isolate* isolate = env->GetIsolate();
     456          10 :   v8::HandleScope scope(isolate);
     457             : 
     458           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
     459          10 :   templ->SetNativeDataProperty(v8_str("foo"), Getter);
     460          10 :   templ->SetNativeDataProperty(
     461             :       v8_str("foo2"), Getter, nullptr, v8::Local<v8::Value>(),
     462             :       v8::PropertyAttribute::None, v8::Local<v8::AccessorSignature>(),
     463           5 :       v8::AccessControl::DEFAULT, v8::SideEffectType::kHasNoSideEffect);
     464           5 :   v8::Local<v8::Object> obj = templ->NewInstance(env.local()).ToLocalChecked();
     465          20 :   CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
     466             : 
     467          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo"), true).IsEmpty());
     468           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo2"), true).ToLocalChecked();
     469             : 
     470             :   // Check that setter is not whitelisted.
     471          10 :   v8::TryCatch try_catch(isolate);
     472          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo2 = 1"), true)
     473             :             .IsEmpty());
     474           5 :   CHECK(try_catch.HasCaught());
     475          15 :   CHECK_NE(1, v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo2"), false)
     476             :                   .ToLocalChecked()
     477             :                   ->Int32Value(env.local())
     478             :                   .FromJust());
     479           5 : }
     480             : 
     481       26644 : TEST(ObjectTemplateSetLazyPropertyHasNoSideEffect) {
     482           5 :   LocalContext env;
     483           5 :   v8::Isolate* isolate = env->GetIsolate();
     484          10 :   v8::HandleScope scope(isolate);
     485             : 
     486           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
     487          10 :   templ->SetLazyDataProperty(v8_str("foo"), Getter);
     488          10 :   templ->SetLazyDataProperty(v8_str("foo2"), Getter, v8::Local<v8::Value>(),
     489             :                              v8::PropertyAttribute::None,
     490           5 :                              v8::SideEffectType::kHasNoSideEffect);
     491           5 :   v8::Local<v8::Object> obj = templ->NewInstance(env.local()).ToLocalChecked();
     492          20 :   CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
     493             : 
     494          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo"), true).IsEmpty());
     495           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo2"), true).ToLocalChecked();
     496             : 
     497             :   // Check that setter is not whitelisted.
     498          10 :   v8::TryCatch try_catch(isolate);
     499          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo2 = 1"), true)
     500             :             .IsEmpty());
     501           5 :   CHECK(try_catch.HasCaught());
     502          15 :   CHECK_NE(1, v8::debug::EvaluateGlobal(isolate, v8_str("obj.foo2"), false)
     503             :                   .ToLocalChecked()
     504             :                   ->Int32Value(env.local())
     505             :                   .FromJust());
     506       79922 : }

Generated by: LCOV version 1.10