LCOV - code coverage report
Current view: top level - test/cctest - test-accessors.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 430 432 99.5 %
Date: 2019-01-20 Functions: 50 52 96.2 %

          Line data    Source code
       1             : // Copyright 2012 the V8 project authors. All rights reserved.
       2             : // Redistribution and use in source and binary forms, with or without
       3             : // modification, are permitted provided that the following conditions are
       4             : // met:
       5             : //
       6             : //     * Redistributions of source code must retain the above copyright
       7             : //       notice, this list of conditions and the following disclaimer.
       8             : //     * Redistributions in binary form must reproduce the above
       9             : //       copyright notice, this list of conditions and the following
      10             : //       disclaimer in the documentation and/or other materials provided
      11             : //       with the distribution.
      12             : //     * Neither the name of Google Inc. nor the names of its
      13             : //       contributors may be used to endorse or promote products derived
      14             : //       from this software without specific prior written permission.
      15             : //
      16             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      17             : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      18             : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      19             : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      20             : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      21             : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      22             : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      23             : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      24             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      25             : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      26             : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      27             : 
      28             : #include <stdlib.h>
      29             : 
      30             : #include "src/v8.h"
      31             : 
      32             : #include "src/api-inl.h"
      33             : #include "src/frames-inl.h"
      34             : #include "src/string-stream.h"
      35             : #include "test/cctest/cctest.h"
      36             : 
      37             : using ::v8::ObjectTemplate;
      38             : using ::v8::Value;
      39             : using ::v8::Context;
      40             : using ::v8::Local;
      41             : using ::v8::Name;
      42             : using ::v8::String;
      43             : using ::v8::Script;
      44             : using ::v8::Function;
      45             : using ::v8::Extension;
      46             : 
      47          24 : static void handle_property(Local<String> name,
      48             :                             const v8::PropertyCallbackInfo<v8::Value>& info) {
      49          24 :   ApiTestFuzzer::Fuzz();
      50          24 :   info.GetReturnValue().Set(v8_num(900));
      51          24 : }
      52             : 
      53          24 : static void handle_property_2(Local<String> name,
      54             :                               const v8::PropertyCallbackInfo<v8::Value>& info) {
      55          24 :   ApiTestFuzzer::Fuzz();
      56          24 :   info.GetReturnValue().Set(v8_num(902));
      57          24 : }
      58             : 
      59             : 
      60         309 : static void handle_property(const v8::FunctionCallbackInfo<v8::Value>& info) {
      61         103 :   ApiTestFuzzer::Fuzz();
      62         103 :   CHECK_EQ(0, info.Length());
      63         103 :   info.GetReturnValue().Set(v8_num(907));
      64         103 : }
      65             : 
      66             : 
      67       28343 : THREADED_TEST(PropertyHandler) {
      68           6 :   LocalContext env;
      69           6 :   v8::Isolate* isolate = env->GetIsolate();
      70          12 :   v8::HandleScope scope(isolate);
      71           6 :   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
      72          12 :   fun_templ->InstanceTemplate()->SetAccessor(v8_str("foo"), handle_property);
      73             :   Local<v8::FunctionTemplate> getter_templ =
      74           6 :       v8::FunctionTemplate::New(isolate, handle_property);
      75           6 :   getter_templ->SetLength(0);
      76             :   fun_templ->
      77          18 :       InstanceTemplate()->SetAccessorProperty(v8_str("bar"), getter_templ);
      78          12 :   fun_templ->InstanceTemplate()->
      79          18 :       SetNativeDataProperty(v8_str("instance_foo"), handle_property);
      80           6 :   fun_templ->SetNativeDataProperty(v8_str("object_foo"), handle_property_2);
      81           6 :   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
      82          30 :   CHECK(env->Global()->Set(env.local(), v8_str("Fun"), fun).FromJust());
      83             :   Local<Script> getter;
      84             :   Local<Script> setter;
      85             :   // check function instance accessors
      86             :   getter = v8_compile("var obj = new Fun(); obj.instance_foo;");
      87          30 :   for (int i = 0; i < 4; i++) {
      88          72 :     CHECK_EQ(900, getter->Run(env.local())
      89             :                       .ToLocalChecked()
      90             :                       ->Int32Value(env.local())
      91             :                       .FromJust());
      92             :   }
      93             :   setter = v8_compile("obj.instance_foo = 901;");
      94          30 :   for (int i = 0; i < 4; i++) {
      95          72 :     CHECK_EQ(901, setter->Run(env.local())
      96             :                       .ToLocalChecked()
      97             :                       ->Int32Value(env.local())
      98             :                       .FromJust());
      99             :   }
     100             :   getter = v8_compile("obj.bar;");
     101          30 :   for (int i = 0; i < 4; i++) {
     102          72 :     CHECK_EQ(907, getter->Run(env.local())
     103             :                       .ToLocalChecked()
     104             :                       ->Int32Value(env.local())
     105             :                       .FromJust());
     106             :   }
     107             :   setter = v8_compile("obj.bar = 908;");
     108          30 :   for (int i = 0; i < 4; i++) {
     109          72 :     CHECK_EQ(908, setter->Run(env.local())
     110             :                       .ToLocalChecked()
     111             :                       ->Int32Value(env.local())
     112             :                       .FromJust());
     113             :   }
     114             :   // check function static accessors
     115             :   getter = v8_compile("Fun.object_foo;");
     116          30 :   for (int i = 0; i < 4; i++) {
     117          72 :     CHECK_EQ(902, getter->Run(env.local())
     118             :                       .ToLocalChecked()
     119             :                       ->Int32Value(env.local())
     120             :                       .FromJust());
     121             :   }
     122             :   setter = v8_compile("Fun.object_foo = 903;");
     123          30 :   for (int i = 0; i < 4; i++) {
     124          72 :     CHECK_EQ(903, setter->Run(env.local())
     125             :                       .ToLocalChecked()
     126             :                       ->Int32Value(env.local())
     127             :                       .FromJust());
     128             :   }
     129             : 
     130             :   // And now with null prototype.
     131           6 :   CompileRun(env.local(), "obj.__proto__ = null;");
     132             :   getter = v8_compile("obj.bar;");
     133          30 :   for (int i = 0; i < 4; i++) {
     134          72 :     CHECK_EQ(907, getter->Run(env.local())
     135             :                       .ToLocalChecked()
     136             :                       ->Int32Value(env.local())
     137             :                       .FromJust());
     138             :   }
     139             :   setter = v8_compile("obj.bar = 908;");
     140          30 :   for (int i = 0; i < 4; i++) {
     141          72 :     CHECK_EQ(908, setter->Run(env.local())
     142             :                       .ToLocalChecked()
     143             :                       ->Int32Value(env.local())
     144             :                       .FromJust());
     145           6 :   }
     146           6 : }
     147             : 
     148             : 
     149          12 : static void GetIntValue(Local<String> property,
     150             :                         const v8::PropertyCallbackInfo<v8::Value>& info) {
     151          12 :   ApiTestFuzzer::Fuzz();
     152             :   int* value =
     153          12 :       static_cast<int*>(v8::Local<v8::External>::Cast(info.Data())->Value());
     154          12 :   info.GetReturnValue().Set(v8_num(*value));
     155          12 : }
     156             : 
     157             : 
     158          12 : static void SetIntValue(Local<String> property,
     159             :                         Local<Value> value,
     160             :                         const v8::PropertyCallbackInfo<void>& info) {
     161             :   int* field =
     162          12 :       static_cast<int*>(v8::Local<v8::External>::Cast(info.Data())->Value());
     163          36 :   *field = value->Int32Value(info.GetIsolate()->GetCurrentContext()).FromJust();
     164          12 : }
     165             : 
     166             : int foo, bar, baz;
     167             : 
     168       28343 : THREADED_TEST(GlobalVariableAccess) {
     169           6 :   foo = 0;
     170           6 :   bar = -4;
     171           6 :   baz = 10;
     172           6 :   v8::Isolate* isolate = CcTest::isolate();
     173           6 :   v8::HandleScope scope(isolate);
     174           6 :   v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
     175             :   templ->InstanceTemplate()->SetAccessor(
     176             :       v8_str("foo"), GetIntValue, SetIntValue,
     177          18 :       v8::External::New(isolate, &foo));
     178             :   templ->InstanceTemplate()->SetAccessor(
     179             :       v8_str("bar"), GetIntValue, SetIntValue,
     180          12 :       v8::External::New(isolate, &bar));
     181             :   templ->InstanceTemplate()->SetAccessor(
     182             :       v8_str("baz"), GetIntValue, SetIntValue,
     183          12 :       v8::External::New(isolate, &baz));
     184          12 :   LocalContext env(nullptr, templ->InstanceTemplate());
     185          12 :   v8_compile("foo = (++bar) + baz")->Run(env.local()).ToLocalChecked();
     186           6 :   CHECK_EQ(-3, bar);
     187          12 :   CHECK_EQ(7, foo);
     188           6 : }
     189             : 
     190             : 
     191             : static int x_register[2] = {0, 0};
     192             : static v8::Local<v8::Object> x_receiver;
     193             : static v8::Local<v8::Object> x_holder;
     194             : 
     195             : template<class Info>
     196         600 : static void XGetter(const Info& info, int offset) {
     197         240 :   ApiTestFuzzer::Fuzz();
     198         240 :   v8::Isolate* isolate = CcTest::isolate();
     199         240 :   CHECK_EQ(isolate, info.GetIsolate());
     200         720 :   CHECK(
     201             :       x_receiver->Equals(isolate->GetCurrentContext(), info.This()).FromJust());
     202         240 :   info.GetReturnValue().Set(v8_num(x_register[offset]));
     203         240 : }
     204             : 
     205             : 
     206         120 : static void XGetter(Local<String> name,
     207             :                     const v8::PropertyCallbackInfo<v8::Value>& info) {
     208         360 :   CHECK(x_holder->Equals(info.GetIsolate()->GetCurrentContext(), info.Holder())
     209             :             .FromJust());
     210         120 :   XGetter(info, 0);
     211         120 : }
     212             : 
     213             : 
     214         120 : static void XGetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
     215         360 :   CHECK(
     216             :       x_receiver->Equals(info.GetIsolate()->GetCurrentContext(), info.Holder())
     217             :           .FromJust());
     218         120 :   XGetter(info, 1);
     219         120 : }
     220             : 
     221             : 
     222             : template<class Info>
     223         840 : static void XSetter(Local<Value> value, const Info& info, int offset) {
     224         240 :   v8::Isolate* isolate = CcTest::isolate();
     225         240 :   CHECK_EQ(isolate, info.GetIsolate());
     226         720 :   CHECK(x_holder->Equals(info.GetIsolate()->GetCurrentContext(), info.This())
     227             :             .FromJust());
     228         720 :   CHECK(x_holder->Equals(info.GetIsolate()->GetCurrentContext(), info.Holder())
     229             :             .FromJust());
     230         720 :   x_register[offset] =
     231             :       value->Int32Value(info.GetIsolate()->GetCurrentContext()).FromJust();
     232         240 :   info.GetReturnValue().Set(v8_num(-1));
     233         240 : }
     234             : 
     235             : 
     236         120 : static void XSetter(Local<String> name,
     237             :                     Local<Value> value,
     238             :                     const v8::PropertyCallbackInfo<void>& info) {
     239         120 :   XSetter(value, info, 0);
     240         120 : }
     241             : 
     242             : 
     243         120 : static void XSetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
     244         120 :   CHECK_EQ(1, info.Length());
     245         120 :   XSetter(info[0], info, 1);
     246         120 : }
     247             : 
     248             : 
     249       28343 : THREADED_TEST(AccessorIC) {
     250           6 :   LocalContext context;
     251           6 :   v8::Isolate* isolate = context->GetIsolate();
     252          12 :   v8::HandleScope scope(isolate);
     253           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
     254           6 :   obj->SetAccessor(v8_str("x0"), XGetter, XSetter);
     255             :   obj->SetAccessorProperty(v8_str("x1"),
     256             :                            v8::FunctionTemplate::New(isolate, XGetter),
     257          18 :                            v8::FunctionTemplate::New(isolate, XSetter));
     258          12 :   x_holder = obj->NewInstance(context.local()).ToLocalChecked();
     259          30 :   CHECK(context->Global()
     260             :             ->Set(context.local(), v8_str("holder"), x_holder)
     261             :             .FromJust());
     262           6 :   x_receiver = v8::Object::New(isolate);
     263          30 :   CHECK(context->Global()
     264             :             ->Set(context.local(), v8_str("obj"), x_receiver)
     265             :             .FromJust());
     266             :   v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(
     267             :       CompileRun("obj.__proto__ = holder;"
     268             :                  "var result = [];"
     269             :                  "var key_0 = 'x0';"
     270             :                  "var key_1 = 'x1';"
     271             :                  "for (var j = 0; j < 10; j++) {"
     272             :                  "  var i = 4*j;"
     273             :                  "  result.push(holder.x0 = i);"
     274             :                  "  result.push(obj.x0);"
     275             :                  "  result.push(holder.x1 = i + 1);"
     276             :                  "  result.push(obj.x1);"
     277             :                  "  result.push(holder[key_0] = i + 2);"
     278             :                  "  result.push(obj[key_0]);"
     279             :                  "  result.push(holder[key_1] = i + 3);"
     280             :                  "  result.push(obj[key_1]);"
     281             :                  "}"
     282             :                  "result"));
     283           6 :   CHECK_EQ(80u, array->Length());
     284         480 :   for (int i = 0; i < 80; i++) {
     285             :     v8::Local<Value> entry =
     286        1440 :         array->Get(context.local(), v8::Integer::New(isolate, i))
     287         960 :             .ToLocalChecked();
     288        1440 :     CHECK(v8::Integer::New(isolate, i / 2)
     289             :               ->Equals(context.local(), entry)
     290             :               .FromJust());
     291           6 :   }
     292           6 : }
     293             : 
     294             : 
     295             : template <int C>
     296       12000 : static void HandleAllocatingGetter(
     297             :     Local<String> name,
     298             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
     299       12000 :   ApiTestFuzzer::Fuzz();
     300     6162000 :   for (int i = 0; i < C; i++) {
     301             :     v8::String::NewFromUtf8(info.GetIsolate(), "foo",
     302             :                             v8::NewStringType::kNormal)
     303     6150000 :         .ToLocalChecked();
     304             :   }
     305             :   info.GetReturnValue().Set(v8::String::NewFromUtf8(info.GetIsolate(), "foo",
     306             :                                                     v8::NewStringType::kNormal)
     307       12000 :                                 .ToLocalChecked());
     308       12000 : }
     309             : 
     310             : 
     311       28343 : THREADED_TEST(HandleScopePop) {
     312           6 :   LocalContext context;
     313           6 :   v8::Isolate* isolate = context->GetIsolate();
     314          12 :   v8::HandleScope scope(isolate);
     315           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
     316           6 :   obj->SetAccessor(v8_str("one"), HandleAllocatingGetter<1>);
     317           6 :   obj->SetAccessor(v8_str("many"), HandleAllocatingGetter<1024>);
     318             :   v8::Local<v8::Object> inst =
     319           6 :       obj->NewInstance(context.local()).ToLocalChecked();
     320          30 :   CHECK(
     321             :       context->Global()->Set(context.local(), v8_str("obj"), inst).FromJust());
     322             :   int count_before =
     323           6 :       i::HandleScope::NumberOfHandles(reinterpret_cast<i::Isolate*>(isolate));
     324             :   {
     325           6 :     v8::HandleScope scope(isolate);
     326             :     CompileRun(
     327             :         "for (var i = 0; i < 1000; i++) {"
     328             :         "  obj.one;"
     329             :         "  obj.many;"
     330           6 :         "}");
     331             :   }
     332             :   int count_after =
     333           6 :       i::HandleScope::NumberOfHandles(reinterpret_cast<i::Isolate*>(isolate));
     334          12 :   CHECK_EQ(count_before, count_after);
     335           6 : }
     336             : 
     337         264 : static void CheckAccessorArgsCorrect(
     338             :     Local<String> name,
     339             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
     340         264 :   CHECK(info.GetIsolate() == CcTest::isolate());
     341         264 :   CHECK(info.This() == info.Holder());
     342        1056 :   CHECK(info.Data()
     343             :             ->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("data"))
     344             :             .FromJust());
     345         264 :   ApiTestFuzzer::Fuzz();
     346         264 :   CHECK(info.GetIsolate() == CcTest::isolate());
     347         264 :   CHECK(info.This() == info.Holder());
     348        1056 :   CHECK(info.Data()
     349             :             ->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("data"))
     350             :             .FromJust());
     351         264 :   CcTest::CollectAllGarbage();
     352         264 :   CHECK(info.GetIsolate() == CcTest::isolate());
     353         264 :   CHECK(info.This() == info.Holder());
     354        1056 :   CHECK(info.Data()
     355             :             ->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("data"))
     356             :             .FromJust());
     357             :   info.GetReturnValue().Set(17);
     358         264 : }
     359             : 
     360             : 
     361       28343 : THREADED_TEST(DirectCall) {
     362           6 :   LocalContext context;
     363           6 :   v8::Isolate* isolate = context->GetIsolate();
     364          12 :   v8::HandleScope scope(isolate);
     365           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
     366             :   obj->SetAccessor(v8_str("xxx"), CheckAccessorArgsCorrect, nullptr,
     367          12 :                    v8_str("data"));
     368             :   v8::Local<v8::Object> inst =
     369           6 :       obj->NewInstance(context.local()).ToLocalChecked();
     370          30 :   CHECK(
     371             :       context->Global()->Set(context.local(), v8_str("obj"), inst).FromJust());
     372             :   Local<Script> scr =
     373           6 :       v8::Script::Compile(context.local(), v8_str("obj.xxx")).ToLocalChecked();
     374          60 :   for (int i = 0; i < 10; i++) {
     375          60 :     Local<Value> result = scr->Run(context.local()).ToLocalChecked();
     376          60 :     CHECK(!result.IsEmpty());
     377         120 :     CHECK_EQ(17, result->Int32Value(context.local()).FromJust());
     378           6 :   }
     379           6 : }
     380             : 
     381          72 : static void EmptyGetter(Local<String> name,
     382             :                         const v8::PropertyCallbackInfo<v8::Value>& info) {
     383          72 :   CheckAccessorArgsCorrect(name, info);
     384          72 :   ApiTestFuzzer::Fuzz();
     385          72 :   CheckAccessorArgsCorrect(name, info);
     386             :   info.GetReturnValue().Set(v8::Local<v8::Value>());
     387          72 : }
     388             : 
     389             : 
     390       28343 : THREADED_TEST(EmptyResult) {
     391           6 :   LocalContext context;
     392           6 :   v8::Isolate* isolate = context->GetIsolate();
     393          12 :   v8::HandleScope scope(isolate);
     394           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
     395          12 :   obj->SetAccessor(v8_str("xxx"), EmptyGetter, nullptr, v8_str("data"));
     396             :   v8::Local<v8::Object> inst =
     397           6 :       obj->NewInstance(context.local()).ToLocalChecked();
     398          30 :   CHECK(
     399             :       context->Global()->Set(context.local(), v8_str("obj"), inst).FromJust());
     400             :   Local<Script> scr =
     401           6 :       v8::Script::Compile(context.local(), v8_str("obj.xxx")).ToLocalChecked();
     402          60 :   for (int i = 0; i < 10; i++) {
     403          60 :     Local<Value> result = scr->Run(context.local()).ToLocalChecked();
     404          60 :     CHECK(result == v8::Undefined(isolate));
     405           6 :   }
     406           6 : }
     407             : 
     408             : 
     409       28343 : THREADED_TEST(NoReuseRegress) {
     410             :   // Check that the IC generated for the one test doesn't get reused
     411             :   // for the other.
     412           6 :   v8::Isolate* isolate = CcTest::isolate();
     413           6 :   v8::HandleScope scope(isolate);
     414             :   {
     415           6 :     v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
     416          12 :     obj->SetAccessor(v8_str("xxx"), EmptyGetter, nullptr, v8_str("data"));
     417           6 :     LocalContext context;
     418             :     v8::Local<v8::Object> inst =
     419           6 :         obj->NewInstance(context.local()).ToLocalChecked();
     420          30 :     CHECK(context->Global()
     421             :               ->Set(context.local(), v8_str("obj"), inst)
     422             :               .FromJust());
     423           6 :     Local<Script> scr = v8::Script::Compile(context.local(), v8_str("obj.xxx"))
     424           6 :                             .ToLocalChecked();
     425          12 :     for (int i = 0; i < 2; i++) {
     426          12 :       Local<Value> result = scr->Run(context.local()).ToLocalChecked();
     427          12 :       CHECK(result == v8::Undefined(isolate));
     428           6 :     }
     429             :   }
     430             :   {
     431           6 :     v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
     432             :     obj->SetAccessor(v8_str("xxx"), CheckAccessorArgsCorrect, nullptr,
     433          12 :                      v8_str("data"));
     434           6 :     LocalContext context;
     435             :     v8::Local<v8::Object> inst =
     436           6 :         obj->NewInstance(context.local()).ToLocalChecked();
     437          30 :     CHECK(context->Global()
     438             :               ->Set(context.local(), v8_str("obj"), inst)
     439             :               .FromJust());
     440           6 :     Local<Script> scr = v8::Script::Compile(context.local(), v8_str("obj.xxx"))
     441           6 :                             .ToLocalChecked();
     442          60 :     for (int i = 0; i < 10; i++) {
     443          60 :       Local<Value> result = scr->Run(context.local()).ToLocalChecked();
     444          60 :       CHECK(!result.IsEmpty());
     445         120 :       CHECK_EQ(17, result->Int32Value(context.local()).FromJust());
     446           6 :     }
     447           6 :   }
     448           6 : }
     449             : 
     450          30 : static void ThrowingGetAccessor(
     451             :     Local<String> name,
     452             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
     453          30 :   ApiTestFuzzer::Fuzz();
     454          60 :   info.GetIsolate()->ThrowException(v8_str("g"));
     455          30 : }
     456             : 
     457             : 
     458          30 : static void ThrowingSetAccessor(Local<String> name,
     459             :                                 Local<Value> value,
     460             :                                 const v8::PropertyCallbackInfo<void>& info) {
     461          30 :   info.GetIsolate()->ThrowException(value);
     462          30 : }
     463             : 
     464             : 
     465       28343 : THREADED_TEST(Regress1054726) {
     466           6 :   LocalContext env;
     467           6 :   v8::Isolate* isolate = env->GetIsolate();
     468          12 :   v8::HandleScope scope(isolate);
     469           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
     470             :   obj->SetAccessor(v8_str("x"),
     471             :                    ThrowingGetAccessor,
     472             :                    ThrowingSetAccessor,
     473           6 :                    Local<Value>());
     474             : 
     475          36 :   CHECK(env->Global()
     476             :             ->Set(env.local(), v8_str("obj"),
     477             :                   obj->NewInstance(env.local()).ToLocalChecked())
     478             :             .FromJust());
     479             : 
     480             :   // Use the throwing property setter/getter in a loop to force
     481             :   // the accessor ICs to be initialized.
     482             :   v8::Local<Value> result;
     483             :   result = Script::Compile(env.local(),
     484             :                            v8_str("var result = '';"
     485             :                                   "for (var i = 0; i < 5; i++) {"
     486             :                                   "  try { obj.x; } catch (e) { result += e; }"
     487           6 :                                   "}; result"))
     488           6 :                .ToLocalChecked()
     489           6 :                ->Run(env.local())
     490          12 :                .ToLocalChecked();
     491          18 :   CHECK(v8_str("ggggg")->Equals(env.local(), result).FromJust());
     492             : 
     493             :   result =
     494             :       Script::Compile(env.local(),
     495             :                       v8_str("var result = '';"
     496             :                              "for (var i = 0; i < 5; i++) {"
     497             :                              "  try { obj.x = i; } catch (e) { result += e; }"
     498           6 :                              "}; result"))
     499           6 :           .ToLocalChecked()
     500           6 :           ->Run(env.local())
     501          12 :           .ToLocalChecked();
     502          24 :   CHECK(v8_str("01234")->Equals(env.local(), result).FromJust());
     503           6 : }
     504             : 
     505             : 
     506       12288 : static void AllocGetter(Local<String> name,
     507             :                         const v8::PropertyCallbackInfo<v8::Value>& info) {
     508       12288 :   ApiTestFuzzer::Fuzz();
     509       12288 :   info.GetReturnValue().Set(v8::Array::New(info.GetIsolate(), 1000));
     510       12288 : }
     511             : 
     512             : 
     513       28343 : THREADED_TEST(Gc) {
     514           6 :   LocalContext env;
     515           6 :   v8::Isolate* isolate = env->GetIsolate();
     516          12 :   v8::HandleScope scope(isolate);
     517           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
     518           6 :   obj->SetAccessor(v8_str("xxx"), AllocGetter);
     519          36 :   CHECK(env->Global()
     520             :             ->Set(env.local(), v8_str("obj"),
     521             :                   obj->NewInstance(env.local()).ToLocalChecked())
     522             :             .FromJust());
     523             :   Script::Compile(env.local(), v8_str("var last = [];"
     524             :                                       "for (var i = 0; i < 2048; i++) {"
     525             :                                       "  var result = obj.xxx;"
     526             :                                       "  result[0] = last;"
     527             :                                       "  last = result;"
     528           6 :                                       "}"))
     529           6 :       .ToLocalChecked()
     530           6 :       ->Run(env.local())
     531          12 :       .ToLocalChecked();
     532           6 : }
     533             : 
     534             : 
     535         600 : static void StackCheck(Local<String> name,
     536             :                        const v8::PropertyCallbackInfo<v8::Value>& info) {
     537         600 :   i::StackFrameIterator iter(reinterpret_cast<i::Isolate*>(info.GetIsolate()));
     538        4100 :   for (int i = 0; !iter.done(); i++) {
     539             :     i::StackFrame* frame = iter.frame();
     540        3500 :     CHECK(i != 0 || (frame->type() == i::StackFrame::EXIT));
     541        3500 :     i::Code code = frame->LookupCode();
     542        3500 :     CHECK(code->IsCode());
     543        3500 :     CHECK(code->contains(frame->pc()));
     544        3500 :     iter.Advance();
     545             :   }
     546         600 : }
     547             : 
     548             : 
     549       28343 : THREADED_TEST(StackIteration) {
     550           6 :   LocalContext env;
     551           6 :   v8::Isolate* isolate = env->GetIsolate();
     552          12 :   v8::HandleScope scope(isolate);
     553           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
     554             :   i::StringStream::ClearMentionedObjectCache(
     555           6 :       reinterpret_cast<i::Isolate*>(isolate));
     556           6 :   obj->SetAccessor(v8_str("xxx"), StackCheck);
     557          36 :   CHECK(env->Global()
     558             :             ->Set(env.local(), v8_str("obj"),
     559             :                   obj->NewInstance(env.local()).ToLocalChecked())
     560             :             .FromJust());
     561             :   Script::Compile(env.local(), v8_str("function foo() {"
     562             :                                       "  return obj.xxx;"
     563             :                                       "}"
     564             :                                       "for (var i = 0; i < 100; i++) {"
     565             :                                       "  foo();"
     566           6 :                                       "}"))
     567           6 :       .ToLocalChecked()
     568           6 :       ->Run(env.local())
     569          12 :       .ToLocalChecked();
     570           6 : }
     571             : 
     572             : 
     573          24 : static void AllocateHandles(Local<String> name,
     574             :                             const v8::PropertyCallbackInfo<v8::Value>& info) {
     575       24576 :   for (int i = 0; i < i::kHandleBlockSize + 1; i++) {
     576             :     v8::Local<v8::Value>::New(info.GetIsolate(), name);
     577             :   }
     578          24 :   info.GetReturnValue().Set(v8::Integer::New(info.GetIsolate(), 100));
     579          24 : }
     580             : 
     581             : 
     582       28343 : THREADED_TEST(HandleScopeSegment) {
     583             :   // Check that we can return values past popping of handle scope
     584             :   // segments.
     585           6 :   LocalContext env;
     586           6 :   v8::Isolate* isolate = env->GetIsolate();
     587          12 :   v8::HandleScope scope(isolate);
     588           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
     589           6 :   obj->SetAccessor(v8_str("xxx"), AllocateHandles);
     590          36 :   CHECK(env->Global()
     591             :             ->Set(env.local(), v8_str("obj"),
     592             :                   obj->NewInstance(env.local()).ToLocalChecked())
     593             :             .FromJust());
     594             :   v8::Local<v8::Value> result =
     595             :       Script::Compile(env.local(), v8_str("var result;"
     596             :                                           "for (var i = 0; i < 4; i++)"
     597             :                                           "  result = obj.xxx;"
     598           6 :                                           "result;"))
     599           6 :           .ToLocalChecked()
     600           6 :           ->Run(env.local())
     601           6 :           .ToLocalChecked();
     602          18 :   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
     603           6 : }
     604             : 
     605             : 
     606           6 : void JSONStringifyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
     607           6 :   v8::Local<v8::Array> array = v8::Array::New(info.GetIsolate(), 1);
     608          24 :   CHECK(array->Set(info.GetIsolate()->GetCurrentContext(), 0, v8_str("regress"))
     609             :             .FromJust());
     610             :   info.GetReturnValue().Set(array);
     611           6 : }
     612             : 
     613             : 
     614           6 : void JSONStringifyGetter(Local<Name> name,
     615             :                          const v8::PropertyCallbackInfo<v8::Value>& info) {
     616           6 :   info.GetReturnValue().Set(v8_str("crbug-161028"));
     617           6 : }
     618             : 
     619             : 
     620       28343 : THREADED_TEST(JSONStringifyNamedInterceptorObject) {
     621           6 :   LocalContext env;
     622           6 :   v8::Isolate* isolate = env->GetIsolate();
     623          12 :   v8::HandleScope scope(isolate);
     624             : 
     625           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
     626             :   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(
     627           6 :       JSONStringifyGetter, nullptr, nullptr, nullptr, JSONStringifyEnumerator));
     628          36 :   CHECK(env->Global()
     629             :             ->Set(env.local(), v8_str("obj"),
     630             :                   obj->NewInstance(env.local()).ToLocalChecked())
     631             :             .FromJust());
     632           6 :   v8::Local<v8::String> expected = v8_str("{\"regress\":\"crbug-161028\"}");
     633          18 :   CHECK(CompileRun("JSON.stringify(obj)")
     634             :             ->Equals(env.local(), expected)
     635           6 :             .FromJust());
     636           6 : }
     637             : 
     638             : 
     639             : static v8::Local<v8::Context> expected_current_context;
     640             : 
     641             : 
     642         120 : static void check_contexts(const v8::FunctionCallbackInfo<v8::Value>& info) {
     643          60 :   ApiTestFuzzer::Fuzz();
     644         120 :   CHECK(expected_current_context == info.GetIsolate()->GetCurrentContext());
     645          60 : }
     646             : 
     647             : 
     648       28343 : THREADED_TEST(AccessorPropertyCrossContext) {
     649           6 :   LocalContext env;
     650           6 :   v8::Isolate* isolate = env->GetIsolate();
     651          12 :   v8::HandleScope scope(isolate);
     652             :   v8::Local<v8::Function> fun =
     653          12 :       v8::Function::New(env.local(), check_contexts).ToLocalChecked();
     654          12 :   LocalContext switch_context;
     655          30 :   CHECK(switch_context->Global()
     656             :             ->Set(switch_context.local(), v8_str("fun"), fun)
     657             :             .FromJust());
     658          12 :   v8::TryCatch try_catch(isolate);
     659           6 :   expected_current_context = env.local();
     660             :   CompileRun(
     661             :       "var o = Object.create(null, { n: { get:fun } });"
     662             :       "for (var i = 0; i < 10; i++) o.n;");
     663          12 :   CHECK(!try_catch.HasCaught());
     664           6 : }
     665             : 
     666             : 
     667       28343 : THREADED_TEST(GlobalObjectAccessor) {
     668           6 :   LocalContext env;
     669           6 :   v8::Isolate* isolate = env->GetIsolate();
     670          12 :   v8::HandleScope scope(isolate);
     671             :   CompileRun(
     672             :       "var set_value = 1;"
     673             :       "Object.defineProperty(this.__proto__, 'x', {"
     674             :       "    get : function() { return this; },"
     675             :       "    set : function() { set_value = this; }"
     676             :       "});"
     677             :       "function getter() { return x; }"
     678             :       "function setter() { x = 1; }");
     679             : 
     680             :   Local<Script> check_getter = v8_compile("getter()");
     681             :   Local<Script> check_setter = v8_compile("setter(); set_value");
     682             : 
     683             :   // Ensure that LoadGlobalICs in getter and StoreGlobalICs setter get
     684             :   // JSGlobalProxy as a receiver regardless of the current IC state and
     685             :   // the order in which ICs are executed.
     686          66 :   for (int i = 0; i < 10; i++) {
     687         180 :     CHECK(
     688             :         v8::Utils::OpenHandle(*check_getter->Run(env.local()).ToLocalChecked())
     689             :             ->IsJSGlobalProxy());
     690             :   }
     691          60 :   for (int i = 0; i < 10; i++) {
     692         180 :     CHECK(
     693             :         v8::Utils::OpenHandle(*check_setter->Run(env.local()).ToLocalChecked())
     694             :             ->IsJSGlobalProxy());
     695             :   }
     696          60 :   for (int i = 0; i < 10; i++) {
     697         180 :     CHECK(
     698             :         v8::Utils::OpenHandle(*check_getter->Run(env.local()).ToLocalChecked())
     699             :             ->IsJSGlobalProxy());
     700         180 :     CHECK(
     701             :         v8::Utils::OpenHandle(*check_setter->Run(env.local()).ToLocalChecked())
     702             :             ->IsJSGlobalProxy());
     703           6 :   }
     704           6 : }
     705             : 
     706             : 
     707          12 : static void EmptyGetter(Local<Name> name,
     708             :                         const v8::PropertyCallbackInfo<v8::Value>& info) {
     709          12 :   ApiTestFuzzer::Fuzz();
     710          12 : }
     711             : 
     712             : 
     713           6 : static void OneProperty(Local<String> name,
     714             :                         const v8::PropertyCallbackInfo<v8::Value>& info) {
     715           6 :   ApiTestFuzzer::Fuzz();
     716           6 :   info.GetReturnValue().Set(v8_num(1));
     717           6 : }
     718             : 
     719             : 
     720       28343 : THREADED_TEST(Regress433458) {
     721           6 :   LocalContext env;
     722           6 :   v8::Isolate* isolate = env->GetIsolate();
     723          12 :   v8::HandleScope scope(isolate);
     724           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
     725           6 :   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(EmptyGetter));
     726           6 :   obj->SetNativeDataProperty(v8_str("prop"), OneProperty);
     727          36 :   CHECK(env->Global()
     728             :             ->Set(env.local(), v8_str("obj"),
     729             :                   obj->NewInstance(env.local()).ToLocalChecked())
     730             :             .FromJust());
     731             :   CompileRun(
     732             :       "Object.defineProperty(obj, 'prop', { writable: false });"
     733           6 :       "Object.defineProperty(obj, 'prop', { writable: true });");
     734           6 : }
     735             : 
     736             : 
     737             : static bool security_check_value = false;
     738             : 
     739         125 : static bool SecurityTestCallback(Local<v8::Context> accessing_context,
     740             :                                  Local<v8::Object> accessed_object,
     741             :                                  Local<v8::Value> data) {
     742         125 :   return security_check_value;
     743             : }
     744             : 
     745             : 
     746       28342 : TEST(PrototypeGetterAccessCheck) {
     747           5 :   i::FLAG_allow_natives_syntax = true;
     748           5 :   LocalContext env;
     749           5 :   v8::Isolate* isolate = env->GetIsolate();
     750          10 :   v8::HandleScope scope(isolate);
     751           5 :   auto fun_templ = v8::FunctionTemplate::New(isolate);
     752           5 :   auto getter_templ = v8::FunctionTemplate::New(isolate, handle_property);
     753           5 :   getter_templ->SetAcceptAnyReceiver(false);
     754          10 :   fun_templ->InstanceTemplate()->SetAccessorProperty(v8_str("foo"),
     755          15 :                                                      getter_templ);
     756           5 :   auto obj_templ = v8::ObjectTemplate::New(isolate);
     757           5 :   obj_templ->SetAccessCheckCallback(SecurityTestCallback);
     758          30 :   CHECK(env->Global()
     759             :             ->Set(env.local(), v8_str("Fun"),
     760             :                   fun_templ->GetFunction(env.local()).ToLocalChecked())
     761             :             .FromJust());
     762          30 :   CHECK(env->Global()
     763             :             ->Set(env.local(), v8_str("obj"),
     764             :                   obj_templ->NewInstance(env.local()).ToLocalChecked())
     765             :             .FromJust());
     766          30 :   CHECK(env->Global()
     767             :             ->Set(env.local(), v8_str("obj2"),
     768             :                   obj_templ->NewInstance(env.local()).ToLocalChecked())
     769             :             .FromJust());
     770             : 
     771           5 :   security_check_value = true;
     772             :   CompileRun("var proto = new Fun();");
     773             :   CompileRun("obj.__proto__ = proto;");
     774           5 :   ExpectInt32("proto.foo", 907);
     775             : 
     776             :   // Test direct.
     777           5 :   security_check_value = true;
     778           5 :   ExpectInt32("obj.foo", 907);
     779           5 :   security_check_value = false;
     780             :   {
     781           5 :     v8::TryCatch try_catch(isolate);
     782             :     CompileRun("obj.foo");
     783           5 :     CHECK(try_catch.HasCaught());
     784             :   }
     785             : 
     786             :   // Test through call.
     787           5 :   security_check_value = true;
     788           5 :   ExpectInt32("proto.__lookupGetter__('foo').call(obj)", 907);
     789           5 :   security_check_value = false;
     790             :   {
     791           5 :     v8::TryCatch try_catch(isolate);
     792             :     CompileRun("proto.__lookupGetter__('foo').call(obj)");
     793           5 :     CHECK(try_catch.HasCaught());
     794             :   }
     795             : 
     796             :   // Test ics.
     797             :   CompileRun(
     798             :       "function f() {"
     799             :       "   var x;"
     800             :       "  for (var i = 0; i < 4; i++) {"
     801             :       "    x = obj.foo;"
     802             :       "  }"
     803             :       "  return x;"
     804             :       "}");
     805             : 
     806           5 :   security_check_value = true;
     807           5 :   ExpectInt32("f()", 907);
     808           5 :   security_check_value = false;
     809             :   {
     810           5 :     v8::TryCatch try_catch(isolate);
     811             :     CompileRun("f();");
     812           5 :     CHECK(try_catch.HasCaught());
     813             :   }
     814             : 
     815             :   // Test TurboFan.
     816             :   CompileRun("%OptimizeFunctionOnNextCall(f);");
     817             : 
     818           5 :   security_check_value = true;
     819           5 :   ExpectInt32("f()", 907);
     820           5 :   security_check_value = false;
     821             :   {
     822           5 :     v8::TryCatch try_catch(isolate);
     823             :     CompileRun("f();");
     824           5 :     CHECK(try_catch.HasCaught());
     825           5 :   }
     826           5 : }
     827             : 
     828          15 : static void CheckReceiver(Local<String> name,
     829             :                           const v8::PropertyCallbackInfo<v8::Value>& info) {
     830          15 :   CHECK(info.This()->IsObject());
     831          15 : }
     832             : 
     833       28342 : TEST(Regress609134) {
     834           5 :   LocalContext env;
     835           5 :   v8::Isolate* isolate = env->GetIsolate();
     836          10 :   v8::HandleScope scope(isolate);
     837           5 :   auto fun_templ = v8::FunctionTemplate::New(isolate);
     838          10 :   fun_templ->InstanceTemplate()->SetNativeDataProperty(v8_str("foo"),
     839          15 :                                                        CheckReceiver);
     840             : 
     841          30 :   CHECK(env->Global()
     842             :             ->Set(env.local(), v8_str("Fun"),
     843             :                   fun_templ->GetFunction(env.local()).ToLocalChecked())
     844             :             .FromJust());
     845             : 
     846             :   CompileRun(
     847             :       "var f = new Fun();"
     848             :       "Number.prototype.__proto__ = f;"
     849             :       "var a = 42;"
     850           5 :       "for (var i = 0; i<3; i++) { a.foo; }");
     851           5 : }
     852             : 
     853       28342 : TEST(ObjectSetLazyDataProperty) {
     854           5 :   LocalContext env;
     855           5 :   v8::Isolate* isolate = env->GetIsolate();
     856          10 :   v8::HandleScope scope(isolate);
     857           5 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
     858          25 :   CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
     859             : 
     860             :   // Despite getting the property multiple times, the getter should only be
     861             :   // called once and data property reads should continue to produce the same
     862             :   // value.
     863             :   static int getter_call_count;
     864           5 :   getter_call_count = 0;
     865             :   auto result = obj->SetLazyDataProperty(
     866             :       env.local(), v8_str("foo"),
     867           5 :       [](Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
     868           5 :         getter_call_count++;
     869             :         info.GetReturnValue().Set(getter_call_count);
     870          15 :       });
     871           5 :   CHECK(result.FromJust());
     872           5 :   CHECK_EQ(0, getter_call_count);
     873          10 :   for (int i = 0; i < 2; i++) {
     874          10 :     ExpectInt32("obj.foo", 1);
     875          10 :     CHECK_EQ(1, getter_call_count);
     876             :   }
     877             : 
     878             :   // Setting should overwrite the data property.
     879             :   result = obj->SetLazyDataProperty(
     880             :       env.local(), v8_str("bar"),
     881           0 :       [](Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
     882           0 :         CHECK(false);
     883          10 :       });
     884           5 :   CHECK(result.FromJust());
     885          10 :   ExpectInt32("obj.bar = -1; obj.bar;", -1);
     886       85016 : }

Generated by: LCOV version 1.10