LCOV - code coverage report
Current view: top level - test/cctest - test-api-interceptors.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 2265 2273 99.6 %
Date: 2017-10-20 Functions: 239 241 99.2 %

          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 <stdlib.h>
       6             : 
       7             : #include "test/cctest/test-api.h"
       8             : 
       9             : #include "include/v8-util.h"
      10             : #include "src/api.h"
      11             : #include "src/arguments.h"
      12             : #include "src/base/platform/platform.h"
      13             : #include "src/compilation-cache.h"
      14             : #include "src/execution.h"
      15             : #include "src/objects-inl.h"
      16             : #include "src/objects.h"
      17             : #include "src/runtime/runtime.h"
      18             : #include "src/unicode-inl.h"
      19             : #include "src/utils.h"
      20             : 
      21             : using ::v8::Boolean;
      22             : using ::v8::BooleanObject;
      23             : using ::v8::Context;
      24             : using ::v8::Extension;
      25             : using ::v8::Function;
      26             : using ::v8::FunctionTemplate;
      27             : using ::v8::HandleScope;
      28             : using ::v8::Local;
      29             : using ::v8::Name;
      30             : using ::v8::Message;
      31             : using ::v8::MessageCallback;
      32             : using ::v8::Object;
      33             : using ::v8::ObjectTemplate;
      34             : using ::v8::Persistent;
      35             : using ::v8::Script;
      36             : using ::v8::StackTrace;
      37             : using ::v8::String;
      38             : using ::v8::Symbol;
      39             : using ::v8::TryCatch;
      40             : using ::v8::Undefined;
      41             : using ::v8::V8;
      42             : using ::v8::Value;
      43             : 
      44             : 
      45             : namespace {
      46             : 
      47          30 : void Returns42(const v8::FunctionCallbackInfo<v8::Value>& info) {
      48             :   info.GetReturnValue().Set(42);
      49          30 : }
      50             : 
      51         288 : void Return239Callback(Local<String> name,
      52             :                        const v8::PropertyCallbackInfo<Value>& info) {
      53         288 :   ApiTestFuzzer::Fuzz();
      54         288 :   CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
      55         288 :   info.GetReturnValue().Set(v8_str("bad value"));
      56         288 :   info.GetReturnValue().Set(v8_num(239));
      57         288 : }
      58             : 
      59             : 
      60        1092 : void EmptyInterceptorGetter(Local<Name> name,
      61        1092 :                             const v8::PropertyCallbackInfo<v8::Value>& info) {}
      62             : 
      63             : 
      64         276 : void EmptyInterceptorSetter(Local<Name> name, Local<Value> value,
      65         276 :                             const v8::PropertyCallbackInfo<v8::Value>& info) {}
      66             : 
      67             : 
      68          12 : void SimpleAccessorGetter(Local<String> name,
      69             :                           const v8::PropertyCallbackInfo<v8::Value>& info) {
      70             :   Local<Object> self = Local<Object>::Cast(info.This());
      71             :   info.GetReturnValue().Set(self->Get(info.GetIsolate()->GetCurrentContext(),
      72          36 :                                       String::Concat(v8_str("accessor_"), name))
      73          12 :                                 .ToLocalChecked());
      74          12 : }
      75             : 
      76      120036 : void SimpleAccessorSetter(Local<String> name, Local<Value> value,
      77             :                           const v8::PropertyCallbackInfo<void>& info) {
      78             :   Local<Object> self = Local<Object>::Cast(info.This());
      79             :   self->Set(info.GetIsolate()->GetCurrentContext(),
      80      360108 :             String::Concat(v8_str("accessor_"), name), value)
      81      240072 :       .FromJust();
      82      120036 : }
      83             : 
      84             : 
      85           6 : void SymbolAccessorGetter(Local<Name> name,
      86             :                           const v8::PropertyCallbackInfo<v8::Value>& info) {
      87           6 :   CHECK(name->IsSymbol());
      88             :   Local<Symbol> sym = Local<Symbol>::Cast(name);
      89          18 :   if (sym->Name()->IsUndefined()) return;
      90           6 :   SimpleAccessorGetter(Local<String>::Cast(sym->Name()), info);
      91             : }
      92             : 
      93           6 : void SymbolAccessorSetter(Local<Name> name, Local<Value> value,
      94             :                           const v8::PropertyCallbackInfo<void>& info) {
      95           6 :   CHECK(name->IsSymbol());
      96             :   Local<Symbol> sym = Local<Symbol>::Cast(name);
      97          18 :   if (sym->Name()->IsUndefined()) return;
      98           6 :   SimpleAccessorSetter(Local<String>::Cast(sym->Name()), value, info);
      99             : }
     100             : 
     101         276 : void StringInterceptorGetter(
     102             :     Local<String> name,
     103             :     const v8::PropertyCallbackInfo<v8::Value>&
     104             :         info) {  // Intercept names that start with 'interceptor_'.
     105         276 :   String::Utf8Value utf8(info.GetIsolate(), name);
     106         276 :   char* name_str = *utf8;
     107         276 :   char prefix[] = "interceptor_";
     108             :   int i;
     109        1716 :   for (i = 0; name_str[i] && prefix[i]; ++i) {
     110        1752 :     if (name_str[i] != prefix[i]) return;
     111             :   }
     112             :   Local<Object> self = Local<Object>::Cast(info.This());
     113             :   info.GetReturnValue().Set(
     114             :       self->GetPrivate(
     115             :               info.GetIsolate()->GetCurrentContext(),
     116         360 :               v8::Private::ForApi(info.GetIsolate(), v8_str(name_str + i)))
     117         240 :           .ToLocalChecked());
     118             : }
     119             : 
     120             : 
     121      660218 : void StringInterceptorSetter(Local<String> name, Local<Value> value,
     122             :                              const v8::PropertyCallbackInfo<v8::Value>& info) {
     123             :   // Intercept accesses that set certain integer values, for which the name does
     124             :   // not start with 'accessor_'.
     125      660218 :   String::Utf8Value utf8(info.GetIsolate(), name);
     126      660218 :   char* name_str = *utf8;
     127      660218 :   char prefix[] = "accessor_";
     128             :   int i;
     129     2760848 :   for (i = 0; name_str[i] && prefix[i]; ++i) {
     130     2580794 :     if (name_str[i] != prefix[i]) break;
     131             :   }
     132      840272 :   if (!prefix[i]) return;
     133             : 
     134      480164 :   Local<Context> context = info.GetIsolate()->GetCurrentContext();
     135      960328 :   if (value->IsInt32() && value->Int32Value(context).FromJust() < 10000) {
     136             :     Local<Object> self = Local<Object>::Cast(info.This());
     137      240110 :     Local<v8::Private> symbol = v8::Private::ForApi(info.GetIsolate(), name);
     138      480220 :     self->SetPrivate(context, symbol, value).FromJust();
     139             :     info.GetReturnValue().Set(value);
     140      480164 :   }
     141             : }
     142             : 
     143         252 : void InterceptorGetter(Local<Name> generic_name,
     144             :                        const v8::PropertyCallbackInfo<v8::Value>& info) {
     145         504 :   if (generic_name->IsSymbol()) return;
     146         252 :   StringInterceptorGetter(Local<String>::Cast(generic_name), info);
     147             : }
     148             : 
     149      660212 : void InterceptorSetter(Local<Name> generic_name, Local<Value> value,
     150             :                        const v8::PropertyCallbackInfo<v8::Value>& info) {
     151     1320424 :   if (generic_name->IsSymbol()) return;
     152      660212 :   StringInterceptorSetter(Local<String>::Cast(generic_name), value, info);
     153             : }
     154             : 
     155       18066 : void GenericInterceptorGetter(Local<Name> generic_name,
     156             :                               const v8::PropertyCallbackInfo<v8::Value>& info) {
     157             :   Local<String> str;
     158       18066 :   if (generic_name->IsSymbol()) {
     159          12 :     Local<Value> name = Local<Symbol>::Cast(generic_name)->Name();
     160          18 :     if (name->IsUndefined()) return;
     161           6 :     str = String::Concat(v8_str("_sym_"), Local<String>::Cast(name));
     162             :   } else {
     163             :     Local<String> name = Local<String>::Cast(generic_name);
     164       18054 :     String::Utf8Value utf8(info.GetIsolate(), name);
     165       18054 :     char* name_str = *utf8;
     166       27078 :     if (*name_str == '_') return;
     167        9030 :     str = String::Concat(v8_str("_str_"), name);
     168             :   }
     169             : 
     170             :   Local<Object> self = Local<Object>::Cast(info.This());
     171             :   info.GetReturnValue().Set(
     172       18072 :       self->Get(info.GetIsolate()->GetCurrentContext(), str).ToLocalChecked());
     173             : }
     174             : 
     175          30 : void GenericInterceptorSetter(Local<Name> generic_name, Local<Value> value,
     176             :                               const v8::PropertyCallbackInfo<v8::Value>& info) {
     177             :   Local<String> str;
     178          30 :   if (generic_name->IsSymbol()) {
     179          12 :     Local<Value> name = Local<Symbol>::Cast(generic_name)->Name();
     180          18 :     if (name->IsUndefined()) return;
     181           6 :     str = String::Concat(v8_str("_sym_"), Local<String>::Cast(name));
     182             :   } else {
     183             :     Local<String> name = Local<String>::Cast(generic_name);
     184          18 :     String::Utf8Value utf8(info.GetIsolate(), name);
     185          18 :     char* name_str = *utf8;
     186          30 :     if (*name_str == '_') return;
     187           6 :     str = String::Concat(v8_str("_str_"), name);
     188             :   }
     189             : 
     190             :   Local<Object> self = Local<Object>::Cast(info.This());
     191          24 :   self->Set(info.GetIsolate()->GetCurrentContext(), str, value).FromJust();
     192             :   info.GetReturnValue().Set(value);
     193             : }
     194             : 
     195          30 : void AddAccessor(Local<FunctionTemplate> templ, Local<String> name,
     196             :                  v8::AccessorGetterCallback getter,
     197             :                  v8::AccessorSetterCallback setter) {
     198          60 :   templ->PrototypeTemplate()->SetAccessor(name, getter, setter);
     199          30 : }
     200             : 
     201           6 : void AddInterceptor(Local<FunctionTemplate> templ,
     202             :                     v8::NamedPropertyGetterCallback getter,
     203             :                     v8::NamedPropertySetterCallback setter) {
     204          12 :   templ->InstanceTemplate()->SetNamedPropertyHandler(getter, setter);
     205           6 : }
     206             : 
     207             : 
     208          12 : void AddAccessor(Local<FunctionTemplate> templ, Local<Name> name,
     209             :                  v8::AccessorNameGetterCallback getter,
     210             :                  v8::AccessorNameSetterCallback setter) {
     211          24 :   templ->PrototypeTemplate()->SetAccessor(name, getter, setter);
     212          12 : }
     213             : 
     214         131 : void AddInterceptor(Local<FunctionTemplate> templ,
     215             :                     v8::GenericNamedPropertyGetterCallback getter,
     216             :                     v8::GenericNamedPropertySetterCallback setter) {
     217             :   templ->InstanceTemplate()->SetHandler(
     218         262 :       v8::NamedPropertyHandlerConfiguration(getter, setter));
     219         131 : }
     220             : 
     221             : 
     222             : v8::Local<v8::Object> bottom;
     223             : 
     224          58 : void CheckThisIndexedPropertyHandler(
     225             :     uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
     226          58 :   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyHandler));
     227          58 :   ApiTestFuzzer::Fuzz();
     228         174 :   CHECK(info.This()
     229             :             ->Equals(info.GetIsolate()->GetCurrentContext(), bottom)
     230             :             .FromJust());
     231          58 : }
     232             : 
     233          58 : void CheckThisNamedPropertyHandler(
     234             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
     235          58 :   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyHandler));
     236          58 :   ApiTestFuzzer::Fuzz();
     237         174 :   CHECK(info.This()
     238             :             ->Equals(info.GetIsolate()->GetCurrentContext(), bottom)
     239             :             .FromJust());
     240          58 : }
     241             : 
     242           5 : void CheckThisIndexedPropertyDefiner(
     243             :     uint32_t index, const v8::PropertyDescriptor& desc,
     244             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
     245           5 :   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyDefiner));
     246           5 :   ApiTestFuzzer::Fuzz();
     247          15 :   CHECK(info.This()
     248             :             ->Equals(info.GetIsolate()->GetCurrentContext(), bottom)
     249             :             .FromJust());
     250           5 : }
     251             : 
     252           5 : void CheckThisNamedPropertyDefiner(
     253             :     Local<Name> property, const v8::PropertyDescriptor& desc,
     254             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
     255           5 :   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyDefiner));
     256           5 :   ApiTestFuzzer::Fuzz();
     257          15 :   CHECK(info.This()
     258             :             ->Equals(info.GetIsolate()->GetCurrentContext(), bottom)
     259             :             .FromJust());
     260           5 : }
     261             : 
     262          16 : void CheckThisIndexedPropertySetter(
     263             :     uint32_t index, Local<Value> value,
     264             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
     265          16 :   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertySetter));
     266          16 :   ApiTestFuzzer::Fuzz();
     267          48 :   CHECK(info.This()
     268             :             ->Equals(info.GetIsolate()->GetCurrentContext(), bottom)
     269             :             .FromJust());
     270          16 : }
     271             : 
     272          10 : void CheckThisIndexedPropertyDescriptor(
     273             :     uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
     274          10 :   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyDescriptor));
     275          10 :   ApiTestFuzzer::Fuzz();
     276          30 :   CHECK(info.This()
     277             :             ->Equals(info.GetIsolate()->GetCurrentContext(), bottom)
     278             :             .FromJust());
     279          10 : }
     280             : 
     281          10 : void CheckThisNamedPropertyDescriptor(
     282             :     Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
     283          10 :   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyDescriptor));
     284          10 :   ApiTestFuzzer::Fuzz();
     285          30 :   CHECK(info.This()
     286             :             ->Equals(info.GetIsolate()->GetCurrentContext(), bottom)
     287             :             .FromJust());
     288          10 : }
     289             : 
     290          16 : void CheckThisNamedPropertySetter(
     291             :     Local<Name> property, Local<Value> value,
     292             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
     293          16 :   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertySetter));
     294          16 :   ApiTestFuzzer::Fuzz();
     295          48 :   CHECK(info.This()
     296             :             ->Equals(info.GetIsolate()->GetCurrentContext(), bottom)
     297             :             .FromJust());
     298          16 : }
     299             : 
     300          36 : void CheckThisIndexedPropertyQuery(
     301             :     uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
     302          36 :   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyQuery));
     303          36 :   ApiTestFuzzer::Fuzz();
     304         108 :   CHECK(info.This()
     305             :             ->Equals(info.GetIsolate()->GetCurrentContext(), bottom)
     306             :             .FromJust());
     307          36 : }
     308             : 
     309             : 
     310          36 : void CheckThisNamedPropertyQuery(
     311             :     Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
     312          36 :   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyQuery));
     313          36 :   ApiTestFuzzer::Fuzz();
     314         108 :   CHECK(info.This()
     315             :             ->Equals(info.GetIsolate()->GetCurrentContext(), bottom)
     316             :             .FromJust());
     317          36 : }
     318             : 
     319             : 
     320          11 : void CheckThisIndexedPropertyDeleter(
     321             :     uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
     322          11 :   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyDeleter));
     323          11 :   ApiTestFuzzer::Fuzz();
     324          33 :   CHECK(info.This()
     325             :             ->Equals(info.GetIsolate()->GetCurrentContext(), bottom)
     326             :             .FromJust());
     327          11 : }
     328             : 
     329             : 
     330          11 : void CheckThisNamedPropertyDeleter(
     331             :     Local<Name> property, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
     332          11 :   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyDeleter));
     333          11 :   ApiTestFuzzer::Fuzz();
     334          33 :   CHECK(info.This()
     335             :             ->Equals(info.GetIsolate()->GetCurrentContext(), bottom)
     336             :             .FromJust());
     337          11 : }
     338             : 
     339             : 
     340          33 : void CheckThisIndexedPropertyEnumerator(
     341             :     const v8::PropertyCallbackInfo<v8::Array>& info) {
     342          33 :   CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyEnumerator));
     343          33 :   ApiTestFuzzer::Fuzz();
     344          99 :   CHECK(info.This()
     345             :             ->Equals(info.GetIsolate()->GetCurrentContext(), bottom)
     346             :             .FromJust());
     347          33 : }
     348             : 
     349             : 
     350          33 : void CheckThisNamedPropertyEnumerator(
     351             :     const v8::PropertyCallbackInfo<v8::Array>& info) {
     352          33 :   CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyEnumerator));
     353          33 :   ApiTestFuzzer::Fuzz();
     354          99 :   CHECK(info.This()
     355             :             ->Equals(info.GetIsolate()->GetCurrentContext(), bottom)
     356             :             .FromJust());
     357          33 : }
     358             : 
     359             : 
     360             : int echo_named_call_count;
     361             : 
     362             : 
     363          24 : void EchoNamedProperty(Local<Name> name,
     364             :                        const v8::PropertyCallbackInfo<v8::Value>& info) {
     365          24 :   ApiTestFuzzer::Fuzz();
     366          72 :   CHECK(v8_str("data")
     367             :             ->Equals(info.GetIsolate()->GetCurrentContext(), info.Data())
     368             :             .FromJust());
     369          24 :   echo_named_call_count++;
     370             :   info.GetReturnValue().Set(name);
     371          24 : }
     372             : 
     373          30 : void InterceptorHasOwnPropertyGetter(
     374             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
     375          30 :   ApiTestFuzzer::Fuzz();
     376          30 : }
     377             : 
     378          12 : void InterceptorHasOwnPropertyGetterGC(
     379             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
     380          12 :   ApiTestFuzzer::Fuzz();
     381          12 :   CcTest::CollectAllGarbage();
     382          12 : }
     383             : 
     384             : int query_counter_int = 0;
     385             : 
     386          48 : void QueryCallback(Local<Name> property,
     387             :                    const v8::PropertyCallbackInfo<v8::Integer>& info) {
     388          48 :   query_counter_int++;
     389          48 : }
     390             : 
     391             : }  // namespace
     392             : 
     393             : // Examples that show when the query callback is triggered.
     394       23724 : THREADED_TEST(QueryInterceptor) {
     395           6 :   v8::HandleScope scope(CcTest::isolate());
     396             :   v8::Local<v8::FunctionTemplate> templ =
     397           6 :       v8::FunctionTemplate::New(CcTest::isolate());
     398             :   templ->InstanceTemplate()->SetHandler(
     399          12 :       v8::NamedPropertyHandlerConfiguration(0, 0, QueryCallback));
     400          12 :   LocalContext env;
     401             :   env->Global()
     402           6 :       ->Set(env.local(), v8_str("obj"), templ->GetFunction(env.local())
     403           6 :                                             .ToLocalChecked()
     404           6 :                                             ->NewInstance(env.local())
     405          24 :                                             .ToLocalChecked())
     406          12 :       .FromJust();
     407           6 :   CHECK_EQ(0, query_counter_int);
     408             :   v8::Local<Value> result =
     409             :       v8_compile("Object.getOwnPropertyDescriptor(obj, 'x');")
     410           6 :           ->Run(env.local())
     411           6 :           .ToLocalChecked();
     412           6 :   CHECK_EQ(1, query_counter_int);
     413          12 :   CHECK_EQ(v8::PropertyAttribute::None,
     414             :            static_cast<v8::PropertyAttribute>(
     415             :                result->Int32Value(env.local()).FromJust()));
     416             : 
     417             :   v8_compile("Object.defineProperty(obj, 'not_enum', {value: 17});")
     418           6 :       ->Run(env.local())
     419           6 :       .ToLocalChecked();
     420           6 :   CHECK_EQ(2, query_counter_int);
     421             : 
     422             :   v8_compile(
     423             :       "Object.defineProperty(obj, 'enum', {value: 17, enumerable: true, "
     424             :       "writable: true});")
     425           6 :       ->Run(env.local())
     426           6 :       .ToLocalChecked();
     427           6 :   CHECK_EQ(3, query_counter_int);
     428             : 
     429          24 :   CHECK(v8_compile("obj.propertyIsEnumerable('enum');")
     430             :             ->Run(env.local())
     431             :             .ToLocalChecked()
     432             :             ->BooleanValue(env.local())
     433             :             .FromJust());
     434           6 :   CHECK_EQ(4, query_counter_int);
     435             : 
     436          24 :   CHECK(!v8_compile("obj.propertyIsEnumerable('not_enum');")
     437             :              ->Run(env.local())
     438             :              .ToLocalChecked()
     439             :              ->BooleanValue(env.local())
     440             :              .FromJust());
     441           6 :   CHECK_EQ(5, query_counter_int);
     442             : 
     443          24 :   CHECK(v8_compile("obj.hasOwnProperty('enum');")
     444             :             ->Run(env.local())
     445             :             .ToLocalChecked()
     446             :             ->BooleanValue(env.local())
     447             :             .FromJust());
     448           6 :   CHECK_EQ(5, query_counter_int);
     449             : 
     450          24 :   CHECK(v8_compile("obj.hasOwnProperty('not_enum');")
     451             :             ->Run(env.local())
     452             :             .ToLocalChecked()
     453             :             ->BooleanValue(env.local())
     454             :             .FromJust());
     455           6 :   CHECK_EQ(5, query_counter_int);
     456             : 
     457          24 :   CHECK(!v8_compile("obj.hasOwnProperty('x');")
     458             :              ->Run(env.local())
     459             :              .ToLocalChecked()
     460             :              ->BooleanValue(env.local())
     461             :              .FromJust());
     462           6 :   CHECK_EQ(6, query_counter_int);
     463             : 
     464          24 :   CHECK(!v8_compile("obj.propertyIsEnumerable('undef');")
     465             :              ->Run(env.local())
     466             :              .ToLocalChecked()
     467             :              ->BooleanValue(env.local())
     468             :              .FromJust());
     469           6 :   CHECK_EQ(7, query_counter_int);
     470             : 
     471             :   v8_compile("Object.defineProperty(obj, 'enum', {value: 42});")
     472           6 :       ->Run(env.local())
     473           6 :       .ToLocalChecked();
     474           6 :   CHECK_EQ(8, query_counter_int);
     475             : 
     476          12 :   v8_compile("Object.isFrozen('obj.x');")->Run(env.local()).ToLocalChecked();
     477          12 :   CHECK_EQ(8, query_counter_int);
     478           6 : }
     479             : 
     480             : namespace {
     481             : 
     482             : bool get_was_called = false;
     483             : bool set_was_called = false;
     484             : 
     485             : int set_was_called_counter = 0;
     486             : 
     487           6 : void GetterCallback(Local<Name> property,
     488             :                     const v8::PropertyCallbackInfo<v8::Value>& info) {
     489           6 :   get_was_called = true;
     490           6 : }
     491             : 
     492          30 : void SetterCallback(Local<Name> property, Local<Value> value,
     493             :                     const v8::PropertyCallbackInfo<v8::Value>& info) {
     494          30 :   set_was_called = true;
     495          30 :   set_was_called_counter++;
     496          30 : }
     497             : 
     498           6 : void InterceptingSetterCallback(
     499             :     Local<Name> property, Local<Value> value,
     500             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
     501             :   info.GetReturnValue().Set(value);
     502           6 : }
     503             : 
     504             : }  // namespace
     505             : 
     506             : // Check that get callback is called in defineProperty with accessor descriptor.
     507       23724 : THREADED_TEST(DefinerCallbackAccessorInterceptor) {
     508           6 :   v8::HandleScope scope(CcTest::isolate());
     509             :   v8::Local<v8::FunctionTemplate> templ =
     510           6 :       v8::FunctionTemplate::New(CcTest::isolate());
     511             :   templ->InstanceTemplate()->SetHandler(
     512          12 :       v8::NamedPropertyHandlerConfiguration(GetterCallback, SetterCallback));
     513          12 :   LocalContext env;
     514             :   env->Global()
     515           6 :       ->Set(env.local(), v8_str("obj"), templ->GetFunction(env.local())
     516           6 :                                             .ToLocalChecked()
     517           6 :                                             ->NewInstance(env.local())
     518          24 :                                             .ToLocalChecked())
     519          12 :       .FromJust();
     520             : 
     521           6 :   get_was_called = false;
     522           6 :   set_was_called = false;
     523             : 
     524             :   v8_compile("Object.defineProperty(obj, 'x', {set: function() {return 17;}});")
     525           6 :       ->Run(env.local())
     526           6 :       .ToLocalChecked();
     527           6 :   CHECK(get_was_called);
     528          12 :   CHECK(!set_was_called);
     529           6 : }
     530             : 
     531             : // Check that set callback is called for function declarations.
     532       23724 : THREADED_TEST(SetterCallbackFunctionDeclarationInterceptor) {
     533           6 :   v8::HandleScope scope(CcTest::isolate());
     534          12 :   LocalContext env;
     535             :   v8::Local<v8::FunctionTemplate> templ =
     536           6 :       v8::FunctionTemplate::New(CcTest::isolate());
     537             : 
     538           6 :   v8::Local<ObjectTemplate> object_template = templ->InstanceTemplate();
     539             :   object_template->SetHandler(
     540           6 :       v8::NamedPropertyHandlerConfiguration(nullptr, SetterCallback));
     541             :   v8::Local<v8::Context> ctx =
     542           6 :       v8::Context::New(CcTest::isolate(), nullptr, object_template);
     543             : 
     544           6 :   set_was_called_counter = 0;
     545             : 
     546             :   // Declare function.
     547           6 :   v8::Local<v8::String> code = v8_str("function x() {return 42;}; x();");
     548          24 :   CHECK_EQ(42, v8::Script::Compile(ctx, code)
     549             :                    .ToLocalChecked()
     550             :                    ->Run(ctx)
     551             :                    .ToLocalChecked()
     552             :                    ->Int32Value(ctx)
     553             :                    .FromJust());
     554           6 :   CHECK_EQ(1, set_was_called_counter);
     555             : 
     556             :   // Redeclare function.
     557           6 :   code = v8_str("function x() {return 43;}; x();");
     558          24 :   CHECK_EQ(43, v8::Script::Compile(ctx, code)
     559             :                    .ToLocalChecked()
     560             :                    ->Run(ctx)
     561             :                    .ToLocalChecked()
     562             :                    ->Int32Value(ctx)
     563             :                    .FromJust());
     564           6 :   CHECK_EQ(2, set_was_called_counter);
     565             : 
     566             :   // Redefine function.
     567           6 :   code = v8_str("x = function() {return 44;}; x();");
     568          24 :   CHECK_EQ(44, v8::Script::Compile(ctx, code)
     569             :                    .ToLocalChecked()
     570             :                    ->Run(ctx)
     571             :                    .ToLocalChecked()
     572             :                    ->Int32Value(ctx)
     573             :                    .FromJust());
     574          12 :   CHECK_EQ(3, set_was_called_counter);
     575           6 : }
     576             : 
     577             : namespace {
     578             : int descriptor_was_called;
     579             : 
     580           6 : void PropertyDescriptorCallback(
     581             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
     582             :   // Intercept the callback by setting a different descriptor.
     583           6 :   descriptor_was_called++;
     584             :   const char* code =
     585             :       "var desc = {value: 5};"
     586             :       "desc;";
     587             :   Local<Value> descriptor = v8_compile(code)
     588           6 :                                 ->Run(info.GetIsolate()->GetCurrentContext())
     589           6 :                                 .ToLocalChecked();
     590             :   info.GetReturnValue().Set(descriptor);
     591           6 : }
     592             : }  // namespace
     593             : 
     594             : // Check that the descriptor callback is called on the global object.
     595       23724 : THREADED_TEST(DescriptorCallbackOnGlobalObject) {
     596           6 :   v8::HandleScope scope(CcTest::isolate());
     597          12 :   LocalContext env;
     598             :   v8::Local<v8::FunctionTemplate> templ =
     599           6 :       v8::FunctionTemplate::New(CcTest::isolate());
     600             : 
     601           6 :   v8::Local<ObjectTemplate> object_template = templ->InstanceTemplate();
     602             :   object_template->SetHandler(v8::NamedPropertyHandlerConfiguration(
     603           6 :       nullptr, nullptr, PropertyDescriptorCallback, nullptr, nullptr, nullptr));
     604             :   v8::Local<v8::Context> ctx =
     605           6 :       v8::Context::New(CcTest::isolate(), nullptr, object_template);
     606             : 
     607           6 :   descriptor_was_called = 0;
     608             : 
     609             :   // Declare function.
     610             :   v8::Local<v8::String> code = v8_str(
     611             :       "var x = 42; var desc = Object.getOwnPropertyDescriptor(this, 'x'); "
     612           6 :       "desc.value;");
     613          24 :   CHECK_EQ(5, v8::Script::Compile(ctx, code)
     614             :                   .ToLocalChecked()
     615             :                   ->Run(ctx)
     616             :                   .ToLocalChecked()
     617             :                   ->Int32Value(ctx)
     618             :                   .FromJust());
     619          12 :   CHECK_EQ(1, descriptor_was_called);
     620           6 : }
     621             : 
     622             : namespace {
     623          12 : void QueryCallbackSetDontDelete(
     624             :     Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
     625             :   info.GetReturnValue().Set(v8::PropertyAttribute::DontDelete);
     626          12 : }
     627             : 
     628             : }  // namespace
     629             : 
     630             : // Regression for a Node.js test that fails in debug mode.
     631       23724 : THREADED_TEST(InterceptorFunctionRedeclareWithQueryCallback) {
     632           6 :   v8::HandleScope scope(CcTest::isolate());
     633          12 :   LocalContext env;
     634             :   v8::Local<v8::FunctionTemplate> templ =
     635           6 :       v8::FunctionTemplate::New(CcTest::isolate());
     636             : 
     637           6 :   v8::Local<ObjectTemplate> object_template = templ->InstanceTemplate();
     638             :   object_template->SetHandler(v8::NamedPropertyHandlerConfiguration(
     639           6 :       nullptr, nullptr, QueryCallbackSetDontDelete));
     640             :   v8::Local<v8::Context> ctx =
     641           6 :       v8::Context::New(CcTest::isolate(), nullptr, object_template);
     642             : 
     643             :   // Declare and redeclare function.
     644             :   v8::Local<v8::String> code = v8_str(
     645             :       "function x() {return 42;};"
     646           6 :       "function x() {return 43;};");
     647          18 :   v8::Script::Compile(ctx, code).ToLocalChecked()->Run(ctx).ToLocalChecked();
     648           6 : }
     649             : 
     650             : // Regression test for chromium bug 656648.
     651             : // Do not crash on non-masking, intercepting setter callbacks.
     652       23724 : THREADED_TEST(NonMaskingInterceptor) {
     653           6 :   v8::HandleScope scope(CcTest::isolate());
     654          12 :   LocalContext env;
     655             :   v8::Local<v8::FunctionTemplate> templ =
     656           6 :       v8::FunctionTemplate::New(CcTest::isolate());
     657             : 
     658           6 :   v8::Local<ObjectTemplate> object_template = templ->InstanceTemplate();
     659             :   object_template->SetHandler(v8::NamedPropertyHandlerConfiguration(
     660             :       nullptr, InterceptingSetterCallback, nullptr, nullptr, nullptr,
     661           6 :       Local<Value>(), v8::PropertyHandlerFlags::kNonMasking));
     662             :   v8::Local<v8::Context> ctx =
     663           6 :       v8::Context::New(CcTest::isolate(), nullptr, object_template);
     664             : 
     665           6 :   v8::Local<v8::String> code = v8_str("function x() {return 43;};");
     666          18 :   v8::Script::Compile(ctx, code).ToLocalChecked()->Run(ctx).ToLocalChecked();
     667           6 : }
     668             : 
     669             : // Check that function re-declarations throw if they are read-only.
     670       23724 : THREADED_TEST(SetterCallbackFunctionDeclarationInterceptorThrow) {
     671           6 :   v8::HandleScope scope(CcTest::isolate());
     672          12 :   LocalContext env;
     673             :   v8::Local<v8::FunctionTemplate> templ =
     674           6 :       v8::FunctionTemplate::New(CcTest::isolate());
     675             : 
     676           6 :   v8::Local<ObjectTemplate> object_template = templ->InstanceTemplate();
     677             :   object_template->SetHandler(
     678           6 :       v8::NamedPropertyHandlerConfiguration(nullptr, SetterCallback));
     679             :   v8::Local<v8::Context> ctx =
     680           6 :       v8::Context::New(CcTest::isolate(), nullptr, object_template);
     681             : 
     682           6 :   set_was_called = false;
     683             : 
     684             :   v8::Local<v8::String> code = v8_str(
     685             :       "function x() {return 42;};"
     686             :       "Object.defineProperty(this, 'x', {"
     687             :       "configurable: false, "
     688             :       "writable: false});"
     689           6 :       "x();");
     690          24 :   CHECK_EQ(42, v8::Script::Compile(ctx, code)
     691             :                    .ToLocalChecked()
     692             :                    ->Run(ctx)
     693             :                    .ToLocalChecked()
     694             :                    ->Int32Value(ctx)
     695             :                    .FromJust());
     696             : 
     697           6 :   CHECK(set_was_called);
     698             : 
     699          12 :   v8::TryCatch try_catch(CcTest::isolate());
     700           6 :   set_was_called = false;
     701             : 
     702             :   // Redeclare function that is read-only.
     703           6 :   code = v8_str("function x() {return 43;};");
     704          18 :   CHECK(v8::Script::Compile(ctx, code).ToLocalChecked()->Run(ctx).IsEmpty());
     705           6 :   CHECK(try_catch.HasCaught());
     706             : 
     707          12 :   CHECK(!set_was_called);
     708           6 : }
     709             : 
     710             : 
     711             : namespace {
     712             : 
     713             : bool get_was_called_in_order = false;
     714             : bool define_was_called_in_order = false;
     715             : 
     716          12 : void GetterCallbackOrder(Local<Name> property,
     717             :                          const v8::PropertyCallbackInfo<v8::Value>& info) {
     718          12 :   get_was_called_in_order = true;
     719          12 :   CHECK(!define_was_called_in_order);
     720             :   info.GetReturnValue().Set(property);
     721          12 : }
     722             : 
     723           6 : void DefinerCallbackOrder(Local<Name> property,
     724             :                           const v8::PropertyDescriptor& desc,
     725             :                           const v8::PropertyCallbackInfo<v8::Value>& info) {
     726             :   // Get called before DefineProperty because we query the descriptor first.
     727           6 :   CHECK(get_was_called_in_order);
     728           6 :   define_was_called_in_order = true;
     729           6 : }
     730             : 
     731             : }  // namespace
     732             : 
     733             : // Check that getter callback is called before definer callback.
     734       23724 : THREADED_TEST(DefinerCallbackGetAndDefine) {
     735           6 :   v8::HandleScope scope(CcTest::isolate());
     736             :   v8::Local<v8::FunctionTemplate> templ =
     737           6 :       v8::FunctionTemplate::New(CcTest::isolate());
     738             :   templ->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration(
     739          12 :       GetterCallbackOrder, SetterCallback, 0, 0, 0, DefinerCallbackOrder));
     740          12 :   LocalContext env;
     741             :   env->Global()
     742           6 :       ->Set(env.local(), v8_str("obj"), templ->GetFunction(env.local())
     743           6 :                                             .ToLocalChecked()
     744           6 :                                             ->NewInstance(env.local())
     745          24 :                                             .ToLocalChecked())
     746          12 :       .FromJust();
     747             : 
     748           6 :   CHECK(!get_was_called_in_order);
     749           6 :   CHECK(!define_was_called_in_order);
     750             : 
     751             :   v8_compile("Object.defineProperty(obj, 'x', {set: function() {return 17;}});")
     752           6 :       ->Run(env.local())
     753           6 :       .ToLocalChecked();
     754           6 :   CHECK(get_was_called_in_order);
     755          12 :   CHECK(define_was_called_in_order);
     756           6 : }
     757             : 
     758             : namespace {  //  namespace for InObjectLiteralDefinitionWithInterceptor
     759             : 
     760             : // Workaround for no-snapshot builds: only intercept once Context::New() is
     761             : // done, otherwise we'll intercept
     762             : // bootstrapping like defining array on the global object.
     763             : bool context_is_done = false;
     764             : bool getter_callback_was_called = false;
     765             : 
     766           6 : void ReturnUndefinedGetterCallback(
     767             :     Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
     768           6 :   if (context_is_done) {
     769           6 :     getter_callback_was_called = true;
     770             :     info.GetReturnValue().SetUndefined();
     771             :   }
     772           6 : }
     773             : 
     774             : }  // namespace
     775             : 
     776             : // Check that an interceptor is not invoked during ES6 style definitions inside
     777             : // an object literal.
     778       23724 : THREADED_TEST(InObjectLiteralDefinitionWithInterceptor) {
     779           6 :   v8::HandleScope scope(CcTest::isolate());
     780          12 :   LocalContext env;
     781             : 
     782             :   // Set up a context in which all global object definitions are intercepted.
     783             :   v8::Local<v8::FunctionTemplate> templ =
     784           6 :       v8::FunctionTemplate::New(CcTest::isolate());
     785           6 :   v8::Local<ObjectTemplate> object_template = templ->InstanceTemplate();
     786             :   object_template->SetHandler(
     787           6 :       v8::NamedPropertyHandlerConfiguration(ReturnUndefinedGetterCallback));
     788             :   v8::Local<v8::Context> ctx =
     789           6 :       v8::Context::New(CcTest::isolate(), nullptr, object_template);
     790             : 
     791           6 :   context_is_done = true;
     792             : 
     793             :   // The interceptor returns undefined for any global object,
     794             :   // so setting a property on an object should throw.
     795           6 :   v8::Local<v8::String> code = v8_str("var o = {}; o.x = 5");
     796             :   {
     797           6 :     getter_callback_was_called = false;
     798           6 :     v8::TryCatch try_catch(CcTest::isolate());
     799          18 :     CHECK(v8::Script::Compile(ctx, code).ToLocalChecked()->Run(ctx).IsEmpty());
     800           6 :     CHECK(try_catch.HasCaught());
     801           6 :     CHECK(getter_callback_was_called);
     802             :   }
     803             : 
     804             :   // Defining a property in the object literal should not throw
     805             :   // because the interceptor is not invoked.
     806             :   {
     807           6 :     getter_callback_was_called = false;
     808           6 :     v8::TryCatch try_catch(CcTest::isolate());
     809           6 :     code = v8_str("var l = {x: 5};");
     810          18 :     CHECK(v8::Script::Compile(ctx, code)
     811             :               .ToLocalChecked()
     812             :               ->Run(ctx)
     813             :               .ToLocalChecked()
     814             :               ->IsUndefined());
     815           6 :     CHECK(!try_catch.HasCaught());
     816           6 :     CHECK(!getter_callback_was_called);
     817           6 :   }
     818           6 : }
     819             : 
     820       23724 : THREADED_TEST(InterceptorHasOwnProperty) {
     821           6 :   LocalContext context;
     822           6 :   v8::Isolate* isolate = context->GetIsolate();
     823          12 :   v8::HandleScope scope(isolate);
     824           6 :   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
     825           6 :   Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
     826             :   instance_templ->SetHandler(
     827           6 :       v8::NamedPropertyHandlerConfiguration(InterceptorHasOwnPropertyGetter));
     828             :   Local<Function> function =
     829           6 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
     830             :   context->Global()
     831          24 :       ->Set(context.local(), v8_str("constructor"), function)
     832          12 :       .FromJust();
     833             :   v8::Local<Value> value = CompileRun(
     834             :       "var o = new constructor();"
     835             :       "o.hasOwnProperty('ostehaps');");
     836          12 :   CHECK(!value->BooleanValue(context.local()).FromJust());
     837             :   value = CompileRun(
     838             :       "o.ostehaps = 42;"
     839             :       "o.hasOwnProperty('ostehaps');");
     840          12 :   CHECK(value->BooleanValue(context.local()).FromJust());
     841             :   value = CompileRun(
     842             :       "var p = new constructor();"
     843             :       "p.hasOwnProperty('ostehaps');");
     844          18 :   CHECK(!value->BooleanValue(context.local()).FromJust());
     845           6 : }
     846             : 
     847             : 
     848       23724 : THREADED_TEST(InterceptorHasOwnPropertyCausingGC) {
     849           6 :   LocalContext context;
     850           6 :   v8::Isolate* isolate = context->GetIsolate();
     851          12 :   v8::HandleScope scope(isolate);
     852           6 :   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
     853           6 :   Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
     854             :   instance_templ->SetHandler(
     855           6 :       v8::NamedPropertyHandlerConfiguration(InterceptorHasOwnPropertyGetterGC));
     856             :   Local<Function> function =
     857           6 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
     858             :   context->Global()
     859          24 :       ->Set(context.local(), v8_str("constructor"), function)
     860          12 :       .FromJust();
     861             :   // Let's first make some stuff so we can be sure to get a good GC.
     862             :   CompileRun(
     863             :       "function makestr(size) {"
     864             :       "  switch (size) {"
     865             :       "    case 1: return 'f';"
     866             :       "    case 2: return 'fo';"
     867             :       "    case 3: return 'foo';"
     868             :       "  }"
     869             :       "  return makestr(size >> 1) + makestr((size + 1) >> 1);"
     870             :       "}"
     871             :       "var x = makestr(12345);"
     872             :       "x = makestr(31415);"
     873             :       "x = makestr(23456);");
     874             :   v8::Local<Value> value = CompileRun(
     875             :       "var o = new constructor();"
     876             :       "o.__proto__ = new String(x);"
     877             :       "o.hasOwnProperty('ostehaps');");
     878          18 :   CHECK(!value->BooleanValue(context.local()).FromJust());
     879           6 : }
     880             : 
     881             : 
     882          66 : static void CheckInterceptorLoadIC(
     883             :     v8::GenericNamedPropertyGetterCallback getter, const char* source,
     884             :     int expected) {
     885          66 :   v8::Isolate* isolate = CcTest::isolate();
     886          66 :   v8::HandleScope scope(isolate);
     887          66 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
     888             :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(getter, 0, 0, 0, 0,
     889         132 :                                                           v8_str("data")));
     890         132 :   LocalContext context;
     891             :   context->Global()
     892             :       ->Set(context.local(), v8_str("o"),
     893         330 :             templ->NewInstance(context.local()).ToLocalChecked())
     894         132 :       .FromJust();
     895             :   v8::Local<Value> value = CompileRun(source);
     896         198 :   CHECK_EQ(expected, value->Int32Value(context.local()).FromJust());
     897          66 : }
     898             : 
     899             : 
     900        6000 : static void InterceptorLoadICGetter(
     901             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
     902        6000 :   ApiTestFuzzer::Fuzz();
     903        6000 :   v8::Isolate* isolate = CcTest::isolate();
     904        6000 :   CHECK_EQ(isolate, info.GetIsolate());
     905        6000 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
     906       18000 :   CHECK(v8_str("data")->Equals(context, info.Data()).FromJust());
     907       18000 :   CHECK(v8_str("x")->Equals(context, name).FromJust());
     908        6000 :   info.GetReturnValue().Set(v8::Integer::New(isolate, 42));
     909        6000 : }
     910             : 
     911             : 
     912             : // This test should hit the load IC for the interceptor case.
     913       23724 : THREADED_TEST(InterceptorLoadIC) {
     914             :   CheckInterceptorLoadIC(InterceptorLoadICGetter,
     915             :                          "var result = 0;"
     916             :                          "for (var i = 0; i < 1000; i++) {"
     917             :                          "  result = o.x;"
     918             :                          "}",
     919           6 :                          42);
     920           6 : }
     921             : 
     922             : 
     923             : // Below go several tests which verify that JITing for various
     924             : // configurations of interceptor and explicit fields works fine
     925             : // (those cases are special cased to get better performance).
     926             : 
     927       66780 : static void InterceptorLoadXICGetter(
     928             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
     929       66780 :   ApiTestFuzzer::Fuzz();
     930             :   info.GetReturnValue().Set(
     931             :       v8_str("x")
     932      133560 :               ->Equals(info.GetIsolate()->GetCurrentContext(), name)
     933      133560 :               .FromJust()
     934             :           ? v8::Local<v8::Value>(v8::Integer::New(info.GetIsolate(), 42))
     935       97014 :           : v8::Local<v8::Value>());
     936       66780 : }
     937             : 
     938             : 
     939       23724 : THREADED_TEST(InterceptorLoadICWithFieldOnHolder) {
     940             :   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
     941             :                          "var result = 0;"
     942             :                          "o.y = 239;"
     943             :                          "for (var i = 0; i < 1000; i++) {"
     944             :                          "  result = o.y;"
     945             :                          "}",
     946           6 :                          239);
     947           6 : }
     948             : 
     949             : 
     950       23724 : THREADED_TEST(InterceptorLoadICWithSubstitutedProto) {
     951             :   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
     952             :                          "var result = 0;"
     953             :                          "o.__proto__ = { 'y': 239 };"
     954             :                          "for (var i = 0; i < 1000; i++) {"
     955             :                          "  result = o.y + o.x;"
     956             :                          "}",
     957           6 :                          239 + 42);
     958           6 : }
     959             : 
     960             : 
     961       23724 : THREADED_TEST(InterceptorLoadICWithPropertyOnProto) {
     962             :   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
     963             :                          "var result = 0;"
     964             :                          "o.__proto__.y = 239;"
     965             :                          "for (var i = 0; i < 1000; i++) {"
     966             :                          "  result = o.y + o.x;"
     967             :                          "}",
     968           6 :                          239 + 42);
     969           6 : }
     970             : 
     971             : 
     972       23724 : THREADED_TEST(InterceptorLoadICUndefined) {
     973             :   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
     974             :                          "var result = 0;"
     975             :                          "for (var i = 0; i < 1000; i++) {"
     976             :                          "  result = (o.y == undefined) ? 239 : 42;"
     977             :                          "}",
     978           6 :                          239);
     979           6 : }
     980             : 
     981             : 
     982       23724 : THREADED_TEST(InterceptorLoadICWithOverride) {
     983             :   CheckInterceptorLoadIC(InterceptorLoadXICGetter,
     984             :                          "fst = new Object();  fst.__proto__ = o;"
     985             :                          "snd = new Object();  snd.__proto__ = fst;"
     986             :                          "var result1 = 0;"
     987             :                          "for (var i = 0; i < 1000;  i++) {"
     988             :                          "  result1 = snd.x;"
     989             :                          "}"
     990             :                          "fst.x = 239;"
     991             :                          "var result = 0;"
     992             :                          "for (var i = 0; i < 1000; i++) {"
     993             :                          "  result = snd.x;"
     994             :                          "}"
     995             :                          "result + result1",
     996           6 :                          239 + 42);
     997           6 : }
     998             : 
     999             : 
    1000             : // Test the case when we stored field into
    1001             : // a stub, but interceptor produced value on its own.
    1002       23724 : THREADED_TEST(InterceptorLoadICFieldNotNeeded) {
    1003             :   CheckInterceptorLoadIC(
    1004             :       InterceptorLoadXICGetter,
    1005             :       "proto = new Object();"
    1006             :       "o.__proto__ = proto;"
    1007             :       "proto.x = 239;"
    1008             :       "for (var i = 0; i < 1000; i++) {"
    1009             :       "  o.x;"
    1010             :       // Now it should be ICed and keep a reference to x defined on proto
    1011             :       "}"
    1012             :       "var result = 0;"
    1013             :       "for (var i = 0; i < 1000; i++) {"
    1014             :       "  result += o.x;"
    1015             :       "}"
    1016             :       "result;",
    1017           6 :       42 * 1000);
    1018           6 : }
    1019             : 
    1020             : 
    1021             : // Test the case when we stored field into
    1022             : // a stub, but it got invalidated later on.
    1023       23724 : THREADED_TEST(InterceptorLoadICInvalidatedField) {
    1024             :   CheckInterceptorLoadIC(
    1025             :       InterceptorLoadXICGetter,
    1026             :       "proto1 = new Object();"
    1027             :       "proto2 = new Object();"
    1028             :       "o.__proto__ = proto1;"
    1029             :       "proto1.__proto__ = proto2;"
    1030             :       "proto2.y = 239;"
    1031             :       "for (var i = 0; i < 1000; i++) {"
    1032             :       "  o.y;"
    1033             :       // Now it should be ICed and keep a reference to y defined on proto2
    1034             :       "}"
    1035             :       "proto1.y = 42;"
    1036             :       "var result = 0;"
    1037             :       "for (var i = 0; i < 1000; i++) {"
    1038             :       "  result += o.y;"
    1039             :       "}"
    1040             :       "result;",
    1041           6 :       42 * 1000);
    1042           6 : }
    1043             : 
    1044             : 
    1045             : static int interceptor_load_not_handled_calls = 0;
    1046        6000 : static void InterceptorLoadNotHandled(
    1047             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    1048        6000 :   ++interceptor_load_not_handled_calls;
    1049        6000 : }
    1050             : 
    1051             : 
    1052             : // Test how post-interceptor lookups are done in the non-cacheable
    1053             : // case: the interceptor should not be invoked during this lookup.
    1054       23724 : THREADED_TEST(InterceptorLoadICPostInterceptor) {
    1055           6 :   interceptor_load_not_handled_calls = 0;
    1056             :   CheckInterceptorLoadIC(InterceptorLoadNotHandled,
    1057             :                          "receiver = new Object();"
    1058             :                          "receiver.__proto__ = o;"
    1059             :                          "proto = new Object();"
    1060             :                          "/* Make proto a slow-case object. */"
    1061             :                          "for (var i = 0; i < 1000; i++) {"
    1062             :                          "  proto[\"xxxxxxxx\" + i] = [];"
    1063             :                          "}"
    1064             :                          "proto.x = 17;"
    1065             :                          "o.__proto__ = proto;"
    1066             :                          "var result = 0;"
    1067             :                          "for (var i = 0; i < 1000; i++) {"
    1068             :                          "  result += receiver.x;"
    1069             :                          "}"
    1070             :                          "result;",
    1071           6 :                          17 * 1000);
    1072           6 :   CHECK_EQ(1000, interceptor_load_not_handled_calls);
    1073           6 : }
    1074             : 
    1075             : 
    1076             : // Test the case when we stored field into
    1077             : // a stub, but it got invalidated later on due to override on
    1078             : // global object which is between interceptor and fields' holders.
    1079       23724 : THREADED_TEST(InterceptorLoadICInvalidatedFieldViaGlobal) {
    1080             :   CheckInterceptorLoadIC(
    1081             :       InterceptorLoadXICGetter,
    1082             :       "o.__proto__ = this;"  // set a global to be a proto of o.
    1083             :       "this.__proto__.y = 239;"
    1084             :       "for (var i = 0; i < 10; i++) {"
    1085             :       "  if (o.y != 239) throw 'oops: ' + o.y;"
    1086             :       // Now it should be ICed and keep a reference to y defined on
    1087             :       // field_holder.
    1088             :       "}"
    1089             :       "this.y = 42;"  // Assign on a global.
    1090             :       "var result = 0;"
    1091             :       "for (var i = 0; i < 10; i++) {"
    1092             :       "  result += o.y;"
    1093             :       "}"
    1094             :       "result;",
    1095           6 :       42 * 10);
    1096           6 : }
    1097             : 
    1098             : 
    1099          12 : static void SetOnThis(Local<String> name, Local<Value> value,
    1100             :                       const v8::PropertyCallbackInfo<void>& info) {
    1101             :   Local<Object>::Cast(info.This())
    1102          24 :       ->CreateDataProperty(info.GetIsolate()->GetCurrentContext(), name, value)
    1103          24 :       .FromJust();
    1104          12 : }
    1105             : 
    1106             : 
    1107       23724 : THREADED_TEST(InterceptorLoadICWithCallbackOnHolder) {
    1108           6 :   v8::Isolate* isolate = CcTest::isolate();
    1109           6 :   v8::HandleScope scope(isolate);
    1110           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    1111             :   templ->SetHandler(
    1112           6 :       v8::NamedPropertyHandlerConfiguration(InterceptorLoadXICGetter));
    1113           6 :   templ->SetAccessor(v8_str("y"), Return239Callback);
    1114          12 :   LocalContext context;
    1115             :   context->Global()
    1116             :       ->Set(context.local(), v8_str("o"),
    1117          30 :             templ->NewInstance(context.local()).ToLocalChecked())
    1118          12 :       .FromJust();
    1119             : 
    1120             :   // Check the case when receiver and interceptor's holder
    1121             :   // are the same objects.
    1122             :   v8::Local<Value> value = CompileRun(
    1123             :       "var result = 0;"
    1124             :       "for (var i = 0; i < 7; i++) {"
    1125             :       "  result = o.y;"
    1126             :       "}");
    1127          12 :   CHECK_EQ(239, value->Int32Value(context.local()).FromJust());
    1128             : 
    1129             :   // Check the case when interceptor's holder is in proto chain
    1130             :   // of receiver.
    1131             :   value = CompileRun(
    1132             :       "r = { __proto__: o };"
    1133             :       "var result = 0;"
    1134             :       "for (var i = 0; i < 7; i++) {"
    1135             :       "  result = r.y;"
    1136             :       "}");
    1137          18 :   CHECK_EQ(239, value->Int32Value(context.local()).FromJust());
    1138           6 : }
    1139             : 
    1140             : 
    1141       23724 : THREADED_TEST(InterceptorLoadICWithCallbackOnProto) {
    1142           6 :   v8::Isolate* isolate = CcTest::isolate();
    1143           6 :   v8::HandleScope scope(isolate);
    1144           6 :   v8::Local<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
    1145             :   templ_o->SetHandler(
    1146           6 :       v8::NamedPropertyHandlerConfiguration(InterceptorLoadXICGetter));
    1147           6 :   v8::Local<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
    1148           6 :   templ_p->SetAccessor(v8_str("y"), Return239Callback);
    1149             : 
    1150          12 :   LocalContext context;
    1151             :   context->Global()
    1152             :       ->Set(context.local(), v8_str("o"),
    1153          30 :             templ_o->NewInstance(context.local()).ToLocalChecked())
    1154          12 :       .FromJust();
    1155             :   context->Global()
    1156             :       ->Set(context.local(), v8_str("p"),
    1157          30 :             templ_p->NewInstance(context.local()).ToLocalChecked())
    1158          12 :       .FromJust();
    1159             : 
    1160             :   // Check the case when receiver and interceptor's holder
    1161             :   // are the same objects.
    1162             :   v8::Local<Value> value = CompileRun(
    1163             :       "o.__proto__ = p;"
    1164             :       "var result = 0;"
    1165             :       "for (var i = 0; i < 7; i++) {"
    1166             :       "  result = o.x + o.y;"
    1167             :       "}");
    1168          12 :   CHECK_EQ(239 + 42, value->Int32Value(context.local()).FromJust());
    1169             : 
    1170             :   // Check the case when interceptor's holder is in proto chain
    1171             :   // of receiver.
    1172             :   value = CompileRun(
    1173             :       "r = { __proto__: o };"
    1174             :       "var result = 0;"
    1175             :       "for (var i = 0; i < 7; i++) {"
    1176             :       "  result = r.x + r.y;"
    1177             :       "}");
    1178          18 :   CHECK_EQ(239 + 42, value->Int32Value(context.local()).FromJust());
    1179           6 : }
    1180             : 
    1181             : 
    1182       23724 : THREADED_TEST(InterceptorLoadICForCallbackWithOverride) {
    1183           6 :   v8::Isolate* isolate = CcTest::isolate();
    1184           6 :   v8::HandleScope scope(isolate);
    1185           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    1186             :   templ->SetHandler(
    1187           6 :       v8::NamedPropertyHandlerConfiguration(InterceptorLoadXICGetter));
    1188           6 :   templ->SetAccessor(v8_str("y"), Return239Callback);
    1189             : 
    1190          12 :   LocalContext context;
    1191             :   context->Global()
    1192             :       ->Set(context.local(), v8_str("o"),
    1193          30 :             templ->NewInstance(context.local()).ToLocalChecked())
    1194          12 :       .FromJust();
    1195             : 
    1196             :   v8::Local<Value> value = CompileRun(
    1197             :       "fst = new Object();  fst.__proto__ = o;"
    1198             :       "snd = new Object();  snd.__proto__ = fst;"
    1199             :       "var result1 = 0;"
    1200             :       "for (var i = 0; i < 7;  i++) {"
    1201             :       "  result1 = snd.x;"
    1202             :       "}"
    1203             :       "fst.x = 239;"
    1204             :       "var result = 0;"
    1205             :       "for (var i = 0; i < 7; i++) {"
    1206             :       "  result = snd.x;"
    1207             :       "}"
    1208             :       "result + result1");
    1209          18 :   CHECK_EQ(239 + 42, value->Int32Value(context.local()).FromJust());
    1210           6 : }
    1211             : 
    1212             : 
    1213             : // Test the case when we stored callback into
    1214             : // a stub, but interceptor produced value on its own.
    1215       23724 : THREADED_TEST(InterceptorLoadICCallbackNotNeeded) {
    1216           6 :   v8::Isolate* isolate = CcTest::isolate();
    1217           6 :   v8::HandleScope scope(isolate);
    1218           6 :   v8::Local<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
    1219             :   templ_o->SetHandler(
    1220           6 :       v8::NamedPropertyHandlerConfiguration(InterceptorLoadXICGetter));
    1221           6 :   v8::Local<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
    1222           6 :   templ_p->SetAccessor(v8_str("y"), Return239Callback);
    1223             : 
    1224          12 :   LocalContext context;
    1225             :   context->Global()
    1226             :       ->Set(context.local(), v8_str("o"),
    1227          30 :             templ_o->NewInstance(context.local()).ToLocalChecked())
    1228          12 :       .FromJust();
    1229             :   context->Global()
    1230             :       ->Set(context.local(), v8_str("p"),
    1231          30 :             templ_p->NewInstance(context.local()).ToLocalChecked())
    1232          12 :       .FromJust();
    1233             : 
    1234             :   v8::Local<Value> value = CompileRun(
    1235             :       "o.__proto__ = p;"
    1236             :       "for (var i = 0; i < 7; i++) {"
    1237             :       "  o.x;"
    1238             :       // Now it should be ICed and keep a reference to x defined on p
    1239             :       "}"
    1240             :       "var result = 0;"
    1241             :       "for (var i = 0; i < 7; i++) {"
    1242             :       "  result += o.x;"
    1243             :       "}"
    1244             :       "result");
    1245          18 :   CHECK_EQ(42 * 7, value->Int32Value(context.local()).FromJust());
    1246           6 : }
    1247             : 
    1248             : 
    1249             : // Test the case when we stored callback into
    1250             : // a stub, but it got invalidated later on.
    1251       23724 : THREADED_TEST(InterceptorLoadICInvalidatedCallback) {
    1252           6 :   v8::Isolate* isolate = CcTest::isolate();
    1253           6 :   v8::HandleScope scope(isolate);
    1254           6 :   v8::Local<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
    1255             :   templ_o->SetHandler(
    1256           6 :       v8::NamedPropertyHandlerConfiguration(InterceptorLoadXICGetter));
    1257           6 :   v8::Local<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
    1258           6 :   templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
    1259             : 
    1260          12 :   LocalContext context;
    1261             :   context->Global()
    1262             :       ->Set(context.local(), v8_str("o"),
    1263          30 :             templ_o->NewInstance(context.local()).ToLocalChecked())
    1264          12 :       .FromJust();
    1265             :   context->Global()
    1266             :       ->Set(context.local(), v8_str("p"),
    1267          30 :             templ_p->NewInstance(context.local()).ToLocalChecked())
    1268          12 :       .FromJust();
    1269             : 
    1270             :   v8::Local<Value> value = CompileRun(
    1271             :       "inbetween = new Object();"
    1272             :       "o.__proto__ = inbetween;"
    1273             :       "inbetween.__proto__ = p;"
    1274             :       "for (var i = 0; i < 10; i++) {"
    1275             :       "  o.y;"
    1276             :       // Now it should be ICed and keep a reference to y defined on p
    1277             :       "}"
    1278             :       "inbetween.y = 42;"
    1279             :       "var result = 0;"
    1280             :       "for (var i = 0; i < 10; i++) {"
    1281             :       "  result += o.y;"
    1282             :       "}"
    1283             :       "result");
    1284          18 :   CHECK_EQ(42 * 10, value->Int32Value(context.local()).FromJust());
    1285           6 : }
    1286             : 
    1287             : 
    1288             : // Test the case when we stored callback into
    1289             : // a stub, but it got invalidated later on due to override on
    1290             : // global object which is between interceptor and callbacks' holders.
    1291       23724 : THREADED_TEST(InterceptorLoadICInvalidatedCallbackViaGlobal) {
    1292           6 :   v8::Isolate* isolate = CcTest::isolate();
    1293           6 :   v8::HandleScope scope(isolate);
    1294           6 :   v8::Local<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
    1295             :   templ_o->SetHandler(
    1296           6 :       v8::NamedPropertyHandlerConfiguration(InterceptorLoadXICGetter));
    1297           6 :   v8::Local<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
    1298           6 :   templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
    1299             : 
    1300          12 :   LocalContext context;
    1301             :   context->Global()
    1302             :       ->Set(context.local(), v8_str("o"),
    1303          30 :             templ_o->NewInstance(context.local()).ToLocalChecked())
    1304          12 :       .FromJust();
    1305             :   context->Global()
    1306             :       ->Set(context.local(), v8_str("p"),
    1307          30 :             templ_p->NewInstance(context.local()).ToLocalChecked())
    1308          12 :       .FromJust();
    1309             : 
    1310             :   v8::Local<Value> value = CompileRun(
    1311             :       "o.__proto__ = this;"
    1312             :       "this.__proto__ = p;"
    1313             :       "for (var i = 0; i < 10; i++) {"
    1314             :       "  if (o.y != 239) throw 'oops: ' + o.y;"
    1315             :       // Now it should be ICed and keep a reference to y defined on p
    1316             :       "}"
    1317             :       "this.y = 42;"
    1318             :       "var result = 0;"
    1319             :       "for (var i = 0; i < 10; i++) {"
    1320             :       "  result += o.y;"
    1321             :       "}"
    1322             :       "result");
    1323          18 :   CHECK_EQ(42 * 10, value->Int32Value(context.local()).FromJust());
    1324           6 : }
    1325             : 
    1326             : // Test load of a non-existing global when a global object has an interceptor.
    1327       23724 : THREADED_TEST(InterceptorLoadGlobalICGlobalWithInterceptor) {
    1328           6 :   v8::Isolate* isolate = CcTest::isolate();
    1329           6 :   v8::HandleScope scope(isolate);
    1330           6 :   v8::Local<v8::ObjectTemplate> templ_global = v8::ObjectTemplate::New(isolate);
    1331             :   templ_global->SetHandler(v8::NamedPropertyHandlerConfiguration(
    1332           6 :       EmptyInterceptorGetter, EmptyInterceptorSetter));
    1333             : 
    1334          12 :   LocalContext context(nullptr, templ_global);
    1335             :   i::Handle<i::JSReceiver> global_proxy =
    1336           6 :       v8::Utils::OpenHandle<Object, i::JSReceiver>(context->Global());
    1337           6 :   CHECK(global_proxy->IsJSGlobalProxy());
    1338             :   i::Handle<i::JSGlobalObject> global(
    1339             :       i::JSGlobalObject::cast(global_proxy->map()->prototype()));
    1340           6 :   CHECK(global->map()->has_named_interceptor());
    1341             : 
    1342             :   v8::Local<Value> value = CompileRun(
    1343             :       "var f = function() { "
    1344             :       "  try {"
    1345             :       "    x1;"
    1346             :       "  } catch(e) {"
    1347             :       "  }"
    1348             :       "  return typeof x1 === 'undefined';"
    1349             :       "};"
    1350             :       "for (var i = 0; i < 10; i++) {"
    1351             :       "  f();"
    1352             :       "};"
    1353             :       "f();");
    1354          12 :   CHECK(value->BooleanValue(context.local()).FromJust());
    1355             : 
    1356             :   value = CompileRun(
    1357             :       "var f = function() { "
    1358             :       "  try {"
    1359             :       "    x2;"
    1360             :       "    return false;"
    1361             :       "  } catch(e) {"
    1362             :       "    return true;"
    1363             :       "  }"
    1364             :       "};"
    1365             :       "for (var i = 0; i < 10; i++) {"
    1366             :       "  f();"
    1367             :       "};"
    1368             :       "f();");
    1369          12 :   CHECK(value->BooleanValue(context.local()).FromJust());
    1370             : 
    1371             :   value = CompileRun(
    1372             :       "var f = function() { "
    1373             :       "  try {"
    1374             :       "    typeof(x3);"
    1375             :       "    return true;"
    1376             :       "  } catch(e) {"
    1377             :       "    return false;"
    1378             :       "  }"
    1379             :       "};"
    1380             :       "for (var i = 0; i < 10; i++) {"
    1381             :       "  f();"
    1382             :       "};"
    1383             :       "f();");
    1384          18 :   CHECK(value->BooleanValue(context.local()).FromJust());
    1385           6 : }
    1386             : 
    1387             : // Test load of a non-existing global through prototype chain when a global
    1388             : // object has an interceptor.
    1389       23724 : THREADED_TEST(InterceptorLoadICGlobalWithInterceptor) {
    1390           6 :   i::FLAG_allow_natives_syntax = true;
    1391           6 :   v8::Isolate* isolate = CcTest::isolate();
    1392           6 :   v8::HandleScope scope(isolate);
    1393           6 :   v8::Local<v8::ObjectTemplate> templ_global = v8::ObjectTemplate::New(isolate);
    1394             :   templ_global->SetHandler(v8::NamedPropertyHandlerConfiguration(
    1395           6 :       GenericInterceptorGetter, GenericInterceptorSetter));
    1396             : 
    1397          12 :   LocalContext context(nullptr, templ_global);
    1398             :   i::Handle<i::JSReceiver> global_proxy =
    1399           6 :       v8::Utils::OpenHandle<Object, i::JSReceiver>(context->Global());
    1400           6 :   CHECK(global_proxy->IsJSGlobalProxy());
    1401             :   i::Handle<i::JSGlobalObject> global(
    1402             :       i::JSGlobalObject::cast(global_proxy->map()->prototype()));
    1403           6 :   CHECK(global->map()->has_named_interceptor());
    1404             : 
    1405             :   ExpectInt32(
    1406             :       "(function() {"
    1407             :       "  var f = function(obj) { "
    1408             :       "    return obj.foo;"
    1409             :       "  };"
    1410             :       "  var obj = { __proto__: this, _str_foo: 42 };"
    1411             :       "  for (var i = 0; i < 1500; i++) obj['p' + i] = 0;"
    1412             :       "  /* Ensure that |obj| is in dictionary mode. */"
    1413             :       "  if (%HasFastProperties(obj)) return -1;"
    1414             :       "  for (var i = 0; i < 3; i++) {"
    1415             :       "    f(obj);"
    1416             :       "  };"
    1417             :       "  return f(obj);"
    1418             :       "})();",
    1419          12 :       42);
    1420           6 : }
    1421             : 
    1422           6 : static void InterceptorLoadICGetter0(
    1423             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    1424           6 :   ApiTestFuzzer::Fuzz();
    1425          18 :   CHECK(v8_str("x")
    1426             :             ->Equals(info.GetIsolate()->GetCurrentContext(), name)
    1427             :             .FromJust());
    1428           6 :   info.GetReturnValue().Set(v8::Integer::New(info.GetIsolate(), 0));
    1429           6 : }
    1430             : 
    1431             : 
    1432       23724 : THREADED_TEST(InterceptorReturningZero) {
    1433             :   CheckInterceptorLoadIC(InterceptorLoadICGetter0, "o.x == undefined ? 1 : 0",
    1434           6 :                          0);
    1435           6 : }
    1436             : 
    1437             : 
    1438        6000 : static void InterceptorStoreICSetter(
    1439             :     Local<Name> key, Local<Value> value,
    1440             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
    1441        6000 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    1442       18000 :   CHECK(v8_str("x")->Equals(context, key).FromJust());
    1443       12000 :   CHECK_EQ(42, value->Int32Value(context).FromJust());
    1444             :   info.GetReturnValue().Set(value);
    1445        6000 : }
    1446             : 
    1447             : 
    1448             : // This test should hit the store IC for the interceptor case.
    1449       23724 : THREADED_TEST(InterceptorStoreIC) {
    1450           6 :   v8::Isolate* isolate = CcTest::isolate();
    1451           6 :   v8::HandleScope scope(isolate);
    1452           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    1453             :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
    1454             :       InterceptorLoadICGetter, InterceptorStoreICSetter, 0, 0, 0,
    1455          12 :       v8_str("data")));
    1456          12 :   LocalContext context;
    1457             :   context->Global()
    1458             :       ->Set(context.local(), v8_str("o"),
    1459          30 :             templ->NewInstance(context.local()).ToLocalChecked())
    1460          12 :       .FromJust();
    1461             :   CompileRun(
    1462             :       "for (var i = 0; i < 1000; i++) {"
    1463             :       "  o.x = 42;"
    1464           6 :       "}");
    1465           6 : }
    1466             : 
    1467             : 
    1468       23724 : THREADED_TEST(InterceptorStoreICWithNoSetter) {
    1469           6 :   v8::Isolate* isolate = CcTest::isolate();
    1470           6 :   v8::HandleScope scope(isolate);
    1471           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    1472             :   templ->SetHandler(
    1473           6 :       v8::NamedPropertyHandlerConfiguration(InterceptorLoadXICGetter));
    1474          12 :   LocalContext context;
    1475             :   context->Global()
    1476             :       ->Set(context.local(), v8_str("o"),
    1477          30 :             templ->NewInstance(context.local()).ToLocalChecked())
    1478          12 :       .FromJust();
    1479             :   v8::Local<Value> value = CompileRun(
    1480             :       "for (var i = 0; i < 1000; i++) {"
    1481             :       "  o.y = 239;"
    1482             :       "}"
    1483             :       "42 + o.y");
    1484          18 :   CHECK_EQ(239 + 42, value->Int32Value(context.local()).FromJust());
    1485           6 : }
    1486             : 
    1487             : 
    1488       23724 : THREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) {
    1489           6 :   v8::HandleScope scope(CcTest::isolate());
    1490           6 :   Local<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
    1491           6 :   Local<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
    1492           6 :   child->Inherit(parent);
    1493             :   AddAccessor(parent, v8_str("age"), SimpleAccessorGetter,
    1494           6 :               SimpleAccessorSetter);
    1495           6 :   AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
    1496          12 :   LocalContext env;
    1497             :   env->Global()
    1498             :       ->Set(env.local(), v8_str("Child"),
    1499          30 :             child->GetFunction(env.local()).ToLocalChecked())
    1500          12 :       .FromJust();
    1501             :   CompileRun(
    1502             :       "var child = new Child;"
    1503             :       "child.age = 10;");
    1504           6 :   ExpectBoolean("child.hasOwnProperty('age')", false);
    1505           6 :   ExpectInt32("child.age", 10);
    1506          12 :   ExpectInt32("child.accessor_age", 10);
    1507           6 : }
    1508             : 
    1509             : 
    1510       23724 : THREADED_TEST(LegacyInterceptorDoesNotSeeSymbols) {
    1511           6 :   LocalContext env;
    1512           6 :   v8::Isolate* isolate = CcTest::isolate();
    1513          12 :   v8::HandleScope scope(isolate);
    1514           6 :   Local<FunctionTemplate> parent = FunctionTemplate::New(isolate);
    1515           6 :   Local<FunctionTemplate> child = FunctionTemplate::New(isolate);
    1516           6 :   v8::Local<v8::Symbol> age = v8::Symbol::New(isolate, v8_str("age"));
    1517             : 
    1518           6 :   child->Inherit(parent);
    1519           6 :   AddAccessor(parent, age, SymbolAccessorGetter, SymbolAccessorSetter);
    1520           6 :   AddInterceptor(child, StringInterceptorGetter, StringInterceptorSetter);
    1521             : 
    1522             :   env->Global()
    1523             :       ->Set(env.local(), v8_str("Child"),
    1524          30 :             child->GetFunction(env.local()).ToLocalChecked())
    1525          12 :       .FromJust();
    1526          30 :   env->Global()->Set(env.local(), v8_str("age"), age).FromJust();
    1527             :   CompileRun(
    1528             :       "var child = new Child;"
    1529             :       "child[age] = 10;");
    1530           6 :   ExpectInt32("child[age]", 10);
    1531           6 :   ExpectBoolean("child.hasOwnProperty('age')", false);
    1532          12 :   ExpectBoolean("child.hasOwnProperty('accessor_age')", true);
    1533           6 : }
    1534             : 
    1535             : 
    1536       23724 : THREADED_TEST(GenericInterceptorDoesSeeSymbols) {
    1537           6 :   LocalContext env;
    1538           6 :   v8::Isolate* isolate = CcTest::isolate();
    1539          12 :   v8::HandleScope scope(isolate);
    1540           6 :   Local<FunctionTemplate> parent = FunctionTemplate::New(isolate);
    1541           6 :   Local<FunctionTemplate> child = FunctionTemplate::New(isolate);
    1542           6 :   v8::Local<v8::Symbol> age = v8::Symbol::New(isolate, v8_str("age"));
    1543           6 :   v8::Local<v8::Symbol> anon = v8::Symbol::New(isolate);
    1544             : 
    1545           6 :   child->Inherit(parent);
    1546           6 :   AddAccessor(parent, age, SymbolAccessorGetter, SymbolAccessorSetter);
    1547           6 :   AddInterceptor(child, GenericInterceptorGetter, GenericInterceptorSetter);
    1548             : 
    1549             :   env->Global()
    1550             :       ->Set(env.local(), v8_str("Child"),
    1551          30 :             child->GetFunction(env.local()).ToLocalChecked())
    1552          12 :       .FromJust();
    1553          30 :   env->Global()->Set(env.local(), v8_str("age"), age).FromJust();
    1554          30 :   env->Global()->Set(env.local(), v8_str("anon"), anon).FromJust();
    1555             :   CompileRun(
    1556             :       "var child = new Child;"
    1557             :       "child[age] = 10;");
    1558           6 :   ExpectInt32("child[age]", 10);
    1559           6 :   ExpectInt32("child._sym_age", 10);
    1560             : 
    1561             :   // Check that it also sees strings.
    1562             :   CompileRun("child.foo = 47");
    1563           6 :   ExpectInt32("child.foo", 47);
    1564           6 :   ExpectInt32("child._str_foo", 47);
    1565             : 
    1566             :   // Check that the interceptor can punt (in this case, on anonymous symbols).
    1567             :   CompileRun("child[anon] = 31337");
    1568          12 :   ExpectInt32("child[anon]", 31337);
    1569           6 : }
    1570             : 
    1571             : 
    1572       23724 : THREADED_TEST(NamedPropertyHandlerGetter) {
    1573           6 :   echo_named_call_count = 0;
    1574           6 :   v8::HandleScope scope(CcTest::isolate());
    1575             :   v8::Local<v8::FunctionTemplate> templ =
    1576           6 :       v8::FunctionTemplate::New(CcTest::isolate());
    1577             :   templ->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration(
    1578          18 :       EchoNamedProperty, 0, 0, 0, 0, v8_str("data")));
    1579          12 :   LocalContext env;
    1580             :   env->Global()
    1581           6 :       ->Set(env.local(), v8_str("obj"), templ->GetFunction(env.local())
    1582           6 :                                             .ToLocalChecked()
    1583           6 :                                             ->NewInstance(env.local())
    1584          24 :                                             .ToLocalChecked())
    1585          12 :       .FromJust();
    1586           6 :   CHECK_EQ(0, echo_named_call_count);
    1587          12 :   v8_compile("obj.x")->Run(env.local()).ToLocalChecked();
    1588           6 :   CHECK_EQ(1, echo_named_call_count);
    1589             :   const char* code = "var str = 'oddle'; obj[str] + obj.poddle;";
    1590           6 :   v8::Local<Value> str = CompileRun(code);
    1591          12 :   String::Utf8Value value(CcTest::isolate(), str);
    1592           6 :   CHECK_EQ(0, strcmp(*value, "oddlepoddle"));
    1593             :   // Check default behavior
    1594          24 :   CHECK_EQ(10, v8_compile("obj.flob = 10;")
    1595             :                    ->Run(env.local())
    1596             :                    .ToLocalChecked()
    1597             :                    ->Int32Value(env.local())
    1598             :                    .FromJust());
    1599          24 :   CHECK(v8_compile("'myProperty' in obj")
    1600             :             ->Run(env.local())
    1601             :             .ToLocalChecked()
    1602             :             ->BooleanValue(env.local())
    1603             :             .FromJust());
    1604          24 :   CHECK(v8_compile("delete obj.myProperty")
    1605             :             ->Run(env.local())
    1606             :             .ToLocalChecked()
    1607             :             ->BooleanValue(env.local())
    1608           6 :             .FromJust());
    1609           6 : }
    1610             : 
    1611             : namespace {
    1612           6 : void NotInterceptingPropertyDefineCallback(
    1613             :     Local<Name> name, const v8::PropertyDescriptor& desc,
    1614             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
    1615             :   // Do not intercept by not calling info.GetReturnValue().Set().
    1616           6 : }
    1617             : 
    1618           6 : void InterceptingPropertyDefineCallback(
    1619             :     Local<Name> name, const v8::PropertyDescriptor& desc,
    1620             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
    1621             :   // Intercept the callback by setting a non-empty handle
    1622             :   info.GetReturnValue().Set(name);
    1623           6 : }
    1624             : 
    1625           6 : void CheckDescriptorInDefineCallback(
    1626             :     Local<Name> name, const v8::PropertyDescriptor& desc,
    1627             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
    1628           6 :   CHECK(!desc.has_writable());
    1629           6 :   CHECK(!desc.has_value());
    1630           6 :   CHECK(!desc.has_enumerable());
    1631           6 :   CHECK(desc.has_configurable());
    1632           6 :   CHECK(!desc.configurable());
    1633           6 :   CHECK(desc.has_get());
    1634          12 :   CHECK(desc.get()->IsFunction());
    1635           6 :   CHECK(desc.has_set());
    1636          12 :   CHECK(desc.set()->IsUndefined());
    1637             :   // intercept the callback by setting a non-empty handle
    1638             :   info.GetReturnValue().Set(name);
    1639           6 : }
    1640             : }  // namespace
    1641             : 
    1642       23724 : THREADED_TEST(PropertyDefinerCallback) {
    1643           6 :   v8::HandleScope scope(CcTest::isolate());
    1644          12 :   LocalContext env;
    1645             : 
    1646             :   {  // Intercept defineProperty()
    1647             :     v8::Local<v8::FunctionTemplate> templ =
    1648           6 :         v8::FunctionTemplate::New(CcTest::isolate());
    1649             :     templ->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration(
    1650          12 :         0, 0, 0, 0, 0, NotInterceptingPropertyDefineCallback));
    1651             :     env->Global()
    1652           6 :         ->Set(env.local(), v8_str("obj"), templ->GetFunction(env.local())
    1653           6 :                                               .ToLocalChecked()
    1654           6 :                                               ->NewInstance(env.local())
    1655          24 :                                               .ToLocalChecked())
    1656          12 :         .FromJust();
    1657             :     const char* code =
    1658             :         "obj.x = 17; "
    1659             :         "Object.defineProperty(obj, 'x', {value: 42});"
    1660             :         "obj.x;";
    1661          24 :     CHECK_EQ(42, v8_compile(code)
    1662             :                      ->Run(env.local())
    1663             :                      .ToLocalChecked()
    1664             :                      ->Int32Value(env.local())
    1665             :                      .FromJust());
    1666             :   }
    1667             : 
    1668             :   {  // Intercept defineProperty() for correct accessor descriptor
    1669             :     v8::Local<v8::FunctionTemplate> templ =
    1670           6 :         v8::FunctionTemplate::New(CcTest::isolate());
    1671             :     templ->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration(
    1672          12 :         0, 0, 0, 0, 0, CheckDescriptorInDefineCallback));
    1673             :     env->Global()
    1674           6 :         ->Set(env.local(), v8_str("obj"), templ->GetFunction(env.local())
    1675           6 :                                               .ToLocalChecked()
    1676           6 :                                               ->NewInstance(env.local())
    1677          24 :                                               .ToLocalChecked())
    1678          12 :         .FromJust();
    1679             :     const char* code =
    1680             :         "obj.x = 17; "
    1681             :         "Object.defineProperty(obj, 'x', {"
    1682             :         "get: function(){ return 42; }, "
    1683             :         "set: undefined,"
    1684             :         "configurable: 0"
    1685             :         "});"
    1686             :         "obj.x;";
    1687          24 :     CHECK_EQ(17, v8_compile(code)
    1688             :                      ->Run(env.local())
    1689             :                      .ToLocalChecked()
    1690             :                      ->Int32Value(env.local())
    1691             :                      .FromJust());
    1692             :   }
    1693             : 
    1694             :   {  // Do not intercept defineProperty()
    1695             :     v8::Local<v8::FunctionTemplate> templ2 =
    1696           6 :         v8::FunctionTemplate::New(CcTest::isolate());
    1697             :     templ2->InstanceTemplate()->SetHandler(
    1698             :         v8::NamedPropertyHandlerConfiguration(
    1699          12 :             0, 0, 0, 0, 0, InterceptingPropertyDefineCallback));
    1700             :     env->Global()
    1701           6 :         ->Set(env.local(), v8_str("obj"), templ2->GetFunction(env.local())
    1702           6 :                                               .ToLocalChecked()
    1703           6 :                                               ->NewInstance(env.local())
    1704          24 :                                               .ToLocalChecked())
    1705          12 :         .FromJust();
    1706             : 
    1707             :     const char* code =
    1708             :         "obj.x = 17; "
    1709             :         "Object.defineProperty(obj, 'x', {value: 42});"
    1710             :         "obj.x;";
    1711          24 :     CHECK_EQ(17, v8_compile(code)
    1712             :                      ->Run(env.local())
    1713             :                      .ToLocalChecked()
    1714             :                      ->Int32Value(env.local())
    1715             :                      .FromJust());
    1716           6 :   }
    1717           6 : }
    1718             : 
    1719             : namespace {
    1720           6 : void NotInterceptingPropertyDefineCallbackIndexed(
    1721             :     uint32_t index, const v8::PropertyDescriptor& desc,
    1722             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
    1723             :   // Do not intercept by not calling info.GetReturnValue().Set()
    1724           6 : }
    1725             : 
    1726           6 : void InterceptingPropertyDefineCallbackIndexed(
    1727             :     uint32_t index, const v8::PropertyDescriptor& desc,
    1728             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
    1729             :   // intercept the callback by setting a non-empty handle
    1730             :   info.GetReturnValue().Set(index);
    1731           6 : }
    1732             : 
    1733           6 : void CheckDescriptorInDefineCallbackIndexed(
    1734             :     uint32_t index, const v8::PropertyDescriptor& desc,
    1735             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
    1736           6 :   CHECK(!desc.has_writable());
    1737           6 :   CHECK(!desc.has_value());
    1738           6 :   CHECK(desc.has_enumerable());
    1739           6 :   CHECK(desc.enumerable());
    1740           6 :   CHECK(!desc.has_configurable());
    1741           6 :   CHECK(desc.has_get());
    1742          12 :   CHECK(desc.get()->IsFunction());
    1743           6 :   CHECK(desc.has_set());
    1744          12 :   CHECK(desc.set()->IsUndefined());
    1745             :   // intercept the callback by setting a non-empty handle
    1746             :   info.GetReturnValue().Set(index);
    1747           6 : }
    1748             : }  // namespace
    1749             : 
    1750       23724 : THREADED_TEST(PropertyDefinerCallbackIndexed) {
    1751           6 :   v8::HandleScope scope(CcTest::isolate());
    1752          12 :   LocalContext env;
    1753             : 
    1754             :   {  // Intercept defineProperty()
    1755             :     v8::Local<v8::FunctionTemplate> templ =
    1756           6 :         v8::FunctionTemplate::New(CcTest::isolate());
    1757             :     templ->InstanceTemplate()->SetHandler(
    1758             :         v8::IndexedPropertyHandlerConfiguration(
    1759          12 :             0, 0, 0, 0, 0, NotInterceptingPropertyDefineCallbackIndexed));
    1760             :     env->Global()
    1761           6 :         ->Set(env.local(), v8_str("obj"), templ->GetFunction(env.local())
    1762           6 :                                               .ToLocalChecked()
    1763           6 :                                               ->NewInstance(env.local())
    1764          24 :                                               .ToLocalChecked())
    1765          12 :         .FromJust();
    1766             :     const char* code =
    1767             :         "obj[2] = 17; "
    1768             :         "Object.defineProperty(obj, 2, {value: 42});"
    1769             :         "obj[2];";
    1770          24 :     CHECK_EQ(42, v8_compile(code)
    1771             :                      ->Run(env.local())
    1772             :                      .ToLocalChecked()
    1773             :                      ->Int32Value(env.local())
    1774             :                      .FromJust());
    1775             :   }
    1776             : 
    1777             :   {  // Intercept defineProperty() for correct accessor descriptor
    1778             :     v8::Local<v8::FunctionTemplate> templ =
    1779           6 :         v8::FunctionTemplate::New(CcTest::isolate());
    1780             :     templ->InstanceTemplate()->SetHandler(
    1781             :         v8::IndexedPropertyHandlerConfiguration(
    1782          12 :             0, 0, 0, 0, 0, CheckDescriptorInDefineCallbackIndexed));
    1783             :     env->Global()
    1784           6 :         ->Set(env.local(), v8_str("obj"), templ->GetFunction(env.local())
    1785           6 :                                               .ToLocalChecked()
    1786           6 :                                               ->NewInstance(env.local())
    1787          24 :                                               .ToLocalChecked())
    1788          12 :         .FromJust();
    1789             :     const char* code =
    1790             :         "obj[2] = 17; "
    1791             :         "Object.defineProperty(obj, 2, {"
    1792             :         "get: function(){ return 42; }, "
    1793             :         "set: undefined,"
    1794             :         "enumerable: true"
    1795             :         "});"
    1796             :         "obj[2];";
    1797          24 :     CHECK_EQ(17, v8_compile(code)
    1798             :                      ->Run(env.local())
    1799             :                      .ToLocalChecked()
    1800             :                      ->Int32Value(env.local())
    1801             :                      .FromJust());
    1802             :   }
    1803             : 
    1804             :   {  // Do not intercept defineProperty()
    1805             :     v8::Local<v8::FunctionTemplate> templ2 =
    1806           6 :         v8::FunctionTemplate::New(CcTest::isolate());
    1807             :     templ2->InstanceTemplate()->SetHandler(
    1808             :         v8::IndexedPropertyHandlerConfiguration(
    1809          12 :             0, 0, 0, 0, 0, InterceptingPropertyDefineCallbackIndexed));
    1810             :     env->Global()
    1811           6 :         ->Set(env.local(), v8_str("obj"), templ2->GetFunction(env.local())
    1812           6 :                                               .ToLocalChecked()
    1813           6 :                                               ->NewInstance(env.local())
    1814          24 :                                               .ToLocalChecked())
    1815          12 :         .FromJust();
    1816             : 
    1817             :     const char* code =
    1818             :         "obj[2] = 17; "
    1819             :         "Object.defineProperty(obj, 2, {value: 42});"
    1820             :         "obj[2];";
    1821          24 :     CHECK_EQ(17, v8_compile(code)
    1822             :                      ->Run(env.local())
    1823             :                      .ToLocalChecked()
    1824             :                      ->Int32Value(env.local())
    1825             :                      .FromJust());
    1826           6 :   }
    1827           6 : }
    1828             : 
    1829             : // Test that freeze() is intercepted.
    1830       23724 : THREADED_TEST(PropertyDefinerCallbackForFreeze) {
    1831           6 :   v8::HandleScope scope(CcTest::isolate());
    1832          12 :   LocalContext env;
    1833             :   v8::Local<v8::FunctionTemplate> templ =
    1834           6 :       v8::FunctionTemplate::New(CcTest::isolate());
    1835             :   templ->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration(
    1836          12 :       0, 0, 0, 0, 0, InterceptingPropertyDefineCallback));
    1837             :   env->Global()
    1838           6 :       ->Set(env.local(), v8_str("obj"), templ->GetFunction(env.local())
    1839           6 :                                             .ToLocalChecked()
    1840           6 :                                             ->NewInstance(env.local())
    1841          24 :                                             .ToLocalChecked())
    1842          12 :       .FromJust();
    1843             :   const char* code =
    1844             :       "obj.x = 17; "
    1845             :       "Object.freeze(obj.x); "
    1846             :       "Object.isFrozen(obj.x);";
    1847             : 
    1848          24 :   CHECK(v8_compile(code)
    1849             :             ->Run(env.local())
    1850             :             .ToLocalChecked()
    1851             :             ->BooleanValue(env.local())
    1852           6 :             .FromJust());
    1853           6 : }
    1854             : 
    1855             : // Check that the descriptor passed to the callback is enumerable.
    1856             : namespace {
    1857           6 : void CheckEnumerablePropertyDefineCallback(
    1858             :     Local<Name> name, const v8::PropertyDescriptor& desc,
    1859             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
    1860           6 :   CHECK(desc.has_value());
    1861          18 :   CHECK_EQ(42, desc.value()
    1862             :                    ->Int32Value(info.GetIsolate()->GetCurrentContext())
    1863             :                    .FromJust());
    1864           6 :   CHECK(desc.has_enumerable());
    1865           6 :   CHECK(desc.enumerable());
    1866           6 :   CHECK(!desc.has_writable());
    1867             : 
    1868             :   // intercept the callback by setting a non-empty handle
    1869             :   info.GetReturnValue().Set(name);
    1870           6 : }
    1871             : }  // namespace
    1872       23724 : THREADED_TEST(PropertyDefinerCallbackEnumerable) {
    1873           6 :   v8::HandleScope scope(CcTest::isolate());
    1874          12 :   LocalContext env;
    1875             :   v8::Local<v8::FunctionTemplate> templ =
    1876           6 :       v8::FunctionTemplate::New(CcTest::isolate());
    1877             :   templ->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration(
    1878          12 :       0, 0, 0, 0, 0, CheckEnumerablePropertyDefineCallback));
    1879             :   env->Global()
    1880           6 :       ->Set(env.local(), v8_str("obj"), templ->GetFunction(env.local())
    1881           6 :                                             .ToLocalChecked()
    1882           6 :                                             ->NewInstance(env.local())
    1883          24 :                                             .ToLocalChecked())
    1884          12 :       .FromJust();
    1885             :   const char* code =
    1886             :       "obj.x = 17; "
    1887             :       "Object.defineProperty(obj, 'x', {value: 42, enumerable: true});"
    1888             :       "obj.x;";
    1889          24 :   CHECK_EQ(17, v8_compile(code)
    1890             :                    ->Run(env.local())
    1891             :                    .ToLocalChecked()
    1892             :                    ->Int32Value(env.local())
    1893           6 :                    .FromJust());
    1894           6 : }
    1895             : 
    1896             : // Check that the descriptor passed to the callback is configurable.
    1897             : namespace {
    1898           6 : void CheckConfigurablePropertyDefineCallback(
    1899             :     Local<Name> name, const v8::PropertyDescriptor& desc,
    1900             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
    1901           6 :   CHECK(desc.has_value());
    1902          18 :   CHECK_EQ(42, desc.value()
    1903             :                    ->Int32Value(info.GetIsolate()->GetCurrentContext())
    1904             :                    .FromJust());
    1905           6 :   CHECK(desc.has_configurable());
    1906           6 :   CHECK(desc.configurable());
    1907             : 
    1908             :   // intercept the callback by setting a non-empty handle
    1909             :   info.GetReturnValue().Set(name);
    1910           6 : }
    1911             : }  // namespace
    1912       23724 : THREADED_TEST(PropertyDefinerCallbackConfigurable) {
    1913           6 :   v8::HandleScope scope(CcTest::isolate());
    1914          12 :   LocalContext env;
    1915             :   v8::Local<v8::FunctionTemplate> templ =
    1916           6 :       v8::FunctionTemplate::New(CcTest::isolate());
    1917             :   templ->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration(
    1918          12 :       0, 0, 0, 0, 0, CheckConfigurablePropertyDefineCallback));
    1919             :   env->Global()
    1920           6 :       ->Set(env.local(), v8_str("obj"), templ->GetFunction(env.local())
    1921           6 :                                             .ToLocalChecked()
    1922           6 :                                             ->NewInstance(env.local())
    1923          24 :                                             .ToLocalChecked())
    1924          12 :       .FromJust();
    1925             :   const char* code =
    1926             :       "obj.x = 17; "
    1927             :       "Object.defineProperty(obj, 'x', {value: 42, configurable: true});"
    1928             :       "obj.x;";
    1929          24 :   CHECK_EQ(17, v8_compile(code)
    1930             :                    ->Run(env.local())
    1931             :                    .ToLocalChecked()
    1932             :                    ->Int32Value(env.local())
    1933           6 :                    .FromJust());
    1934           6 : }
    1935             : 
    1936             : // Check that the descriptor passed to the callback is writable.
    1937             : namespace {
    1938           6 : void CheckWritablePropertyDefineCallback(
    1939             :     Local<Name> name, const v8::PropertyDescriptor& desc,
    1940             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
    1941           6 :   CHECK(desc.has_writable());
    1942           6 :   CHECK(desc.writable());
    1943             : 
    1944             :   // intercept the callback by setting a non-empty handle
    1945             :   info.GetReturnValue().Set(name);
    1946           6 : }
    1947             : }  // namespace
    1948       23724 : THREADED_TEST(PropertyDefinerCallbackWritable) {
    1949           6 :   v8::HandleScope scope(CcTest::isolate());
    1950          12 :   LocalContext env;
    1951             :   v8::Local<v8::FunctionTemplate> templ =
    1952           6 :       v8::FunctionTemplate::New(CcTest::isolate());
    1953             :   templ->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration(
    1954          12 :       0, 0, 0, 0, 0, CheckWritablePropertyDefineCallback));
    1955             :   env->Global()
    1956           6 :       ->Set(env.local(), v8_str("obj"), templ->GetFunction(env.local())
    1957           6 :                                             .ToLocalChecked()
    1958           6 :                                             ->NewInstance(env.local())
    1959          24 :                                             .ToLocalChecked())
    1960          12 :       .FromJust();
    1961             :   const char* code =
    1962             :       "obj.x = 17; "
    1963             :       "Object.defineProperty(obj, 'x', {value: 42, writable: true});"
    1964             :       "obj.x;";
    1965          24 :   CHECK_EQ(17, v8_compile(code)
    1966             :                    ->Run(env.local())
    1967             :                    .ToLocalChecked()
    1968             :                    ->Int32Value(env.local())
    1969           6 :                    .FromJust());
    1970           6 : }
    1971             : 
    1972             : // Check that the descriptor passed to the callback has a getter.
    1973             : namespace {
    1974           6 : void CheckGetterPropertyDefineCallback(
    1975             :     Local<Name> name, const v8::PropertyDescriptor& desc,
    1976             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
    1977           6 :   CHECK(desc.has_get());
    1978           6 :   CHECK(!desc.has_set());
    1979             :   // intercept the callback by setting a non-empty handle
    1980             :   info.GetReturnValue().Set(name);
    1981           6 : }
    1982             : }  // namespace
    1983       23724 : THREADED_TEST(PropertyDefinerCallbackWithGetter) {
    1984           6 :   v8::HandleScope scope(CcTest::isolate());
    1985          12 :   LocalContext env;
    1986             :   v8::Local<v8::FunctionTemplate> templ =
    1987           6 :       v8::FunctionTemplate::New(CcTest::isolate());
    1988             :   templ->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration(
    1989          12 :       0, 0, 0, 0, 0, CheckGetterPropertyDefineCallback));
    1990             :   env->Global()
    1991           6 :       ->Set(env.local(), v8_str("obj"), templ->GetFunction(env.local())
    1992           6 :                                             .ToLocalChecked()
    1993           6 :                                             ->NewInstance(env.local())
    1994          24 :                                             .ToLocalChecked())
    1995          12 :       .FromJust();
    1996             :   const char* code =
    1997             :       "obj.x = 17;"
    1998             :       "Object.defineProperty(obj, 'x', {get: function() {return 42;}});"
    1999             :       "obj.x;";
    2000          24 :   CHECK_EQ(17, v8_compile(code)
    2001             :                    ->Run(env.local())
    2002             :                    .ToLocalChecked()
    2003             :                    ->Int32Value(env.local())
    2004           6 :                    .FromJust());
    2005           6 : }
    2006             : 
    2007             : // Check that the descriptor passed to the callback has a setter.
    2008             : namespace {
    2009           6 : void CheckSetterPropertyDefineCallback(
    2010             :     Local<Name> name, const v8::PropertyDescriptor& desc,
    2011             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
    2012           6 :   CHECK(desc.has_set());
    2013           6 :   CHECK(!desc.has_get());
    2014             :   // intercept the callback by setting a non-empty handle
    2015             :   info.GetReturnValue().Set(name);
    2016           6 : }
    2017             : }  // namespace
    2018       23724 : THREADED_TEST(PropertyDefinerCallbackWithSetter) {
    2019           6 :   v8::HandleScope scope(CcTest::isolate());
    2020          12 :   LocalContext env;
    2021             :   v8::Local<v8::FunctionTemplate> templ =
    2022           6 :       v8::FunctionTemplate::New(CcTest::isolate());
    2023             :   templ->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration(
    2024          12 :       0, 0, 0, 0, 0, CheckSetterPropertyDefineCallback));
    2025             :   env->Global()
    2026           6 :       ->Set(env.local(), v8_str("obj"), templ->GetFunction(env.local())
    2027           6 :                                             .ToLocalChecked()
    2028           6 :                                             ->NewInstance(env.local())
    2029          24 :                                             .ToLocalChecked())
    2030          12 :       .FromJust();
    2031             :   const char* code =
    2032             :       "Object.defineProperty(obj, 'x', {set: function() {return 42;}});"
    2033             :       "obj.x = 17;";
    2034          24 :   CHECK_EQ(17, v8_compile(code)
    2035             :                    ->Run(env.local())
    2036             :                    .ToLocalChecked()
    2037             :                    ->Int32Value(env.local())
    2038           6 :                    .FromJust());
    2039           6 : }
    2040             : 
    2041             : namespace {
    2042           6 : void EmptyPropertyDescriptorCallback(
    2043             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2044             :   // Do not intercept by not calling info.GetReturnValue().Set().
    2045           6 : }
    2046             : 
    2047           6 : void InterceptingPropertyDescriptorCallback(
    2048             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2049             :   // Intercept the callback by setting a different descriptor.
    2050             :   const char* code =
    2051             :       "var desc = {value: 42};"
    2052             :       "desc;";
    2053             :   Local<Value> descriptor = v8_compile(code)
    2054           6 :                                 ->Run(info.GetIsolate()->GetCurrentContext())
    2055           6 :                                 .ToLocalChecked();
    2056             :   info.GetReturnValue().Set(descriptor);
    2057           6 : }
    2058             : }  // namespace
    2059             : 
    2060       23724 : THREADED_TEST(PropertyDescriptorCallback) {
    2061           6 :   v8::HandleScope scope(CcTest::isolate());
    2062          12 :   LocalContext env;
    2063             : 
    2064             :   {  // Normal behavior of getOwnPropertyDescriptor() with empty callback.
    2065             :     v8::Local<v8::FunctionTemplate> templ =
    2066           6 :         v8::FunctionTemplate::New(CcTest::isolate());
    2067             :     templ->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration(
    2068          12 :         0, 0, EmptyPropertyDescriptorCallback, 0, 0, 0));
    2069             :     env->Global()
    2070           6 :         ->Set(env.local(), v8_str("obj"), templ->GetFunction(env.local())
    2071           6 :                                               .ToLocalChecked()
    2072           6 :                                               ->NewInstance(env.local())
    2073          24 :                                               .ToLocalChecked())
    2074          12 :         .FromJust();
    2075             :     const char* code =
    2076             :         "obj.x = 17; "
    2077             :         "var desc = Object.getOwnPropertyDescriptor(obj, 'x');"
    2078             :         "desc.value;";
    2079          24 :     CHECK_EQ(17, v8_compile(code)
    2080             :                      ->Run(env.local())
    2081             :                      .ToLocalChecked()
    2082             :                      ->Int32Value(env.local())
    2083             :                      .FromJust());
    2084             :   }
    2085             : 
    2086             :   {  // Intercept getOwnPropertyDescriptor().
    2087             :     v8::Local<v8::FunctionTemplate> templ =
    2088           6 :         v8::FunctionTemplate::New(CcTest::isolate());
    2089             :     templ->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration(
    2090          12 :         0, 0, InterceptingPropertyDescriptorCallback, 0, 0, 0));
    2091             :     env->Global()
    2092           6 :         ->Set(env.local(), v8_str("obj"), templ->GetFunction(env.local())
    2093           6 :                                               .ToLocalChecked()
    2094           6 :                                               ->NewInstance(env.local())
    2095          24 :                                               .ToLocalChecked())
    2096          12 :         .FromJust();
    2097             :     const char* code =
    2098             :         "obj.x = 17; "
    2099             :         "var desc = Object.getOwnPropertyDescriptor(obj, 'x');"
    2100             :         "desc.value;";
    2101          24 :     CHECK_EQ(42, v8_compile(code)
    2102             :                      ->Run(env.local())
    2103             :                      .ToLocalChecked()
    2104             :                      ->Int32Value(env.local())
    2105             :                      .FromJust());
    2106           6 :   }
    2107           6 : }
    2108             : 
    2109             : namespace {
    2110             : int echo_indexed_call_count = 0;
    2111             : }  // namespace
    2112             : 
    2113           6 : static void EchoIndexedProperty(
    2114             :     uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2115           6 :   ApiTestFuzzer::Fuzz();
    2116          18 :   CHECK(v8_num(637)
    2117             :             ->Equals(info.GetIsolate()->GetCurrentContext(), info.Data())
    2118             :             .FromJust());
    2119           6 :   echo_indexed_call_count++;
    2120           6 :   info.GetReturnValue().Set(v8_num(index));
    2121           6 : }
    2122             : 
    2123             : 
    2124       23724 : THREADED_TEST(IndexedPropertyHandlerGetter) {
    2125           6 :   v8::Isolate* isolate = CcTest::isolate();
    2126           6 :   v8::HandleScope scope(isolate);
    2127           6 :   v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
    2128             :   templ->InstanceTemplate()->SetHandler(v8::IndexedPropertyHandlerConfiguration(
    2129          18 :       EchoIndexedProperty, 0, 0, 0, 0, v8_num(637)));
    2130          12 :   LocalContext env;
    2131             :   env->Global()
    2132           6 :       ->Set(env.local(), v8_str("obj"), templ->GetFunction(env.local())
    2133           6 :                                             .ToLocalChecked()
    2134           6 :                                             ->NewInstance(env.local())
    2135          24 :                                             .ToLocalChecked())
    2136          12 :       .FromJust();
    2137             :   Local<Script> script = v8_compile("obj[900]");
    2138          18 :   CHECK_EQ(900, script->Run(env.local())
    2139             :                     .ToLocalChecked()
    2140             :                     ->Int32Value(env.local())
    2141           6 :                     .FromJust());
    2142           6 : }
    2143             : 
    2144             : 
    2145       23724 : THREADED_TEST(PropertyHandlerInPrototype) {
    2146           6 :   LocalContext env;
    2147           6 :   v8::Isolate* isolate = env->GetIsolate();
    2148          12 :   v8::HandleScope scope(isolate);
    2149             : 
    2150           6 :   v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
    2151             :   templ->InstanceTemplate()->SetHandler(v8::IndexedPropertyHandlerConfiguration(
    2152             :       CheckThisIndexedPropertyHandler, CheckThisIndexedPropertySetter,
    2153             :       CheckThisIndexedPropertyQuery, CheckThisIndexedPropertyDeleter,
    2154          12 :       CheckThisIndexedPropertyEnumerator));
    2155             : 
    2156             :   templ->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration(
    2157             :       CheckThisNamedPropertyHandler, CheckThisNamedPropertySetter,
    2158             :       CheckThisNamedPropertyQuery, CheckThisNamedPropertyDeleter,
    2159          12 :       CheckThisNamedPropertyEnumerator));
    2160             : 
    2161           6 :   bottom = templ->GetFunction(env.local())
    2162           6 :                .ToLocalChecked()
    2163           6 :                ->NewInstance(env.local())
    2164           6 :                .ToLocalChecked();
    2165           6 :   Local<v8::Object> top = templ->GetFunction(env.local())
    2166           6 :                               .ToLocalChecked()
    2167           6 :                               ->NewInstance(env.local())
    2168             :                               .ToLocalChecked();
    2169           6 :   Local<v8::Object> middle = templ->GetFunction(env.local())
    2170           6 :                                  .ToLocalChecked()
    2171           6 :                                  ->NewInstance(env.local())
    2172             :                                  .ToLocalChecked();
    2173             : 
    2174          18 :   bottom->SetPrototype(env.local(), middle).FromJust();
    2175          12 :   middle->SetPrototype(env.local(), top).FromJust();
    2176          30 :   env->Global()->Set(env.local(), v8_str("obj"), bottom).FromJust();
    2177             : 
    2178             :   // Indexed and named get.
    2179             :   CompileRun("obj[0]");
    2180             :   CompileRun("obj.x");
    2181             : 
    2182             :   // Indexed and named set.
    2183             :   CompileRun("obj[1] = 42");
    2184             :   CompileRun("obj.y = 42");
    2185             : 
    2186             :   // Indexed and named query.
    2187             :   CompileRun("0 in obj");
    2188             :   CompileRun("'x' in obj");
    2189             : 
    2190             :   // Indexed and named deleter.
    2191             :   CompileRun("delete obj[0]");
    2192             :   CompileRun("delete obj.x");
    2193             : 
    2194             :   // Enumerators.
    2195           6 :   CompileRun("for (var p in obj) ;");
    2196           6 : }
    2197             : 
    2198       23723 : TEST(PropertyHandlerInPrototypeWithDefine) {
    2199           5 :   LocalContext env;
    2200           5 :   v8::Isolate* isolate = env->GetIsolate();
    2201          10 :   v8::HandleScope scope(isolate);
    2202             : 
    2203           5 :   v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
    2204             :   templ->InstanceTemplate()->SetHandler(v8::IndexedPropertyHandlerConfiguration(
    2205             :       CheckThisIndexedPropertyHandler, CheckThisIndexedPropertySetter,
    2206             :       CheckThisIndexedPropertyDescriptor, CheckThisIndexedPropertyDeleter,
    2207          10 :       CheckThisIndexedPropertyEnumerator, CheckThisIndexedPropertyDefiner));
    2208             : 
    2209             :   templ->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration(
    2210             :       CheckThisNamedPropertyHandler, CheckThisNamedPropertySetter,
    2211             :       CheckThisNamedPropertyDescriptor, CheckThisNamedPropertyDeleter,
    2212          10 :       CheckThisNamedPropertyEnumerator, CheckThisNamedPropertyDefiner));
    2213             : 
    2214           5 :   bottom = templ->GetFunction(env.local())
    2215           5 :                .ToLocalChecked()
    2216           5 :                ->NewInstance(env.local())
    2217           5 :                .ToLocalChecked();
    2218           5 :   Local<v8::Object> top = templ->GetFunction(env.local())
    2219           5 :                               .ToLocalChecked()
    2220           5 :                               ->NewInstance(env.local())
    2221             :                               .ToLocalChecked();
    2222           5 :   Local<v8::Object> middle = templ->GetFunction(env.local())
    2223           5 :                                  .ToLocalChecked()
    2224           5 :                                  ->NewInstance(env.local())
    2225             :                                  .ToLocalChecked();
    2226             : 
    2227          15 :   bottom->SetPrototype(env.local(), middle).FromJust();
    2228          10 :   middle->SetPrototype(env.local(), top).FromJust();
    2229          25 :   env->Global()->Set(env.local(), v8_str("obj"), bottom).FromJust();
    2230             : 
    2231             :   // Indexed and named get.
    2232             :   CompileRun("obj[0]");
    2233             :   CompileRun("obj.x");
    2234             : 
    2235             :   // Indexed and named set.
    2236             :   CompileRun("obj[1] = 42");
    2237             :   CompileRun("obj.y = 42");
    2238             : 
    2239             :   // Indexed and named deleter.
    2240             :   CompileRun("delete obj[0]");
    2241             :   CompileRun("delete obj.x");
    2242             : 
    2243             :   // Enumerators.
    2244             :   CompileRun("for (var p in obj) ;");
    2245             : 
    2246             :   // Indexed and named definer.
    2247             :   CompileRun("Object.defineProperty(obj, 2, {});");
    2248             :   CompileRun("Object.defineProperty(obj, 'z', {});");
    2249             : 
    2250             :   // Indexed and named propertyDescriptor.
    2251             :   CompileRun("Object.getOwnPropertyDescriptor(obj, 2);");
    2252           5 :   CompileRun("Object.getOwnPropertyDescriptor(obj, 'z');");
    2253           5 : }
    2254             : 
    2255             : 
    2256             : bool is_bootstrapping = false;
    2257          18 : static void PrePropertyHandlerGet(
    2258             :     Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2259          18 :   ApiTestFuzzer::Fuzz();
    2260          54 :   if (!is_bootstrapping &&
    2261             :       v8_str("pre")
    2262          54 :           ->Equals(info.GetIsolate()->GetCurrentContext(), key)
    2263          36 :           .FromJust()) {
    2264           6 :     info.GetReturnValue().Set(v8_str("PrePropertyHandler: pre"));
    2265             :   }
    2266          18 : }
    2267             : 
    2268             : 
    2269           0 : static void PrePropertyHandlerQuery(
    2270             :     Local<Name> key, const v8::PropertyCallbackInfo<v8::Integer>& info) {
    2271           0 :   if (!is_bootstrapping &&
    2272             :       v8_str("pre")
    2273           0 :           ->Equals(info.GetIsolate()->GetCurrentContext(), key)
    2274           0 :           .FromJust()) {
    2275             :     info.GetReturnValue().Set(static_cast<int32_t>(v8::None));
    2276             :   }
    2277           0 : }
    2278             : 
    2279             : 
    2280       23724 : THREADED_TEST(PrePropertyHandler) {
    2281           6 :   v8::Isolate* isolate = CcTest::isolate();
    2282           6 :   v8::HandleScope scope(isolate);
    2283           6 :   v8::Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
    2284             :   desc->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration(
    2285          12 :       PrePropertyHandlerGet, 0, PrePropertyHandlerQuery));
    2286           6 :   is_bootstrapping = true;
    2287          12 :   LocalContext env(nullptr, desc->InstanceTemplate());
    2288           6 :   is_bootstrapping = false;
    2289             :   CompileRun("var pre = 'Object: pre'; var on = 'Object: on';");
    2290           6 :   v8::Local<Value> result_pre = CompileRun("pre");
    2291          18 :   CHECK(v8_str("PrePropertyHandler: pre")
    2292             :             ->Equals(env.local(), result_pre)
    2293             :             .FromJust());
    2294           6 :   v8::Local<Value> result_on = CompileRun("on");
    2295          18 :   CHECK(v8_str("Object: on")->Equals(env.local(), result_on).FromJust());
    2296             :   v8::Local<Value> result_post = CompileRun("post");
    2297          12 :   CHECK(result_post.IsEmpty());
    2298           6 : }
    2299             : 
    2300             : 
    2301       23724 : THREADED_TEST(EmptyInterceptorBreakTransitions) {
    2302           6 :   v8::HandleScope scope(CcTest::isolate());
    2303           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
    2304           6 :   AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
    2305          12 :   LocalContext env;
    2306             :   env->Global()
    2307             :       ->Set(env.local(), v8_str("Constructor"),
    2308          36 :             templ->GetFunction(env.local()).ToLocalChecked())
    2309          12 :       .FromJust();
    2310             :   CompileRun(
    2311             :       "var o1 = new Constructor;"
    2312             :       "o1.a = 1;"  // Ensure a and x share the descriptor array.
    2313             :       "Object.defineProperty(o1, 'x', {value: 10});");
    2314             :   CompileRun(
    2315             :       "var o2 = new Constructor;"
    2316             :       "o2.a = 1;"
    2317           6 :       "Object.defineProperty(o2, 'x', {value: 10});");
    2318           6 : }
    2319             : 
    2320             : 
    2321       23724 : THREADED_TEST(EmptyInterceptorDoesNotShadowJSAccessors) {
    2322           6 :   v8::Isolate* isolate = CcTest::isolate();
    2323           6 :   v8::HandleScope scope(isolate);
    2324           6 :   Local<FunctionTemplate> parent = FunctionTemplate::New(isolate);
    2325           6 :   Local<FunctionTemplate> child = FunctionTemplate::New(isolate);
    2326           6 :   child->Inherit(parent);
    2327           6 :   AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
    2328          12 :   LocalContext env;
    2329             :   env->Global()
    2330             :       ->Set(env.local(), v8_str("Child"),
    2331          30 :             child->GetFunction(env.local()).ToLocalChecked())
    2332          12 :       .FromJust();
    2333             :   CompileRun(
    2334             :       "var child = new Child;"
    2335             :       "var parent = child.__proto__;"
    2336             :       "Object.defineProperty(parent, 'age', "
    2337             :       "  {get: function(){ return this.accessor_age; }, "
    2338             :       "   set: function(v){ this.accessor_age = v; }, "
    2339             :       "   enumerable: true, configurable: true});"
    2340             :       "child.age = 10;");
    2341           6 :   ExpectBoolean("child.hasOwnProperty('age')", false);
    2342           6 :   ExpectInt32("child.age", 10);
    2343          12 :   ExpectInt32("child.accessor_age", 10);
    2344           6 : }
    2345             : 
    2346             : 
    2347       23724 : THREADED_TEST(EmptyInterceptorDoesNotShadowApiAccessors) {
    2348           6 :   v8::Isolate* isolate = CcTest::isolate();
    2349           6 :   v8::HandleScope scope(isolate);
    2350           6 :   Local<FunctionTemplate> parent = FunctionTemplate::New(isolate);
    2351           6 :   auto returns_42 = FunctionTemplate::New(isolate, Returns42);
    2352          18 :   parent->PrototypeTemplate()->SetAccessorProperty(v8_str("age"), returns_42);
    2353           6 :   Local<FunctionTemplate> child = FunctionTemplate::New(isolate);
    2354           6 :   child->Inherit(parent);
    2355           6 :   AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
    2356          12 :   LocalContext env;
    2357             :   env->Global()
    2358             :       ->Set(env.local(), v8_str("Child"),
    2359          30 :             child->GetFunction(env.local()).ToLocalChecked())
    2360          12 :       .FromJust();
    2361             :   CompileRun(
    2362             :       "var child = new Child;"
    2363             :       "var parent = child.__proto__;");
    2364           6 :   ExpectBoolean("child.hasOwnProperty('age')", false);
    2365           6 :   ExpectInt32("child.age", 42);
    2366             :   // Check interceptor followup.
    2367             :   ExpectInt32(
    2368             :       "var result;"
    2369             :       "for (var i = 0; i < 4; ++i) {"
    2370             :       "  result = child.age;"
    2371             :       "}"
    2372             :       "result",
    2373          12 :       42);
    2374           6 : }
    2375             : 
    2376             : 
    2377       23724 : THREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) {
    2378           6 :   v8::Isolate* isolate = CcTest::isolate();
    2379           6 :   v8::HandleScope scope(isolate);
    2380           6 :   Local<FunctionTemplate> parent = FunctionTemplate::New(isolate);
    2381           6 :   Local<FunctionTemplate> child = FunctionTemplate::New(isolate);
    2382           6 :   child->Inherit(parent);
    2383           6 :   AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
    2384          12 :   LocalContext env;
    2385             :   env->Global()
    2386             :       ->Set(env.local(), v8_str("Child"),
    2387          30 :             child->GetFunction(env.local()).ToLocalChecked())
    2388          12 :       .FromJust();
    2389             :   CompileRun(
    2390             :       "var child = new Child;"
    2391             :       "var parent = child.__proto__;"
    2392             :       "parent.name = 'Alice';");
    2393           6 :   ExpectBoolean("child.hasOwnProperty('name')", false);
    2394           6 :   ExpectString("child.name", "Alice");
    2395             :   CompileRun("child.name = 'Bob';");
    2396           6 :   ExpectString("child.name", "Bob");
    2397           6 :   ExpectBoolean("child.hasOwnProperty('name')", true);
    2398          12 :   ExpectString("parent.name", "Alice");
    2399           6 : }
    2400             : 
    2401             : 
    2402       23724 : THREADED_TEST(SwitchFromInterceptorToAccessor) {
    2403           6 :   v8::HandleScope scope(CcTest::isolate());
    2404           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
    2405           6 :   AddAccessor(templ, v8_str("age"), SimpleAccessorGetter, SimpleAccessorSetter);
    2406           6 :   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
    2407          12 :   LocalContext env;
    2408             :   env->Global()
    2409             :       ->Set(env.local(), v8_str("Obj"),
    2410          36 :             templ->GetFunction(env.local()).ToLocalChecked())
    2411          12 :       .FromJust();
    2412             :   CompileRun(
    2413             :       "var obj = new Obj;"
    2414             :       "function setAge(i){ obj.age = i; };"
    2415             :       "for(var i = 0; i <= 10000; i++) setAge(i);");
    2416             :   // All i < 10000 go to the interceptor.
    2417           6 :   ExpectInt32("obj.interceptor_age", 9999);
    2418             :   // The last i goes to the accessor.
    2419          12 :   ExpectInt32("obj.accessor_age", 10000);
    2420           6 : }
    2421             : 
    2422             : 
    2423       23724 : THREADED_TEST(SwitchFromAccessorToInterceptor) {
    2424           6 :   v8::HandleScope scope(CcTest::isolate());
    2425           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
    2426           6 :   AddAccessor(templ, v8_str("age"), SimpleAccessorGetter, SimpleAccessorSetter);
    2427           6 :   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
    2428          12 :   LocalContext env;
    2429             :   env->Global()
    2430             :       ->Set(env.local(), v8_str("Obj"),
    2431          36 :             templ->GetFunction(env.local()).ToLocalChecked())
    2432          12 :       .FromJust();
    2433             :   CompileRun(
    2434             :       "var obj = new Obj;"
    2435             :       "function setAge(i){ obj.age = i; };"
    2436             :       "for(var i = 20000; i >= 9999; i--) setAge(i);");
    2437             :   // All i >= 10000 go to the accessor.
    2438           6 :   ExpectInt32("obj.accessor_age", 10000);
    2439             :   // The last i goes to the interceptor.
    2440          12 :   ExpectInt32("obj.interceptor_age", 9999);
    2441           6 : }
    2442             : 
    2443             : 
    2444       23724 : THREADED_TEST(SwitchFromInterceptorToAccessorWithInheritance) {
    2445           6 :   v8::HandleScope scope(CcTest::isolate());
    2446           6 :   Local<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
    2447           6 :   Local<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
    2448           6 :   child->Inherit(parent);
    2449             :   AddAccessor(parent, v8_str("age"), SimpleAccessorGetter,
    2450           6 :               SimpleAccessorSetter);
    2451           6 :   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
    2452          12 :   LocalContext env;
    2453             :   env->Global()
    2454             :       ->Set(env.local(), v8_str("Child"),
    2455          30 :             child->GetFunction(env.local()).ToLocalChecked())
    2456          12 :       .FromJust();
    2457             :   CompileRun(
    2458             :       "var child = new Child;"
    2459             :       "function setAge(i){ child.age = i; };"
    2460             :       "for(var i = 0; i <= 10000; i++) setAge(i);");
    2461             :   // All i < 10000 go to the interceptor.
    2462           6 :   ExpectInt32("child.interceptor_age", 9999);
    2463             :   // The last i goes to the accessor.
    2464          12 :   ExpectInt32("child.accessor_age", 10000);
    2465           6 : }
    2466             : 
    2467             : 
    2468       23724 : THREADED_TEST(SwitchFromAccessorToInterceptorWithInheritance) {
    2469           6 :   v8::HandleScope scope(CcTest::isolate());
    2470           6 :   Local<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
    2471           6 :   Local<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
    2472           6 :   child->Inherit(parent);
    2473             :   AddAccessor(parent, v8_str("age"), SimpleAccessorGetter,
    2474           6 :               SimpleAccessorSetter);
    2475           6 :   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
    2476          12 :   LocalContext env;
    2477             :   env->Global()
    2478             :       ->Set(env.local(), v8_str("Child"),
    2479          30 :             child->GetFunction(env.local()).ToLocalChecked())
    2480          12 :       .FromJust();
    2481             :   CompileRun(
    2482             :       "var child = new Child;"
    2483             :       "function setAge(i){ child.age = i; };"
    2484             :       "for(var i = 20000; i >= 9999; i--) setAge(i);");
    2485             :   // All i >= 10000 go to the accessor.
    2486           6 :   ExpectInt32("child.accessor_age", 10000);
    2487             :   // The last i goes to the interceptor.
    2488          12 :   ExpectInt32("child.interceptor_age", 9999);
    2489           6 : }
    2490             : 
    2491             : 
    2492       23724 : THREADED_TEST(SwitchFromInterceptorToJSAccessor) {
    2493           6 :   v8::HandleScope scope(CcTest::isolate());
    2494           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
    2495           6 :   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
    2496          12 :   LocalContext env;
    2497             :   env->Global()
    2498             :       ->Set(env.local(), v8_str("Obj"),
    2499          36 :             templ->GetFunction(env.local()).ToLocalChecked())
    2500          12 :       .FromJust();
    2501             :   CompileRun(
    2502             :       "var obj = new Obj;"
    2503             :       "function setter(i) { this.accessor_age = i; };"
    2504             :       "function getter() { return this.accessor_age; };"
    2505             :       "function setAge(i) { obj.age = i; };"
    2506             :       "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
    2507             :       "for(var i = 0; i <= 10000; i++) setAge(i);");
    2508             :   // All i < 10000 go to the interceptor.
    2509           6 :   ExpectInt32("obj.interceptor_age", 9999);
    2510             :   // The last i goes to the JavaScript accessor.
    2511           6 :   ExpectInt32("obj.accessor_age", 10000);
    2512             :   // The installed JavaScript getter is still intact.
    2513             :   // This last part is a regression test for issue 1651 and relies on the fact
    2514             :   // that both interceptor and accessor are being installed on the same object.
    2515           6 :   ExpectInt32("obj.age", 10000);
    2516           6 :   ExpectBoolean("obj.hasOwnProperty('age')", true);
    2517          12 :   ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
    2518           6 : }
    2519             : 
    2520             : 
    2521       23724 : THREADED_TEST(SwitchFromJSAccessorToInterceptor) {
    2522           6 :   v8::HandleScope scope(CcTest::isolate());
    2523           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
    2524           6 :   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
    2525          12 :   LocalContext env;
    2526             :   env->Global()
    2527             :       ->Set(env.local(), v8_str("Obj"),
    2528          36 :             templ->GetFunction(env.local()).ToLocalChecked())
    2529          12 :       .FromJust();
    2530             :   CompileRun(
    2531             :       "var obj = new Obj;"
    2532             :       "function setter(i) { this.accessor_age = i; };"
    2533             :       "function getter() { return this.accessor_age; };"
    2534             :       "function setAge(i) { obj.age = i; };"
    2535             :       "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
    2536             :       "for(var i = 20000; i >= 9999; i--) setAge(i);");
    2537             :   // All i >= 10000 go to the accessor.
    2538           6 :   ExpectInt32("obj.accessor_age", 10000);
    2539             :   // The last i goes to the interceptor.
    2540           6 :   ExpectInt32("obj.interceptor_age", 9999);
    2541             :   // The installed JavaScript getter is still intact.
    2542             :   // This last part is a regression test for issue 1651 and relies on the fact
    2543             :   // that both interceptor and accessor are being installed on the same object.
    2544           6 :   ExpectInt32("obj.age", 10000);
    2545           6 :   ExpectBoolean("obj.hasOwnProperty('age')", true);
    2546          12 :   ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
    2547           6 : }
    2548             : 
    2549             : 
    2550       23724 : THREADED_TEST(SwitchFromInterceptorToProperty) {
    2551           6 :   v8::HandleScope scope(CcTest::isolate());
    2552           6 :   Local<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
    2553           6 :   Local<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
    2554           6 :   child->Inherit(parent);
    2555           6 :   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
    2556          12 :   LocalContext env;
    2557             :   env->Global()
    2558             :       ->Set(env.local(), v8_str("Child"),
    2559          30 :             child->GetFunction(env.local()).ToLocalChecked())
    2560          12 :       .FromJust();
    2561             :   CompileRun(
    2562             :       "var child = new Child;"
    2563             :       "function setAge(i){ child.age = i; };"
    2564             :       "for(var i = 0; i <= 10000; i++) setAge(i);");
    2565             :   // All i < 10000 go to the interceptor.
    2566           6 :   ExpectInt32("child.interceptor_age", 9999);
    2567             :   // The last i goes to child's own property.
    2568          12 :   ExpectInt32("child.age", 10000);
    2569           6 : }
    2570             : 
    2571             : 
    2572       23724 : THREADED_TEST(SwitchFromPropertyToInterceptor) {
    2573           6 :   v8::HandleScope scope(CcTest::isolate());
    2574           6 :   Local<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
    2575           6 :   Local<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
    2576           6 :   child->Inherit(parent);
    2577           6 :   AddInterceptor(child, InterceptorGetter, InterceptorSetter);
    2578          12 :   LocalContext env;
    2579             :   env->Global()
    2580             :       ->Set(env.local(), v8_str("Child"),
    2581          30 :             child->GetFunction(env.local()).ToLocalChecked())
    2582          12 :       .FromJust();
    2583             :   CompileRun(
    2584             :       "var child = new Child;"
    2585             :       "function setAge(i){ child.age = i; };"
    2586             :       "for(var i = 20000; i >= 9999; i--) setAge(i);");
    2587             :   // All i >= 10000 go to child's own property.
    2588           6 :   ExpectInt32("child.age", 10000);
    2589             :   // The last i goes to the interceptor.
    2590          12 :   ExpectInt32("child.interceptor_age", 9999);
    2591           6 : }
    2592             : 
    2593             : 
    2594             : static bool interceptor_for_hidden_properties_called;
    2595           0 : static void InterceptorForHiddenProperties(
    2596             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2597           0 :   interceptor_for_hidden_properties_called = true;
    2598           0 : }
    2599             : 
    2600             : 
    2601       23724 : THREADED_TEST(HiddenPropertiesWithInterceptors) {
    2602           6 :   LocalContext context;
    2603           6 :   v8::Isolate* isolate = context->GetIsolate();
    2604          12 :   v8::HandleScope scope(isolate);
    2605             : 
    2606           6 :   interceptor_for_hidden_properties_called = false;
    2607             : 
    2608             :   v8::Local<v8::Private> key =
    2609           6 :       v8::Private::New(isolate, v8_str("api-test::hidden-key"));
    2610             : 
    2611             :   // Associate an interceptor with an object and start setting hidden values.
    2612           6 :   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
    2613           6 :   Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
    2614             :   instance_templ->SetHandler(
    2615           6 :       v8::NamedPropertyHandlerConfiguration(InterceptorForHiddenProperties));
    2616             :   Local<v8::Function> function =
    2617           6 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
    2618             :   Local<v8::Object> obj =
    2619           6 :       function->NewInstance(context.local()).ToLocalChecked();
    2620          18 :   CHECK(obj->SetPrivate(context.local(), key, v8::Integer::New(isolate, 2302))
    2621             :             .FromJust());
    2622          18 :   CHECK_EQ(2302, obj->GetPrivate(context.local(), key)
    2623             :                      .ToLocalChecked()
    2624             :                      ->Int32Value(context.local())
    2625             :                      .FromJust());
    2626          12 :   CHECK(!interceptor_for_hidden_properties_called);
    2627           6 : }
    2628             : 
    2629             : 
    2630         192 : static void XPropertyGetter(Local<Name> property,
    2631             :                             const v8::PropertyCallbackInfo<v8::Value>& info) {
    2632         192 :   ApiTestFuzzer::Fuzz();
    2633         192 :   CHECK(info.Data()->IsUndefined());
    2634             :   info.GetReturnValue().Set(property);
    2635         192 : }
    2636             : 
    2637             : 
    2638       23724 : THREADED_TEST(NamedInterceptorPropertyRead) {
    2639           6 :   v8::Isolate* isolate = CcTest::isolate();
    2640           6 :   v8::HandleScope scope(isolate);
    2641           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    2642           6 :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(XPropertyGetter));
    2643          12 :   LocalContext context;
    2644             :   context->Global()
    2645             :       ->Set(context.local(), v8_str("obj"),
    2646          30 :             templ->NewInstance(context.local()).ToLocalChecked())
    2647          12 :       .FromJust();
    2648             :   Local<Script> script = v8_compile("obj.x");
    2649          66 :   for (int i = 0; i < 10; i++) {
    2650          60 :     Local<Value> result = script->Run(context.local()).ToLocalChecked();
    2651         180 :     CHECK(result->Equals(context.local(), v8_str("x")).FromJust());
    2652           6 :   }
    2653           6 : }
    2654             : 
    2655             : 
    2656       23724 : THREADED_TEST(NamedInterceptorDictionaryIC) {
    2657           6 :   v8::Isolate* isolate = CcTest::isolate();
    2658           6 :   v8::HandleScope scope(isolate);
    2659           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    2660           6 :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(XPropertyGetter));
    2661          12 :   LocalContext context;
    2662             :   // Create an object with a named interceptor.
    2663             :   context->Global()
    2664             :       ->Set(context.local(), v8_str("interceptor_obj"),
    2665          30 :             templ->NewInstance(context.local()).ToLocalChecked())
    2666          12 :       .FromJust();
    2667             :   Local<Script> script = v8_compile("interceptor_obj.x");
    2668          66 :   for (int i = 0; i < 10; i++) {
    2669          60 :     Local<Value> result = script->Run(context.local()).ToLocalChecked();
    2670         180 :     CHECK(result->Equals(context.local(), v8_str("x")).FromJust());
    2671             :   }
    2672             :   // Create a slow case object and a function accessing a property in
    2673             :   // that slow case object (with dictionary probing in generated
    2674             :   // code). Then force object with a named interceptor into slow-case,
    2675             :   // pass it to the function, and check that the interceptor is called
    2676             :   // instead of accessing the local property.
    2677             :   Local<Value> result = CompileRun(
    2678             :       "function get_x(o) { return o.x; };"
    2679             :       "var obj = { x : 42, y : 0 };"
    2680             :       "delete obj.y;"
    2681             :       "for (var i = 0; i < 10; i++) get_x(obj);"
    2682             :       "interceptor_obj.x = 42;"
    2683             :       "interceptor_obj.y = 10;"
    2684             :       "delete interceptor_obj.y;"
    2685             :       "get_x(interceptor_obj)");
    2686          24 :   CHECK(result->Equals(context.local(), v8_str("x")).FromJust());
    2687           6 : }
    2688             : 
    2689             : 
    2690       23724 : THREADED_TEST(NamedInterceptorDictionaryICMultipleContext) {
    2691           6 :   v8::Isolate* isolate = CcTest::isolate();
    2692           6 :   v8::HandleScope scope(isolate);
    2693           6 :   v8::Local<Context> context1 = Context::New(isolate);
    2694             : 
    2695           6 :   context1->Enter();
    2696           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    2697           6 :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(XPropertyGetter));
    2698             :   // Create an object with a named interceptor.
    2699           6 :   v8::Local<v8::Object> object = templ->NewInstance(context1).ToLocalChecked();
    2700             :   context1->Global()
    2701          18 :       ->Set(context1, v8_str("interceptor_obj"), object)
    2702          12 :       .FromJust();
    2703             : 
    2704             :   // Force the object into the slow case.
    2705             :   CompileRun(
    2706             :       "interceptor_obj.y = 0;"
    2707             :       "delete interceptor_obj.y;");
    2708           6 :   context1->Exit();
    2709             : 
    2710             :   {
    2711             :     // Introduce the object into a different context.
    2712             :     // Repeat named loads to exercise ICs.
    2713           6 :     LocalContext context2;
    2714             :     context2->Global()
    2715          24 :         ->Set(context2.local(), v8_str("interceptor_obj"), object)
    2716          12 :         .FromJust();
    2717             :     Local<Value> result = CompileRun(
    2718             :         "function get_x(o) { return o.x; }"
    2719             :         "interceptor_obj.x = 42;"
    2720             :         "for (var i=0; i != 10; i++) {"
    2721             :         "  get_x(interceptor_obj);"
    2722             :         "}"
    2723             :         "get_x(interceptor_obj)");
    2724             :     // Check that the interceptor was actually invoked.
    2725          18 :     CHECK(result->Equals(context2.local(), v8_str("x")).FromJust());
    2726             :   }
    2727             : 
    2728             :   // Return to the original context and force some object to the slow case
    2729             :   // to cause the NormalizedMapCache to verify.
    2730           6 :   context1->Enter();
    2731             :   CompileRun("var obj = { x : 0 }; delete obj.x;");
    2732           6 :   context1->Exit();
    2733           6 : }
    2734             : 
    2735             : 
    2736           6 : static void SetXOnPrototypeGetter(
    2737             :     Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2738             :   // Set x on the prototype object and do not handle the get request.
    2739           6 :   v8::Local<v8::Value> proto = info.Holder()->GetPrototype();
    2740             :   proto.As<v8::Object>()
    2741             :       ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("x"),
    2742          24 :             v8::Integer::New(info.GetIsolate(), 23))
    2743          12 :       .FromJust();
    2744           6 : }
    2745             : 
    2746             : 
    2747             : // This is a regression test for http://crbug.com/20104. Map
    2748             : // transitions should not interfere with post interceptor lookup.
    2749       23724 : THREADED_TEST(NamedInterceptorMapTransitionRead) {
    2750           6 :   v8::Isolate* isolate = CcTest::isolate();
    2751           6 :   v8::HandleScope scope(isolate);
    2752             :   Local<v8::FunctionTemplate> function_template =
    2753           6 :       v8::FunctionTemplate::New(isolate);
    2754             :   Local<v8::ObjectTemplate> instance_template =
    2755           6 :       function_template->InstanceTemplate();
    2756             :   instance_template->SetHandler(
    2757           6 :       v8::NamedPropertyHandlerConfiguration(SetXOnPrototypeGetter));
    2758          12 :   LocalContext context;
    2759             :   context->Global()
    2760             :       ->Set(context.local(), v8_str("F"),
    2761          30 :             function_template->GetFunction(context.local()).ToLocalChecked())
    2762          12 :       .FromJust();
    2763             :   // Create an instance of F and introduce a map transition for x.
    2764             :   CompileRun("var o = new F(); o.x = 23;");
    2765             :   // Create an instance of F and invoke the getter. The result should be 23.
    2766             :   Local<Value> result = CompileRun("o = new F(); o.x");
    2767          18 :   CHECK_EQ(23, result->Int32Value(context.local()).FromJust());
    2768           6 : }
    2769             : 
    2770             : 
    2771          30 : static void IndexedPropertyGetter(
    2772             :     uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2773          30 :   ApiTestFuzzer::Fuzz();
    2774          30 :   if (index == 37) {
    2775           6 :     info.GetReturnValue().Set(v8_num(625));
    2776             :   }
    2777          30 : }
    2778             : 
    2779             : 
    2780          12 : static void IndexedPropertySetter(
    2781             :     uint32_t index, Local<Value> value,
    2782             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
    2783          12 :   ApiTestFuzzer::Fuzz();
    2784          12 :   if (index == 39) {
    2785             :     info.GetReturnValue().Set(value);
    2786             :   }
    2787          12 : }
    2788             : 
    2789             : 
    2790       23724 : THREADED_TEST(IndexedInterceptorWithIndexedAccessor) {
    2791           6 :   v8::Isolate* isolate = CcTest::isolate();
    2792           6 :   v8::HandleScope scope(isolate);
    2793           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    2794             :   templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
    2795           6 :       IndexedPropertyGetter, IndexedPropertySetter));
    2796          12 :   LocalContext context;
    2797             :   context->Global()
    2798             :       ->Set(context.local(), v8_str("obj"),
    2799          30 :             templ->NewInstance(context.local()).ToLocalChecked())
    2800          12 :       .FromJust();
    2801             :   Local<Script> getter_script =
    2802             :       v8_compile("obj.__defineGetter__(\"3\", function(){return 5;});obj[3];");
    2803             :   Local<Script> setter_script = v8_compile(
    2804             :       "obj.__defineSetter__(\"17\", function(val){this.foo = val;});"
    2805             :       "obj[17] = 23;"
    2806             :       "obj.foo;");
    2807             :   Local<Script> interceptor_setter_script = v8_compile(
    2808             :       "obj.__defineSetter__(\"39\", function(val){this.foo = \"hit\";});"
    2809             :       "obj[39] = 47;"
    2810             :       "obj.foo;");  // This setter should not run, due to the interceptor.
    2811             :   Local<Script> interceptor_getter_script = v8_compile("obj[37];");
    2812          12 :   Local<Value> result = getter_script->Run(context.local()).ToLocalChecked();
    2813          18 :   CHECK(v8_num(5)->Equals(context.local(), result).FromJust());
    2814          12 :   result = setter_script->Run(context.local()).ToLocalChecked();
    2815          18 :   CHECK(v8_num(23)->Equals(context.local(), result).FromJust());
    2816          12 :   result = interceptor_setter_script->Run(context.local()).ToLocalChecked();
    2817          18 :   CHECK(v8_num(23)->Equals(context.local(), result).FromJust());
    2818          12 :   result = interceptor_getter_script->Run(context.local()).ToLocalChecked();
    2819          24 :   CHECK(v8_num(625)->Equals(context.local(), result).FromJust());
    2820           6 : }
    2821             : 
    2822             : 
    2823      240078 : static void UnboxedDoubleIndexedPropertyGetter(
    2824             :     uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2825      240078 :   ApiTestFuzzer::Fuzz();
    2826      240078 :   if (index < 25) {
    2827         150 :     info.GetReturnValue().Set(v8_num(index));
    2828             :   }
    2829      240078 : }
    2830             : 
    2831             : 
    2832       65634 : static void UnboxedDoubleIndexedPropertySetter(
    2833             :     uint32_t index, Local<Value> value,
    2834             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
    2835       65634 :   ApiTestFuzzer::Fuzz();
    2836       65634 :   if (index < 25) {
    2837          78 :     info.GetReturnValue().Set(v8_num(index));
    2838             :   }
    2839       65634 : }
    2840             : 
    2841             : 
    2842           6 : void UnboxedDoubleIndexedPropertyEnumerator(
    2843             :     const v8::PropertyCallbackInfo<v8::Array>& info) {
    2844             :   // Force the list of returned keys to be stored in a FastDoubleArray.
    2845             :   Local<Script> indexed_property_names_script = v8_compile(
    2846             :       "keys = new Array(); keys[125000] = 1;"
    2847             :       "for(i = 0; i < 80000; i++) { keys[i] = i; };"
    2848             :       "keys.length = 25; keys;");
    2849             :   Local<Value> result =
    2850           6 :       indexed_property_names_script->Run(info.GetIsolate()->GetCurrentContext())
    2851           6 :           .ToLocalChecked();
    2852             :   info.GetReturnValue().Set(Local<v8::Array>::Cast(result));
    2853           6 : }
    2854             : 
    2855             : 
    2856             : // Make sure that the the interceptor code in the runtime properly handles
    2857             : // merging property name lists for double-array-backed arrays.
    2858       23724 : THREADED_TEST(IndexedInterceptorUnboxedDoubleWithIndexedAccessor) {
    2859           6 :   v8::Isolate* isolate = CcTest::isolate();
    2860           6 :   v8::HandleScope scope(isolate);
    2861           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    2862             :   templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
    2863             :       UnboxedDoubleIndexedPropertyGetter, UnboxedDoubleIndexedPropertySetter, 0,
    2864           6 :       0, UnboxedDoubleIndexedPropertyEnumerator));
    2865          12 :   LocalContext context;
    2866             :   context->Global()
    2867             :       ->Set(context.local(), v8_str("obj"),
    2868          30 :             templ->NewInstance(context.local()).ToLocalChecked())
    2869          12 :       .FromJust();
    2870             :   // When obj is created, force it to be Stored in a FastDoubleArray.
    2871             :   Local<Script> create_unboxed_double_script = v8_compile(
    2872             :       "obj[125000] = 1; for(i = 0; i < 80000; i+=2) { obj[i] = i; } "
    2873             :       "key_count = 0; "
    2874             :       "for (x in obj) {key_count++;};"
    2875             :       "obj;");
    2876             :   Local<Value> result =
    2877           6 :       create_unboxed_double_script->Run(context.local()).ToLocalChecked();
    2878          18 :   CHECK(result->ToObject(context.local())
    2879             :             .ToLocalChecked()
    2880             :             ->HasRealIndexedProperty(context.local(), 2000)
    2881             :             .FromJust());
    2882             :   Local<Script> key_count_check = v8_compile("key_count;");
    2883           6 :   result = key_count_check->Run(context.local()).ToLocalChecked();
    2884          24 :   CHECK(v8_num(40013)->Equals(context.local(), result).FromJust());
    2885           6 : }
    2886             : 
    2887             : 
    2888          78 : void SloppyArgsIndexedPropertyEnumerator(
    2889             :     const v8::PropertyCallbackInfo<v8::Array>& info) {
    2890             :   // Force the list of returned keys to be stored in a Arguments object.
    2891             :   Local<Script> indexed_property_names_script = v8_compile(
    2892             :       "function f(w,x) {"
    2893             :       " return arguments;"
    2894             :       "}"
    2895             :       "keys = f(0, 1, 2, 3);"
    2896             :       "keys;");
    2897             :   Local<Object> result = Local<Object>::Cast(
    2898          78 :       indexed_property_names_script->Run(info.GetIsolate()->GetCurrentContext())
    2899          78 :           .ToLocalChecked());
    2900             :   // Have to populate the handle manually, as it's not Cast-able.
    2901             :   i::Handle<i::JSReceiver> o =
    2902             :       v8::Utils::OpenHandle<Object, i::JSReceiver>(result);
    2903             :   i::Handle<i::JSArray> array(reinterpret_cast<i::JSArray*>(*o));
    2904             :   info.GetReturnValue().Set(v8::Utils::ToLocal(array));
    2905          78 : }
    2906             : 
    2907             : 
    2908          24 : static void SloppyIndexedPropertyGetter(
    2909             :     uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2910          24 :   ApiTestFuzzer::Fuzz();
    2911          24 :   if (index < 4) {
    2912          24 :     info.GetReturnValue().Set(v8_num(index));
    2913             :   }
    2914          24 : }
    2915             : 
    2916             : 
    2917             : // Make sure that the the interceptor code in the runtime properly handles
    2918             : // merging property name lists for non-string arguments arrays.
    2919       23724 : THREADED_TEST(IndexedInterceptorSloppyArgsWithIndexedAccessor) {
    2920           6 :   v8::Isolate* isolate = CcTest::isolate();
    2921           6 :   v8::HandleScope scope(isolate);
    2922           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    2923             :   templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
    2924             :       SloppyIndexedPropertyGetter, 0, 0, 0,
    2925           6 :       SloppyArgsIndexedPropertyEnumerator));
    2926          12 :   LocalContext context;
    2927             :   context->Global()
    2928             :       ->Set(context.local(), v8_str("obj"),
    2929          30 :             templ->NewInstance(context.local()).ToLocalChecked())
    2930          12 :       .FromJust();
    2931             :   Local<Script> create_args_script = v8_compile(
    2932             :       "var key_count = 0;"
    2933             :       "for (x in obj) {key_count++;} key_count;");
    2934             :   Local<Value> result =
    2935          12 :       create_args_script->Run(context.local()).ToLocalChecked();
    2936          24 :   CHECK(v8_num(4)->Equals(context.local(), result).FromJust());
    2937           6 : }
    2938             : 
    2939             : 
    2940        4188 : static void IdentityIndexedPropertyGetter(
    2941             :     uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2942             :   info.GetReturnValue().Set(index);
    2943        4188 : }
    2944             : 
    2945             : 
    2946       23724 : THREADED_TEST(IndexedInterceptorWithGetOwnPropertyDescriptor) {
    2947           6 :   v8::Isolate* isolate = CcTest::isolate();
    2948           6 :   v8::HandleScope scope(isolate);
    2949           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    2950             :   templ->SetHandler(
    2951           6 :       v8::IndexedPropertyHandlerConfiguration(IdentityIndexedPropertyGetter));
    2952             : 
    2953          12 :   LocalContext context;
    2954             :   context->Global()
    2955             :       ->Set(context.local(), v8_str("obj"),
    2956          30 :             templ->NewInstance(context.local()).ToLocalChecked())
    2957          12 :       .FromJust();
    2958             : 
    2959             :   // Check fast object case.
    2960             :   const char* fast_case_code =
    2961             :       "Object.getOwnPropertyDescriptor(obj, 0).value.toString()";
    2962           6 :   ExpectString(fast_case_code, "0");
    2963             : 
    2964             :   // Check slow case.
    2965             :   const char* slow_case_code =
    2966             :       "obj.x = 1; delete obj.x;"
    2967             :       "Object.getOwnPropertyDescriptor(obj, 1).value.toString()";
    2968          12 :   ExpectString(slow_case_code, "1");
    2969           6 : }
    2970             : 
    2971             : 
    2972       23724 : THREADED_TEST(IndexedInterceptorWithNoSetter) {
    2973           6 :   v8::Isolate* isolate = CcTest::isolate();
    2974           6 :   v8::HandleScope scope(isolate);
    2975           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    2976             :   templ->SetHandler(
    2977           6 :       v8::IndexedPropertyHandlerConfiguration(IdentityIndexedPropertyGetter));
    2978             : 
    2979          12 :   LocalContext context;
    2980             :   context->Global()
    2981             :       ->Set(context.local(), v8_str("obj"),
    2982          30 :             templ->NewInstance(context.local()).ToLocalChecked())
    2983          12 :       .FromJust();
    2984             : 
    2985             :   const char* code =
    2986             :       "try {"
    2987             :       "  obj[0] = 239;"
    2988             :       "  for (var i = 0; i < 100; i++) {"
    2989             :       "    var v = obj[0];"
    2990             :       "    if (v != 0) throw 'Wrong value ' + v + ' at iteration ' + i;"
    2991             :       "  }"
    2992             :       "  'PASSED'"
    2993             :       "} catch(e) {"
    2994             :       "  e"
    2995             :       "}";
    2996          12 :   ExpectString(code, "PASSED");
    2997           6 : }
    2998             : 
    2999         600 : static bool AccessAlwaysBlocked(Local<v8::Context> accessing_context,
    3000             :                                 Local<v8::Object> accessed_object,
    3001             :                                 Local<v8::Value> data) {
    3002         600 :   return false;
    3003             : }
    3004             : 
    3005             : 
    3006       23724 : THREADED_TEST(IndexedInterceptorWithAccessorCheck) {
    3007           6 :   v8::Isolate* isolate = CcTest::isolate();
    3008           6 :   v8::HandleScope scope(isolate);
    3009           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    3010             :   templ->SetHandler(
    3011           6 :       v8::IndexedPropertyHandlerConfiguration(IdentityIndexedPropertyGetter));
    3012             : 
    3013           6 :   templ->SetAccessCheckCallback(AccessAlwaysBlocked);
    3014             : 
    3015          12 :   LocalContext context;
    3016           6 :   Local<v8::Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
    3017          30 :   context->Global()->Set(context.local(), v8_str("obj"), obj).FromJust();
    3018             : 
    3019             :   const char* code =
    3020             :       "var result = 'PASSED';"
    3021             :       "for (var i = 0; i < 100; i++) {"
    3022             :       "  try {"
    3023             :       "    var v = obj[0];"
    3024             :       "    result = 'Wrong value ' + v + ' at iteration ' + i;"
    3025             :       "    break;"
    3026             :       "  } catch (e) {"
    3027             :       "    /* pass */"
    3028             :       "  }"
    3029             :       "}"
    3030             :       "result";
    3031          12 :   ExpectString(code, "PASSED");
    3032           6 : }
    3033             : 
    3034             : 
    3035       23724 : THREADED_TEST(IndexedInterceptorWithDifferentIndices) {
    3036           6 :   v8::Isolate* isolate = CcTest::isolate();
    3037           6 :   v8::HandleScope scope(isolate);
    3038           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    3039             :   templ->SetHandler(
    3040           6 :       v8::IndexedPropertyHandlerConfiguration(IdentityIndexedPropertyGetter));
    3041             : 
    3042          12 :   LocalContext context;
    3043           6 :   Local<v8::Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
    3044          30 :   context->Global()->Set(context.local(), v8_str("obj"), obj).FromJust();
    3045             : 
    3046             :   const char* code =
    3047             :       "try {"
    3048             :       "  for (var i = 0; i < 100; i++) {"
    3049             :       "    var v = obj[i];"
    3050             :       "    if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
    3051             :       "  }"
    3052             :       "  'PASSED'"
    3053             :       "} catch(e) {"
    3054             :       "  e"
    3055             :       "}";
    3056          12 :   ExpectString(code, "PASSED");
    3057           6 : }
    3058             : 
    3059             : 
    3060       23724 : THREADED_TEST(IndexedInterceptorWithNegativeIndices) {
    3061           6 :   v8::Isolate* isolate = CcTest::isolate();
    3062           6 :   v8::HandleScope scope(isolate);
    3063           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    3064             :   templ->SetHandler(
    3065           6 :       v8::IndexedPropertyHandlerConfiguration(IdentityIndexedPropertyGetter));
    3066             : 
    3067          12 :   LocalContext context;
    3068           6 :   Local<v8::Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
    3069          30 :   context->Global()->Set(context.local(), v8_str("obj"), obj).FromJust();
    3070             : 
    3071             :   const char* code =
    3072             :       "try {"
    3073             :       "  for (var i = 0; i < 100; i++) {"
    3074             :       "    var expected = i;"
    3075             :       "    var key = i;"
    3076             :       "    if (i == 25) {"
    3077             :       "       key = -1;"
    3078             :       "       expected = undefined;"
    3079             :       "    }"
    3080             :       "    if (i == 50) {"
    3081             :       "       /* probe minimal Smi number on 32-bit platforms */"
    3082             :       "       key = -(1 << 30);"
    3083             :       "       expected = undefined;"
    3084             :       "    }"
    3085             :       "    if (i == 75) {"
    3086             :       "       /* probe minimal Smi number on 64-bit platforms */"
    3087             :       "       key = 1 << 31;"
    3088             :       "       expected = undefined;"
    3089             :       "    }"
    3090             :       "    var v = obj[key];"
    3091             :       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
    3092             :       "  }"
    3093             :       "  'PASSED'"
    3094             :       "} catch(e) {"
    3095             :       "  e"
    3096             :       "}";
    3097          12 :   ExpectString(code, "PASSED");
    3098           6 : }
    3099             : 
    3100             : 
    3101       23724 : THREADED_TEST(IndexedInterceptorWithNotSmiLookup) {
    3102           6 :   v8::Isolate* isolate = CcTest::isolate();
    3103           6 :   v8::HandleScope scope(isolate);
    3104           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    3105             :   templ->SetHandler(
    3106           6 :       v8::IndexedPropertyHandlerConfiguration(IdentityIndexedPropertyGetter));
    3107             : 
    3108          12 :   LocalContext context;
    3109           6 :   Local<v8::Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
    3110          30 :   context->Global()->Set(context.local(), v8_str("obj"), obj).FromJust();
    3111             : 
    3112             :   const char* code =
    3113             :       "try {"
    3114             :       "  for (var i = 0; i < 100; i++) {"
    3115             :       "    var expected = i;"
    3116             :       "    var key = i;"
    3117             :       "    if (i == 50) {"
    3118             :       "       key = 'foobar';"
    3119             :       "       expected = undefined;"
    3120             :       "    }"
    3121             :       "    var v = obj[key];"
    3122             :       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
    3123             :       "  }"
    3124             :       "  'PASSED'"
    3125             :       "} catch(e) {"
    3126             :       "  e"
    3127             :       "}";
    3128          12 :   ExpectString(code, "PASSED");
    3129           6 : }
    3130             : 
    3131             : 
    3132       23724 : THREADED_TEST(IndexedInterceptorGoingMegamorphic) {
    3133           6 :   v8::Isolate* isolate = CcTest::isolate();
    3134           6 :   v8::HandleScope scope(isolate);
    3135           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    3136             :   templ->SetHandler(
    3137           6 :       v8::IndexedPropertyHandlerConfiguration(IdentityIndexedPropertyGetter));
    3138             : 
    3139          12 :   LocalContext context;
    3140           6 :   Local<v8::Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
    3141          30 :   context->Global()->Set(context.local(), v8_str("obj"), obj).FromJust();
    3142             : 
    3143             :   const char* code =
    3144             :       "var original = obj;"
    3145             :       "try {"
    3146             :       "  for (var i = 0; i < 100; i++) {"
    3147             :       "    var expected = i;"
    3148             :       "    if (i == 50) {"
    3149             :       "       obj = {50: 'foobar'};"
    3150             :       "       expected = 'foobar';"
    3151             :       "    }"
    3152             :       "    var v = obj[i];"
    3153             :       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
    3154             :       "    if (i == 50) obj = original;"
    3155             :       "  }"
    3156             :       "  'PASSED'"
    3157             :       "} catch(e) {"
    3158             :       "  e"
    3159             :       "}";
    3160          12 :   ExpectString(code, "PASSED");
    3161           6 : }
    3162             : 
    3163             : 
    3164       23724 : THREADED_TEST(IndexedInterceptorReceiverTurningSmi) {
    3165           6 :   v8::Isolate* isolate = CcTest::isolate();
    3166           6 :   v8::HandleScope scope(isolate);
    3167           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    3168             :   templ->SetHandler(
    3169           6 :       v8::IndexedPropertyHandlerConfiguration(IdentityIndexedPropertyGetter));
    3170             : 
    3171          12 :   LocalContext context;
    3172           6 :   Local<v8::Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
    3173          30 :   context->Global()->Set(context.local(), v8_str("obj"), obj).FromJust();
    3174             : 
    3175             :   const char* code =
    3176             :       "var original = obj;"
    3177             :       "try {"
    3178             :       "  for (var i = 0; i < 100; i++) {"
    3179             :       "    var expected = i;"
    3180             :       "    if (i == 5) {"
    3181             :       "       obj = 239;"
    3182             :       "       expected = undefined;"
    3183             :       "    }"
    3184             :       "    var v = obj[i];"
    3185             :       "    if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
    3186             :       "    if (i == 5) obj = original;"
    3187             :       "  }"
    3188             :       "  'PASSED'"
    3189             :       "} catch(e) {"
    3190             :       "  e"
    3191             :       "}";
    3192          12 :   ExpectString(code, "PASSED");
    3193           6 : }
    3194             : 
    3195             : 
    3196       23724 : THREADED_TEST(IndexedInterceptorOnProto) {
    3197           6 :   v8::Isolate* isolate = CcTest::isolate();
    3198           6 :   v8::HandleScope scope(isolate);
    3199           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    3200             :   templ->SetHandler(
    3201           6 :       v8::IndexedPropertyHandlerConfiguration(IdentityIndexedPropertyGetter));
    3202             : 
    3203          12 :   LocalContext context;
    3204           6 :   Local<v8::Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
    3205          30 :   context->Global()->Set(context.local(), v8_str("obj"), obj).FromJust();
    3206             : 
    3207             :   const char* code =
    3208             :       "var o = {__proto__: obj};"
    3209             :       "try {"
    3210             :       "  for (var i = 0; i < 100; i++) {"
    3211             :       "    var v = o[i];"
    3212             :       "    if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
    3213             :       "  }"
    3214             :       "  'PASSED'"
    3215             :       "} catch(e) {"
    3216             :       "  e"
    3217             :       "}";
    3218          12 :   ExpectString(code, "PASSED");
    3219           6 : }
    3220             : 
    3221             : 
    3222        6672 : static void NoBlockGetterX(Local<Name> name,
    3223        6672 :                            const v8::PropertyCallbackInfo<v8::Value>&) {}
    3224             : 
    3225             : 
    3226          12 : static void NoBlockGetterI(uint32_t index,
    3227          12 :                            const v8::PropertyCallbackInfo<v8::Value>&) {}
    3228             : 
    3229             : 
    3230          12 : static void PDeleter(Local<Name> name,
    3231             :                      const v8::PropertyCallbackInfo<v8::Boolean>& info) {
    3232          36 :   if (!name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
    3233          24 :            .FromJust()) {
    3234          12 :     return;  // not intercepted
    3235             :   }
    3236             : 
    3237             :   info.GetReturnValue().Set(false);  // intercepted, don't delete the property
    3238             : }
    3239             : 
    3240             : 
    3241          12 : static void IDeleter(uint32_t index,
    3242             :                      const v8::PropertyCallbackInfo<v8::Boolean>& info) {
    3243          12 :   if (index != 2) {
    3244          12 :     return;  // not intercepted
    3245             :   }
    3246             : 
    3247             :   info.GetReturnValue().Set(false);  // intercepted, don't delete the property
    3248             : }
    3249             : 
    3250             : 
    3251       23724 : THREADED_TEST(Deleter) {
    3252           6 :   v8::Isolate* isolate = CcTest::isolate();
    3253           6 :   v8::HandleScope scope(isolate);
    3254           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    3255             :   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(
    3256           6 :       NoBlockGetterX, nullptr, nullptr, PDeleter, nullptr));
    3257             :   obj->SetHandler(v8::IndexedPropertyHandlerConfiguration(
    3258           6 :       NoBlockGetterI, nullptr, nullptr, IDeleter, nullptr));
    3259          12 :   LocalContext context;
    3260             :   context->Global()
    3261             :       ->Set(context.local(), v8_str("k"),
    3262          30 :             obj->NewInstance(context.local()).ToLocalChecked())
    3263          12 :       .FromJust();
    3264             :   CompileRun(
    3265             :       "k.foo = 'foo';"
    3266             :       "k.bar = 'bar';"
    3267             :       "k[2] = 2;"
    3268             :       "k[4] = 4;");
    3269          18 :   CHECK(v8_compile("delete k.foo")
    3270             :             ->Run(context.local())
    3271             :             .ToLocalChecked()
    3272             :             ->IsFalse());
    3273          18 :   CHECK(v8_compile("delete k.bar")
    3274             :             ->Run(context.local())
    3275             :             .ToLocalChecked()
    3276             :             ->IsTrue());
    3277             : 
    3278          30 :   CHECK(v8_compile("k.foo")
    3279             :             ->Run(context.local())
    3280             :             .ToLocalChecked()
    3281             :             ->Equals(context.local(), v8_str("foo"))
    3282             :             .FromJust());
    3283          18 :   CHECK(v8_compile("k.bar")
    3284             :             ->Run(context.local())
    3285             :             .ToLocalChecked()
    3286             :             ->IsUndefined());
    3287             : 
    3288          18 :   CHECK(v8_compile("delete k[2]")
    3289             :             ->Run(context.local())
    3290             :             .ToLocalChecked()
    3291             :             ->IsFalse());
    3292          18 :   CHECK(v8_compile("delete k[4]")
    3293             :             ->Run(context.local())
    3294             :             .ToLocalChecked()
    3295             :             ->IsTrue());
    3296             : 
    3297          24 :   CHECK(v8_compile("k[2]")
    3298             :             ->Run(context.local())
    3299             :             .ToLocalChecked()
    3300             :             ->Equals(context.local(), v8_num(2))
    3301             :             .FromJust());
    3302          18 :   CHECK(
    3303           6 :       v8_compile("k[4]")->Run(context.local()).ToLocalChecked()->IsUndefined());
    3304           6 : }
    3305             : 
    3306             : 
    3307          66 : static void GetK(Local<Name> name,
    3308             :                  const v8::PropertyCallbackInfo<v8::Value>& info) {
    3309          66 :   ApiTestFuzzer::Fuzz();
    3310          66 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    3311         258 :   if (name->Equals(context, v8_str("foo")).FromJust() ||
    3312         246 :       name->Equals(context, v8_str("bar")).FromJust() ||
    3313         174 :       name->Equals(context, v8_str("baz")).FromJust()) {
    3314             :     info.GetReturnValue().SetUndefined();
    3315             :   }
    3316          66 : }
    3317             : 
    3318             : 
    3319          36 : static void IndexedGetK(uint32_t index,
    3320             :                         const v8::PropertyCallbackInfo<v8::Value>& info) {
    3321          36 :   ApiTestFuzzer::Fuzz();
    3322          36 :   if (index == 0 || index == 1) info.GetReturnValue().SetUndefined();
    3323          36 : }
    3324             : 
    3325             : 
    3326          24 : static void NamedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
    3327          24 :   ApiTestFuzzer::Fuzz();
    3328          24 :   v8::Local<v8::Array> result = v8::Array::New(info.GetIsolate(), 3);
    3329          24 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    3330          96 :   CHECK(
    3331             :       result
    3332             :           ->Set(context, v8::Integer::New(info.GetIsolate(), 0), v8_str("foo"))
    3333             :           .FromJust());
    3334          96 :   CHECK(
    3335             :       result
    3336             :           ->Set(context, v8::Integer::New(info.GetIsolate(), 1), v8_str("bar"))
    3337             :           .FromJust());
    3338          96 :   CHECK(
    3339             :       result
    3340             :           ->Set(context, v8::Integer::New(info.GetIsolate(), 2), v8_str("baz"))
    3341             :           .FromJust());
    3342             :   info.GetReturnValue().Set(result);
    3343          24 : }
    3344             : 
    3345             : 
    3346           6 : static void IndexedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
    3347           6 :   ApiTestFuzzer::Fuzz();
    3348           6 :   v8::Local<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
    3349           6 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    3350          24 :   CHECK(
    3351             :       result->Set(context, v8::Integer::New(info.GetIsolate(), 0), v8_str("0"))
    3352             :           .FromJust());
    3353          24 :   CHECK(
    3354             :       result->Set(context, v8::Integer::New(info.GetIsolate(), 1), v8_str("1"))
    3355             :           .FromJust());
    3356             :   info.GetReturnValue().Set(result);
    3357           6 : }
    3358             : 
    3359             : 
    3360       23724 : THREADED_TEST(Enumerators) {
    3361           6 :   v8::Isolate* isolate = CcTest::isolate();
    3362           6 :   v8::HandleScope scope(isolate);
    3363           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    3364             :   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(GetK, nullptr, nullptr,
    3365           6 :                                                         nullptr, NamedEnum));
    3366             :   obj->SetHandler(v8::IndexedPropertyHandlerConfiguration(
    3367           6 :       IndexedGetK, nullptr, nullptr, nullptr, IndexedEnum));
    3368          12 :   LocalContext context;
    3369             :   context->Global()
    3370             :       ->Set(context.local(), v8_str("k"),
    3371          30 :             obj->NewInstance(context.local()).ToLocalChecked())
    3372          12 :       .FromJust();
    3373             :   v8::Local<v8::Array> result =
    3374             :       v8::Local<v8::Array>::Cast(CompileRun("k[10] = 0;"
    3375             :                                             "k.a = 0;"
    3376             :                                             "k[5] = 0;"
    3377             :                                             "k.b = 0;"
    3378             :                                             "k[4294967294] = 0;"
    3379             :                                             "k.c = 0;"
    3380             :                                             "k[4294967295] = 0;"
    3381             :                                             "k.d = 0;"
    3382             :                                             "k[140000] = 0;"
    3383             :                                             "k.e = 0;"
    3384             :                                             "k[30000000000] = 0;"
    3385             :                                             "k.f = 0;"
    3386             :                                             "var result = [];"
    3387             :                                             "for (var prop in k) {"
    3388             :                                             "  result.push(prop);"
    3389             :                                             "}"
    3390             :                                             "result"));
    3391             :   // Check that we get all the property names returned including the
    3392             :   // ones from the enumerators in the right order: indexed properties
    3393             :   // in numerical order, indexed interceptor properties, named
    3394             :   // properties in insertion order, named interceptor properties.
    3395             :   // This order is not mandated by the spec, so this test is just
    3396             :   // documenting our behavior.
    3397           6 :   CHECK_EQ(17u, result->Length());
    3398             :   // Indexed properties.
    3399          30 :   CHECK(v8_str("5")
    3400             :             ->Equals(context.local(),
    3401             :                      result->Get(context.local(), v8::Integer::New(isolate, 0))
    3402             :                          .ToLocalChecked())
    3403             :             .FromJust());
    3404          30 :   CHECK(v8_str("10")
    3405             :             ->Equals(context.local(),
    3406             :                      result->Get(context.local(), v8::Integer::New(isolate, 1))
    3407             :                          .ToLocalChecked())
    3408             :             .FromJust());
    3409          30 :   CHECK(v8_str("140000")
    3410             :             ->Equals(context.local(),
    3411             :                      result->Get(context.local(), v8::Integer::New(isolate, 2))
    3412             :                          .ToLocalChecked())
    3413             :             .FromJust());
    3414          30 :   CHECK(v8_str("4294967294")
    3415             :             ->Equals(context.local(),
    3416             :                      result->Get(context.local(), v8::Integer::New(isolate, 3))
    3417             :                          .ToLocalChecked())
    3418             :             .FromJust());
    3419             :   // Indexed Interceptor properties
    3420          30 :   CHECK(v8_str("0")
    3421             :             ->Equals(context.local(),
    3422             :                      result->Get(context.local(), v8::Integer::New(isolate, 4))
    3423             :                          .ToLocalChecked())
    3424             :             .FromJust());
    3425          30 :   CHECK(v8_str("1")
    3426             :             ->Equals(context.local(),
    3427             :                      result->Get(context.local(), v8::Integer::New(isolate, 5))
    3428             :                          .ToLocalChecked())
    3429             :             .FromJust());
    3430             :   // Named properties in insertion order.
    3431          30 :   CHECK(v8_str("a")
    3432             :             ->Equals(context.local(),
    3433             :                      result->Get(context.local(), v8::Integer::New(isolate, 6))
    3434             :                          .ToLocalChecked())
    3435             :             .FromJust());
    3436          30 :   CHECK(v8_str("b")
    3437             :             ->Equals(context.local(),
    3438             :                      result->Get(context.local(), v8::Integer::New(isolate, 7))
    3439             :                          .ToLocalChecked())
    3440             :             .FromJust());
    3441          30 :   CHECK(v8_str("c")
    3442             :             ->Equals(context.local(),
    3443             :                      result->Get(context.local(), v8::Integer::New(isolate, 8))
    3444             :                          .ToLocalChecked())
    3445             :             .FromJust());
    3446          30 :   CHECK(v8_str("4294967295")
    3447             :             ->Equals(context.local(),
    3448             :                      result->Get(context.local(), v8::Integer::New(isolate, 9))
    3449             :                          .ToLocalChecked())
    3450             :             .FromJust());
    3451          30 :   CHECK(v8_str("d")
    3452             :             ->Equals(context.local(),
    3453             :                      result->Get(context.local(), v8::Integer::New(isolate, 10))
    3454             :                          .ToLocalChecked())
    3455             :             .FromJust());
    3456          30 :   CHECK(v8_str("e")
    3457             :             ->Equals(context.local(),
    3458             :                      result->Get(context.local(), v8::Integer::New(isolate, 11))
    3459             :                          .ToLocalChecked())
    3460             :             .FromJust());
    3461          30 :   CHECK(v8_str("30000000000")
    3462             :             ->Equals(context.local(),
    3463             :                      result->Get(context.local(), v8::Integer::New(isolate, 12))
    3464             :                          .ToLocalChecked())
    3465             :             .FromJust());
    3466          30 :   CHECK(v8_str("f")
    3467             :             ->Equals(context.local(),
    3468             :                      result->Get(context.local(), v8::Integer::New(isolate, 13))
    3469             :                          .ToLocalChecked())
    3470             :             .FromJust());
    3471             :   // Named interceptor properties.
    3472          30 :   CHECK(v8_str("foo")
    3473             :             ->Equals(context.local(),
    3474             :                      result->Get(context.local(), v8::Integer::New(isolate, 14))
    3475             :                          .ToLocalChecked())
    3476             :             .FromJust());
    3477          30 :   CHECK(v8_str("bar")
    3478             :             ->Equals(context.local(),
    3479             :                      result->Get(context.local(), v8::Integer::New(isolate, 15))
    3480             :                          .ToLocalChecked())
    3481             :             .FromJust());
    3482          30 :   CHECK(v8_str("baz")
    3483             :             ->Equals(context.local(),
    3484             :                      result->Get(context.local(), v8::Integer::New(isolate, 16))
    3485             :                          .ToLocalChecked())
    3486           6 :             .FromJust());
    3487           6 : }
    3488             : 
    3489             : 
    3490             : v8::Local<Value> call_ic_function;
    3491             : v8::Local<Value> call_ic_function2;
    3492             : v8::Local<Value> call_ic_function3;
    3493             : 
    3494        6000 : static void InterceptorCallICGetter(
    3495             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    3496        6000 :   ApiTestFuzzer::Fuzz();
    3497       18000 :   CHECK(v8_str("x")
    3498             :             ->Equals(info.GetIsolate()->GetCurrentContext(), name)
    3499             :             .FromJust());
    3500             :   info.GetReturnValue().Set(call_ic_function);
    3501        6000 : }
    3502             : 
    3503             : 
    3504             : // This test should hit the call IC for the interceptor case.
    3505       23724 : THREADED_TEST(InterceptorCallIC) {
    3506           6 :   v8::Isolate* isolate = CcTest::isolate();
    3507           6 :   v8::HandleScope scope(isolate);
    3508           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    3509             :   templ->SetHandler(
    3510           6 :       v8::NamedPropertyHandlerConfiguration(InterceptorCallICGetter));
    3511          12 :   LocalContext context;
    3512             :   context->Global()
    3513             :       ->Set(context.local(), v8_str("o"),
    3514          30 :             templ->NewInstance(context.local()).ToLocalChecked())
    3515          12 :       .FromJust();
    3516             :   call_ic_function = v8_compile("function f(x) { return x + 1; }; f")
    3517           6 :                          ->Run(context.local())
    3518          12 :                          .ToLocalChecked();
    3519             :   v8::Local<Value> value = CompileRun(
    3520             :       "var result = 0;"
    3521             :       "for (var i = 0; i < 1000; i++) {"
    3522             :       "  result = o.x(41);"
    3523             :       "}");
    3524          18 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
    3525           6 : }
    3526             : 
    3527             : 
    3528             : // This test checks that if interceptor doesn't provide
    3529             : // a value, we can fetch regular value.
    3530       23724 : THREADED_TEST(InterceptorCallICSeesOthers) {
    3531           6 :   v8::Isolate* isolate = CcTest::isolate();
    3532           6 :   v8::HandleScope scope(isolate);
    3533           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    3534           6 :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(NoBlockGetterX));
    3535          12 :   LocalContext context;
    3536             :   context->Global()
    3537             :       ->Set(context.local(), v8_str("o"),
    3538          30 :             templ->NewInstance(context.local()).ToLocalChecked())
    3539          12 :       .FromJust();
    3540             :   v8::Local<Value> value = CompileRun(
    3541             :       "o.x = function f(x) { return x + 1; };"
    3542             :       "var result = 0;"
    3543             :       "for (var i = 0; i < 7; i++) {"
    3544             :       "  result = o.x(41);"
    3545             :       "}");
    3546          18 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
    3547           6 : }
    3548             : 
    3549             : 
    3550             : static v8::Local<Value> call_ic_function4;
    3551        6000 : static void InterceptorCallICGetter4(
    3552             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    3553        6000 :   ApiTestFuzzer::Fuzz();
    3554       18000 :   CHECK(v8_str("x")
    3555             :             ->Equals(info.GetIsolate()->GetCurrentContext(), name)
    3556             :             .FromJust());
    3557             :   info.GetReturnValue().Set(call_ic_function4);
    3558        6000 : }
    3559             : 
    3560             : 
    3561             : // This test checks that if interceptor provides a function,
    3562             : // even if we cached shadowed variant, interceptor's function
    3563             : // is invoked
    3564       23724 : THREADED_TEST(InterceptorCallICCacheableNotNeeded) {
    3565           6 :   v8::Isolate* isolate = CcTest::isolate();
    3566           6 :   v8::HandleScope scope(isolate);
    3567           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    3568             :   templ->SetHandler(
    3569           6 :       v8::NamedPropertyHandlerConfiguration(InterceptorCallICGetter4));
    3570          12 :   LocalContext context;
    3571             :   context->Global()
    3572             :       ->Set(context.local(), v8_str("o"),
    3573          30 :             templ->NewInstance(context.local()).ToLocalChecked())
    3574          12 :       .FromJust();
    3575             :   call_ic_function4 = v8_compile("function f(x) { return x - 1; }; f")
    3576           6 :                           ->Run(context.local())
    3577          12 :                           .ToLocalChecked();
    3578             :   v8::Local<Value> value = CompileRun(
    3579             :       "Object.getPrototypeOf(o).x = function(x) { return x + 1; };"
    3580             :       "var result = 0;"
    3581             :       "for (var i = 0; i < 1000; i++) {"
    3582             :       "  result = o.x(42);"
    3583             :       "}");
    3584          18 :   CHECK_EQ(41, value->Int32Value(context.local()).FromJust());
    3585           6 : }
    3586             : 
    3587             : 
    3588             : // Test the case when we stored cacheable lookup into
    3589             : // a stub, but it got invalidated later on
    3590       23724 : THREADED_TEST(InterceptorCallICInvalidatedCacheable) {
    3591           6 :   v8::Isolate* isolate = CcTest::isolate();
    3592           6 :   v8::HandleScope scope(isolate);
    3593           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    3594           6 :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(NoBlockGetterX));
    3595          12 :   LocalContext context;
    3596             :   context->Global()
    3597             :       ->Set(context.local(), v8_str("o"),
    3598          30 :             templ->NewInstance(context.local()).ToLocalChecked())
    3599          12 :       .FromJust();
    3600             :   v8::Local<Value> value = CompileRun(
    3601             :       "proto1 = new Object();"
    3602             :       "proto2 = new Object();"
    3603             :       "o.__proto__ = proto1;"
    3604             :       "proto1.__proto__ = proto2;"
    3605             :       "proto2.y = function(x) { return x + 1; };"
    3606             :       // Invoke it many times to compile a stub
    3607             :       "for (var i = 0; i < 7; i++) {"
    3608             :       "  o.y(42);"
    3609             :       "}"
    3610             :       "proto1.y = function(x) { return x - 1; };"
    3611             :       "var result = 0;"
    3612             :       "for (var i = 0; i < 7; i++) {"
    3613             :       "  result += o.y(42);"
    3614             :       "}");
    3615          18 :   CHECK_EQ(41 * 7, value->Int32Value(context.local()).FromJust());
    3616           6 : }
    3617             : 
    3618             : 
    3619             : // This test checks that if interceptor doesn't provide a function,
    3620             : // cached constant function is used
    3621       23724 : THREADED_TEST(InterceptorCallICConstantFunctionUsed) {
    3622           6 :   v8::Isolate* isolate = CcTest::isolate();
    3623           6 :   v8::HandleScope scope(isolate);
    3624           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    3625           6 :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(NoBlockGetterX));
    3626          12 :   LocalContext context;
    3627             :   context->Global()
    3628             :       ->Set(context.local(), v8_str("o"),
    3629          30 :             templ->NewInstance(context.local()).ToLocalChecked())
    3630          12 :       .FromJust();
    3631             :   v8::Local<Value> value = CompileRun(
    3632             :       "function inc(x) { return x + 1; };"
    3633             :       "inc(1);"
    3634             :       "o.x = inc;"
    3635             :       "var result = 0;"
    3636             :       "for (var i = 0; i < 1000; i++) {"
    3637             :       "  result = o.x(42);"
    3638             :       "}");
    3639          18 :   CHECK_EQ(43, value->Int32Value(context.local()).FromJust());
    3640           6 : }
    3641             : 
    3642             : 
    3643             : static v8::Local<Value> call_ic_function5;
    3644        6000 : static void InterceptorCallICGetter5(
    3645             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    3646        6000 :   ApiTestFuzzer::Fuzz();
    3647        6000 :   if (v8_str("x")
    3648       12000 :           ->Equals(info.GetIsolate()->GetCurrentContext(), name)
    3649       12000 :           .FromJust())
    3650             :     info.GetReturnValue().Set(call_ic_function5);
    3651        6000 : }
    3652             : 
    3653             : 
    3654             : // This test checks that if interceptor provides a function,
    3655             : // even if we cached constant function, interceptor's function
    3656             : // is invoked
    3657       23724 : THREADED_TEST(InterceptorCallICConstantFunctionNotNeeded) {
    3658           6 :   v8::Isolate* isolate = CcTest::isolate();
    3659           6 :   v8::HandleScope scope(isolate);
    3660           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    3661             :   templ->SetHandler(
    3662           6 :       v8::NamedPropertyHandlerConfiguration(InterceptorCallICGetter5));
    3663          12 :   LocalContext context;
    3664             :   context->Global()
    3665             :       ->Set(context.local(), v8_str("o"),
    3666          30 :             templ->NewInstance(context.local()).ToLocalChecked())
    3667          12 :       .FromJust();
    3668             :   call_ic_function5 = v8_compile("function f(x) { return x - 1; }; f")
    3669           6 :                           ->Run(context.local())
    3670          12 :                           .ToLocalChecked();
    3671             :   v8::Local<Value> value = CompileRun(
    3672             :       "function inc(x) { return x + 1; };"
    3673             :       "inc(1);"
    3674             :       "o.x = inc;"
    3675             :       "var result = 0;"
    3676             :       "for (var i = 0; i < 1000; i++) {"
    3677             :       "  result = o.x(42);"
    3678             :       "}");
    3679          18 :   CHECK_EQ(41, value->Int32Value(context.local()).FromJust());
    3680           6 : }
    3681             : 
    3682             : 
    3683             : static v8::Local<Value> call_ic_function6;
    3684       24000 : static void InterceptorCallICGetter6(
    3685             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    3686       24000 :   ApiTestFuzzer::Fuzz();
    3687       24000 :   if (v8_str("x")
    3688       48000 :           ->Equals(info.GetIsolate()->GetCurrentContext(), name)
    3689       48000 :           .FromJust())
    3690             :     info.GetReturnValue().Set(call_ic_function6);
    3691       24000 : }
    3692             : 
    3693             : 
    3694             : // Same test as above, except the code is wrapped in a function
    3695             : // to test the optimized compiler.
    3696       23724 : THREADED_TEST(InterceptorCallICConstantFunctionNotNeededWrapped) {
    3697           6 :   i::FLAG_allow_natives_syntax = true;
    3698           6 :   v8::Isolate* isolate = CcTest::isolate();
    3699           6 :   v8::HandleScope scope(isolate);
    3700           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    3701             :   templ->SetHandler(
    3702           6 :       v8::NamedPropertyHandlerConfiguration(InterceptorCallICGetter6));
    3703          12 :   LocalContext context;
    3704             :   context->Global()
    3705             :       ->Set(context.local(), v8_str("o"),
    3706          30 :             templ->NewInstance(context.local()).ToLocalChecked())
    3707          12 :       .FromJust();
    3708             :   call_ic_function6 = v8_compile("function f(x) { return x - 1; }; f")
    3709           6 :                           ->Run(context.local())
    3710          12 :                           .ToLocalChecked();
    3711             :   v8::Local<Value> value = CompileRun(
    3712             :       "function inc(x) { return x + 1; };"
    3713             :       "inc(1);"
    3714             :       "o.x = inc;"
    3715             :       "function test() {"
    3716             :       "  var result = 0;"
    3717             :       "  for (var i = 0; i < 1000; i++) {"
    3718             :       "    result = o.x(42);"
    3719             :       "  }"
    3720             :       "  return result;"
    3721             :       "};"
    3722             :       "test();"
    3723             :       "test();"
    3724             :       "test();"
    3725             :       "%OptimizeFunctionOnNextCall(test);"
    3726             :       "test()");
    3727          18 :   CHECK_EQ(41, value->Int32Value(context.local()).FromJust());
    3728           6 : }
    3729             : 
    3730             : 
    3731             : // Test the case when we stored constant function into
    3732             : // a stub, but it got invalidated later on
    3733       23724 : THREADED_TEST(InterceptorCallICInvalidatedConstantFunction) {
    3734           6 :   v8::Isolate* isolate = CcTest::isolate();
    3735           6 :   v8::HandleScope scope(isolate);
    3736           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    3737           6 :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(NoBlockGetterX));
    3738          12 :   LocalContext context;
    3739             :   context->Global()
    3740             :       ->Set(context.local(), v8_str("o"),
    3741          30 :             templ->NewInstance(context.local()).ToLocalChecked())
    3742          12 :       .FromJust();
    3743             :   v8::Local<Value> value = CompileRun(
    3744             :       "function inc(x) { return x + 1; };"
    3745             :       "inc(1);"
    3746             :       "proto1 = new Object();"
    3747             :       "proto2 = new Object();"
    3748             :       "o.__proto__ = proto1;"
    3749             :       "proto1.__proto__ = proto2;"
    3750             :       "proto2.y = inc;"
    3751             :       // Invoke it many times to compile a stub
    3752             :       "for (var i = 0; i < 7; i++) {"
    3753             :       "  o.y(42);"
    3754             :       "}"
    3755             :       "proto1.y = function(x) { return x - 1; };"
    3756             :       "var result = 0;"
    3757             :       "for (var i = 0; i < 7; i++) {"
    3758             :       "  result += o.y(42);"
    3759             :       "}");
    3760          18 :   CHECK_EQ(41 * 7, value->Int32Value(context.local()).FromJust());
    3761           6 : }
    3762             : 
    3763             : 
    3764             : // Test the case when we stored constant function into
    3765             : // a stub, but it got invalidated later on due to override on
    3766             : // global object which is between interceptor and constant function' holders.
    3767       23724 : THREADED_TEST(InterceptorCallICInvalidatedConstantFunctionViaGlobal) {
    3768           6 :   v8::Isolate* isolate = CcTest::isolate();
    3769           6 :   v8::HandleScope scope(isolate);
    3770           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    3771           6 :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(NoBlockGetterX));
    3772          12 :   LocalContext context;
    3773             :   context->Global()
    3774             :       ->Set(context.local(), v8_str("o"),
    3775          30 :             templ->NewInstance(context.local()).ToLocalChecked())
    3776          12 :       .FromJust();
    3777             :   v8::Local<Value> value = CompileRun(
    3778             :       "function inc(x) { return x + 1; };"
    3779             :       "inc(1);"
    3780             :       "o.__proto__ = this;"
    3781             :       "this.__proto__.y = inc;"
    3782             :       // Invoke it many times to compile a stub
    3783             :       "for (var i = 0; i < 7; i++) {"
    3784             :       "  if (o.y(42) != 43) throw 'oops: ' + o.y(42);"
    3785             :       "}"
    3786             :       "this.y = function(x) { return x - 1; };"
    3787             :       "var result = 0;"
    3788             :       "for (var i = 0; i < 7; i++) {"
    3789             :       "  result += o.y(42);"
    3790             :       "}");
    3791          18 :   CHECK_EQ(41 * 7, value->Int32Value(context.local()).FromJust());
    3792           6 : }
    3793             : 
    3794             : 
    3795             : // Test the case when actual function to call sits on global object.
    3796       23724 : THREADED_TEST(InterceptorCallICCachedFromGlobal) {
    3797           6 :   v8::Isolate* isolate = CcTest::isolate();
    3798           6 :   v8::HandleScope scope(isolate);
    3799           6 :   v8::Local<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
    3800           6 :   templ_o->SetHandler(v8::NamedPropertyHandlerConfiguration(NoBlockGetterX));
    3801             : 
    3802          12 :   LocalContext context;
    3803             :   context->Global()
    3804             :       ->Set(context.local(), v8_str("o"),
    3805          30 :             templ_o->NewInstance(context.local()).ToLocalChecked())
    3806          12 :       .FromJust();
    3807             : 
    3808             :   v8::Local<Value> value = CompileRun(
    3809             :       "try {"
    3810             :       "  o.__proto__ = this;"
    3811             :       "  for (var i = 0; i < 10; i++) {"
    3812             :       "    var v = o.parseFloat('239');"
    3813             :       "    if (v != 239) throw v;"
    3814             :       // Now it should be ICed and keep a reference to parseFloat.
    3815             :       "  }"
    3816             :       "  var result = 0;"
    3817             :       "  for (var i = 0; i < 10; i++) {"
    3818             :       "    result += o.parseFloat('239');"
    3819             :       "  }"
    3820             :       "  result"
    3821             :       "} catch(e) {"
    3822             :       "  e"
    3823             :       "};");
    3824          18 :   CHECK_EQ(239 * 10, value->Int32Value(context.local()).FromJust());
    3825           6 : }
    3826             : 
    3827             : 
    3828             : v8::Local<Value> keyed_call_ic_function;
    3829             : 
    3830          30 : static void InterceptorKeyedCallICGetter(
    3831             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    3832          30 :   ApiTestFuzzer::Fuzz();
    3833          30 :   if (v8_str("x")
    3834          60 :           ->Equals(info.GetIsolate()->GetCurrentContext(), name)
    3835          60 :           .FromJust()) {
    3836             :     info.GetReturnValue().Set(keyed_call_ic_function);
    3837             :   }
    3838          30 : }
    3839             : 
    3840             : 
    3841             : // Test the case when we stored cacheable lookup into
    3842             : // a stub, but the function name changed (to another cacheable function).
    3843       23724 : THREADED_TEST(InterceptorKeyedCallICKeyChange1) {
    3844           6 :   v8::Isolate* isolate = CcTest::isolate();
    3845           6 :   v8::HandleScope scope(isolate);
    3846           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    3847           6 :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(NoBlockGetterX));
    3848          12 :   LocalContext context;
    3849             :   context->Global()
    3850             :       ->Set(context.local(), v8_str("o"),
    3851          30 :             templ->NewInstance(context.local()).ToLocalChecked())
    3852          12 :       .FromJust();
    3853             :   CompileRun(
    3854             :       "proto = new Object();"
    3855             :       "proto.y = function(x) { return x + 1; };"
    3856             :       "proto.z = function(x) { return x - 1; };"
    3857             :       "o.__proto__ = proto;"
    3858             :       "var result = 0;"
    3859             :       "var method = 'y';"
    3860             :       "for (var i = 0; i < 10; i++) {"
    3861             :       "  if (i == 5) { method = 'z'; };"
    3862             :       "  result += o[method](41);"
    3863             :       "}");
    3864          36 :   CHECK_EQ(42 * 5 + 40 * 5, context->Global()
    3865             :                                 ->Get(context.local(), v8_str("result"))
    3866             :                                 .ToLocalChecked()
    3867             :                                 ->Int32Value(context.local())
    3868           6 :                                 .FromJust());
    3869           6 : }
    3870             : 
    3871             : 
    3872             : // Test the case when we stored cacheable lookup into
    3873             : // a stub, but the function name changed (and the new function is present
    3874             : // both before and after the interceptor in the prototype chain).
    3875       23724 : THREADED_TEST(InterceptorKeyedCallICKeyChange2) {
    3876           6 :   v8::Isolate* isolate = CcTest::isolate();
    3877           6 :   v8::HandleScope scope(isolate);
    3878           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    3879             :   templ->SetHandler(
    3880           6 :       v8::NamedPropertyHandlerConfiguration(InterceptorKeyedCallICGetter));
    3881          12 :   LocalContext context;
    3882             :   context->Global()
    3883             :       ->Set(context.local(), v8_str("proto1"),
    3884          30 :             templ->NewInstance(context.local()).ToLocalChecked())
    3885          12 :       .FromJust();
    3886             :   keyed_call_ic_function = v8_compile("function f(x) { return x - 1; }; f")
    3887           6 :                                ->Run(context.local())
    3888          12 :                                .ToLocalChecked();
    3889             :   CompileRun(
    3890             :       "o = new Object();"
    3891             :       "proto2 = new Object();"
    3892             :       "o.y = function(x) { return x + 1; };"
    3893             :       "proto2.y = function(x) { return x + 2; };"
    3894             :       "o.__proto__ = proto1;"
    3895             :       "proto1.__proto__ = proto2;"
    3896             :       "var result = 0;"
    3897             :       "var method = 'x';"
    3898             :       "for (var i = 0; i < 10; i++) {"
    3899             :       "  if (i == 5) { method = 'y'; };"
    3900             :       "  result += o[method](41);"
    3901             :       "}");
    3902          36 :   CHECK_EQ(42 * 5 + 40 * 5, context->Global()
    3903             :                                 ->Get(context.local(), v8_str("result"))
    3904             :                                 .ToLocalChecked()
    3905             :                                 ->Int32Value(context.local())
    3906           6 :                                 .FromJust());
    3907           6 : }
    3908             : 
    3909             : 
    3910             : // Same as InterceptorKeyedCallICKeyChange1 only the cacheable function sit
    3911             : // on the global object.
    3912       23724 : THREADED_TEST(InterceptorKeyedCallICKeyChangeOnGlobal) {
    3913           6 :   v8::Isolate* isolate = CcTest::isolate();
    3914           6 :   v8::HandleScope scope(isolate);
    3915           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    3916           6 :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(NoBlockGetterX));
    3917          12 :   LocalContext context;
    3918             :   context->Global()
    3919             :       ->Set(context.local(), v8_str("o"),
    3920          30 :             templ->NewInstance(context.local()).ToLocalChecked())
    3921          12 :       .FromJust();
    3922             :   CompileRun(
    3923             :       "function inc(x) { return x + 1; };"
    3924             :       "inc(1);"
    3925             :       "function dec(x) { return x - 1; };"
    3926             :       "dec(1);"
    3927             :       "o.__proto__ = this;"
    3928             :       "this.__proto__.x = inc;"
    3929             :       "this.__proto__.y = dec;"
    3930             :       "var result = 0;"
    3931             :       "var method = 'x';"
    3932             :       "for (var i = 0; i < 10; i++) {"
    3933             :       "  if (i == 5) { method = 'y'; };"
    3934             :       "  result += o[method](41);"
    3935             :       "}");
    3936          36 :   CHECK_EQ(42 * 5 + 40 * 5, context->Global()
    3937             :                                 ->Get(context.local(), v8_str("result"))
    3938             :                                 .ToLocalChecked()
    3939             :                                 ->Int32Value(context.local())
    3940           6 :                                 .FromJust());
    3941           6 : }
    3942             : 
    3943             : 
    3944             : // Test the case when actual function to call sits on global object.
    3945       23724 : THREADED_TEST(InterceptorKeyedCallICFromGlobal) {
    3946           6 :   v8::Isolate* isolate = CcTest::isolate();
    3947           6 :   v8::HandleScope scope(isolate);
    3948           6 :   v8::Local<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
    3949           6 :   templ_o->SetHandler(v8::NamedPropertyHandlerConfiguration(NoBlockGetterX));
    3950          12 :   LocalContext context;
    3951             :   context->Global()
    3952             :       ->Set(context.local(), v8_str("o"),
    3953          30 :             templ_o->NewInstance(context.local()).ToLocalChecked())
    3954          12 :       .FromJust();
    3955             : 
    3956             :   CompileRun(
    3957             :       "function len(x) { return x.length; };"
    3958             :       "o.__proto__ = this;"
    3959             :       "var m = 'parseFloat';"
    3960             :       "var result = 0;"
    3961             :       "for (var i = 0; i < 10; i++) {"
    3962             :       "  if (i == 5) {"
    3963             :       "    m = 'len';"
    3964             :       "    saved_result = result;"
    3965             :       "  };"
    3966             :       "  result = o[m]('239');"
    3967             :       "}");
    3968          36 :   CHECK_EQ(3, context->Global()
    3969             :                   ->Get(context.local(), v8_str("result"))
    3970             :                   .ToLocalChecked()
    3971             :                   ->Int32Value(context.local())
    3972             :                   .FromJust());
    3973          36 :   CHECK_EQ(239, context->Global()
    3974             :                     ->Get(context.local(), v8_str("saved_result"))
    3975             :                     .ToLocalChecked()
    3976             :                     ->Int32Value(context.local())
    3977           6 :                     .FromJust());
    3978           6 : }
    3979             : 
    3980             : 
    3981             : // Test the map transition before the interceptor.
    3982       23724 : THREADED_TEST(InterceptorKeyedCallICMapChangeBefore) {
    3983           6 :   v8::Isolate* isolate = CcTest::isolate();
    3984           6 :   v8::HandleScope scope(isolate);
    3985           6 :   v8::Local<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
    3986           6 :   templ_o->SetHandler(v8::NamedPropertyHandlerConfiguration(NoBlockGetterX));
    3987          12 :   LocalContext context;
    3988             :   context->Global()
    3989             :       ->Set(context.local(), v8_str("proto"),
    3990          30 :             templ_o->NewInstance(context.local()).ToLocalChecked())
    3991          12 :       .FromJust();
    3992             : 
    3993             :   CompileRun(
    3994             :       "var o = new Object();"
    3995             :       "o.__proto__ = proto;"
    3996             :       "o.method = function(x) { return x + 1; };"
    3997             :       "var m = 'method';"
    3998             :       "var result = 0;"
    3999             :       "for (var i = 0; i < 10; i++) {"
    4000             :       "  if (i == 5) { o.method = function(x) { return x - 1; }; };"
    4001             :       "  result += o[m](41);"
    4002             :       "}");
    4003          36 :   CHECK_EQ(42 * 5 + 40 * 5, context->Global()
    4004             :                                 ->Get(context.local(), v8_str("result"))
    4005             :                                 .ToLocalChecked()
    4006             :                                 ->Int32Value(context.local())
    4007           6 :                                 .FromJust());
    4008           6 : }
    4009             : 
    4010             : 
    4011             : // Test the map transition after the interceptor.
    4012       23724 : THREADED_TEST(InterceptorKeyedCallICMapChangeAfter) {
    4013           6 :   v8::Isolate* isolate = CcTest::isolate();
    4014           6 :   v8::HandleScope scope(isolate);
    4015           6 :   v8::Local<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
    4016           6 :   templ_o->SetHandler(v8::NamedPropertyHandlerConfiguration(NoBlockGetterX));
    4017          12 :   LocalContext context;
    4018             :   context->Global()
    4019             :       ->Set(context.local(), v8_str("o"),
    4020          30 :             templ_o->NewInstance(context.local()).ToLocalChecked())
    4021          12 :       .FromJust();
    4022             : 
    4023             :   CompileRun(
    4024             :       "var proto = new Object();"
    4025             :       "o.__proto__ = proto;"
    4026             :       "proto.method = function(x) { return x + 1; };"
    4027             :       "var m = 'method';"
    4028             :       "var result = 0;"
    4029             :       "for (var i = 0; i < 10; i++) {"
    4030             :       "  if (i == 5) { proto.method = function(x) { return x - 1; }; };"
    4031             :       "  result += o[m](41);"
    4032             :       "}");
    4033          36 :   CHECK_EQ(42 * 5 + 40 * 5, context->Global()
    4034             :                                 ->Get(context.local(), v8_str("result"))
    4035             :                                 .ToLocalChecked()
    4036             :                                 ->Int32Value(context.local())
    4037           6 :                                 .FromJust());
    4038           6 : }
    4039             : 
    4040             : 
    4041             : static int interceptor_call_count = 0;
    4042             : 
    4043         288 : static void InterceptorICRefErrorGetter(
    4044             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    4045         288 :   ApiTestFuzzer::Fuzz();
    4046         864 :   if (!is_bootstrapping &&
    4047             :       v8_str("x")
    4048         864 :           ->Equals(info.GetIsolate()->GetCurrentContext(), name)
    4049         828 :           .FromJust() &&
    4050         252 :       interceptor_call_count++ < 20) {
    4051             :     info.GetReturnValue().Set(call_ic_function2);
    4052             :   }
    4053         288 : }
    4054             : 
    4055             : 
    4056             : // This test should hit load and call ICs for the interceptor case.
    4057             : // Once in a while, the interceptor will reply that a property was not
    4058             : // found in which case we should get a reference error.
    4059       23724 : THREADED_TEST(InterceptorICReferenceErrors) {
    4060           6 :   v8::Isolate* isolate = CcTest::isolate();
    4061           6 :   v8::HandleScope scope(isolate);
    4062           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    4063             :   templ->SetHandler(
    4064           6 :       v8::NamedPropertyHandlerConfiguration(InterceptorICRefErrorGetter));
    4065           6 :   is_bootstrapping = true;
    4066          12 :   LocalContext context(0, templ, v8::Local<Value>());
    4067           6 :   is_bootstrapping = false;
    4068             :   call_ic_function2 = v8_compile("function h(x) { return x; }; h")
    4069           6 :                           ->Run(context.local())
    4070          12 :                           .ToLocalChecked();
    4071             :   v8::Local<Value> value = CompileRun(
    4072             :       "function f() {"
    4073             :       "  for (var i = 0; i < 1000; i++) {"
    4074             :       "    try { x; } catch(e) { return true; }"
    4075             :       "  }"
    4076             :       "  return false;"
    4077             :       "};"
    4078             :       "f();");
    4079          12 :   CHECK(value->BooleanValue(context.local()).FromJust());
    4080           6 :   interceptor_call_count = 0;
    4081             :   value = CompileRun(
    4082             :       "function g() {"
    4083             :       "  for (var i = 0; i < 1000; i++) {"
    4084             :       "    try { x(42); } catch(e) { return true; }"
    4085             :       "  }"
    4086             :       "  return false;"
    4087             :       "};"
    4088             :       "g();");
    4089          18 :   CHECK(value->BooleanValue(context.local()).FromJust());
    4090           6 : }
    4091             : 
    4092             : 
    4093             : static int interceptor_ic_exception_get_count = 0;
    4094             : 
    4095         276 : static void InterceptorICExceptionGetter(
    4096             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    4097         276 :   ApiTestFuzzer::Fuzz();
    4098         276 :   if (is_bootstrapping) return;
    4099         276 :   if (v8_str("x")
    4100         552 :           ->Equals(info.GetIsolate()->GetCurrentContext(), name)
    4101         792 :           .FromJust() &&
    4102         240 :       ++interceptor_ic_exception_get_count < 20) {
    4103             :     info.GetReturnValue().Set(call_ic_function3);
    4104             :   }
    4105         276 :   if (interceptor_ic_exception_get_count == 20) {
    4106          24 :     info.GetIsolate()->ThrowException(v8_num(42));
    4107          12 :     return;
    4108             :   }
    4109             : }
    4110             : 
    4111             : 
    4112             : // Test interceptor load/call IC where the interceptor throws an
    4113             : // exception once in a while.
    4114       23724 : THREADED_TEST(InterceptorICGetterExceptions) {
    4115           6 :   interceptor_ic_exception_get_count = 0;
    4116           6 :   v8::Isolate* isolate = CcTest::isolate();
    4117           6 :   v8::HandleScope scope(isolate);
    4118           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    4119             :   templ->SetHandler(
    4120           6 :       v8::NamedPropertyHandlerConfiguration(InterceptorICExceptionGetter));
    4121           6 :   is_bootstrapping = true;
    4122          12 :   LocalContext context(0, templ, v8::Local<Value>());
    4123           6 :   is_bootstrapping = false;
    4124             :   call_ic_function3 = v8_compile("function h(x) { return x; }; h")
    4125           6 :                           ->Run(context.local())
    4126          12 :                           .ToLocalChecked();
    4127             :   v8::Local<Value> value = CompileRun(
    4128             :       "function f() {"
    4129             :       "  for (var i = 0; i < 100; i++) {"
    4130             :       "    try { x; } catch(e) { return true; }"
    4131             :       "  }"
    4132             :       "  return false;"
    4133             :       "};"
    4134             :       "f();");
    4135          12 :   CHECK(value->BooleanValue(context.local()).FromJust());
    4136           6 :   interceptor_ic_exception_get_count = 0;
    4137             :   value = CompileRun(
    4138             :       "function f() {"
    4139             :       "  for (var i = 0; i < 100; i++) {"
    4140             :       "    try { x(42); } catch(e) { return true; }"
    4141             :       "  }"
    4142             :       "  return false;"
    4143             :       "};"
    4144             :       "f();");
    4145          18 :   CHECK(value->BooleanValue(context.local()).FromJust());
    4146           6 : }
    4147             : 
    4148             : 
    4149             : static int interceptor_ic_exception_set_count = 0;
    4150             : 
    4151         126 : static void InterceptorICExceptionSetter(
    4152             :     Local<Name> key, Local<Value> value,
    4153             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
    4154         126 :   ApiTestFuzzer::Fuzz();
    4155         126 :   if (++interceptor_ic_exception_set_count > 20) {
    4156          12 :     info.GetIsolate()->ThrowException(v8_num(42));
    4157             :   }
    4158         126 : }
    4159             : 
    4160             : 
    4161             : // Test interceptor store IC where the interceptor throws an exception
    4162             : // once in a while.
    4163       23724 : THREADED_TEST(InterceptorICSetterExceptions) {
    4164           6 :   interceptor_ic_exception_set_count = 0;
    4165           6 :   v8::Isolate* isolate = CcTest::isolate();
    4166           6 :   v8::HandleScope scope(isolate);
    4167           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    4168             :   templ->SetHandler(
    4169           6 :       v8::NamedPropertyHandlerConfiguration(0, InterceptorICExceptionSetter));
    4170          12 :   LocalContext context(0, templ, v8::Local<Value>());
    4171             :   v8::Local<Value> value = CompileRun(
    4172             :       "function f() {"
    4173             :       "  for (var i = 0; i < 100; i++) {"
    4174             :       "    try { x = 42; } catch(e) { return true; }"
    4175             :       "  }"
    4176             :       "  return false;"
    4177             :       "};"
    4178             :       "f();");
    4179          18 :   CHECK(value->BooleanValue(context.local()).FromJust());
    4180           6 : }
    4181             : 
    4182             : 
    4183             : // Test that we ignore null interceptors.
    4184       23724 : THREADED_TEST(NullNamedInterceptor) {
    4185           6 :   v8::Isolate* isolate = CcTest::isolate();
    4186           6 :   v8::HandleScope scope(isolate);
    4187           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    4188             :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
    4189           6 :       static_cast<v8::GenericNamedPropertyGetterCallback>(0)));
    4190          12 :   LocalContext context;
    4191           6 :   templ->Set(CcTest::isolate(), "x", v8_num(42));
    4192             :   v8::Local<v8::Object> obj =
    4193           6 :       templ->NewInstance(context.local()).ToLocalChecked();
    4194          30 :   context->Global()->Set(context.local(), v8_str("obj"), obj).FromJust();
    4195             :   v8::Local<Value> value = CompileRun("obj.x");
    4196           6 :   CHECK(value->IsInt32());
    4197          18 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
    4198           6 : }
    4199             : 
    4200             : 
    4201             : // Test that we ignore null interceptors.
    4202       23724 : THREADED_TEST(NullIndexedInterceptor) {
    4203           6 :   v8::Isolate* isolate = CcTest::isolate();
    4204           6 :   v8::HandleScope scope(isolate);
    4205           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    4206             :   templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
    4207           6 :       static_cast<v8::IndexedPropertyGetterCallback>(0)));
    4208          12 :   LocalContext context;
    4209           6 :   templ->Set(CcTest::isolate(), "42", v8_num(42));
    4210             :   v8::Local<v8::Object> obj =
    4211           6 :       templ->NewInstance(context.local()).ToLocalChecked();
    4212          30 :   context->Global()->Set(context.local(), v8_str("obj"), obj).FromJust();
    4213             :   v8::Local<Value> value = CompileRun("obj[42]");
    4214           6 :   CHECK(value->IsInt32());
    4215          18 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
    4216           6 : }
    4217             : 
    4218             : 
    4219       23724 : THREADED_TEST(NamedPropertyHandlerGetterAttributes) {
    4220           6 :   v8::Isolate* isolate = CcTest::isolate();
    4221           6 :   v8::HandleScope scope(isolate);
    4222           6 :   v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
    4223             :   templ->InstanceTemplate()->SetHandler(
    4224          12 :       v8::NamedPropertyHandlerConfiguration(InterceptorLoadXICGetter));
    4225          12 :   LocalContext env;
    4226             :   env->Global()
    4227           6 :       ->Set(env.local(), v8_str("obj"), templ->GetFunction(env.local())
    4228           6 :                                             .ToLocalChecked()
    4229           6 :                                             ->NewInstance(env.local())
    4230          24 :                                             .ToLocalChecked())
    4231          12 :       .FromJust();
    4232             :   ExpectTrue("obj.x === 42");
    4233           6 :   ExpectTrue("!obj.propertyIsEnumerable('x')");
    4234           6 : }
    4235             : 
    4236             : 
    4237       23724 : THREADED_TEST(Regress256330) {
    4238           7 :   if (!i::FLAG_opt) return;
    4239           5 :   i::FLAG_allow_natives_syntax = true;
    4240           5 :   LocalContext context;
    4241          10 :   v8::HandleScope scope(context->GetIsolate());
    4242           5 :   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
    4243           5 :   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
    4244             :   context->Global()
    4245             :       ->Set(context.local(), v8_str("Bug"),
    4246          30 :             templ->GetFunction(context.local()).ToLocalChecked())
    4247          10 :       .FromJust();
    4248             :   CompileRun(
    4249             :       "\"use strict\"; var o = new Bug;"
    4250             :       "function f(o) { o.x = 10; };"
    4251             :       "f(o); f(o); f(o);"
    4252             :       "%OptimizeFunctionOnNextCall(f);"
    4253             :       "f(o);");
    4254           5 :   int status = v8_run_int32value(v8_compile("%GetOptimizationStatus(f)"));
    4255             :   int mask = static_cast<int>(i::OptimizationStatus::kIsFunction) |
    4256             :              static_cast<int>(i::OptimizationStatus::kOptimized);
    4257          10 :   CHECK_EQ(mask, status & mask);
    4258             : }
    4259             : 
    4260             : 
    4261       23724 : THREADED_TEST(CrankshaftInterceptorSetter) {
    4262           6 :   i::FLAG_allow_natives_syntax = true;
    4263           6 :   v8::HandleScope scope(CcTest::isolate());
    4264           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
    4265           6 :   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
    4266          12 :   LocalContext env;
    4267             :   env->Global()
    4268             :       ->Set(env.local(), v8_str("Obj"),
    4269          36 :             templ->GetFunction(env.local()).ToLocalChecked())
    4270          12 :       .FromJust();
    4271             :   CompileRun(
    4272             :       "var obj = new Obj;"
    4273             :       // Initialize fields to avoid transitions later.
    4274             :       "obj.age = 0;"
    4275             :       "obj.accessor_age = 42;"
    4276             :       "function setter(i) { this.accessor_age = i; };"
    4277             :       "function getter() { return this.accessor_age; };"
    4278             :       "function setAge(i) { obj.age = i; };"
    4279             :       "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
    4280             :       "setAge(1);"
    4281             :       "setAge(2);"
    4282             :       "setAge(3);"
    4283             :       "%OptimizeFunctionOnNextCall(setAge);"
    4284             :       "setAge(4);");
    4285             :   // All stores went through the interceptor.
    4286           6 :   ExpectInt32("obj.interceptor_age", 4);
    4287          12 :   ExpectInt32("obj.accessor_age", 42);
    4288           6 : }
    4289             : 
    4290             : 
    4291       23724 : THREADED_TEST(CrankshaftInterceptorGetter) {
    4292           6 :   i::FLAG_allow_natives_syntax = true;
    4293           6 :   v8::HandleScope scope(CcTest::isolate());
    4294           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
    4295           6 :   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
    4296          12 :   LocalContext env;
    4297             :   env->Global()
    4298             :       ->Set(env.local(), v8_str("Obj"),
    4299          36 :             templ->GetFunction(env.local()).ToLocalChecked())
    4300          12 :       .FromJust();
    4301             :   CompileRun(
    4302             :       "var obj = new Obj;"
    4303             :       // Initialize fields to avoid transitions later.
    4304             :       "obj.age = 1;"
    4305             :       "obj.accessor_age = 42;"
    4306             :       "function getter() { return this.accessor_age; };"
    4307             :       "function getAge() { return obj.interceptor_age; };"
    4308             :       "Object.defineProperty(obj, 'interceptor_age', { get:getter });"
    4309             :       "getAge();"
    4310             :       "getAge();"
    4311             :       "getAge();"
    4312             :       "%OptimizeFunctionOnNextCall(getAge);");
    4313             :   // Access through interceptor.
    4314          12 :   ExpectInt32("getAge()", 1);
    4315           6 : }
    4316             : 
    4317             : 
    4318       23724 : THREADED_TEST(CrankshaftInterceptorFieldRead) {
    4319           6 :   i::FLAG_allow_natives_syntax = true;
    4320           6 :   v8::HandleScope scope(CcTest::isolate());
    4321           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
    4322           6 :   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
    4323          12 :   LocalContext env;
    4324             :   env->Global()
    4325             :       ->Set(env.local(), v8_str("Obj"),
    4326          36 :             templ->GetFunction(env.local()).ToLocalChecked())
    4327          12 :       .FromJust();
    4328             :   CompileRun(
    4329             :       "var obj = new Obj;"
    4330             :       "obj.__proto__.interceptor_age = 42;"
    4331             :       "obj.age = 100;"
    4332             :       "function getAge() { return obj.interceptor_age; };");
    4333           6 :   ExpectInt32("getAge();", 100);
    4334           6 :   ExpectInt32("getAge();", 100);
    4335           6 :   ExpectInt32("getAge();", 100);
    4336             :   CompileRun("%OptimizeFunctionOnNextCall(getAge);");
    4337             :   // Access through interceptor.
    4338          12 :   ExpectInt32("getAge();", 100);
    4339           6 : }
    4340             : 
    4341             : 
    4342       23724 : THREADED_TEST(CrankshaftInterceptorFieldWrite) {
    4343           6 :   i::FLAG_allow_natives_syntax = true;
    4344           6 :   v8::HandleScope scope(CcTest::isolate());
    4345           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
    4346           6 :   AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
    4347          12 :   LocalContext env;
    4348             :   env->Global()
    4349             :       ->Set(env.local(), v8_str("Obj"),
    4350          36 :             templ->GetFunction(env.local()).ToLocalChecked())
    4351          12 :       .FromJust();
    4352             :   CompileRun(
    4353             :       "var obj = new Obj;"
    4354             :       "obj.age = 100000;"
    4355             :       "function setAge(i) { obj.age = i };"
    4356             :       "setAge(100);"
    4357             :       "setAge(101);"
    4358             :       "setAge(102);"
    4359             :       "%OptimizeFunctionOnNextCall(setAge);"
    4360             :       "setAge(103);");
    4361           6 :   ExpectInt32("obj.age", 100000);
    4362          12 :   ExpectInt32("obj.interceptor_age", 103);
    4363           6 : }
    4364             : 
    4365             : 
    4366       23724 : THREADED_TEST(Regress149912) {
    4367           6 :   LocalContext context;
    4368          12 :   v8::HandleScope scope(context->GetIsolate());
    4369           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
    4370           6 :   AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
    4371             :   context->Global()
    4372             :       ->Set(context.local(), v8_str("Bug"),
    4373          36 :             templ->GetFunction(context.local()).ToLocalChecked())
    4374          12 :       .FromJust();
    4375           6 :   CompileRun("Number.prototype.__proto__ = new Bug; var x = 0; x.foo();");
    4376           6 : }
    4377             : 
    4378       23724 : THREADED_TEST(Regress625155) {
    4379           6 :   LocalContext context;
    4380          12 :   v8::HandleScope scope(context->GetIsolate());
    4381           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
    4382           6 :   AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
    4383             :   context->Global()
    4384             :       ->Set(context.local(), v8_str("Bug"),
    4385          36 :             templ->GetFunction(context.local()).ToLocalChecked())
    4386          12 :       .FromJust();
    4387             :   CompileRun(
    4388             :       "Number.prototype.__proto__ = new Bug;"
    4389             :       "var x;"
    4390             :       "x = 0xdead;"
    4391             :       "x.boom = 0;"
    4392             :       "x = 's';"
    4393             :       "x.boom = 0;"
    4394             :       "x = 1.5;"
    4395           6 :       "x.boom = 0;");
    4396           6 : }
    4397             : 
    4398       23724 : THREADED_TEST(Regress125988) {
    4399           6 :   v8::HandleScope scope(CcTest::isolate());
    4400           6 :   Local<FunctionTemplate> intercept = FunctionTemplate::New(CcTest::isolate());
    4401           6 :   AddInterceptor(intercept, EmptyInterceptorGetter, EmptyInterceptorSetter);
    4402          12 :   LocalContext env;
    4403             :   env->Global()
    4404             :       ->Set(env.local(), v8_str("Intercept"),
    4405          36 :             intercept->GetFunction(env.local()).ToLocalChecked())
    4406          12 :       .FromJust();
    4407             :   CompileRun(
    4408             :       "var a = new Object();"
    4409             :       "var b = new Intercept();"
    4410             :       "var c = new Object();"
    4411             :       "c.__proto__ = b;"
    4412             :       "b.__proto__ = a;"
    4413             :       "a.x = 23;"
    4414             :       "for (var i = 0; i < 3; i++) c.x;");
    4415           6 :   ExpectBoolean("c.hasOwnProperty('x')", false);
    4416           6 :   ExpectInt32("c.x", 23);
    4417             :   CompileRun(
    4418             :       "a.y = 42;"
    4419             :       "for (var i = 0; i < 3; i++) c.x;");
    4420           6 :   ExpectBoolean("c.hasOwnProperty('x')", false);
    4421           6 :   ExpectInt32("c.x", 23);
    4422           6 :   ExpectBoolean("c.hasOwnProperty('y')", false);
    4423          12 :   ExpectInt32("c.y", 42);
    4424           6 : }
    4425             : 
    4426             : 
    4427          12 : static void IndexedPropertyEnumerator(
    4428             :     const v8::PropertyCallbackInfo<v8::Array>& info) {
    4429          12 :   v8::Local<v8::Array> result = v8::Array::New(info.GetIsolate(), 1);
    4430             :   result->Set(info.GetIsolate()->GetCurrentContext(), 0,
    4431          36 :               v8::Integer::New(info.GetIsolate(), 7))
    4432          24 :       .FromJust();
    4433             :   info.GetReturnValue().Set(result);
    4434          12 : }
    4435             : 
    4436             : 
    4437          18 : static void NamedPropertyEnumerator(
    4438             :     const v8::PropertyCallbackInfo<v8::Array>& info) {
    4439          18 :   v8::Local<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
    4440          18 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    4441          54 :   result->Set(context, 0, v8_str("x")).FromJust();
    4442          36 :   result->Set(context, 1, v8::Symbol::GetIterator(info.GetIsolate()))
    4443          36 :       .FromJust();
    4444             :   info.GetReturnValue().Set(result);
    4445          18 : }
    4446             : 
    4447             : 
    4448       23724 : THREADED_TEST(GetOwnPropertyNamesWithInterceptor) {
    4449           6 :   v8::Isolate* isolate = CcTest::isolate();
    4450           6 :   v8::HandleScope handle_scope(isolate);
    4451           6 :   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
    4452             : 
    4453          18 :   obj_template->Set(v8_str("7"), v8::Integer::New(CcTest::isolate(), 7));
    4454          18 :   obj_template->Set(v8_str("x"), v8::Integer::New(CcTest::isolate(), 42));
    4455             :   obj_template->SetHandler(v8::IndexedPropertyHandlerConfiguration(
    4456           6 :       nullptr, nullptr, nullptr, nullptr, IndexedPropertyEnumerator));
    4457             :   obj_template->SetHandler(v8::NamedPropertyHandlerConfiguration(
    4458           6 :       nullptr, nullptr, nullptr, nullptr, NamedPropertyEnumerator));
    4459             : 
    4460          12 :   LocalContext context;
    4461           6 :   v8::Local<v8::Object> global = context->Global();
    4462             :   global->Set(context.local(), v8_str("object"),
    4463          24 :               obj_template->NewInstance(context.local()).ToLocalChecked())
    4464          12 :       .FromJust();
    4465             : 
    4466             :   v8::Local<v8::Value> result =
    4467             :       CompileRun("Object.getOwnPropertyNames(object)");
    4468           6 :   CHECK(result->IsArray());
    4469             :   v8::Local<v8::Array> result_array = v8::Local<v8::Array>::Cast(result);
    4470           6 :   CHECK_EQ(2u, result_array->Length());
    4471          12 :   CHECK(result_array->Get(context.local(), 0).ToLocalChecked()->IsString());
    4472          12 :   CHECK(result_array->Get(context.local(), 1).ToLocalChecked()->IsString());
    4473          24 :   CHECK(v8_str("7")
    4474             :             ->Equals(context.local(),
    4475             :                      result_array->Get(context.local(), 0).ToLocalChecked())
    4476             :             .FromJust());
    4477          24 :   CHECK(v8_str("x")
    4478             :             ->Equals(context.local(),
    4479             :                      result_array->Get(context.local(), 1).ToLocalChecked())
    4480             :             .FromJust());
    4481             : 
    4482             :   result = CompileRun("var ret = []; for (var k in object) ret.push(k); ret");
    4483           6 :   CHECK(result->IsArray());
    4484             :   result_array = v8::Local<v8::Array>::Cast(result);
    4485           6 :   CHECK_EQ(2u, result_array->Length());
    4486          12 :   CHECK(result_array->Get(context.local(), 0).ToLocalChecked()->IsString());
    4487          12 :   CHECK(result_array->Get(context.local(), 1).ToLocalChecked()->IsString());
    4488          24 :   CHECK(v8_str("7")
    4489             :             ->Equals(context.local(),
    4490             :                      result_array->Get(context.local(), 0).ToLocalChecked())
    4491             :             .FromJust());
    4492          24 :   CHECK(v8_str("x")
    4493             :             ->Equals(context.local(),
    4494             :                      result_array->Get(context.local(), 1).ToLocalChecked())
    4495             :             .FromJust());
    4496             : 
    4497             :   result = CompileRun("Object.getOwnPropertySymbols(object)");
    4498           6 :   CHECK(result->IsArray());
    4499             :   result_array = v8::Local<v8::Array>::Cast(result);
    4500           6 :   CHECK_EQ(1u, result_array->Length());
    4501          24 :   CHECK(result_array->Get(context.local(), 0)
    4502             :             .ToLocalChecked()
    4503             :             ->Equals(context.local(), v8::Symbol::GetIterator(isolate))
    4504           6 :             .FromJust());
    4505           6 : }
    4506             : 
    4507             : 
    4508          12 : static void IndexedPropertyEnumeratorException(
    4509             :     const v8::PropertyCallbackInfo<v8::Array>& info) {
    4510          24 :   info.GetIsolate()->ThrowException(v8_num(42));
    4511          12 : }
    4512             : 
    4513             : 
    4514       23724 : THREADED_TEST(GetOwnPropertyNamesWithIndexedInterceptorExceptions_regress4026) {
    4515           6 :   v8::Isolate* isolate = CcTest::isolate();
    4516           6 :   v8::HandleScope handle_scope(isolate);
    4517           6 :   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
    4518             : 
    4519          18 :   obj_template->Set(v8_str("7"), v8::Integer::New(CcTest::isolate(), 7));
    4520          18 :   obj_template->Set(v8_str("x"), v8::Integer::New(CcTest::isolate(), 42));
    4521             :   // First just try a failing indexed interceptor.
    4522             :   obj_template->SetHandler(v8::IndexedPropertyHandlerConfiguration(
    4523           6 :       nullptr, nullptr, nullptr, nullptr, IndexedPropertyEnumeratorException));
    4524             : 
    4525          12 :   LocalContext context;
    4526           6 :   v8::Local<v8::Object> global = context->Global();
    4527             :   global->Set(context.local(), v8_str("object"),
    4528          24 :               obj_template->NewInstance(context.local()).ToLocalChecked())
    4529          12 :       .FromJust();
    4530             :   v8::Local<v8::Value> result = CompileRun(
    4531             :       "var result  = []; "
    4532             :       "try { "
    4533             :       "  for (var k in object) result .push(k);"
    4534             :       "} catch (e) {"
    4535             :       "  result  = e"
    4536             :       "}"
    4537             :       "result ");
    4538           6 :   CHECK(!result->IsArray());
    4539          18 :   CHECK(v8_num(42)->Equals(context.local(), result).FromJust());
    4540             : 
    4541             :   result = CompileRun(
    4542             :       "var result = [];"
    4543             :       "try { "
    4544             :       "  result = Object.keys(object);"
    4545             :       "} catch (e) {"
    4546             :       "  result = e;"
    4547             :       "}"
    4548             :       "result");
    4549           6 :   CHECK(!result->IsArray());
    4550          24 :   CHECK(v8_num(42)->Equals(context.local(), result).FromJust());
    4551           6 : }
    4552             : 
    4553             : 
    4554          12 : static void NamedPropertyEnumeratorException(
    4555             :     const v8::PropertyCallbackInfo<v8::Array>& info) {
    4556          24 :   info.GetIsolate()->ThrowException(v8_num(43));
    4557          12 : }
    4558             : 
    4559             : 
    4560       23724 : THREADED_TEST(GetOwnPropertyNamesWithNamedInterceptorExceptions_regress4026) {
    4561           6 :   v8::Isolate* isolate = CcTest::isolate();
    4562           6 :   v8::HandleScope handle_scope(isolate);
    4563           6 :   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
    4564             : 
    4565          18 :   obj_template->Set(v8_str("7"), v8::Integer::New(CcTest::isolate(), 7));
    4566          18 :   obj_template->Set(v8_str("x"), v8::Integer::New(CcTest::isolate(), 42));
    4567             :   // First just try a failing indexed interceptor.
    4568             :   obj_template->SetHandler(v8::NamedPropertyHandlerConfiguration(
    4569           6 :       nullptr, nullptr, nullptr, nullptr, NamedPropertyEnumeratorException));
    4570             : 
    4571          12 :   LocalContext context;
    4572           6 :   v8::Local<v8::Object> global = context->Global();
    4573             :   global->Set(context.local(), v8_str("object"),
    4574          24 :               obj_template->NewInstance(context.local()).ToLocalChecked())
    4575          12 :       .FromJust();
    4576             : 
    4577             :   v8::Local<v8::Value> result = CompileRun(
    4578             :       "var result = []; "
    4579             :       "try { "
    4580             :       "  for (var k in object) result.push(k);"
    4581             :       "} catch (e) {"
    4582             :       "  result = e"
    4583             :       "}"
    4584             :       "result");
    4585           6 :   CHECK(!result->IsArray());
    4586          18 :   CHECK(v8_num(43)->Equals(context.local(), result).FromJust());
    4587             : 
    4588             :   result = CompileRun(
    4589             :       "var result = [];"
    4590             :       "try { "
    4591             :       "  result = Object.keys(object);"
    4592             :       "} catch (e) {"
    4593             :       "  result = e;"
    4594             :       "}"
    4595             :       "result");
    4596           6 :   CHECK(!result->IsArray());
    4597          24 :   CHECK(v8_num(43)->Equals(context.local(), result).FromJust());
    4598           6 : }
    4599             : 
    4600             : namespace {
    4601             : 
    4602             : template <typename T>
    4603          38 : Local<Object> BuildWrappedObject(v8::Isolate* isolate, T* data) {
    4604          38 :   auto templ = v8::ObjectTemplate::New(isolate);
    4605          38 :   templ->SetInternalFieldCount(1);
    4606             :   auto instance =
    4607          38 :       templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
    4608          38 :   instance->SetAlignedPointerInInternalField(0, data);
    4609          38 :   return instance;
    4610             : }
    4611             : 
    4612             : 
    4613             : template <typename T>
    4614         276 : T* GetWrappedObject(Local<Value> data) {
    4615             :   return reinterpret_cast<T*>(
    4616         276 :       Object::Cast(*data)->GetAlignedPointerFromInternalField(0));
    4617             : }
    4618             : 
    4619             : 
    4620             : struct AccessCheckData {
    4621             :   int count;
    4622             :   bool result;
    4623             : };
    4624             : 
    4625             : AccessCheckData* g_access_check_data = nullptr;
    4626             : 
    4627         120 : bool SimpleAccessChecker(Local<v8::Context> accessing_context,
    4628             :                          Local<v8::Object> access_object,
    4629             :                          Local<v8::Value> data) {
    4630         120 :   g_access_check_data->count++;
    4631         120 :   return g_access_check_data->result;
    4632             : }
    4633             : 
    4634             : 
    4635             : struct ShouldInterceptData {
    4636             :   int value;
    4637             :   bool should_intercept;
    4638             : };
    4639             : 
    4640             : 
    4641         261 : void ShouldNamedInterceptor(Local<Name> name,
    4642             :                             const v8::PropertyCallbackInfo<Value>& info) {
    4643         261 :   ApiTestFuzzer::Fuzz();
    4644         261 :   CheckReturnValue(info, FUNCTION_ADDR(ShouldNamedInterceptor));
    4645         261 :   auto data = GetWrappedObject<ShouldInterceptData>(info.Data());
    4646         522 :   if (!data->should_intercept) return;
    4647         256 :   info.GetReturnValue().Set(v8_num(data->value));
    4648             : }
    4649             : 
    4650             : 
    4651          15 : void ShouldIndexedInterceptor(uint32_t,
    4652             :                               const v8::PropertyCallbackInfo<Value>& info) {
    4653          15 :   ApiTestFuzzer::Fuzz();
    4654          15 :   CheckReturnValue(info, FUNCTION_ADDR(ShouldIndexedInterceptor));
    4655          15 :   auto data = GetWrappedObject<ShouldInterceptData>(info.Data());
    4656          30 :   if (!data->should_intercept) return;
    4657          10 :   info.GetReturnValue().Set(v8_num(data->value));
    4658             : }
    4659             : 
    4660             : }  // namespace
    4661             : 
    4662             : 
    4663       23723 : TEST(NamedAllCanReadInterceptor) {
    4664           5 :   auto isolate = CcTest::isolate();
    4665           5 :   v8::HandleScope handle_scope(isolate);
    4666          10 :   LocalContext context;
    4667             : 
    4668             :   AccessCheckData access_check_data;
    4669           5 :   access_check_data.result = true;
    4670           5 :   access_check_data.count = 0;
    4671             : 
    4672           5 :   g_access_check_data = &access_check_data;
    4673             : 
    4674             :   ShouldInterceptData intercept_data_0;
    4675           5 :   intercept_data_0.value = 239;
    4676           5 :   intercept_data_0.should_intercept = true;
    4677             : 
    4678             :   ShouldInterceptData intercept_data_1;
    4679           5 :   intercept_data_1.value = 165;
    4680           5 :   intercept_data_1.should_intercept = false;
    4681             : 
    4682           5 :   auto intercepted_0 = v8::ObjectTemplate::New(isolate);
    4683             :   {
    4684             :     v8::NamedPropertyHandlerConfiguration conf(ShouldNamedInterceptor);
    4685           5 :     conf.flags = v8::PropertyHandlerFlags::kAllCanRead;
    4686             :     conf.data =
    4687           5 :         BuildWrappedObject<ShouldInterceptData>(isolate, &intercept_data_0);
    4688           5 :     intercepted_0->SetHandler(conf);
    4689             :   }
    4690             : 
    4691           5 :   auto intercepted_1 = v8::ObjectTemplate::New(isolate);
    4692             :   {
    4693             :     v8::NamedPropertyHandlerConfiguration conf(ShouldNamedInterceptor);
    4694           5 :     conf.flags = v8::PropertyHandlerFlags::kAllCanRead;
    4695             :     conf.data =
    4696           5 :         BuildWrappedObject<ShouldInterceptData>(isolate, &intercept_data_1);
    4697           5 :     intercepted_1->SetHandler(conf);
    4698             :   }
    4699             : 
    4700           5 :   auto checked = v8::ObjectTemplate::New(isolate);
    4701           5 :   checked->SetAccessCheckCallback(SimpleAccessChecker);
    4702             : 
    4703             :   context->Global()
    4704             :       ->Set(context.local(), v8_str("intercepted_0"),
    4705          25 :             intercepted_0->NewInstance(context.local()).ToLocalChecked())
    4706          10 :       .FromJust();
    4707             :   context->Global()
    4708             :       ->Set(context.local(), v8_str("intercepted_1"),
    4709          25 :             intercepted_1->NewInstance(context.local()).ToLocalChecked())
    4710          10 :       .FromJust();
    4711             :   auto checked_instance =
    4712           5 :       checked->NewInstance(context.local()).ToLocalChecked();
    4713          15 :   checked_instance->Set(context.local(), v8_str("whatever"), v8_num(17))
    4714          10 :       .FromJust();
    4715             :   context->Global()
    4716          20 :       ->Set(context.local(), v8_str("checked"), checked_instance)
    4717          10 :       .FromJust();
    4718             :   CompileRun(
    4719             :       "checked.__proto__ = intercepted_1;"
    4720             :       "intercepted_1.__proto__ = intercepted_0;");
    4721             : 
    4722           5 :   CHECK_EQ(3, access_check_data.count);
    4723             : 
    4724           5 :   ExpectInt32("checked.whatever", 17);
    4725           5 :   CHECK(!CompileRun("Object.getOwnPropertyDescriptor(checked, 'whatever')")
    4726             :              ->IsUndefined());
    4727           5 :   CHECK_EQ(6, access_check_data.count);
    4728             : 
    4729           5 :   access_check_data.result = false;
    4730           5 :   ExpectInt32("checked.whatever", intercept_data_0.value);
    4731             :   {
    4732           5 :     v8::TryCatch try_catch(isolate);
    4733             :     CompileRun("Object.getOwnPropertyDescriptor(checked, 'whatever')");
    4734           5 :     CHECK(try_catch.HasCaught());
    4735             :   }
    4736           5 :   CHECK_EQ(9, access_check_data.count);
    4737             : 
    4738           5 :   intercept_data_1.should_intercept = true;
    4739           5 :   ExpectInt32("checked.whatever", intercept_data_1.value);
    4740             :   {
    4741           5 :     v8::TryCatch try_catch(isolate);
    4742             :     CompileRun("Object.getOwnPropertyDescriptor(checked, 'whatever')");
    4743           5 :     CHECK(try_catch.HasCaught());
    4744             :   }
    4745           5 :   CHECK_EQ(12, access_check_data.count);
    4746          10 :   g_access_check_data = nullptr;
    4747           5 : }
    4748             : 
    4749             : 
    4750       23723 : TEST(IndexedAllCanReadInterceptor) {
    4751           5 :   auto isolate = CcTest::isolate();
    4752           5 :   v8::HandleScope handle_scope(isolate);
    4753          10 :   LocalContext context;
    4754             : 
    4755             :   AccessCheckData access_check_data;
    4756           5 :   access_check_data.result = true;
    4757           5 :   access_check_data.count = 0;
    4758             : 
    4759           5 :   g_access_check_data = &access_check_data;
    4760             : 
    4761             :   ShouldInterceptData intercept_data_0;
    4762           5 :   intercept_data_0.value = 239;
    4763           5 :   intercept_data_0.should_intercept = true;
    4764             : 
    4765             :   ShouldInterceptData intercept_data_1;
    4766           5 :   intercept_data_1.value = 165;
    4767           5 :   intercept_data_1.should_intercept = false;
    4768             : 
    4769           5 :   auto intercepted_0 = v8::ObjectTemplate::New(isolate);
    4770             :   {
    4771             :     v8::IndexedPropertyHandlerConfiguration conf(ShouldIndexedInterceptor);
    4772           5 :     conf.flags = v8::PropertyHandlerFlags::kAllCanRead;
    4773             :     conf.data =
    4774           5 :         BuildWrappedObject<ShouldInterceptData>(isolate, &intercept_data_0);
    4775           5 :     intercepted_0->SetHandler(conf);
    4776             :   }
    4777             : 
    4778           5 :   auto intercepted_1 = v8::ObjectTemplate::New(isolate);
    4779             :   {
    4780             :     v8::IndexedPropertyHandlerConfiguration conf(ShouldIndexedInterceptor);
    4781           5 :     conf.flags = v8::PropertyHandlerFlags::kAllCanRead;
    4782             :     conf.data =
    4783           5 :         BuildWrappedObject<ShouldInterceptData>(isolate, &intercept_data_1);
    4784           5 :     intercepted_1->SetHandler(conf);
    4785             :   }
    4786             : 
    4787           5 :   auto checked = v8::ObjectTemplate::New(isolate);
    4788           5 :   checked->SetAccessCheckCallback(SimpleAccessChecker);
    4789             : 
    4790             :   context->Global()
    4791             :       ->Set(context.local(), v8_str("intercepted_0"),
    4792          25 :             intercepted_0->NewInstance(context.local()).ToLocalChecked())
    4793          10 :       .FromJust();
    4794             :   context->Global()
    4795             :       ->Set(context.local(), v8_str("intercepted_1"),
    4796          25 :             intercepted_1->NewInstance(context.local()).ToLocalChecked())
    4797          10 :       .FromJust();
    4798             :   auto checked_instance =
    4799           5 :       checked->NewInstance(context.local()).ToLocalChecked();
    4800             :   context->Global()
    4801          20 :       ->Set(context.local(), v8_str("checked"), checked_instance)
    4802          10 :       .FromJust();
    4803          10 :   checked_instance->Set(context.local(), 15, v8_num(17)).FromJust();
    4804             :   CompileRun(
    4805             :       "checked.__proto__ = intercepted_1;"
    4806             :       "intercepted_1.__proto__ = intercepted_0;");
    4807             : 
    4808           5 :   CHECK_EQ(3, access_check_data.count);
    4809             : 
    4810           5 :   access_check_data.result = true;
    4811           5 :   ExpectInt32("checked[15]", 17);
    4812           5 :   CHECK(!CompileRun("Object.getOwnPropertyDescriptor(checked, '15')")
    4813             :              ->IsUndefined());
    4814           5 :   CHECK_EQ(6, access_check_data.count);
    4815             : 
    4816           5 :   access_check_data.result = false;
    4817           5 :   ExpectInt32("checked[15]", intercept_data_0.value);
    4818             :   {
    4819           5 :     v8::TryCatch try_catch(isolate);
    4820             :     CompileRun("Object.getOwnPropertyDescriptor(checked, '15')");
    4821           5 :     CHECK(try_catch.HasCaught());
    4822             :   }
    4823           5 :   CHECK_EQ(9, access_check_data.count);
    4824             : 
    4825           5 :   intercept_data_1.should_intercept = true;
    4826           5 :   ExpectInt32("checked[15]", intercept_data_1.value);
    4827             :   {
    4828           5 :     v8::TryCatch try_catch(isolate);
    4829             :     CompileRun("Object.getOwnPropertyDescriptor(checked, '15')");
    4830           5 :     CHECK(try_catch.HasCaught());
    4831             :   }
    4832           5 :   CHECK_EQ(12, access_check_data.count);
    4833             : 
    4834          10 :   g_access_check_data = nullptr;
    4835           5 : }
    4836             : 
    4837             : 
    4838       23724 : THREADED_TEST(NonMaskingInterceptorOwnProperty) {
    4839           6 :   auto isolate = CcTest::isolate();
    4840           6 :   v8::HandleScope handle_scope(isolate);
    4841          12 :   LocalContext context;
    4842             : 
    4843             :   ShouldInterceptData intercept_data;
    4844           6 :   intercept_data.value = 239;
    4845           6 :   intercept_data.should_intercept = true;
    4846             : 
    4847           6 :   auto interceptor_templ = v8::ObjectTemplate::New(isolate);
    4848             :   v8::NamedPropertyHandlerConfiguration conf(ShouldNamedInterceptor);
    4849           6 :   conf.flags = v8::PropertyHandlerFlags::kNonMasking;
    4850           6 :   conf.data = BuildWrappedObject<ShouldInterceptData>(isolate, &intercept_data);
    4851           6 :   interceptor_templ->SetHandler(conf);
    4852             : 
    4853             :   auto interceptor =
    4854           6 :       interceptor_templ->NewInstance(context.local()).ToLocalChecked();
    4855             :   context->Global()
    4856          24 :       ->Set(context.local(), v8_str("obj"), interceptor)
    4857          12 :       .FromJust();
    4858             : 
    4859           6 :   ExpectInt32("obj.whatever", 239);
    4860             : 
    4861             :   CompileRun("obj.whatever = 4;");
    4862             : 
    4863             :   // obj.whatever exists, thus it is not affected by the non-masking
    4864             :   // interceptor.
    4865           6 :   ExpectInt32("obj.whatever", 4);
    4866             : 
    4867             :   CompileRun("delete obj.whatever;");
    4868          12 :   ExpectInt32("obj.whatever", 239);
    4869           6 : }
    4870             : 
    4871             : 
    4872       23724 : THREADED_TEST(NonMaskingInterceptorPrototypeProperty) {
    4873           6 :   auto isolate = CcTest::isolate();
    4874           6 :   v8::HandleScope handle_scope(isolate);
    4875          12 :   LocalContext context;
    4876             : 
    4877             :   ShouldInterceptData intercept_data;
    4878           6 :   intercept_data.value = 239;
    4879           6 :   intercept_data.should_intercept = true;
    4880             : 
    4881           6 :   auto interceptor_templ = v8::ObjectTemplate::New(isolate);
    4882             :   v8::NamedPropertyHandlerConfiguration conf(ShouldNamedInterceptor);
    4883           6 :   conf.flags = v8::PropertyHandlerFlags::kNonMasking;
    4884           6 :   conf.data = BuildWrappedObject<ShouldInterceptData>(isolate, &intercept_data);
    4885           6 :   interceptor_templ->SetHandler(conf);
    4886             : 
    4887             :   auto interceptor =
    4888           6 :       interceptor_templ->NewInstance(context.local()).ToLocalChecked();
    4889             :   context->Global()
    4890          24 :       ->Set(context.local(), v8_str("obj"), interceptor)
    4891          12 :       .FromJust();
    4892             : 
    4893           6 :   ExpectInt32("obj.whatever", 239);
    4894             : 
    4895             :   CompileRun("obj.__proto__ = {'whatever': 4};");
    4896           6 :   ExpectInt32("obj.whatever", 4);
    4897             : 
    4898             :   CompileRun("delete obj.__proto__.whatever;");
    4899          12 :   ExpectInt32("obj.whatever", 239);
    4900           6 : }
    4901             : 
    4902             : 
    4903       23724 : THREADED_TEST(NonMaskingInterceptorPrototypePropertyIC) {
    4904           6 :   auto isolate = CcTest::isolate();
    4905           6 :   v8::HandleScope handle_scope(isolate);
    4906          12 :   LocalContext context;
    4907             : 
    4908             :   ShouldInterceptData intercept_data;
    4909           6 :   intercept_data.value = 239;
    4910           6 :   intercept_data.should_intercept = true;
    4911             : 
    4912           6 :   auto interceptor_templ = v8::ObjectTemplate::New(isolate);
    4913             :   v8::NamedPropertyHandlerConfiguration conf(ShouldNamedInterceptor);
    4914           6 :   conf.flags = v8::PropertyHandlerFlags::kNonMasking;
    4915           6 :   conf.data = BuildWrappedObject<ShouldInterceptData>(isolate, &intercept_data);
    4916           6 :   interceptor_templ->SetHandler(conf);
    4917             : 
    4918             :   auto interceptor =
    4919           6 :       interceptor_templ->NewInstance(context.local()).ToLocalChecked();
    4920             :   context->Global()
    4921          24 :       ->Set(context.local(), v8_str("obj"), interceptor)
    4922          12 :       .FromJust();
    4923             : 
    4924             :   CompileRun(
    4925             :       "outer = {};"
    4926             :       "outer.__proto__ = obj;"
    4927             :       "function f(obj) {"
    4928             :       "  var x;"
    4929             :       "  for (var i = 0; i < 4; i++) {"
    4930             :       "    x = obj.whatever;"
    4931             :       "  }"
    4932             :       "  return x;"
    4933             :       "}");
    4934             : 
    4935             :   // Receiver == holder.
    4936             :   CompileRun("obj.__proto__ = null;");
    4937           6 :   ExpectInt32("f(obj)", 239);
    4938           6 :   ExpectInt32("f(outer)", 239);
    4939             : 
    4940             :   // Receiver != holder.
    4941             :   CompileRun("Object.setPrototypeOf(obj, {});");
    4942           6 :   ExpectInt32("f(obj)", 239);
    4943           6 :   ExpectInt32("f(outer)", 239);
    4944             : 
    4945             :   // Masked value on prototype.
    4946             :   CompileRun("obj.__proto__.whatever = 4;");
    4947             :   CompileRun("obj.__proto__.__proto__ = { 'whatever' : 5 };");
    4948           6 :   ExpectInt32("f(obj)", 4);
    4949           6 :   ExpectInt32("f(outer)", 4);
    4950             : 
    4951             :   // Masked value on prototype prototype.
    4952             :   CompileRun("delete obj.__proto__.whatever;");
    4953           6 :   ExpectInt32("f(obj)", 5);
    4954           6 :   ExpectInt32("f(outer)", 5);
    4955             : 
    4956             :   // Reset.
    4957             :   CompileRun("delete obj.__proto__.__proto__.whatever;");
    4958           6 :   ExpectInt32("f(obj)", 239);
    4959           6 :   ExpectInt32("f(outer)", 239);
    4960             : 
    4961             :   // Masked value on self.
    4962             :   CompileRun("obj.whatever = 4;");
    4963           6 :   ExpectInt32("f(obj)", 4);
    4964           6 :   ExpectInt32("f(outer)", 4);
    4965             : 
    4966             :   // Reset.
    4967             :   CompileRun("delete obj.whatever;");
    4968           6 :   ExpectInt32("f(obj)", 239);
    4969           6 :   ExpectInt32("f(outer)", 239);
    4970             : 
    4971             :   CompileRun("outer.whatever = 4;");
    4972           6 :   ExpectInt32("f(obj)", 239);
    4973          12 :   ExpectInt32("f(outer)", 4);
    4974           6 : }
    4975             : 
    4976             : namespace {
    4977             : 
    4978         120 : void ConcatNamedPropertyGetter(
    4979             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    4980             :   info.GetReturnValue().Set(
    4981             :       // Return the property name concatenated with itself.
    4982         120 :       String::Concat(name.As<String>(), name.As<String>()));
    4983         120 : }
    4984             : 
    4985         288 : void ConcatIndexedPropertyGetter(
    4986             :     uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) {
    4987             :   info.GetReturnValue().Set(
    4988             :       // Return the double value of the index.
    4989         288 :       v8_num(index + index));
    4990         288 : }
    4991             : 
    4992          96 : void EnumCallbackWithNames(const v8::PropertyCallbackInfo<v8::Array>& info) {
    4993          96 :   ApiTestFuzzer::Fuzz();
    4994          96 :   v8::Local<v8::Array> result = v8::Array::New(info.GetIsolate(), 4);
    4995          96 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    4996         384 :   CHECK(
    4997             :       result
    4998             :           ->Set(context, v8::Integer::New(info.GetIsolate(), 0), v8_str("foo"))
    4999             :           .FromJust());
    5000         384 :   CHECK(
    5001             :       result
    5002             :           ->Set(context, v8::Integer::New(info.GetIsolate(), 1), v8_str("bar"))
    5003             :           .FromJust());
    5004         384 :   CHECK(
    5005             :       result
    5006             :           ->Set(context, v8::Integer::New(info.GetIsolate(), 2), v8_str("baz"))
    5007             :           .FromJust());
    5008         384 :   CHECK(
    5009             :       result->Set(context, v8::Integer::New(info.GetIsolate(), 3), v8_str("10"))
    5010             :           .FromJust());
    5011             : 
    5012             :   //  Create a holey array.
    5013         288 :   CHECK(result->Delete(context, v8::Integer::New(info.GetIsolate(), 1))
    5014             :             .FromJust());
    5015             :   info.GetReturnValue().Set(result);
    5016          96 : }
    5017             : 
    5018          66 : void EnumCallbackWithIndices(const v8::PropertyCallbackInfo<v8::Array>& info) {
    5019          66 :   ApiTestFuzzer::Fuzz();
    5020          66 :   v8::Local<v8::Array> result = v8::Array::New(info.GetIsolate(), 4);
    5021          66 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    5022             : 
    5023         264 :   CHECK(result->Set(context, v8::Integer::New(info.GetIsolate(), 0), v8_num(10))
    5024             :             .FromJust());
    5025         264 :   CHECK(result->Set(context, v8::Integer::New(info.GetIsolate(), 1), v8_num(11))
    5026             :             .FromJust());
    5027         264 :   CHECK(result->Set(context, v8::Integer::New(info.GetIsolate(), 2), v8_num(12))
    5028             :             .FromJust());
    5029         264 :   CHECK(result->Set(context, v8::Integer::New(info.GetIsolate(), 3), v8_num(14))
    5030             :             .FromJust());
    5031             : 
    5032             :   //  Create a holey array.
    5033         198 :   CHECK(result->Delete(context, v8::Integer::New(info.GetIsolate(), 1))
    5034             :             .FromJust());
    5035             :   info.GetReturnValue().Set(result);
    5036          66 : }
    5037             : 
    5038         138 : void RestrictiveNamedQuery(Local<Name> property,
    5039             :                            const v8::PropertyCallbackInfo<v8::Integer>& info) {
    5040             :   // Only "foo" is enumerable.
    5041         138 :   if (v8_str("foo")
    5042         276 :           ->Equals(info.GetIsolate()->GetCurrentContext(), property)
    5043         276 :           .FromJust()) {
    5044             :     info.GetReturnValue().Set(v8::PropertyAttribute::None);
    5045         204 :     return;
    5046             :   }
    5047             :   info.GetReturnValue().Set(v8::PropertyAttribute::DontEnum);
    5048             : }
    5049             : 
    5050         312 : void RestrictiveIndexedQuery(
    5051             :     uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
    5052             :   // Only index 2 and 12 are enumerable.
    5053         312 :   if (index == 2 || index == 12) {
    5054             :     info.GetReturnValue().Set(v8::PropertyAttribute::None);
    5055         408 :     return;
    5056             :   }
    5057             :   info.GetReturnValue().Set(v8::PropertyAttribute::DontEnum);
    5058             : }
    5059             : }  // namespace
    5060             : 
    5061             : // Regression test for V8 bug 6627.
    5062             : // Object.keys() must return enumerable keys only.
    5063       23724 : THREADED_TEST(EnumeratorsAndUnenumerableNamedProperties) {
    5064             :   // The enumerator interceptor returns a list
    5065             :   // of items which are filtered according to the
    5066             :   // properties defined in the query interceptor.
    5067           6 :   v8::Isolate* isolate = CcTest::isolate();
    5068           6 :   v8::HandleScope scope(isolate);
    5069           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    5070             :   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(
    5071             :       ConcatNamedPropertyGetter, nullptr, RestrictiveNamedQuery, nullptr,
    5072           6 :       EnumCallbackWithNames));
    5073          12 :   LocalContext context;
    5074             :   context->Global()
    5075             :       ->Set(context.local(), v8_str("obj"),
    5076          30 :             obj->NewInstance(context.local()).ToLocalChecked())
    5077          12 :       .FromJust();
    5078             : 
    5079           6 :   ExpectInt32("Object.getOwnPropertyNames(obj).length", 3);
    5080           6 :   ExpectString("Object.getOwnPropertyNames(obj)[0]", "foo");
    5081           6 :   ExpectString("Object.getOwnPropertyNames(obj)[1]", "baz");
    5082           6 :   ExpectString("Object.getOwnPropertyNames(obj)[2]", "10");
    5083             : 
    5084             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj, 'foo').enumerable");
    5085             :   ExpectFalse("Object.getOwnPropertyDescriptor(obj, 'baz').enumerable");
    5086             : 
    5087           6 :   ExpectInt32("Object.entries(obj).length", 1);
    5088           6 :   ExpectString("Object.entries(obj)[0][0]", "foo");
    5089           6 :   ExpectString("Object.entries(obj)[0][1]", "foofoo");
    5090             : 
    5091           6 :   ExpectInt32("Object.keys(obj).length", 1);
    5092           6 :   ExpectString("Object.keys(obj)[0]", "foo");
    5093             : 
    5094           6 :   ExpectInt32("Object.values(obj).length", 1);
    5095          12 :   ExpectString("Object.values(obj)[0]", "foofoo");
    5096           6 : }
    5097             : 
    5098             : namespace {
    5099          24 : void QueryInterceptorForFoo(Local<Name> property,
    5100             :                             const v8::PropertyCallbackInfo<v8::Integer>& info) {
    5101             :   // Don't intercept anything except "foo."
    5102          24 :   if (!v8_str("foo")
    5103          48 :            ->Equals(info.GetIsolate()->GetCurrentContext(), property)
    5104          48 :            .FromJust()) {
    5105          24 :     return;
    5106             :   }
    5107             :   // "foo" is enumerable.
    5108             :   info.GetReturnValue().Set(v8::PropertyAttribute::None);
    5109             : }
    5110             : }  // namespace
    5111             : 
    5112             : // Test that calls to the query interceptor are independent of each
    5113             : // other.
    5114       23724 : THREADED_TEST(EnumeratorsAndUnenumerableNamedPropertiesWithoutSet) {
    5115             :   // The enumerator interceptor returns a list
    5116             :   // of items which are filtered according to the
    5117             :   // properties defined in the query interceptor.
    5118           6 :   v8::Isolate* isolate = CcTest::isolate();
    5119           6 :   v8::HandleScope scope(isolate);
    5120           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    5121             :   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(
    5122             :       ConcatNamedPropertyGetter, nullptr, QueryInterceptorForFoo, nullptr,
    5123           6 :       EnumCallbackWithNames));
    5124          12 :   LocalContext context;
    5125             :   context->Global()
    5126             :       ->Set(context.local(), v8_str("obj"),
    5127          30 :             obj->NewInstance(context.local()).ToLocalChecked())
    5128          12 :       .FromJust();
    5129             : 
    5130           6 :   ExpectInt32("Object.getOwnPropertyNames(obj).length", 3);
    5131           6 :   ExpectString("Object.getOwnPropertyNames(obj)[0]", "foo");
    5132           6 :   ExpectString("Object.getOwnPropertyNames(obj)[1]", "baz");
    5133           6 :   ExpectString("Object.getOwnPropertyNames(obj)[2]", "10");
    5134             : 
    5135             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj, 'foo').enumerable");
    5136          12 :   ExpectInt32("Object.keys(obj).length", 1);
    5137           6 : }
    5138             : 
    5139       23724 : THREADED_TEST(EnumeratorsAndUnenumerableIndexedPropertiesArgumentsElements) {
    5140           6 :   v8::Isolate* isolate = CcTest::isolate();
    5141           6 :   v8::HandleScope scope(isolate);
    5142           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    5143             :   obj->SetHandler(v8::IndexedPropertyHandlerConfiguration(
    5144             :       ConcatIndexedPropertyGetter, nullptr, RestrictiveIndexedQuery, nullptr,
    5145           6 :       SloppyArgsIndexedPropertyEnumerator));
    5146          12 :   LocalContext context;
    5147             :   context->Global()
    5148             :       ->Set(context.local(), v8_str("obj"),
    5149          30 :             obj->NewInstance(context.local()).ToLocalChecked())
    5150          12 :       .FromJust();
    5151             : 
    5152           6 :   ExpectInt32("Object.getOwnPropertyNames(obj).length", 4);
    5153           6 :   ExpectString("Object.getOwnPropertyNames(obj)[0]", "0");
    5154           6 :   ExpectString("Object.getOwnPropertyNames(obj)[1]", "1");
    5155           6 :   ExpectString("Object.getOwnPropertyNames(obj)[2]", "2");
    5156           6 :   ExpectString("Object.getOwnPropertyNames(obj)[3]", "3");
    5157             : 
    5158             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj, '2').enumerable");
    5159             : 
    5160           6 :   ExpectInt32("Object.entries(obj).length", 1);
    5161           6 :   ExpectString("Object.entries(obj)[0][0]", "2");
    5162           6 :   ExpectInt32("Object.entries(obj)[0][1]", 4);
    5163             : 
    5164           6 :   ExpectInt32("Object.keys(obj).length", 1);
    5165           6 :   ExpectString("Object.keys(obj)[0]", "2");
    5166             : 
    5167           6 :   ExpectInt32("Object.values(obj).length", 1);
    5168          12 :   ExpectInt32("Object.values(obj)[0]", 4);
    5169           6 : }
    5170             : 
    5171       23724 : THREADED_TEST(EnumeratorsAndUnenumerableIndexedProperties) {
    5172             :   // The enumerator interceptor returns a list
    5173             :   // of items which are filtered according to the
    5174             :   // properties defined in the query interceptor.
    5175           6 :   v8::Isolate* isolate = CcTest::isolate();
    5176           6 :   v8::HandleScope scope(isolate);
    5177           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    5178             :   obj->SetHandler(v8::IndexedPropertyHandlerConfiguration(
    5179             :       ConcatIndexedPropertyGetter, nullptr, RestrictiveIndexedQuery, nullptr,
    5180           6 :       EnumCallbackWithIndices));
    5181          12 :   LocalContext context;
    5182             :   context->Global()
    5183             :       ->Set(context.local(), v8_str("obj"),
    5184          30 :             obj->NewInstance(context.local()).ToLocalChecked())
    5185          12 :       .FromJust();
    5186             : 
    5187           6 :   ExpectInt32("Object.getOwnPropertyNames(obj).length", 3);
    5188           6 :   ExpectString("Object.getOwnPropertyNames(obj)[0]", "10");
    5189           6 :   ExpectString("Object.getOwnPropertyNames(obj)[1]", "12");
    5190           6 :   ExpectString("Object.getOwnPropertyNames(obj)[2]", "14");
    5191             : 
    5192             :   ExpectFalse("Object.getOwnPropertyDescriptor(obj, '10').enumerable");
    5193             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj, '12').enumerable");
    5194             : 
    5195           6 :   ExpectInt32("Object.entries(obj).length", 1);
    5196           6 :   ExpectString("Object.entries(obj)[0][0]", "12");
    5197           6 :   ExpectInt32("Object.entries(obj)[0][1]", 24);
    5198             : 
    5199           6 :   ExpectInt32("Object.keys(obj).length", 1);
    5200           6 :   ExpectString("Object.keys(obj)[0]", "12");
    5201             : 
    5202           6 :   ExpectInt32("Object.values(obj).length", 1);
    5203          12 :   ExpectInt32("Object.values(obj)[0]", 24);
    5204           6 : }
    5205             : 
    5206       23724 : THREADED_TEST(EnumeratorsAndForIn) {
    5207           6 :   v8::Isolate* isolate = CcTest::isolate();
    5208           6 :   v8::HandleScope scope(isolate);
    5209           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    5210             :   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(
    5211             :       ConcatNamedPropertyGetter, nullptr, RestrictiveNamedQuery, nullptr,
    5212           6 :       NamedEnum));
    5213          12 :   LocalContext context;
    5214             :   context->Global()
    5215             :       ->Set(context.local(), v8_str("obj"),
    5216          30 :             obj->NewInstance(context.local()).ToLocalChecked())
    5217          12 :       .FromJust();
    5218             : 
    5219           6 :   ExpectInt32("Object.getOwnPropertyNames(obj).length", 3);
    5220           6 :   ExpectString("Object.getOwnPropertyNames(obj)[0]", "foo");
    5221             : 
    5222             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj, 'foo').enumerable");
    5223             : 
    5224             :   CompileRun(
    5225             :       "let concat = '';"
    5226             :       "for(var prop in obj) {"
    5227             :       "  concat += `key:${prop}:value:${obj[prop]}`;"
    5228             :       "}");
    5229             : 
    5230             :   // Check that for...in only iterates over enumerable properties.
    5231          12 :   ExpectString("concat", "key:foo:value:foofoo");
    5232           6 : }
    5233             : 
    5234             : namespace {
    5235             : 
    5236          24 : void DatabaseGetter(Local<Name> name,
    5237             :                     const v8::PropertyCallbackInfo<Value>& info) {
    5238          24 :   ApiTestFuzzer::Fuzz();
    5239          24 :   auto context = info.GetIsolate()->GetCurrentContext();
    5240             :   Local<v8::Object> db = info.Holder()
    5241          48 :                              ->GetRealNamedProperty(context, v8_str("db"))
    5242          24 :                              .ToLocalChecked()
    5243             :                              .As<v8::Object>();
    5244          48 :   if (!db->Has(context, name).FromJust()) return;
    5245          48 :   info.GetReturnValue().Set(db->Get(context, name).ToLocalChecked());
    5246             : }
    5247             : 
    5248             : 
    5249          24 : void DatabaseSetter(Local<Name> name, Local<Value> value,
    5250             :                     const v8::PropertyCallbackInfo<Value>& info) {
    5251          24 :   ApiTestFuzzer::Fuzz();
    5252          24 :   auto context = info.GetIsolate()->GetCurrentContext();
    5253          84 :   if (name->Equals(context, v8_str("db")).FromJust()) return;
    5254             :   Local<v8::Object> db = info.Holder()
    5255          24 :                              ->GetRealNamedProperty(context, v8_str("db"))
    5256          12 :                              .ToLocalChecked()
    5257             :                              .As<v8::Object>();
    5258          24 :   db->Set(context, name, value).FromJust();
    5259             :   info.GetReturnValue().Set(value);
    5260             : }
    5261             : 
    5262             : }  // namespace
    5263             : 
    5264             : 
    5265       23724 : THREADED_TEST(NonMaskingInterceptorGlobalEvalRegression) {
    5266           6 :   auto isolate = CcTest::isolate();
    5267           6 :   v8::HandleScope handle_scope(isolate);
    5268          12 :   LocalContext context;
    5269             : 
    5270           6 :   auto interceptor_templ = v8::ObjectTemplate::New(isolate);
    5271             :   v8::NamedPropertyHandlerConfiguration conf(DatabaseGetter, DatabaseSetter);
    5272           6 :   conf.flags = v8::PropertyHandlerFlags::kNonMasking;
    5273           6 :   interceptor_templ->SetHandler(conf);
    5274             : 
    5275             :   context->Global()
    5276             :       ->Set(context.local(), v8_str("intercepted_1"),
    5277          30 :             interceptor_templ->NewInstance(context.local()).ToLocalChecked())
    5278          12 :       .FromJust();
    5279             :   context->Global()
    5280             :       ->Set(context.local(), v8_str("intercepted_2"),
    5281          30 :             interceptor_templ->NewInstance(context.local()).ToLocalChecked())
    5282          12 :       .FromJust();
    5283             : 
    5284             :   // Init dbs.
    5285             :   CompileRun(
    5286             :       "intercepted_1.db = {};"
    5287             :       "intercepted_2.db = {};");
    5288             : 
    5289             :   ExpectInt32(
    5290             :       "var obj = intercepted_1;"
    5291             :       "obj.x = 4;"
    5292             :       "eval('obj.x');"
    5293             :       "eval('obj.x');"
    5294             :       "eval('obj.x');"
    5295             :       "obj = intercepted_2;"
    5296             :       "obj.x = 9;"
    5297             :       "eval('obj.x');",
    5298          12 :       9);
    5299           6 : }
    5300             : 
    5301          15 : static void CheckReceiver(Local<Name> name,
    5302             :                           const v8::PropertyCallbackInfo<v8::Value>& info) {
    5303          15 :   CHECK(info.This()->IsObject());
    5304          15 : }
    5305             : 
    5306       23723 : TEST(Regress609134Interceptor) {
    5307           5 :   LocalContext env;
    5308           5 :   v8::Isolate* isolate = env->GetIsolate();
    5309          10 :   v8::HandleScope scope(isolate);
    5310           5 :   auto fun_templ = v8::FunctionTemplate::New(isolate);
    5311             :   fun_templ->InstanceTemplate()->SetHandler(
    5312          10 :       v8::NamedPropertyHandlerConfiguration(CheckReceiver));
    5313             : 
    5314          30 :   CHECK(env->Global()
    5315             :             ->Set(env.local(), v8_str("Fun"),
    5316             :                   fun_templ->GetFunction(env.local()).ToLocalChecked())
    5317             :             .FromJust());
    5318             : 
    5319             :   CompileRun(
    5320             :       "var f = new Fun();"
    5321             :       "Number.prototype.__proto__ = f;"
    5322             :       "var a = 42;"
    5323           5 :       "for (var i = 0; i<3; i++) { a.foo; }");
    5324       71159 : }

Generated by: LCOV version 1.10