Home | History | Annotate | Download | only in cctest
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #include <climits>
     29 #include <csignal>
     30 #include <map>
     31 #include <string>
     32 
     33 #include "test/cctest/test-api.h"
     34 
     35 #if V8_OS_POSIX
     36 #include <unistd.h>  // NOLINT
     37 #endif
     38 
     39 #include "include/v8-util.h"
     40 #include "src/api.h"
     41 #include "src/arguments.h"
     42 #include "src/base/platform/platform.h"
     43 #include "src/base/smart-pointers.h"
     44 #include "src/compilation-cache.h"
     45 #include "src/debug/debug.h"
     46 #include "src/execution.h"
     47 #include "src/futex-emulation.h"
     48 #include "src/objects.h"
     49 #include "src/parsing/parser.h"
     50 #include "src/profiler/cpu-profiler.h"
     51 #include "src/unicode-inl.h"
     52 #include "src/utils.h"
     53 #include "src/vm-state.h"
     54 #include "test/cctest/heap/heap-tester.h"
     55 #include "test/cctest/heap/heap-utils.h"
     56 
     57 static const bool kLogThreading = false;
     58 
     59 using ::v8::Boolean;
     60 using ::v8::BooleanObject;
     61 using ::v8::Context;
     62 using ::v8::Extension;
     63 using ::v8::Function;
     64 using ::v8::FunctionTemplate;
     65 using ::v8::HandleScope;
     66 using ::v8::Local;
     67 using ::v8::Maybe;
     68 using ::v8::Message;
     69 using ::v8::MessageCallback;
     70 using ::v8::Name;
     71 using ::v8::None;
     72 using ::v8::Object;
     73 using ::v8::ObjectTemplate;
     74 using ::v8::Persistent;
     75 using ::v8::PropertyAttribute;
     76 using ::v8::Script;
     77 using ::v8::StackTrace;
     78 using ::v8::String;
     79 using ::v8::Symbol;
     80 using ::v8::TryCatch;
     81 using ::v8::Undefined;
     82 using ::v8::UniqueId;
     83 using ::v8::V8;
     84 using ::v8::Value;
     85 
     86 
     87 #define THREADED_PROFILED_TEST(Name)                                 \
     88   static void Test##Name();                                          \
     89   TEST(Name##WithProfiler) {                                         \
     90     RunWithProfiler(&Test##Name);                                    \
     91   }                                                                  \
     92   THREADED_TEST(Name)
     93 
     94 
     95 void RunWithProfiler(void (*test)()) {
     96   LocalContext env;
     97   v8::HandleScope scope(env->GetIsolate());
     98   v8::Local<v8::String> profile_name = v8_str("my_profile1");
     99   v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
    100 
    101   cpu_profiler->StartProfiling(profile_name);
    102   (*test)();
    103   reinterpret_cast<i::CpuProfiler*>(cpu_profiler)->DeleteAllProfiles();
    104 }
    105 
    106 
    107 static int signature_callback_count;
    108 static Local<Value> signature_expected_receiver;
    109 static void IncrementingSignatureCallback(
    110     const v8::FunctionCallbackInfo<v8::Value>& args) {
    111   ApiTestFuzzer::Fuzz();
    112   signature_callback_count++;
    113   CHECK(signature_expected_receiver->Equals(
    114                                        args.GetIsolate()->GetCurrentContext(),
    115                                        args.Holder())
    116             .FromJust());
    117   CHECK(signature_expected_receiver->Equals(
    118                                        args.GetIsolate()->GetCurrentContext(),
    119                                        args.This())
    120             .FromJust());
    121   v8::Local<v8::Array> result =
    122       v8::Array::New(args.GetIsolate(), args.Length());
    123   for (int i = 0; i < args.Length(); i++) {
    124     CHECK(result->Set(args.GetIsolate()->GetCurrentContext(),
    125                       v8::Integer::New(args.GetIsolate(), i), args[i])
    126               .FromJust());
    127   }
    128   args.GetReturnValue().Set(result);
    129 }
    130 
    131 
    132 static void Returns42(const v8::FunctionCallbackInfo<v8::Value>& info) {
    133   info.GetReturnValue().Set(42);
    134 }
    135 
    136 
    137 // Tests that call v8::V8::Dispose() cannot be threaded.
    138 UNINITIALIZED_TEST(InitializeAndDisposeOnce) {
    139   CHECK(v8::V8::Initialize());
    140   CHECK(v8::V8::Dispose());
    141 }
    142 
    143 
    144 // Tests that call v8::V8::Dispose() cannot be threaded.
    145 UNINITIALIZED_TEST(InitializeAndDisposeMultiple) {
    146   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
    147   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
    148   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
    149   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
    150   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
    151 }
    152 
    153 
    154 THREADED_TEST(Handles) {
    155   v8::HandleScope scope(CcTest::isolate());
    156   Local<Context> local_env;
    157   {
    158     LocalContext env;
    159     local_env = env.local();
    160   }
    161 
    162   // Local context should still be live.
    163   CHECK(!local_env.IsEmpty());
    164   local_env->Enter();
    165 
    166   v8::Local<v8::Primitive> undef = v8::Undefined(CcTest::isolate());
    167   CHECK(!undef.IsEmpty());
    168   CHECK(undef->IsUndefined());
    169 
    170   const char* source = "1 + 2 + 3";
    171   Local<Script> script = v8_compile(source);
    172   CHECK_EQ(6, v8_run_int32value(script));
    173 
    174   local_env->Exit();
    175 }
    176 
    177 
    178 THREADED_TEST(IsolateOfContext) {
    179   v8::HandleScope scope(CcTest::isolate());
    180   v8::Local<Context> env = Context::New(CcTest::isolate());
    181 
    182   CHECK(!env->GetIsolate()->InContext());
    183   CHECK(env->GetIsolate() == CcTest::isolate());
    184   env->Enter();
    185   CHECK(env->GetIsolate()->InContext());
    186   CHECK(env->GetIsolate() == CcTest::isolate());
    187   env->Exit();
    188   CHECK(!env->GetIsolate()->InContext());
    189   CHECK(env->GetIsolate() == CcTest::isolate());
    190 }
    191 
    192 
    193 static void TestSignature(const char* loop_js, Local<Value> receiver,
    194                           v8::Isolate* isolate) {
    195   i::ScopedVector<char> source(200);
    196   i::SNPrintF(source,
    197               "for (var i = 0; i < 10; i++) {"
    198               "  %s"
    199               "}",
    200               loop_js);
    201   signature_callback_count = 0;
    202   signature_expected_receiver = receiver;
    203   bool expected_to_throw = receiver.IsEmpty();
    204   v8::TryCatch try_catch(isolate);
    205   CompileRun(source.start());
    206   CHECK_EQ(expected_to_throw, try_catch.HasCaught());
    207   if (!expected_to_throw) {
    208     CHECK_EQ(10, signature_callback_count);
    209   } else {
    210     CHECK(v8_str("TypeError: Illegal invocation")
    211               ->Equals(isolate->GetCurrentContext(),
    212                        try_catch.Exception()
    213                            ->ToString(isolate->GetCurrentContext())
    214                            .ToLocalChecked())
    215               .FromJust());
    216   }
    217 }
    218 
    219 
    220 THREADED_TEST(ReceiverSignature) {
    221   LocalContext env;
    222   v8::Isolate* isolate = env->GetIsolate();
    223   v8::HandleScope scope(isolate);
    224   // Setup templates.
    225   v8::Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
    226   v8::Local<v8::Signature> sig = v8::Signature::New(isolate, fun);
    227   v8::Local<v8::FunctionTemplate> callback_sig = v8::FunctionTemplate::New(
    228       isolate, IncrementingSignatureCallback, Local<Value>(), sig);
    229   v8::Local<v8::FunctionTemplate> callback =
    230       v8::FunctionTemplate::New(isolate, IncrementingSignatureCallback);
    231   v8::Local<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New(isolate);
    232   sub_fun->Inherit(fun);
    233   v8::Local<v8::FunctionTemplate> unrel_fun =
    234       v8::FunctionTemplate::New(isolate);
    235   // Install properties.
    236   v8::Local<v8::ObjectTemplate> fun_proto = fun->PrototypeTemplate();
    237   fun_proto->Set(v8_str("prop_sig"), callback_sig);
    238   fun_proto->Set(v8_str("prop"), callback);
    239   fun_proto->SetAccessorProperty(
    240       v8_str("accessor_sig"), callback_sig, callback_sig);
    241   fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback);
    242   // Instantiate templates.
    243   Local<Value> fun_instance =
    244       fun->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
    245   Local<Value> sub_fun_instance =
    246       sub_fun->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
    247   // Setup global variables.
    248   CHECK(env->Global()
    249             ->Set(env.local(), v8_str("Fun"),
    250                   fun->GetFunction(env.local()).ToLocalChecked())
    251             .FromJust());
    252   CHECK(env->Global()
    253             ->Set(env.local(), v8_str("UnrelFun"),
    254                   unrel_fun->GetFunction(env.local()).ToLocalChecked())
    255             .FromJust());
    256   CHECK(env->Global()
    257             ->Set(env.local(), v8_str("fun_instance"), fun_instance)
    258             .FromJust());
    259   CHECK(env->Global()
    260             ->Set(env.local(), v8_str("sub_fun_instance"), sub_fun_instance)
    261             .FromJust());
    262   CompileRun(
    263       "var accessor_sig_key = 'accessor_sig';"
    264       "var accessor_key = 'accessor';"
    265       "var prop_sig_key = 'prop_sig';"
    266       "var prop_key = 'prop';"
    267       ""
    268       "function copy_props(obj) {"
    269       "  var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];"
    270       "  var source = Fun.prototype;"
    271       "  for (var i in keys) {"
    272       "    var key = keys[i];"
    273       "    var desc = Object.getOwnPropertyDescriptor(source, key);"
    274       "    Object.defineProperty(obj, key, desc);"
    275       "  }"
    276       "}"
    277       ""
    278       "var obj = {};"
    279       "copy_props(obj);"
    280       "var unrel = new UnrelFun();"
    281       "copy_props(unrel);");
    282   // Test with and without ICs
    283   const char* test_objects[] = {
    284       "fun_instance", "sub_fun_instance", "obj", "unrel" };
    285   unsigned bad_signature_start_offset = 2;
    286   for (unsigned i = 0; i < arraysize(test_objects); i++) {
    287     i::ScopedVector<char> source(200);
    288     i::SNPrintF(
    289         source, "var test_object = %s; test_object", test_objects[i]);
    290     Local<Value> test_object = CompileRun(source.start());
    291     TestSignature("test_object.prop();", test_object, isolate);
    292     TestSignature("test_object.accessor;", test_object, isolate);
    293     TestSignature("test_object[accessor_key];", test_object, isolate);
    294     TestSignature("test_object.accessor = 1;", test_object, isolate);
    295     TestSignature("test_object[accessor_key] = 1;", test_object, isolate);
    296     if (i >= bad_signature_start_offset) test_object = Local<Value>();
    297     TestSignature("test_object.prop_sig();", test_object, isolate);
    298     TestSignature("test_object.accessor_sig;", test_object, isolate);
    299     TestSignature("test_object[accessor_sig_key];", test_object, isolate);
    300     TestSignature("test_object.accessor_sig = 1;", test_object, isolate);
    301     TestSignature("test_object[accessor_sig_key] = 1;", test_object, isolate);
    302   }
    303 }
    304 
    305 
    306 THREADED_TEST(HulIgennem) {
    307   LocalContext env;
    308   v8::Isolate* isolate = env->GetIsolate();
    309   v8::HandleScope scope(isolate);
    310   v8::Local<v8::Primitive> undef = v8::Undefined(isolate);
    311   Local<String> undef_str = undef->ToString(env.local()).ToLocalChecked();
    312   char* value = i::NewArray<char>(undef_str->Utf8Length() + 1);
    313   undef_str->WriteUtf8(value);
    314   CHECK_EQ(0, strcmp(value, "undefined"));
    315   i::DeleteArray(value);
    316 }
    317 
    318 
    319 THREADED_TEST(Access) {
    320   LocalContext env;
    321   v8::Isolate* isolate = env->GetIsolate();
    322   v8::HandleScope scope(isolate);
    323   Local<v8::Object> obj = v8::Object::New(isolate);
    324   Local<Value> foo_before =
    325       obj->Get(env.local(), v8_str("foo")).ToLocalChecked();
    326   CHECK(foo_before->IsUndefined());
    327   Local<String> bar_str = v8_str("bar");
    328   CHECK(obj->Set(env.local(), v8_str("foo"), bar_str).FromJust());
    329   Local<Value> foo_after =
    330       obj->Get(env.local(), v8_str("foo")).ToLocalChecked();
    331   CHECK(!foo_after->IsUndefined());
    332   CHECK(foo_after->IsString());
    333   CHECK(bar_str->Equals(env.local(), foo_after).FromJust());
    334 }
    335 
    336 
    337 THREADED_TEST(AccessElement) {
    338   LocalContext env;
    339   v8::HandleScope scope(env->GetIsolate());
    340   Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
    341   Local<Value> before = obj->Get(env.local(), 1).ToLocalChecked();
    342   CHECK(before->IsUndefined());
    343   Local<String> bar_str = v8_str("bar");
    344   CHECK(obj->Set(env.local(), 1, bar_str).FromJust());
    345   Local<Value> after = obj->Get(env.local(), 1).ToLocalChecked();
    346   CHECK(!after->IsUndefined());
    347   CHECK(after->IsString());
    348   CHECK(bar_str->Equals(env.local(), after).FromJust());
    349 
    350   Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
    351   CHECK(v8_str("a")
    352             ->Equals(env.local(), value->Get(env.local(), 0).ToLocalChecked())
    353             .FromJust());
    354   CHECK(v8_str("b")
    355             ->Equals(env.local(), value->Get(env.local(), 1).ToLocalChecked())
    356             .FromJust());
    357 }
    358 
    359 
    360 THREADED_TEST(Script) {
    361   LocalContext env;
    362   v8::HandleScope scope(env->GetIsolate());
    363   const char* source = "1 + 2 + 3";
    364   Local<Script> script = v8_compile(source);
    365   CHECK_EQ(6, v8_run_int32value(script));
    366 }
    367 
    368 
    369 class TestResource: public String::ExternalStringResource {
    370  public:
    371   explicit TestResource(uint16_t* data, int* counter = NULL,
    372                         bool owning_data = true)
    373       : data_(data), length_(0), counter_(counter), owning_data_(owning_data) {
    374     while (data[length_]) ++length_;
    375   }
    376 
    377   ~TestResource() {
    378     if (owning_data_) i::DeleteArray(data_);
    379     if (counter_ != NULL) ++*counter_;
    380   }
    381 
    382   const uint16_t* data() const {
    383     return data_;
    384   }
    385 
    386   size_t length() const {
    387     return length_;
    388   }
    389 
    390  private:
    391   uint16_t* data_;
    392   size_t length_;
    393   int* counter_;
    394   bool owning_data_;
    395 };
    396 
    397 
    398 class TestOneByteResource : public String::ExternalOneByteStringResource {
    399  public:
    400   explicit TestOneByteResource(const char* data, int* counter = NULL,
    401                                size_t offset = 0)
    402       : orig_data_(data),
    403         data_(data + offset),
    404         length_(strlen(data) - offset),
    405         counter_(counter) {}
    406 
    407   ~TestOneByteResource() {
    408     i::DeleteArray(orig_data_);
    409     if (counter_ != NULL) ++*counter_;
    410   }
    411 
    412   const char* data() const {
    413     return data_;
    414   }
    415 
    416   size_t length() const {
    417     return length_;
    418   }
    419 
    420  private:
    421   const char* orig_data_;
    422   const char* data_;
    423   size_t length_;
    424   int* counter_;
    425 };
    426 
    427 
    428 THREADED_TEST(ScriptUsingStringResource) {
    429   int dispose_count = 0;
    430   const char* c_source = "1 + 2 * 3";
    431   uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
    432   {
    433     LocalContext env;
    434     v8::HandleScope scope(env->GetIsolate());
    435     TestResource* resource = new TestResource(two_byte_source, &dispose_count);
    436     Local<String> source =
    437         String::NewExternalTwoByte(env->GetIsolate(), resource)
    438             .ToLocalChecked();
    439     Local<Script> script = v8_compile(source);
    440     Local<Value> value = script->Run(env.local()).ToLocalChecked();
    441     CHECK(value->IsNumber());
    442     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
    443     CHECK(source->IsExternal());
    444     CHECK_EQ(resource,
    445              static_cast<TestResource*>(source->GetExternalStringResource()));
    446     String::Encoding encoding = String::UNKNOWN_ENCODING;
    447     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
    448              source->GetExternalStringResourceBase(&encoding));
    449     CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
    450     CcTest::heap()->CollectAllGarbage();
    451     CHECK_EQ(0, dispose_count);
    452   }
    453   CcTest::i_isolate()->compilation_cache()->Clear();
    454   CcTest::heap()->CollectAllAvailableGarbage();
    455   CHECK_EQ(1, dispose_count);
    456 }
    457 
    458 
    459 THREADED_TEST(ScriptUsingOneByteStringResource) {
    460   int dispose_count = 0;
    461   const char* c_source = "1 + 2 * 3";
    462   {
    463     LocalContext env;
    464     v8::HandleScope scope(env->GetIsolate());
    465     TestOneByteResource* resource =
    466         new TestOneByteResource(i::StrDup(c_source), &dispose_count);
    467     Local<String> source =
    468         String::NewExternalOneByte(env->GetIsolate(), resource)
    469             .ToLocalChecked();
    470     CHECK(source->IsExternalOneByte());
    471     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
    472              source->GetExternalOneByteStringResource());
    473     String::Encoding encoding = String::UNKNOWN_ENCODING;
    474     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
    475              source->GetExternalStringResourceBase(&encoding));
    476     CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
    477     Local<Script> script = v8_compile(source);
    478     Local<Value> value = script->Run(env.local()).ToLocalChecked();
    479     CHECK(value->IsNumber());
    480     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
    481     CcTest::heap()->CollectAllGarbage();
    482     CHECK_EQ(0, dispose_count);
    483   }
    484   CcTest::i_isolate()->compilation_cache()->Clear();
    485   CcTest::heap()->CollectAllAvailableGarbage();
    486   CHECK_EQ(1, dispose_count);
    487 }
    488 
    489 
    490 THREADED_TEST(ScriptMakingExternalString) {
    491   int dispose_count = 0;
    492   uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
    493   {
    494     LocalContext env;
    495     v8::HandleScope scope(env->GetIsolate());
    496     Local<String> source =
    497         String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
    498                                v8::NewStringType::kNormal)
    499             .ToLocalChecked();
    500     // Trigger GCs so that the newly allocated string moves to old gen.
    501     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    502     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    503     CHECK_EQ(source->IsExternal(), false);
    504     CHECK_EQ(source->IsExternalOneByte(), false);
    505     String::Encoding encoding = String::UNKNOWN_ENCODING;
    506     CHECK(!source->GetExternalStringResourceBase(&encoding));
    507     CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
    508     bool success = source->MakeExternal(new TestResource(two_byte_source,
    509                                                          &dispose_count));
    510     CHECK(success);
    511     Local<Script> script = v8_compile(source);
    512     Local<Value> value = script->Run(env.local()).ToLocalChecked();
    513     CHECK(value->IsNumber());
    514     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
    515     CcTest::heap()->CollectAllGarbage();
    516     CHECK_EQ(0, dispose_count);
    517   }
    518   CcTest::i_isolate()->compilation_cache()->Clear();
    519   CcTest::heap()->CollectAllGarbage();
    520   CHECK_EQ(1, dispose_count);
    521 }
    522 
    523 
    524 THREADED_TEST(ScriptMakingExternalOneByteString) {
    525   int dispose_count = 0;
    526   const char* c_source = "1 + 2 * 3";
    527   {
    528     LocalContext env;
    529     v8::HandleScope scope(env->GetIsolate());
    530     Local<String> source = v8_str(c_source);
    531     // Trigger GCs so that the newly allocated string moves to old gen.
    532     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    533     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    534     bool success = source->MakeExternal(
    535         new TestOneByteResource(i::StrDup(c_source), &dispose_count));
    536     CHECK(success);
    537     Local<Script> script = v8_compile(source);
    538     Local<Value> value = script->Run(env.local()).ToLocalChecked();
    539     CHECK(value->IsNumber());
    540     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
    541     CcTest::heap()->CollectAllGarbage();
    542     CHECK_EQ(0, dispose_count);
    543   }
    544   CcTest::i_isolate()->compilation_cache()->Clear();
    545   CcTest::heap()->CollectAllGarbage();
    546   CHECK_EQ(1, dispose_count);
    547 }
    548 
    549 
    550 TEST(MakingExternalStringConditions) {
    551   LocalContext env;
    552   v8::HandleScope scope(env->GetIsolate());
    553 
    554   // Free some space in the new space so that we can check freshness.
    555   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
    556   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
    557 
    558   uint16_t* two_byte_string = AsciiToTwoByteString("s1");
    559   Local<String> local_string =
    560       String::NewFromTwoByte(env->GetIsolate(), two_byte_string,
    561                              v8::NewStringType::kNormal)
    562           .ToLocalChecked();
    563   i::DeleteArray(two_byte_string);
    564 
    565   // We should refuse to externalize new space strings.
    566   CHECK(!local_string->CanMakeExternal());
    567   // Trigger GCs so that the newly allocated string moves to old gen.
    568   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    569   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    570   // Old space strings should be accepted.
    571   CHECK(local_string->CanMakeExternal());
    572 }
    573 
    574 
    575 TEST(MakingExternalOneByteStringConditions) {
    576   LocalContext env;
    577   v8::HandleScope scope(env->GetIsolate());
    578 
    579   // Free some space in the new space so that we can check freshness.
    580   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
    581   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
    582 
    583   Local<String> local_string = v8_str("s1");
    584   // We should refuse to externalize new space strings.
    585   CHECK(!local_string->CanMakeExternal());
    586   // Trigger GCs so that the newly allocated string moves to old gen.
    587   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    588   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    589   // Old space strings should be accepted.
    590   CHECK(local_string->CanMakeExternal());
    591 }
    592 
    593 
    594 TEST(MakingExternalUnalignedOneByteString) {
    595   LocalContext env;
    596   v8::HandleScope scope(env->GetIsolate());
    597 
    598   CompileRun("function cons(a, b) { return a + b; }"
    599              "function slice(a) { return a.substring(1); }");
    600   // Create a cons string that will land in old pointer space.
    601   Local<String> cons = Local<String>::Cast(CompileRun(
    602       "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
    603   // Create a sliced string that will land in old pointer space.
    604   Local<String> slice = Local<String>::Cast(CompileRun(
    605       "slice('abcdefghijklmnopqrstuvwxyz');"));
    606 
    607   // Trigger GCs so that the newly allocated string moves to old gen.
    608   i::heap::SimulateFullSpace(CcTest::heap()->old_space());
    609   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    610   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    611 
    612   // Turn into external string with unaligned resource data.
    613   const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
    614   bool success =
    615       cons->MakeExternal(new TestOneByteResource(i::StrDup(c_cons), NULL, 1));
    616   CHECK(success);
    617   const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
    618   success =
    619       slice->MakeExternal(new TestOneByteResource(i::StrDup(c_slice), NULL, 1));
    620   CHECK(success);
    621 
    622   // Trigger GCs and force evacuation.
    623   CcTest::heap()->CollectAllGarbage();
    624   CcTest::heap()->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask);
    625 }
    626 
    627 
    628 THREADED_TEST(UsingExternalString) {
    629   i::Factory* factory = CcTest::i_isolate()->factory();
    630   {
    631     v8::HandleScope scope(CcTest::isolate());
    632     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
    633     Local<String> string =
    634         String::NewExternalTwoByte(CcTest::isolate(),
    635                                    new TestResource(two_byte_string))
    636             .ToLocalChecked();
    637     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    638     // Trigger GCs so that the newly allocated string moves to old gen.
    639     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    640     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    641     i::Handle<i::String> isymbol =
    642         factory->InternalizeString(istring);
    643     CHECK(isymbol->IsInternalizedString());
    644   }
    645   CcTest::heap()->CollectAllGarbage();
    646   CcTest::heap()->CollectAllGarbage();
    647 }
    648 
    649 
    650 THREADED_TEST(UsingExternalOneByteString) {
    651   i::Factory* factory = CcTest::i_isolate()->factory();
    652   {
    653     v8::HandleScope scope(CcTest::isolate());
    654     const char* one_byte_string = "test string";
    655     Local<String> string =
    656         String::NewExternalOneByte(
    657             CcTest::isolate(),
    658             new TestOneByteResource(i::StrDup(one_byte_string)))
    659             .ToLocalChecked();
    660     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    661     // Trigger GCs so that the newly allocated string moves to old gen.
    662     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    663     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    664     i::Handle<i::String> isymbol =
    665         factory->InternalizeString(istring);
    666     CHECK(isymbol->IsInternalizedString());
    667   }
    668   CcTest::heap()->CollectAllGarbage();
    669   CcTest::heap()->CollectAllGarbage();
    670 }
    671 
    672 
    673 class RandomLengthResource : public v8::String::ExternalStringResource {
    674  public:
    675   explicit RandomLengthResource(int length) : length_(length) {}
    676   virtual const uint16_t* data() const { return string_; }
    677   virtual size_t length() const { return length_; }
    678 
    679  private:
    680   uint16_t string_[10];
    681   int length_;
    682 };
    683 
    684 
    685 class RandomLengthOneByteResource
    686     : public v8::String::ExternalOneByteStringResource {
    687  public:
    688   explicit RandomLengthOneByteResource(int length) : length_(length) {}
    689   virtual const char* data() const { return string_; }
    690   virtual size_t length() const { return length_; }
    691 
    692  private:
    693   char string_[10];
    694   int length_;
    695 };
    696 
    697 
    698 THREADED_TEST(NewExternalForVeryLongString) {
    699   auto isolate = CcTest::isolate();
    700   {
    701     v8::HandleScope scope(isolate);
    702     v8::TryCatch try_catch(isolate);
    703     RandomLengthOneByteResource r(1 << 30);
    704     v8::MaybeLocal<v8::String> maybe_str =
    705         v8::String::NewExternalOneByte(isolate, &r);
    706     CHECK(maybe_str.IsEmpty());
    707     CHECK(!try_catch.HasCaught());
    708   }
    709 
    710   {
    711     v8::HandleScope scope(isolate);
    712     v8::TryCatch try_catch(isolate);
    713     RandomLengthResource r(1 << 30);
    714     v8::MaybeLocal<v8::String> maybe_str =
    715         v8::String::NewExternalTwoByte(isolate, &r);
    716     CHECK(maybe_str.IsEmpty());
    717     CHECK(!try_catch.HasCaught());
    718   }
    719 }
    720 
    721 
    722 THREADED_TEST(ScavengeExternalString) {
    723   i::FLAG_stress_compaction = false;
    724   i::FLAG_gc_global = false;
    725   int dispose_count = 0;
    726   bool in_new_space = false;
    727   {
    728     v8::HandleScope scope(CcTest::isolate());
    729     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
    730     Local<String> string =
    731         String::NewExternalTwoByte(
    732             CcTest::isolate(),
    733             new TestResource(two_byte_string, &dispose_count))
    734             .ToLocalChecked();
    735     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    736     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
    737     in_new_space = CcTest::heap()->InNewSpace(*istring);
    738     CHECK(in_new_space || CcTest::heap()->old_space()->Contains(*istring));
    739     CHECK_EQ(0, dispose_count);
    740   }
    741   CcTest::heap()->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_SPACE);
    742   CHECK_EQ(1, dispose_count);
    743 }
    744 
    745 
    746 THREADED_TEST(ScavengeExternalOneByteString) {
    747   i::FLAG_stress_compaction = false;
    748   i::FLAG_gc_global = false;
    749   int dispose_count = 0;
    750   bool in_new_space = false;
    751   {
    752     v8::HandleScope scope(CcTest::isolate());
    753     const char* one_byte_string = "test string";
    754     Local<String> string =
    755         String::NewExternalOneByte(
    756             CcTest::isolate(),
    757             new TestOneByteResource(i::StrDup(one_byte_string), &dispose_count))
    758             .ToLocalChecked();
    759     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    760     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
    761     in_new_space = CcTest::heap()->InNewSpace(*istring);
    762     CHECK(in_new_space || CcTest::heap()->old_space()->Contains(*istring));
    763     CHECK_EQ(0, dispose_count);
    764   }
    765   CcTest::heap()->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_SPACE);
    766   CHECK_EQ(1, dispose_count);
    767 }
    768 
    769 
    770 class TestOneByteResourceWithDisposeControl : public TestOneByteResource {
    771  public:
    772   // Only used by non-threaded tests, so it can use static fields.
    773   static int dispose_calls;
    774   static int dispose_count;
    775 
    776   TestOneByteResourceWithDisposeControl(const char* data, bool dispose)
    777       : TestOneByteResource(data, &dispose_count), dispose_(dispose) {}
    778 
    779   void Dispose() {
    780     ++dispose_calls;
    781     if (dispose_) delete this;
    782   }
    783  private:
    784   bool dispose_;
    785 };
    786 
    787 
    788 int TestOneByteResourceWithDisposeControl::dispose_count = 0;
    789 int TestOneByteResourceWithDisposeControl::dispose_calls = 0;
    790 
    791 
    792 TEST(ExternalStringWithDisposeHandling) {
    793   const char* c_source = "1 + 2 * 3";
    794 
    795   // Use a stack allocated external string resource allocated object.
    796   TestOneByteResourceWithDisposeControl::dispose_count = 0;
    797   TestOneByteResourceWithDisposeControl::dispose_calls = 0;
    798   TestOneByteResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
    799   {
    800     LocalContext env;
    801     v8::HandleScope scope(env->GetIsolate());
    802     Local<String> source =
    803         String::NewExternalOneByte(env->GetIsolate(), &res_stack)
    804             .ToLocalChecked();
    805     Local<Script> script = v8_compile(source);
    806     Local<Value> value = script->Run(env.local()).ToLocalChecked();
    807     CHECK(value->IsNumber());
    808     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
    809     CcTest::heap()->CollectAllAvailableGarbage();
    810     CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
    811   }
    812   CcTest::i_isolate()->compilation_cache()->Clear();
    813   CcTest::heap()->CollectAllAvailableGarbage();
    814   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
    815   CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
    816 
    817   // Use a heap allocated external string resource allocated object.
    818   TestOneByteResourceWithDisposeControl::dispose_count = 0;
    819   TestOneByteResourceWithDisposeControl::dispose_calls = 0;
    820   TestOneByteResource* res_heap =
    821       new TestOneByteResourceWithDisposeControl(i::StrDup(c_source), true);
    822   {
    823     LocalContext env;
    824     v8::HandleScope scope(env->GetIsolate());
    825     Local<String> source =
    826         String::NewExternalOneByte(env->GetIsolate(), res_heap)
    827             .ToLocalChecked();
    828     Local<Script> script = v8_compile(source);
    829     Local<Value> value = script->Run(env.local()).ToLocalChecked();
    830     CHECK(value->IsNumber());
    831     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
    832     CcTest::heap()->CollectAllAvailableGarbage();
    833     CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
    834   }
    835   CcTest::i_isolate()->compilation_cache()->Clear();
    836   CcTest::heap()->CollectAllAvailableGarbage();
    837   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
    838   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_count);
    839 }
    840 
    841 
    842 THREADED_TEST(StringConcat) {
    843   {
    844     LocalContext env;
    845     v8::HandleScope scope(env->GetIsolate());
    846     const char* one_byte_string_1 = "function a_times_t";
    847     const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
    848     const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
    849     const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
    850     const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
    851     const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
    852     const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
    853     Local<String> left = v8_str(one_byte_string_1);
    854 
    855     uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
    856     Local<String> right =
    857         String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
    858                                v8::NewStringType::kNormal)
    859             .ToLocalChecked();
    860     i::DeleteArray(two_byte_source);
    861 
    862     Local<String> source = String::Concat(left, right);
    863     right = String::NewExternalOneByte(
    864                 env->GetIsolate(),
    865                 new TestOneByteResource(i::StrDup(one_byte_extern_1)))
    866                 .ToLocalChecked();
    867     source = String::Concat(source, right);
    868     right = String::NewExternalTwoByte(
    869                 env->GetIsolate(),
    870                 new TestResource(AsciiToTwoByteString(two_byte_extern_1)))
    871                 .ToLocalChecked();
    872     source = String::Concat(source, right);
    873     right = v8_str(one_byte_string_2);
    874     source = String::Concat(source, right);
    875 
    876     two_byte_source = AsciiToTwoByteString(two_byte_string_2);
    877     right = String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
    878                                    v8::NewStringType::kNormal)
    879                 .ToLocalChecked();
    880     i::DeleteArray(two_byte_source);
    881 
    882     source = String::Concat(source, right);
    883     right = String::NewExternalTwoByte(
    884                 env->GetIsolate(),
    885                 new TestResource(AsciiToTwoByteString(two_byte_extern_2)))
    886                 .ToLocalChecked();
    887     source = String::Concat(source, right);
    888     Local<Script> script = v8_compile(source);
    889     Local<Value> value = script->Run(env.local()).ToLocalChecked();
    890     CHECK(value->IsNumber());
    891     CHECK_EQ(68, value->Int32Value(env.local()).FromJust());
    892   }
    893   CcTest::i_isolate()->compilation_cache()->Clear();
    894   CcTest::heap()->CollectAllGarbage();
    895   CcTest::heap()->CollectAllGarbage();
    896 }
    897 
    898 
    899 THREADED_TEST(GlobalProperties) {
    900   LocalContext env;
    901   v8::HandleScope scope(env->GetIsolate());
    902   v8::Local<v8::Object> global = env->Global();
    903   CHECK(global->Set(env.local(), v8_str("pi"), v8_num(3.1415926)).FromJust());
    904   Local<Value> pi = global->Get(env.local(), v8_str("pi")).ToLocalChecked();
    905   CHECK_EQ(3.1415926, pi->NumberValue(env.local()).FromJust());
    906 }
    907 
    908 
    909 static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
    910                                  i::Address callback) {
    911   ApiTestFuzzer::Fuzz();
    912   CheckReturnValue(info, callback);
    913   info.GetReturnValue().Set(v8_str("bad value"));
    914   info.GetReturnValue().Set(v8_num(102));
    915 }
    916 
    917 
    918 static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
    919   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
    920 }
    921 
    922 
    923 static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
    924   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
    925 }
    926 
    927 static void construct_callback(
    928     const v8::FunctionCallbackInfo<Value>& info) {
    929   ApiTestFuzzer::Fuzz();
    930   CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
    931   CHECK(
    932       info.This()
    933           ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("x"), v8_num(1))
    934           .FromJust());
    935   CHECK(
    936       info.This()
    937           ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(2))
    938           .FromJust());
    939   info.GetReturnValue().Set(v8_str("bad value"));
    940   info.GetReturnValue().Set(info.This());
    941 }
    942 
    943 
    944 static void Return239Callback(
    945     Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
    946   ApiTestFuzzer::Fuzz();
    947   CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
    948   info.GetReturnValue().Set(v8_str("bad value"));
    949   info.GetReturnValue().Set(v8_num(239));
    950 }
    951 
    952 
    953 template<typename Handler>
    954 static void TestFunctionTemplateInitializer(Handler handler,
    955                                             Handler handler_2) {
    956   // Test constructor calls.
    957   {
    958     LocalContext env;
    959     v8::Isolate* isolate = env->GetIsolate();
    960     v8::HandleScope scope(isolate);
    961 
    962     Local<v8::FunctionTemplate> fun_templ =
    963         v8::FunctionTemplate::New(isolate, handler);
    964     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    965     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    966     Local<Script> script = v8_compile("obj()");
    967     for (int i = 0; i < 30; i++) {
    968       CHECK_EQ(102, v8_run_int32value(script));
    969     }
    970   }
    971   // Use SetCallHandler to initialize a function template, should work like
    972   // the previous one.
    973   {
    974     LocalContext env;
    975     v8::Isolate* isolate = env->GetIsolate();
    976     v8::HandleScope scope(isolate);
    977 
    978     Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
    979     fun_templ->SetCallHandler(handler_2);
    980     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    981     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    982     Local<Script> script = v8_compile("obj()");
    983     for (int i = 0; i < 30; i++) {
    984       CHECK_EQ(102, v8_run_int32value(script));
    985     }
    986   }
    987 }
    988 
    989 
    990 template<typename Constructor, typename Accessor>
    991 static void TestFunctionTemplateAccessor(Constructor constructor,
    992                                          Accessor accessor) {
    993   LocalContext env;
    994   v8::HandleScope scope(env->GetIsolate());
    995 
    996   Local<v8::FunctionTemplate> fun_templ =
    997       v8::FunctionTemplate::New(env->GetIsolate(), constructor);
    998   fun_templ->SetClassName(v8_str("funky"));
    999   fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
   1000   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   1001   CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
   1002   Local<Value> result =
   1003       v8_compile("(new obj()).toString()")->Run(env.local()).ToLocalChecked();
   1004   CHECK(v8_str("[object funky]")->Equals(env.local(), result).FromJust());
   1005   CompileRun("var obj_instance = new obj();");
   1006   Local<Script> script;
   1007   script = v8_compile("obj_instance.x");
   1008   for (int i = 0; i < 30; i++) {
   1009     CHECK_EQ(1, v8_run_int32value(script));
   1010   }
   1011   script = v8_compile("obj_instance.m");
   1012   for (int i = 0; i < 30; i++) {
   1013     CHECK_EQ(239, v8_run_int32value(script));
   1014   }
   1015 }
   1016 
   1017 
   1018 THREADED_PROFILED_TEST(FunctionTemplate) {
   1019   TestFunctionTemplateInitializer(handle_callback, handle_callback_2);
   1020   TestFunctionTemplateAccessor(construct_callback, Return239Callback);
   1021 }
   1022 
   1023 
   1024 static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
   1025   ApiTestFuzzer::Fuzz();
   1026   CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
   1027   info.GetReturnValue().Set(v8_num(51423 + info.Length()));
   1028 }
   1029 
   1030 
   1031 template<typename Callback>
   1032 static void TestSimpleCallback(Callback callback) {
   1033   LocalContext env;
   1034   v8::Isolate* isolate = env->GetIsolate();
   1035   v8::HandleScope scope(isolate);
   1036 
   1037   v8::Local<v8::ObjectTemplate> object_template =
   1038       v8::ObjectTemplate::New(isolate);
   1039   object_template->Set(isolate, "callback",
   1040                        v8::FunctionTemplate::New(isolate, callback));
   1041   v8::Local<v8::Object> object =
   1042       object_template->NewInstance(env.local()).ToLocalChecked();
   1043   CHECK((*env)
   1044             ->Global()
   1045             ->Set(env.local(), v8_str("callback_object"), object)
   1046             .FromJust());
   1047   v8::Local<v8::Script> script;
   1048   script = v8_compile("callback_object.callback(17)");
   1049   for (int i = 0; i < 30; i++) {
   1050     CHECK_EQ(51424, v8_run_int32value(script));
   1051   }
   1052   script = v8_compile("callback_object.callback(17, 24)");
   1053   for (int i = 0; i < 30; i++) {
   1054     CHECK_EQ(51425, v8_run_int32value(script));
   1055   }
   1056 }
   1057 
   1058 
   1059 THREADED_PROFILED_TEST(SimpleCallback) {
   1060   TestSimpleCallback(SimpleCallback);
   1061 }
   1062 
   1063 
   1064 template<typename T>
   1065 void FastReturnValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
   1066 
   1067 // constant return values
   1068 static int32_t fast_return_value_int32 = 471;
   1069 static uint32_t fast_return_value_uint32 = 571;
   1070 static const double kFastReturnValueDouble = 2.7;
   1071 // variable return values
   1072 static bool fast_return_value_bool = false;
   1073 enum ReturnValueOddball {
   1074   kNullReturnValue,
   1075   kUndefinedReturnValue,
   1076   kEmptyStringReturnValue
   1077 };
   1078 static ReturnValueOddball fast_return_value_void;
   1079 static bool fast_return_value_object_is_empty = false;
   1080 
   1081 // Helper function to avoid compiler error: insufficient contextual information
   1082 // to determine type when applying FUNCTION_ADDR to a template function.
   1083 static i::Address address_of(v8::FunctionCallback callback) {
   1084   return FUNCTION_ADDR(callback);
   1085 }
   1086 
   1087 template<>
   1088 void FastReturnValueCallback<int32_t>(
   1089     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1090   CheckReturnValue(info, address_of(FastReturnValueCallback<int32_t>));
   1091   info.GetReturnValue().Set(fast_return_value_int32);
   1092 }
   1093 
   1094 template<>
   1095 void FastReturnValueCallback<uint32_t>(
   1096     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1097   CheckReturnValue(info, address_of(FastReturnValueCallback<uint32_t>));
   1098   info.GetReturnValue().Set(fast_return_value_uint32);
   1099 }
   1100 
   1101 template<>
   1102 void FastReturnValueCallback<double>(
   1103     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1104   CheckReturnValue(info, address_of(FastReturnValueCallback<double>));
   1105   info.GetReturnValue().Set(kFastReturnValueDouble);
   1106 }
   1107 
   1108 template<>
   1109 void FastReturnValueCallback<bool>(
   1110     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1111   CheckReturnValue(info, address_of(FastReturnValueCallback<bool>));
   1112   info.GetReturnValue().Set(fast_return_value_bool);
   1113 }
   1114 
   1115 template<>
   1116 void FastReturnValueCallback<void>(
   1117     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1118   CheckReturnValue(info, address_of(FastReturnValueCallback<void>));
   1119   switch (fast_return_value_void) {
   1120     case kNullReturnValue:
   1121       info.GetReturnValue().SetNull();
   1122       break;
   1123     case kUndefinedReturnValue:
   1124       info.GetReturnValue().SetUndefined();
   1125       break;
   1126     case kEmptyStringReturnValue:
   1127       info.GetReturnValue().SetEmptyString();
   1128       break;
   1129   }
   1130 }
   1131 
   1132 template<>
   1133 void FastReturnValueCallback<Object>(
   1134     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1135   v8::Local<v8::Object> object;
   1136   if (!fast_return_value_object_is_empty) {
   1137     object = Object::New(info.GetIsolate());
   1138   }
   1139   info.GetReturnValue().Set(object);
   1140 }
   1141 
   1142 template <typename T>
   1143 Local<Value> TestFastReturnValues() {
   1144   LocalContext env;
   1145   v8::Isolate* isolate = env->GetIsolate();
   1146   v8::EscapableHandleScope scope(isolate);
   1147   v8::Local<v8::ObjectTemplate> object_template =
   1148       v8::ObjectTemplate::New(isolate);
   1149   v8::FunctionCallback callback = &FastReturnValueCallback<T>;
   1150   object_template->Set(isolate, "callback",
   1151                        v8::FunctionTemplate::New(isolate, callback));
   1152   v8::Local<v8::Object> object =
   1153       object_template->NewInstance(env.local()).ToLocalChecked();
   1154   CHECK((*env)
   1155             ->Global()
   1156             ->Set(env.local(), v8_str("callback_object"), object)
   1157             .FromJust());
   1158   return scope.Escape(CompileRun("callback_object.callback()"));
   1159 }
   1160 
   1161 
   1162 THREADED_PROFILED_TEST(FastReturnValues) {
   1163   LocalContext env;
   1164   v8::Isolate* isolate = env->GetIsolate();
   1165   v8::HandleScope scope(isolate);
   1166   v8::Local<v8::Value> value;
   1167   // check int32_t and uint32_t
   1168   int32_t int_values[] = {
   1169       0, 234, -723,
   1170       i::Smi::kMinValue, i::Smi::kMaxValue
   1171   };
   1172   for (size_t i = 0; i < arraysize(int_values); i++) {
   1173     for (int modifier = -1; modifier <= 1; modifier++) {
   1174       int int_value = int_values[i] + modifier;
   1175       // check int32_t
   1176       fast_return_value_int32 = int_value;
   1177       value = TestFastReturnValues<int32_t>();
   1178       CHECK(value->IsInt32());
   1179       CHECK_EQ(fast_return_value_int32,
   1180                value->Int32Value(env.local()).FromJust());
   1181       // check uint32_t
   1182       fast_return_value_uint32 = static_cast<uint32_t>(int_value);
   1183       value = TestFastReturnValues<uint32_t>();
   1184       CHECK(value->IsUint32());
   1185       CHECK_EQ(fast_return_value_uint32,
   1186                value->Uint32Value(env.local()).FromJust());
   1187     }
   1188   }
   1189   // check double
   1190   value = TestFastReturnValues<double>();
   1191   CHECK(value->IsNumber());
   1192   CHECK_EQ(kFastReturnValueDouble,
   1193            value->ToNumber(env.local()).ToLocalChecked()->Value());
   1194   // check bool values
   1195   for (int i = 0; i < 2; i++) {
   1196     fast_return_value_bool = i == 0;
   1197     value = TestFastReturnValues<bool>();
   1198     CHECK(value->IsBoolean());
   1199     CHECK_EQ(fast_return_value_bool,
   1200              value->ToBoolean(env.local()).ToLocalChecked()->Value());
   1201   }
   1202   // check oddballs
   1203   ReturnValueOddball oddballs[] = {
   1204       kNullReturnValue,
   1205       kUndefinedReturnValue,
   1206       kEmptyStringReturnValue
   1207   };
   1208   for (size_t i = 0; i < arraysize(oddballs); i++) {
   1209     fast_return_value_void = oddballs[i];
   1210     value = TestFastReturnValues<void>();
   1211     switch (fast_return_value_void) {
   1212       case kNullReturnValue:
   1213         CHECK(value->IsNull());
   1214         break;
   1215       case kUndefinedReturnValue:
   1216         CHECK(value->IsUndefined());
   1217         break;
   1218       case kEmptyStringReturnValue:
   1219         CHECK(value->IsString());
   1220         CHECK_EQ(0, v8::String::Cast(*value)->Length());
   1221         break;
   1222     }
   1223   }
   1224   // check handles
   1225   fast_return_value_object_is_empty = false;
   1226   value = TestFastReturnValues<Object>();
   1227   CHECK(value->IsObject());
   1228   fast_return_value_object_is_empty = true;
   1229   value = TestFastReturnValues<Object>();
   1230   CHECK(value->IsUndefined());
   1231 }
   1232 
   1233 
   1234 THREADED_TEST(FunctionTemplateSetLength) {
   1235   LocalContext env;
   1236   v8::Isolate* isolate = env->GetIsolate();
   1237   v8::HandleScope scope(isolate);
   1238   {
   1239     Local<v8::FunctionTemplate> fun_templ =
   1240         v8::FunctionTemplate::New(isolate, handle_callback, Local<v8::Value>(),
   1241                                   Local<v8::Signature>(), 23);
   1242     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   1243     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
   1244     Local<Script> script = v8_compile("obj.length");
   1245     CHECK_EQ(23, v8_run_int32value(script));
   1246   }
   1247   {
   1248     Local<v8::FunctionTemplate> fun_templ =
   1249         v8::FunctionTemplate::New(isolate, handle_callback);
   1250     fun_templ->SetLength(22);
   1251     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   1252     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
   1253     Local<Script> script = v8_compile("obj.length");
   1254     CHECK_EQ(22, v8_run_int32value(script));
   1255   }
   1256   {
   1257     // Without setting length it defaults to 0.
   1258     Local<v8::FunctionTemplate> fun_templ =
   1259         v8::FunctionTemplate::New(isolate, handle_callback);
   1260     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   1261     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
   1262     Local<Script> script = v8_compile("obj.length");
   1263     CHECK_EQ(0, v8_run_int32value(script));
   1264   }
   1265 }
   1266 
   1267 
   1268 static void* expected_ptr;
   1269 static void callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   1270   void* ptr = v8::External::Cast(*args.Data())->Value();
   1271   CHECK_EQ(expected_ptr, ptr);
   1272   args.GetReturnValue().Set(true);
   1273 }
   1274 
   1275 
   1276 static void TestExternalPointerWrapping() {
   1277   LocalContext env;
   1278   v8::Isolate* isolate = env->GetIsolate();
   1279   v8::HandleScope scope(isolate);
   1280 
   1281   v8::Local<v8::Value> data = v8::External::New(isolate, expected_ptr);
   1282 
   1283   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   1284   CHECK(obj->Set(env.local(), v8_str("func"),
   1285                  v8::FunctionTemplate::New(isolate, callback, data)
   1286                      ->GetFunction(env.local())
   1287                      .ToLocalChecked())
   1288             .FromJust());
   1289   CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
   1290 
   1291   CHECK(CompileRun("function foo() {\n"
   1292                    "  for (var i = 0; i < 13; i++) obj.func();\n"
   1293                    "}\n"
   1294                    "foo(), true")
   1295             ->BooleanValue(env.local())
   1296             .FromJust());
   1297 }
   1298 
   1299 
   1300 THREADED_TEST(ExternalWrap) {
   1301   // Check heap allocated object.
   1302   int* ptr = new int;
   1303   expected_ptr = ptr;
   1304   TestExternalPointerWrapping();
   1305   delete ptr;
   1306 
   1307   // Check stack allocated object.
   1308   int foo;
   1309   expected_ptr = &foo;
   1310   TestExternalPointerWrapping();
   1311 
   1312   // Check not aligned addresses.
   1313   const int n = 100;
   1314   char* s = new char[n];
   1315   for (int i = 0; i < n; i++) {
   1316     expected_ptr = s + i;
   1317     TestExternalPointerWrapping();
   1318   }
   1319 
   1320   delete[] s;
   1321 
   1322   // Check several invalid addresses.
   1323   expected_ptr = reinterpret_cast<void*>(1);
   1324   TestExternalPointerWrapping();
   1325 
   1326   expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
   1327   TestExternalPointerWrapping();
   1328 
   1329   expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
   1330   TestExternalPointerWrapping();
   1331 
   1332 #if defined(V8_HOST_ARCH_X64)
   1333   // Check a value with a leading 1 bit in x64 Smi encoding.
   1334   expected_ptr = reinterpret_cast<void*>(0x400000000);
   1335   TestExternalPointerWrapping();
   1336 
   1337   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
   1338   TestExternalPointerWrapping();
   1339 
   1340   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
   1341   TestExternalPointerWrapping();
   1342 #endif
   1343 }
   1344 
   1345 
   1346 THREADED_TEST(FindInstanceInPrototypeChain) {
   1347   LocalContext env;
   1348   v8::Isolate* isolate = env->GetIsolate();
   1349   v8::HandleScope scope(isolate);
   1350 
   1351   Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New(isolate);
   1352   Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New(isolate);
   1353   Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New(isolate);
   1354   derived->Inherit(base);
   1355 
   1356   Local<v8::Function> base_function =
   1357       base->GetFunction(env.local()).ToLocalChecked();
   1358   Local<v8::Function> derived_function =
   1359       derived->GetFunction(env.local()).ToLocalChecked();
   1360   Local<v8::Function> other_function =
   1361       other->GetFunction(env.local()).ToLocalChecked();
   1362 
   1363   Local<v8::Object> base_instance =
   1364       base_function->NewInstance(env.local()).ToLocalChecked();
   1365   Local<v8::Object> derived_instance =
   1366       derived_function->NewInstance(env.local()).ToLocalChecked();
   1367   Local<v8::Object> derived_instance2 =
   1368       derived_function->NewInstance(env.local()).ToLocalChecked();
   1369   Local<v8::Object> other_instance =
   1370       other_function->NewInstance(env.local()).ToLocalChecked();
   1371   CHECK(
   1372       derived_instance2->Set(env.local(), v8_str("__proto__"), derived_instance)
   1373           .FromJust());
   1374   CHECK(other_instance->Set(env.local(), v8_str("__proto__"), derived_instance2)
   1375             .FromJust());
   1376 
   1377   // base_instance is only an instance of base.
   1378   CHECK(base_instance->Equals(env.local(),
   1379                               base_instance->FindInstanceInPrototypeChain(base))
   1380             .FromJust());
   1381   CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
   1382   CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
   1383 
   1384   // derived_instance is an instance of base and derived.
   1385   CHECK(derived_instance->Equals(env.local(),
   1386                                  derived_instance->FindInstanceInPrototypeChain(
   1387                                      base))
   1388             .FromJust());
   1389   CHECK(derived_instance->Equals(env.local(),
   1390                                  derived_instance->FindInstanceInPrototypeChain(
   1391                                      derived))
   1392             .FromJust());
   1393   CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
   1394 
   1395   // other_instance is an instance of other and its immediate
   1396   // prototype derived_instance2 is an instance of base and derived.
   1397   // Note, derived_instance is an instance of base and derived too,
   1398   // but it comes after derived_instance2 in the prototype chain of
   1399   // other_instance.
   1400   CHECK(derived_instance2->Equals(
   1401                              env.local(),
   1402                              other_instance->FindInstanceInPrototypeChain(base))
   1403             .FromJust());
   1404   CHECK(derived_instance2->Equals(env.local(),
   1405                                   other_instance->FindInstanceInPrototypeChain(
   1406                                       derived))
   1407             .FromJust());
   1408   CHECK(other_instance->Equals(
   1409                           env.local(),
   1410                           other_instance->FindInstanceInPrototypeChain(other))
   1411             .FromJust());
   1412 }
   1413 
   1414 
   1415 THREADED_TEST(TinyInteger) {
   1416   LocalContext env;
   1417   v8::Isolate* isolate = env->GetIsolate();
   1418   v8::HandleScope scope(isolate);
   1419 
   1420   int32_t value = 239;
   1421   Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
   1422   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1423 
   1424   value_obj = v8::Integer::New(isolate, value);
   1425   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1426 }
   1427 
   1428 
   1429 THREADED_TEST(BigSmiInteger) {
   1430   LocalContext env;
   1431   v8::HandleScope scope(env->GetIsolate());
   1432   v8::Isolate* isolate = CcTest::isolate();
   1433 
   1434   int32_t value = i::Smi::kMaxValue;
   1435   // We cannot add one to a Smi::kMaxValue without wrapping.
   1436   if (i::SmiValuesAre31Bits()) {
   1437     CHECK(i::Smi::IsValid(value));
   1438     CHECK(!i::Smi::IsValid(value + 1));
   1439 
   1440     Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
   1441     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1442 
   1443     value_obj = v8::Integer::New(isolate, value);
   1444     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1445   }
   1446 }
   1447 
   1448 
   1449 THREADED_TEST(BigInteger) {
   1450   LocalContext env;
   1451   v8::HandleScope scope(env->GetIsolate());
   1452   v8::Isolate* isolate = CcTest::isolate();
   1453 
   1454   // We cannot add one to a Smi::kMaxValue without wrapping.
   1455   if (i::SmiValuesAre31Bits()) {
   1456     // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
   1457     // The code will not be run in that case, due to the "if" guard.
   1458     int32_t value =
   1459         static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
   1460     CHECK(value > i::Smi::kMaxValue);
   1461     CHECK(!i::Smi::IsValid(value));
   1462 
   1463     Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
   1464     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1465 
   1466     value_obj = v8::Integer::New(isolate, value);
   1467     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1468   }
   1469 }
   1470 
   1471 
   1472 THREADED_TEST(TinyUnsignedInteger) {
   1473   LocalContext env;
   1474   v8::HandleScope scope(env->GetIsolate());
   1475   v8::Isolate* isolate = CcTest::isolate();
   1476 
   1477   uint32_t value = 239;
   1478 
   1479   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
   1480   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1481 
   1482   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
   1483   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1484 }
   1485 
   1486 
   1487 THREADED_TEST(BigUnsignedSmiInteger) {
   1488   LocalContext env;
   1489   v8::HandleScope scope(env->GetIsolate());
   1490   v8::Isolate* isolate = CcTest::isolate();
   1491 
   1492   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
   1493   CHECK(i::Smi::IsValid(value));
   1494   CHECK(!i::Smi::IsValid(value + 1));
   1495 
   1496   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
   1497   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1498 
   1499   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
   1500   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1501 }
   1502 
   1503 
   1504 THREADED_TEST(BigUnsignedInteger) {
   1505   LocalContext env;
   1506   v8::HandleScope scope(env->GetIsolate());
   1507   v8::Isolate* isolate = CcTest::isolate();
   1508 
   1509   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
   1510   CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
   1511   CHECK(!i::Smi::IsValid(value));
   1512 
   1513   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
   1514   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1515 
   1516   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
   1517   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1518 }
   1519 
   1520 
   1521 THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
   1522   LocalContext env;
   1523   v8::HandleScope scope(env->GetIsolate());
   1524   v8::Isolate* isolate = CcTest::isolate();
   1525 
   1526   uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
   1527   uint32_t value = INT32_MAX_AS_UINT + 1;
   1528   CHECK(value > INT32_MAX_AS_UINT);  // No overflow.
   1529 
   1530   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
   1531   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1532 
   1533   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
   1534   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1535 }
   1536 
   1537 
   1538 THREADED_TEST(IsNativeError) {
   1539   LocalContext env;
   1540   v8::HandleScope scope(env->GetIsolate());
   1541   v8::Local<Value> syntax_error = CompileRun(
   1542       "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
   1543   CHECK(syntax_error->IsNativeError());
   1544   v8::Local<Value> not_error = CompileRun("{a:42}");
   1545   CHECK(!not_error->IsNativeError());
   1546   v8::Local<Value> not_object = CompileRun("42");
   1547   CHECK(!not_object->IsNativeError());
   1548 }
   1549 
   1550 
   1551 THREADED_TEST(IsGeneratorFunctionOrObject) {
   1552   LocalContext env;
   1553   v8::HandleScope scope(env->GetIsolate());
   1554 
   1555   CompileRun("function *gen() { yield 1; }\nfunction func() {}");
   1556   v8::Local<Value> gen = CompileRun("gen");
   1557   v8::Local<Value> genObj = CompileRun("gen()");
   1558   v8::Local<Value> object = CompileRun("{a:42}");
   1559   v8::Local<Value> func = CompileRun("func");
   1560 
   1561   CHECK(gen->IsGeneratorFunction());
   1562   CHECK(gen->IsFunction());
   1563   CHECK(!gen->IsGeneratorObject());
   1564 
   1565   CHECK(!genObj->IsGeneratorFunction());
   1566   CHECK(!genObj->IsFunction());
   1567   CHECK(genObj->IsGeneratorObject());
   1568 
   1569   CHECK(!object->IsGeneratorFunction());
   1570   CHECK(!object->IsFunction());
   1571   CHECK(!object->IsGeneratorObject());
   1572 
   1573   CHECK(!func->IsGeneratorFunction());
   1574   CHECK(func->IsFunction());
   1575   CHECK(!func->IsGeneratorObject());
   1576 }
   1577 
   1578 
   1579 THREADED_TEST(ArgumentsObject) {
   1580   LocalContext env;
   1581   v8::HandleScope scope(env->GetIsolate());
   1582   v8::Local<Value> arguments_object =
   1583       CompileRun("var out = 0; (function(){ out = arguments; })(1,2,3); out;");
   1584   CHECK(arguments_object->IsArgumentsObject());
   1585   v8::Local<Value> array = CompileRun("[1,2,3]");
   1586   CHECK(!array->IsArgumentsObject());
   1587   v8::Local<Value> object = CompileRun("{a:42}");
   1588   CHECK(!object->IsArgumentsObject());
   1589 }
   1590 
   1591 
   1592 THREADED_TEST(IsMapOrSet) {
   1593   LocalContext env;
   1594   v8::HandleScope scope(env->GetIsolate());
   1595   v8::Local<Value> map = CompileRun("new Map()");
   1596   v8::Local<Value> set = CompileRun("new Set()");
   1597   v8::Local<Value> weak_map = CompileRun("new WeakMap()");
   1598   v8::Local<Value> weak_set = CompileRun("new WeakSet()");
   1599   CHECK(map->IsMap());
   1600   CHECK(set->IsSet());
   1601   CHECK(weak_map->IsWeakMap());
   1602   CHECK(weak_set->IsWeakSet());
   1603 
   1604   CHECK(!map->IsSet());
   1605   CHECK(!map->IsWeakMap());
   1606   CHECK(!map->IsWeakSet());
   1607 
   1608   CHECK(!set->IsMap());
   1609   CHECK(!set->IsWeakMap());
   1610   CHECK(!set->IsWeakSet());
   1611 
   1612   CHECK(!weak_map->IsMap());
   1613   CHECK(!weak_map->IsSet());
   1614   CHECK(!weak_map->IsWeakSet());
   1615 
   1616   CHECK(!weak_set->IsMap());
   1617   CHECK(!weak_set->IsSet());
   1618   CHECK(!weak_set->IsWeakMap());
   1619 
   1620   v8::Local<Value> object = CompileRun("{a:42}");
   1621   CHECK(!object->IsMap());
   1622   CHECK(!object->IsSet());
   1623   CHECK(!object->IsWeakMap());
   1624   CHECK(!object->IsWeakSet());
   1625 }
   1626 
   1627 
   1628 THREADED_TEST(StringObject) {
   1629   LocalContext env;
   1630   v8::HandleScope scope(env->GetIsolate());
   1631   v8::Local<Value> boxed_string = CompileRun("new String(\"test\")");
   1632   CHECK(boxed_string->IsStringObject());
   1633   v8::Local<Value> unboxed_string = CompileRun("\"test\"");
   1634   CHECK(!unboxed_string->IsStringObject());
   1635   v8::Local<Value> boxed_not_string = CompileRun("new Number(42)");
   1636   CHECK(!boxed_not_string->IsStringObject());
   1637   v8::Local<Value> not_object = CompileRun("0");
   1638   CHECK(!not_object->IsStringObject());
   1639   v8::Local<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
   1640   CHECK(!as_boxed.IsEmpty());
   1641   Local<v8::String> the_string = as_boxed->ValueOf();
   1642   CHECK(!the_string.IsEmpty());
   1643   ExpectObject("\"test\"", the_string);
   1644   v8::Local<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
   1645   CHECK(new_boxed_string->IsStringObject());
   1646   as_boxed = new_boxed_string.As<v8::StringObject>();
   1647   the_string = as_boxed->ValueOf();
   1648   CHECK(!the_string.IsEmpty());
   1649   ExpectObject("\"test\"", the_string);
   1650 }
   1651 
   1652 
   1653 TEST(StringObjectDelete) {
   1654   LocalContext context;
   1655   v8::HandleScope scope(context->GetIsolate());
   1656   v8::Local<Value> boxed_string = CompileRun("new String(\"test\")");
   1657   CHECK(boxed_string->IsStringObject());
   1658   v8::Local<v8::Object> str_obj = boxed_string.As<v8::Object>();
   1659   CHECK(!str_obj->Delete(context.local(), 2).FromJust());
   1660   CHECK(!str_obj->Delete(context.local(), v8_num(2)).FromJust());
   1661 }
   1662 
   1663 
   1664 THREADED_TEST(NumberObject) {
   1665   LocalContext env;
   1666   v8::HandleScope scope(env->GetIsolate());
   1667   v8::Local<Value> boxed_number = CompileRun("new Number(42)");
   1668   CHECK(boxed_number->IsNumberObject());
   1669   v8::Local<Value> unboxed_number = CompileRun("42");
   1670   CHECK(!unboxed_number->IsNumberObject());
   1671   v8::Local<Value> boxed_not_number = CompileRun("new Boolean(false)");
   1672   CHECK(!boxed_not_number->IsNumberObject());
   1673   v8::Local<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
   1674   CHECK(!as_boxed.IsEmpty());
   1675   double the_number = as_boxed->ValueOf();
   1676   CHECK_EQ(42.0, the_number);
   1677   v8::Local<v8::Value> new_boxed_number =
   1678       v8::NumberObject::New(env->GetIsolate(), 43);
   1679   CHECK(new_boxed_number->IsNumberObject());
   1680   as_boxed = new_boxed_number.As<v8::NumberObject>();
   1681   the_number = as_boxed->ValueOf();
   1682   CHECK_EQ(43.0, the_number);
   1683 }
   1684 
   1685 
   1686 THREADED_TEST(BooleanObject) {
   1687   LocalContext env;
   1688   v8::HandleScope scope(env->GetIsolate());
   1689   v8::Local<Value> boxed_boolean = CompileRun("new Boolean(true)");
   1690   CHECK(boxed_boolean->IsBooleanObject());
   1691   v8::Local<Value> unboxed_boolean = CompileRun("true");
   1692   CHECK(!unboxed_boolean->IsBooleanObject());
   1693   v8::Local<Value> boxed_not_boolean = CompileRun("new Number(42)");
   1694   CHECK(!boxed_not_boolean->IsBooleanObject());
   1695   v8::Local<v8::BooleanObject> as_boxed = boxed_boolean.As<v8::BooleanObject>();
   1696   CHECK(!as_boxed.IsEmpty());
   1697   bool the_boolean = as_boxed->ValueOf();
   1698   CHECK_EQ(true, the_boolean);
   1699   v8::Local<v8::Value> boxed_true =
   1700       v8::BooleanObject::New(env->GetIsolate(), true);
   1701   v8::Local<v8::Value> boxed_false =
   1702       v8::BooleanObject::New(env->GetIsolate(), false);
   1703   CHECK(boxed_true->IsBooleanObject());
   1704   CHECK(boxed_false->IsBooleanObject());
   1705   as_boxed = boxed_true.As<v8::BooleanObject>();
   1706   CHECK_EQ(true, as_boxed->ValueOf());
   1707   as_boxed = boxed_false.As<v8::BooleanObject>();
   1708   CHECK_EQ(false, as_boxed->ValueOf());
   1709 }
   1710 
   1711 
   1712 THREADED_TEST(PrimitiveAndWrappedBooleans) {
   1713   LocalContext env;
   1714   v8::HandleScope scope(env->GetIsolate());
   1715 
   1716   Local<Value> primitive_false = Boolean::New(env->GetIsolate(), false);
   1717   CHECK(primitive_false->IsBoolean());
   1718   CHECK(!primitive_false->IsBooleanObject());
   1719   CHECK(!primitive_false->BooleanValue(env.local()).FromJust());
   1720   CHECK(!primitive_false->IsTrue());
   1721   CHECK(primitive_false->IsFalse());
   1722 
   1723   Local<Value> false_value = BooleanObject::New(env->GetIsolate(), false);
   1724   CHECK(!false_value->IsBoolean());
   1725   CHECK(false_value->IsBooleanObject());
   1726   CHECK(false_value->BooleanValue(env.local()).FromJust());
   1727   CHECK(!false_value->IsTrue());
   1728   CHECK(!false_value->IsFalse());
   1729 
   1730   Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
   1731   CHECK(!false_boolean_object->IsBoolean());
   1732   CHECK(false_boolean_object->IsBooleanObject());
   1733   CHECK(false_boolean_object->BooleanValue(env.local()).FromJust());
   1734   CHECK(!false_boolean_object->ValueOf());
   1735   CHECK(!false_boolean_object->IsTrue());
   1736   CHECK(!false_boolean_object->IsFalse());
   1737 
   1738   Local<Value> primitive_true = Boolean::New(env->GetIsolate(), true);
   1739   CHECK(primitive_true->IsBoolean());
   1740   CHECK(!primitive_true->IsBooleanObject());
   1741   CHECK(primitive_true->BooleanValue(env.local()).FromJust());
   1742   CHECK(primitive_true->IsTrue());
   1743   CHECK(!primitive_true->IsFalse());
   1744 
   1745   Local<Value> true_value = BooleanObject::New(env->GetIsolate(), true);
   1746   CHECK(!true_value->IsBoolean());
   1747   CHECK(true_value->IsBooleanObject());
   1748   CHECK(true_value->BooleanValue(env.local()).FromJust());
   1749   CHECK(!true_value->IsTrue());
   1750   CHECK(!true_value->IsFalse());
   1751 
   1752   Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
   1753   CHECK(!true_boolean_object->IsBoolean());
   1754   CHECK(true_boolean_object->IsBooleanObject());
   1755   CHECK(true_boolean_object->BooleanValue(env.local()).FromJust());
   1756   CHECK(true_boolean_object->ValueOf());
   1757   CHECK(!true_boolean_object->IsTrue());
   1758   CHECK(!true_boolean_object->IsFalse());
   1759 }
   1760 
   1761 
   1762 THREADED_TEST(Number) {
   1763   LocalContext env;
   1764   v8::HandleScope scope(env->GetIsolate());
   1765   double PI = 3.1415926;
   1766   Local<v8::Number> pi_obj = v8::Number::New(env->GetIsolate(), PI);
   1767   CHECK_EQ(PI, pi_obj->NumberValue(env.local()).FromJust());
   1768 }
   1769 
   1770 
   1771 THREADED_TEST(ToNumber) {
   1772   LocalContext env;
   1773   v8::Isolate* isolate = CcTest::isolate();
   1774   v8::HandleScope scope(isolate);
   1775   Local<String> str = v8_str("3.1415926");
   1776   CHECK_EQ(3.1415926, str->NumberValue(env.local()).FromJust());
   1777   v8::Local<v8::Boolean> t = v8::True(isolate);
   1778   CHECK_EQ(1.0, t->NumberValue(env.local()).FromJust());
   1779   v8::Local<v8::Boolean> f = v8::False(isolate);
   1780   CHECK_EQ(0.0, f->NumberValue(env.local()).FromJust());
   1781 }
   1782 
   1783 
   1784 THREADED_TEST(Date) {
   1785   LocalContext env;
   1786   v8::HandleScope scope(env->GetIsolate());
   1787   double PI = 3.1415926;
   1788   Local<Value> date = v8::Date::New(env.local(), PI).ToLocalChecked();
   1789   CHECK_EQ(3.0, date->NumberValue(env.local()).FromJust());
   1790   CHECK(date.As<v8::Date>()
   1791             ->Set(env.local(), v8_str("property"),
   1792                   v8::Integer::New(env->GetIsolate(), 42))
   1793             .FromJust());
   1794   CHECK_EQ(42, date.As<v8::Date>()
   1795                    ->Get(env.local(), v8_str("property"))
   1796                    .ToLocalChecked()
   1797                    ->Int32Value(env.local())
   1798                    .FromJust());
   1799 }
   1800 
   1801 
   1802 THREADED_TEST(Boolean) {
   1803   LocalContext env;
   1804   v8::Isolate* isolate = env->GetIsolate();
   1805   v8::HandleScope scope(isolate);
   1806   v8::Local<v8::Boolean> t = v8::True(isolate);
   1807   CHECK(t->Value());
   1808   v8::Local<v8::Boolean> f = v8::False(isolate);
   1809   CHECK(!f->Value());
   1810   v8::Local<v8::Primitive> u = v8::Undefined(isolate);
   1811   CHECK(!u->BooleanValue(env.local()).FromJust());
   1812   v8::Local<v8::Primitive> n = v8::Null(isolate);
   1813   CHECK(!n->BooleanValue(env.local()).FromJust());
   1814   v8::Local<String> str1 = v8_str("");
   1815   CHECK(!str1->BooleanValue(env.local()).FromJust());
   1816   v8::Local<String> str2 = v8_str("x");
   1817   CHECK(str2->BooleanValue(env.local()).FromJust());
   1818   CHECK(!v8::Number::New(isolate, 0)->BooleanValue(env.local()).FromJust());
   1819   CHECK(v8::Number::New(isolate, -1)->BooleanValue(env.local()).FromJust());
   1820   CHECK(v8::Number::New(isolate, 1)->BooleanValue(env.local()).FromJust());
   1821   CHECK(v8::Number::New(isolate, 42)->BooleanValue(env.local()).FromJust());
   1822   CHECK(!v8_compile("NaN")
   1823              ->Run(env.local())
   1824              .ToLocalChecked()
   1825              ->BooleanValue(env.local())
   1826              .FromJust());
   1827 }
   1828 
   1829 
   1830 static void DummyCallHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
   1831   ApiTestFuzzer::Fuzz();
   1832   args.GetReturnValue().Set(v8_num(13.4));
   1833 }
   1834 
   1835 
   1836 static void GetM(Local<String> name,
   1837                  const v8::PropertyCallbackInfo<v8::Value>& info) {
   1838   ApiTestFuzzer::Fuzz();
   1839   info.GetReturnValue().Set(v8_num(876));
   1840 }
   1841 
   1842 
   1843 THREADED_TEST(GlobalPrototype) {
   1844   v8::Isolate* isolate = CcTest::isolate();
   1845   v8::HandleScope scope(isolate);
   1846   v8::Local<v8::FunctionTemplate> func_templ =
   1847       v8::FunctionTemplate::New(isolate);
   1848   func_templ->PrototypeTemplate()->Set(
   1849       isolate, "dummy", v8::FunctionTemplate::New(isolate, DummyCallHandler));
   1850   v8::Local<ObjectTemplate> templ = func_templ->InstanceTemplate();
   1851   templ->Set(isolate, "x", v8_num(200));
   1852   templ->SetAccessor(v8_str("m"), GetM);
   1853   LocalContext env(0, templ);
   1854   v8::Local<Script> script(v8_compile("dummy()"));
   1855   v8::Local<Value> result(script->Run(env.local()).ToLocalChecked());
   1856   CHECK_EQ(13.4, result->NumberValue(env.local()).FromJust());
   1857   CHECK_EQ(200, v8_run_int32value(v8_compile("x")));
   1858   CHECK_EQ(876, v8_run_int32value(v8_compile("m")));
   1859 }
   1860 
   1861 
   1862 THREADED_TEST(ObjectTemplate) {
   1863   LocalContext env;
   1864   v8::Isolate* isolate = CcTest::isolate();
   1865   v8::HandleScope scope(isolate);
   1866   Local<v8::FunctionTemplate> acc =
   1867       v8::FunctionTemplate::New(isolate, Returns42);
   1868   CHECK(env->Global()
   1869             ->Set(env.local(), v8_str("acc"),
   1870                   acc->GetFunction(env.local()).ToLocalChecked())
   1871             .FromJust());
   1872 
   1873   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
   1874   v8::Local<v8::String> class_name = v8_str("the_class_name");
   1875   fun->SetClassName(class_name);
   1876   Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate, fun);
   1877   templ1->Set(isolate, "x", v8_num(10));
   1878   templ1->Set(isolate, "y", v8_num(13));
   1879   templ1->Set(v8_str("foo"), acc);
   1880   Local<v8::Object> instance1 =
   1881       templ1->NewInstance(env.local()).ToLocalChecked();
   1882   CHECK(class_name->StrictEquals(instance1->GetConstructorName()));
   1883   CHECK(env->Global()->Set(env.local(), v8_str("p"), instance1).FromJust());
   1884   CHECK(CompileRun("(p.x == 10)")->BooleanValue(env.local()).FromJust());
   1885   CHECK(CompileRun("(p.y == 13)")->BooleanValue(env.local()).FromJust());
   1886   CHECK(CompileRun("(p.foo() == 42)")->BooleanValue(env.local()).FromJust());
   1887   CHECK(CompileRun("(p.foo == acc)")->BooleanValue(env.local()).FromJust());
   1888   // Ensure that foo become a data field.
   1889   CompileRun("p.foo = function() {}");
   1890   Local<v8::FunctionTemplate> fun2 = v8::FunctionTemplate::New(isolate);
   1891   fun2->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
   1892   Local<ObjectTemplate> templ2 = fun2->InstanceTemplate();
   1893   templ2->Set(isolate, "a", v8_num(12));
   1894   templ2->Set(isolate, "b", templ1);
   1895   templ2->Set(v8_str("bar"), acc);
   1896   templ2->SetAccessorProperty(v8_str("acc"), acc);
   1897   Local<v8::Object> instance2 =
   1898       templ2->NewInstance(env.local()).ToLocalChecked();
   1899   CHECK(env->Global()->Set(env.local(), v8_str("q"), instance2).FromJust());
   1900   CHECK(CompileRun("(q.nirk == 123)")->BooleanValue(env.local()).FromJust());
   1901   CHECK(CompileRun("(q.a == 12)")->BooleanValue(env.local()).FromJust());
   1902   CHECK(CompileRun("(q.b.x == 10)")->BooleanValue(env.local()).FromJust());
   1903   CHECK(CompileRun("(q.b.y == 13)")->BooleanValue(env.local()).FromJust());
   1904   CHECK(CompileRun("(q.b.foo() == 42)")->BooleanValue(env.local()).FromJust());
   1905   CHECK(CompileRun("(q.b.foo === acc)")->BooleanValue(env.local()).FromJust());
   1906   CHECK(CompileRun("(q.b !== p)")->BooleanValue(env.local()).FromJust());
   1907   CHECK(CompileRun("(q.acc == 42)")->BooleanValue(env.local()).FromJust());
   1908   CHECK(CompileRun("(q.bar() == 42)")->BooleanValue(env.local()).FromJust());
   1909   CHECK(CompileRun("(q.bar == acc)")->BooleanValue(env.local()).FromJust());
   1910 
   1911   instance2 = templ2->NewInstance(env.local()).ToLocalChecked();
   1912   CHECK(env->Global()->Set(env.local(), v8_str("q2"), instance2).FromJust());
   1913   CHECK(CompileRun("(q2.nirk == 123)")->BooleanValue(env.local()).FromJust());
   1914   CHECK(CompileRun("(q2.a == 12)")->BooleanValue(env.local()).FromJust());
   1915   CHECK(CompileRun("(q2.b.x == 10)")->BooleanValue(env.local()).FromJust());
   1916   CHECK(CompileRun("(q2.b.y == 13)")->BooleanValue(env.local()).FromJust());
   1917   CHECK(CompileRun("(q2.b.foo() == 42)")->BooleanValue(env.local()).FromJust());
   1918   CHECK(CompileRun("(q2.b.foo === acc)")->BooleanValue(env.local()).FromJust());
   1919   CHECK(CompileRun("(q2.acc == 42)")->BooleanValue(env.local()).FromJust());
   1920   CHECK(CompileRun("(q2.bar() == 42)")->BooleanValue(env.local()).FromJust());
   1921   CHECK(CompileRun("(q2.bar === acc)")->BooleanValue(env.local()).FromJust());
   1922 
   1923   CHECK(CompileRun("(q.b !== q2.b)")->BooleanValue(env.local()).FromJust());
   1924   CHECK(CompileRun("q.b.x = 17; (q2.b.x == 10)")
   1925             ->BooleanValue(env.local())
   1926             .FromJust());
   1927   CHECK(CompileRun("desc1 = Object.getOwnPropertyDescriptor(q, 'acc');"
   1928                    "(desc1.get === acc)")
   1929             ->BooleanValue(env.local())
   1930             .FromJust());
   1931   CHECK(CompileRun("desc2 = Object.getOwnPropertyDescriptor(q2, 'acc');"
   1932                    "(desc2.get === acc)")
   1933             ->BooleanValue(env.local())
   1934             .FromJust());
   1935 }
   1936 
   1937 THREADED_TEST(IntegerValue) {
   1938   LocalContext env;
   1939   v8::Isolate* isolate = CcTest::isolate();
   1940   v8::HandleScope scope(isolate);
   1941 
   1942   CHECK_EQ(0, CompileRun("undefined")->IntegerValue(env.local()).FromJust());
   1943 }
   1944 
   1945 static void GetNirk(Local<String> name,
   1946                     const v8::PropertyCallbackInfo<v8::Value>& info) {
   1947   ApiTestFuzzer::Fuzz();
   1948   info.GetReturnValue().Set(v8_num(900));
   1949 }
   1950 
   1951 static void GetRino(Local<String> name,
   1952                     const v8::PropertyCallbackInfo<v8::Value>& info) {
   1953   ApiTestFuzzer::Fuzz();
   1954   info.GetReturnValue().Set(v8_num(560));
   1955 }
   1956 
   1957 enum ObjectInstantiationMode {
   1958   // Create object using ObjectTemplate::NewInstance.
   1959   ObjectTemplate_NewInstance,
   1960   // Create object using FunctionTemplate::NewInstance on constructor.
   1961   Constructor_GetFunction_NewInstance,
   1962   // Create object using new operator on constructor.
   1963   Constructor_GetFunction_New
   1964 };
   1965 
   1966 // Test object instance creation using a function template with an instance
   1967 // template inherited from another function template with accessors and data
   1968 // properties in prototype template.
   1969 static void TestObjectTemplateInheritedWithPrototype(
   1970     ObjectInstantiationMode mode) {
   1971   LocalContext env;
   1972   v8::Isolate* isolate = CcTest::isolate();
   1973   v8::HandleScope scope(isolate);
   1974 
   1975   Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
   1976   fun_A->SetClassName(v8_str("A"));
   1977   v8::Local<v8::ObjectTemplate> prototype_templ = fun_A->PrototypeTemplate();
   1978   prototype_templ->Set(isolate, "a", v8_num(113));
   1979   prototype_templ->SetNativeDataProperty(v8_str("nirk"), GetNirk);
   1980   prototype_templ->Set(isolate, "b", v8_num(153));
   1981 
   1982   Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
   1983   v8::Local<v8::String> class_name = v8_str("B");
   1984   fun_B->SetClassName(class_name);
   1985   fun_B->Inherit(fun_A);
   1986   prototype_templ = fun_B->PrototypeTemplate();
   1987   prototype_templ->Set(isolate, "c", v8_num(713));
   1988   prototype_templ->SetNativeDataProperty(v8_str("rino"), GetRino);
   1989   prototype_templ->Set(isolate, "d", v8_num(753));
   1990 
   1991   Local<ObjectTemplate> templ = fun_B->InstanceTemplate();
   1992   templ->Set(isolate, "x", v8_num(10));
   1993   templ->Set(isolate, "y", v8_num(13));
   1994 
   1995   // Perform several iterations to trigger creation from cached boilerplate.
   1996   for (int i = 0; i < 3; i++) {
   1997     Local<v8::Object> instance;
   1998     switch (mode) {
   1999       case ObjectTemplate_NewInstance:
   2000         instance = templ->NewInstance(env.local()).ToLocalChecked();
   2001         break;
   2002 
   2003       case Constructor_GetFunction_NewInstance: {
   2004         Local<v8::Function> function_B =
   2005             fun_B->GetFunction(env.local()).ToLocalChecked();
   2006         instance = function_B->NewInstance(env.local()).ToLocalChecked();
   2007         break;
   2008       }
   2009       case Constructor_GetFunction_New: {
   2010         Local<v8::Function> function_B =
   2011             fun_B->GetFunction(env.local()).ToLocalChecked();
   2012         if (i == 0) {
   2013           CHECK(env->Global()
   2014                     ->Set(env.local(), class_name, function_B)
   2015                     .FromJust());
   2016         }
   2017         instance =
   2018             CompileRun("new B()")->ToObject(env.local()).ToLocalChecked();
   2019         break;
   2020       }
   2021       default:
   2022         UNREACHABLE();
   2023     }
   2024 
   2025     CHECK(class_name->StrictEquals(instance->GetConstructorName()));
   2026     CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
   2027 
   2028     CHECK_EQ(10, CompileRun("o.x")->IntegerValue(env.local()).FromJust());
   2029     CHECK_EQ(13, CompileRun("o.y")->IntegerValue(env.local()).FromJust());
   2030 
   2031     CHECK_EQ(113, CompileRun("o.a")->IntegerValue(env.local()).FromJust());
   2032     CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
   2033     CHECK_EQ(153, CompileRun("o.b")->IntegerValue(env.local()).FromJust());
   2034     CHECK_EQ(713, CompileRun("o.c")->IntegerValue(env.local()).FromJust());
   2035     CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
   2036     CHECK_EQ(753, CompileRun("o.d")->IntegerValue(env.local()).FromJust());
   2037   }
   2038 }
   2039 
   2040 THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype1) {
   2041   TestObjectTemplateInheritedWithPrototype(ObjectTemplate_NewInstance);
   2042 }
   2043 
   2044 THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype2) {
   2045   TestObjectTemplateInheritedWithPrototype(Constructor_GetFunction_NewInstance);
   2046 }
   2047 
   2048 THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype3) {
   2049   TestObjectTemplateInheritedWithPrototype(Constructor_GetFunction_New);
   2050 }
   2051 
   2052 // Test object instance creation using a function template without an instance
   2053 // template inherited from another function template.
   2054 static void TestObjectTemplateInheritedWithoutInstanceTemplate(
   2055     ObjectInstantiationMode mode) {
   2056   LocalContext env;
   2057   v8::Isolate* isolate = CcTest::isolate();
   2058   v8::HandleScope scope(isolate);
   2059 
   2060   Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
   2061   fun_A->SetClassName(v8_str("A"));
   2062 
   2063   Local<ObjectTemplate> templ_A = fun_A->InstanceTemplate();
   2064   templ_A->SetNativeDataProperty(v8_str("nirk"), GetNirk);
   2065   templ_A->SetNativeDataProperty(v8_str("rino"), GetRino);
   2066 
   2067   Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
   2068   v8::Local<v8::String> class_name = v8_str("B");
   2069   fun_B->SetClassName(class_name);
   2070   fun_B->Inherit(fun_A);
   2071 
   2072   // Perform several iterations to trigger creation from cached boilerplate.
   2073   for (int i = 0; i < 3; i++) {
   2074     Local<v8::Object> instance;
   2075     switch (mode) {
   2076       case Constructor_GetFunction_NewInstance: {
   2077         Local<v8::Function> function_B =
   2078             fun_B->GetFunction(env.local()).ToLocalChecked();
   2079         instance = function_B->NewInstance(env.local()).ToLocalChecked();
   2080         break;
   2081       }
   2082       case Constructor_GetFunction_New: {
   2083         Local<v8::Function> function_B =
   2084             fun_B->GetFunction(env.local()).ToLocalChecked();
   2085         if (i == 0) {
   2086           CHECK(env->Global()
   2087                     ->Set(env.local(), class_name, function_B)
   2088                     .FromJust());
   2089         }
   2090         instance =
   2091             CompileRun("new B()")->ToObject(env.local()).ToLocalChecked();
   2092         break;
   2093       }
   2094       default:
   2095         UNREACHABLE();
   2096     }
   2097 
   2098     CHECK(class_name->StrictEquals(instance->GetConstructorName()));
   2099     CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
   2100 
   2101     CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
   2102     CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
   2103   }
   2104 }
   2105 
   2106 THREADED_TEST(TestObjectTemplateInheritedWithPrototype1) {
   2107   TestObjectTemplateInheritedWithoutInstanceTemplate(
   2108       Constructor_GetFunction_NewInstance);
   2109 }
   2110 
   2111 THREADED_TEST(TestObjectTemplateInheritedWithPrototype2) {
   2112   TestObjectTemplateInheritedWithoutInstanceTemplate(
   2113       Constructor_GetFunction_New);
   2114 }
   2115 
   2116 THREADED_TEST(TestObjectTemplateClassInheritance) {
   2117   LocalContext env;
   2118   v8::Isolate* isolate = CcTest::isolate();
   2119   v8::HandleScope scope(isolate);
   2120 
   2121   Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
   2122   fun_A->SetClassName(v8_str("A"));
   2123 
   2124   Local<ObjectTemplate> templ_A = fun_A->InstanceTemplate();
   2125   templ_A->SetNativeDataProperty(v8_str("nirk"), GetNirk);
   2126   templ_A->SetNativeDataProperty(v8_str("rino"), GetRino);
   2127 
   2128   Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
   2129   v8::Local<v8::String> class_name = v8_str("B");
   2130   fun_B->SetClassName(class_name);
   2131   fun_B->Inherit(fun_A);
   2132 
   2133   v8::Local<v8::String> subclass_name = v8_str("C");
   2134   v8::Local<v8::Object> b_proto;
   2135   v8::Local<v8::Object> c_proto;
   2136   // Perform several iterations to make sure the cache doesn't break
   2137   // subclassing.
   2138   for (int i = 0; i < 3; i++) {
   2139     Local<v8::Function> function_B =
   2140         fun_B->GetFunction(env.local()).ToLocalChecked();
   2141     if (i == 0) {
   2142       CHECK(env->Global()->Set(env.local(), class_name, function_B).FromJust());
   2143       CompileRun("class C extends B {}");
   2144       b_proto =
   2145           CompileRun("B.prototype")->ToObject(env.local()).ToLocalChecked();
   2146       c_proto =
   2147           CompileRun("C.prototype")->ToObject(env.local()).ToLocalChecked();
   2148       CHECK(b_proto->Equals(env.local(), c_proto->GetPrototype()).FromJust());
   2149     }
   2150     Local<v8::Object> instance =
   2151         CompileRun("new C()")->ToObject(env.local()).ToLocalChecked();
   2152     CHECK(c_proto->Equals(env.local(), instance->GetPrototype()).FromJust());
   2153 
   2154     CHECK(subclass_name->StrictEquals(instance->GetConstructorName()));
   2155     CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
   2156 
   2157     CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
   2158     CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
   2159   }
   2160 }
   2161 
   2162 static void NamedPropertyGetterWhichReturns42(
   2163     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   2164   info.GetReturnValue().Set(v8_num(42));
   2165 }
   2166 
   2167 THREADED_TEST(TestObjectTemplateReflectConstruct) {
   2168   LocalContext env;
   2169   v8::Isolate* isolate = CcTest::isolate();
   2170   v8::HandleScope scope(isolate);
   2171 
   2172   Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
   2173   fun_B->InstanceTemplate()->SetHandler(
   2174       v8::NamedPropertyHandlerConfiguration(NamedPropertyGetterWhichReturns42));
   2175   v8::Local<v8::String> class_name = v8_str("B");
   2176   fun_B->SetClassName(class_name);
   2177 
   2178   v8::Local<v8::String> subclass_name = v8_str("C");
   2179   v8::Local<v8::Object> b_proto;
   2180   v8::Local<v8::Object> c_proto;
   2181   // Perform several iterations to make sure the cache doesn't break
   2182   // subclassing.
   2183   for (int i = 0; i < 3; i++) {
   2184     Local<v8::Function> function_B =
   2185         fun_B->GetFunction(env.local()).ToLocalChecked();
   2186     if (i == 0) {
   2187       CHECK(env->Global()->Set(env.local(), class_name, function_B).FromJust());
   2188       CompileRun("function C() {}");
   2189       c_proto =
   2190           CompileRun("C.prototype")->ToObject(env.local()).ToLocalChecked();
   2191     }
   2192     Local<v8::Object> instance = CompileRun("Reflect.construct(B, [], C)")
   2193                                      ->ToObject(env.local())
   2194                                      .ToLocalChecked();
   2195     CHECK(c_proto->Equals(env.local(), instance->GetPrototype()).FromJust());
   2196 
   2197     CHECK(subclass_name->StrictEquals(instance->GetConstructorName()));
   2198     CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
   2199 
   2200     CHECK_EQ(42, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
   2201     CHECK_EQ(42, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
   2202   }
   2203 }
   2204 
   2205 static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
   2206   ApiTestFuzzer::Fuzz();
   2207   args.GetReturnValue().Set(v8_num(17.2));
   2208 }
   2209 
   2210 
   2211 static void GetKnurd(Local<String> property,
   2212                      const v8::PropertyCallbackInfo<v8::Value>& info) {
   2213   ApiTestFuzzer::Fuzz();
   2214   info.GetReturnValue().Set(v8_num(15.2));
   2215 }
   2216 
   2217 
   2218 THREADED_TEST(DescriptorInheritance) {
   2219   v8::Isolate* isolate = CcTest::isolate();
   2220   v8::HandleScope scope(isolate);
   2221   v8::Local<v8::FunctionTemplate> super = v8::FunctionTemplate::New(isolate);
   2222   super->PrototypeTemplate()->Set(isolate, "flabby",
   2223                                   v8::FunctionTemplate::New(isolate,
   2224                                                             GetFlabby));
   2225   super->PrototypeTemplate()->Set(isolate, "PI", v8_num(3.14));
   2226 
   2227   super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
   2228 
   2229   v8::Local<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New(isolate);
   2230   base1->Inherit(super);
   2231   base1->PrototypeTemplate()->Set(isolate, "v1", v8_num(20.1));
   2232 
   2233   v8::Local<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New(isolate);
   2234   base2->Inherit(super);
   2235   base2->PrototypeTemplate()->Set(isolate, "v2", v8_num(10.1));
   2236 
   2237   LocalContext env;
   2238 
   2239   CHECK(env->Global()
   2240             ->Set(env.local(), v8_str("s"),
   2241                   super->GetFunction(env.local()).ToLocalChecked())
   2242             .FromJust());
   2243   CHECK(env->Global()
   2244             ->Set(env.local(), v8_str("base1"),
   2245                   base1->GetFunction(env.local()).ToLocalChecked())
   2246             .FromJust());
   2247   CHECK(env->Global()
   2248             ->Set(env.local(), v8_str("base2"),
   2249                   base2->GetFunction(env.local()).ToLocalChecked())
   2250             .FromJust());
   2251 
   2252   // Checks right __proto__ chain.
   2253   CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")
   2254             ->BooleanValue(env.local())
   2255             .FromJust());
   2256   CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")
   2257             ->BooleanValue(env.local())
   2258             .FromJust());
   2259 
   2260   CHECK(v8_compile("s.prototype.PI == 3.14")
   2261             ->Run(env.local())
   2262             .ToLocalChecked()
   2263             ->BooleanValue(env.local())
   2264             .FromJust());
   2265 
   2266   // Instance accessor should not be visible on function object or its prototype
   2267   CHECK(
   2268       CompileRun("s.knurd == undefined")->BooleanValue(env.local()).FromJust());
   2269   CHECK(CompileRun("s.prototype.knurd == undefined")
   2270             ->BooleanValue(env.local())
   2271             .FromJust());
   2272   CHECK(CompileRun("base1.prototype.knurd == undefined")
   2273             ->BooleanValue(env.local())
   2274             .FromJust());
   2275 
   2276   CHECK(env->Global()
   2277             ->Set(env.local(), v8_str("obj"), base1->GetFunction(env.local())
   2278                                                   .ToLocalChecked()
   2279                                                   ->NewInstance(env.local())
   2280                                                   .ToLocalChecked())
   2281             .FromJust());
   2282   CHECK_EQ(17.2,
   2283            CompileRun("obj.flabby()")->NumberValue(env.local()).FromJust());
   2284   CHECK(CompileRun("'flabby' in obj")->BooleanValue(env.local()).FromJust());
   2285   CHECK_EQ(15.2, CompileRun("obj.knurd")->NumberValue(env.local()).FromJust());
   2286   CHECK(CompileRun("'knurd' in obj")->BooleanValue(env.local()).FromJust());
   2287   CHECK_EQ(20.1, CompileRun("obj.v1")->NumberValue(env.local()).FromJust());
   2288 
   2289   CHECK(env->Global()
   2290             ->Set(env.local(), v8_str("obj2"), base2->GetFunction(env.local())
   2291                                                    .ToLocalChecked()
   2292                                                    ->NewInstance(env.local())
   2293                                                    .ToLocalChecked())
   2294             .FromJust());
   2295   CHECK_EQ(17.2,
   2296            CompileRun("obj2.flabby()")->NumberValue(env.local()).FromJust());
   2297   CHECK(CompileRun("'flabby' in obj2")->BooleanValue(env.local()).FromJust());
   2298   CHECK_EQ(15.2, CompileRun("obj2.knurd")->NumberValue(env.local()).FromJust());
   2299   CHECK(CompileRun("'knurd' in obj2")->BooleanValue(env.local()).FromJust());
   2300   CHECK_EQ(10.1, CompileRun("obj2.v2")->NumberValue(env.local()).FromJust());
   2301 
   2302   // base1 and base2 cannot cross reference to each's prototype
   2303   CHECK(CompileRun("obj.v2")->IsUndefined());
   2304   CHECK(CompileRun("obj2.v1")->IsUndefined());
   2305 }
   2306 
   2307 THREADED_TEST(DescriptorInheritance2) {
   2308   LocalContext env;
   2309   v8::Isolate* isolate = CcTest::isolate();
   2310   v8::HandleScope scope(isolate);
   2311   v8::Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
   2312   fun_A->SetClassName(v8_str("A"));
   2313   fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd1"), GetKnurd);
   2314   fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk1"), GetNirk);
   2315   fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("rino1"), GetRino);
   2316 
   2317   v8::Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
   2318   fun_B->SetClassName(v8_str("B"));
   2319   fun_B->Inherit(fun_A);
   2320 
   2321   v8::Local<v8::FunctionTemplate> fun_C = v8::FunctionTemplate::New(isolate);
   2322   fun_C->SetClassName(v8_str("C"));
   2323   fun_C->Inherit(fun_B);
   2324   fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd2"), GetKnurd);
   2325   fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk2"), GetNirk);
   2326   fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("rino2"), GetRino);
   2327 
   2328   v8::Local<v8::FunctionTemplate> fun_D = v8::FunctionTemplate::New(isolate);
   2329   fun_D->SetClassName(v8_str("D"));
   2330   fun_D->Inherit(fun_C);
   2331 
   2332   v8::Local<v8::FunctionTemplate> fun_E = v8::FunctionTemplate::New(isolate);
   2333   fun_E->SetClassName(v8_str("E"));
   2334   fun_E->Inherit(fun_D);
   2335   fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd3"), GetKnurd);
   2336   fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk3"), GetNirk);
   2337   fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("rino3"), GetRino);
   2338 
   2339   v8::Local<v8::FunctionTemplate> fun_F = v8::FunctionTemplate::New(isolate);
   2340   fun_F->SetClassName(v8_str("F"));
   2341   fun_F->Inherit(fun_E);
   2342   v8::Local<v8::ObjectTemplate> templ = fun_F->InstanceTemplate();
   2343   const int kDataPropertiesNumber = 100;
   2344   for (int i = 0; i < kDataPropertiesNumber; i++) {
   2345     v8::Local<v8::Value> val = v8_num(i);
   2346     v8::Local<v8::String> val_str = val->ToString(env.local()).ToLocalChecked();
   2347     v8::Local<v8::String> name = String::Concat(v8_str("p"), val_str);
   2348 
   2349     templ->Set(name, val);
   2350     templ->Set(val_str, val);
   2351   }
   2352 
   2353   CHECK(env->Global()
   2354             ->Set(env.local(), v8_str("F"),
   2355                   fun_F->GetFunction(env.local()).ToLocalChecked())
   2356             .FromJust());
   2357 
   2358   v8::Local<v8::Script> script = v8_compile("o = new F()");
   2359 
   2360   for (int i = 0; i < 100; i++) {
   2361     v8::HandleScope scope(isolate);
   2362     script->Run(env.local()).ToLocalChecked();
   2363   }
   2364   v8::Local<v8::Object> object = script->Run(env.local())
   2365                                      .ToLocalChecked()
   2366                                      ->ToObject(env.local())
   2367                                      .ToLocalChecked();
   2368 
   2369   CHECK_EQ(15.2, CompileRun("o.knurd1")->NumberValue(env.local()).FromJust());
   2370   CHECK_EQ(15.2, CompileRun("o.knurd2")->NumberValue(env.local()).FromJust());
   2371   CHECK_EQ(15.2, CompileRun("o.knurd3")->NumberValue(env.local()).FromJust());
   2372 
   2373   CHECK_EQ(900, CompileRun("o.nirk1")->IntegerValue(env.local()).FromJust());
   2374   CHECK_EQ(900, CompileRun("o.nirk2")->IntegerValue(env.local()).FromJust());
   2375   CHECK_EQ(900, CompileRun("o.nirk3")->IntegerValue(env.local()).FromJust());
   2376 
   2377   CHECK_EQ(560, CompileRun("o.rino1")->IntegerValue(env.local()).FromJust());
   2378   CHECK_EQ(560, CompileRun("o.rino2")->IntegerValue(env.local()).FromJust());
   2379   CHECK_EQ(560, CompileRun("o.rino3")->IntegerValue(env.local()).FromJust());
   2380 
   2381   for (int i = 0; i < kDataPropertiesNumber; i++) {
   2382     v8::Local<v8::Value> val = v8_num(i);
   2383     v8::Local<v8::String> val_str = val->ToString(env.local()).ToLocalChecked();
   2384     v8::Local<v8::String> name = String::Concat(v8_str("p"), val_str);
   2385 
   2386     CHECK_EQ(i, object->Get(env.local(), name)
   2387                     .ToLocalChecked()
   2388                     ->IntegerValue(env.local())
   2389                     .FromJust());
   2390     CHECK_EQ(i, object->Get(env.local(), val)
   2391                     .ToLocalChecked()
   2392                     ->IntegerValue(env.local())
   2393                     .FromJust());
   2394   }
   2395 }
   2396 
   2397 
   2398 // Helper functions for Interceptor/Accessor interaction tests
   2399 
   2400 void SimpleAccessorGetter(Local<String> name,
   2401                           const v8::PropertyCallbackInfo<v8::Value>& info) {
   2402   Local<Object> self = Local<Object>::Cast(info.This());
   2403   info.GetReturnValue().Set(self->Get(info.GetIsolate()->GetCurrentContext(),
   2404                                       String::Concat(v8_str("accessor_"), name))
   2405                                 .ToLocalChecked());
   2406 }
   2407 
   2408 void SimpleAccessorSetter(Local<String> name, Local<Value> value,
   2409                           const v8::PropertyCallbackInfo<void>& info) {
   2410   Local<Object> self = Local<Object>::Cast(info.This());
   2411   CHECK(self->Set(info.GetIsolate()->GetCurrentContext(),
   2412                   String::Concat(v8_str("accessor_"), name), value)
   2413             .FromJust());
   2414 }
   2415 
   2416 void SymbolAccessorGetter(Local<Name> name,
   2417                           const v8::PropertyCallbackInfo<v8::Value>& info) {
   2418   CHECK(name->IsSymbol());
   2419   Local<Symbol> sym = Local<Symbol>::Cast(name);
   2420   if (sym->Name()->IsUndefined())
   2421     return;
   2422   SimpleAccessorGetter(Local<String>::Cast(sym->Name()), info);
   2423 }
   2424 
   2425 void SymbolAccessorSetter(Local<Name> name, Local<Value> value,
   2426                           const v8::PropertyCallbackInfo<void>& info) {
   2427   CHECK(name->IsSymbol());
   2428   Local<Symbol> sym = Local<Symbol>::Cast(name);
   2429   if (sym->Name()->IsUndefined())
   2430     return;
   2431   SimpleAccessorSetter(Local<String>::Cast(sym->Name()), value, info);
   2432 }
   2433 
   2434 void SymbolAccessorGetterReturnsDefault(
   2435     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   2436   CHECK(name->IsSymbol());
   2437   Local<Symbol> sym = Local<Symbol>::Cast(name);
   2438   if (sym->Name()->IsUndefined()) return;
   2439   info.GetReturnValue().Set(info.Data());
   2440 }
   2441 
   2442 static void ThrowingSymbolAccessorGetter(
   2443     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   2444   info.GetReturnValue().Set(info.GetIsolate()->ThrowException(name));
   2445 }
   2446 
   2447 
   2448 THREADED_TEST(AccessorIsPreservedOnAttributeChange) {
   2449   v8::Isolate* isolate = CcTest::isolate();
   2450   v8::HandleScope scope(isolate);
   2451   LocalContext env;
   2452   v8::Local<v8::Value> res = CompileRun("var a = []; a;");
   2453   i::Handle<i::JSReceiver> a(v8::Utils::OpenHandle(v8::Object::Cast(*res)));
   2454   CHECK(a->map()->instance_descriptors()->IsFixedArray());
   2455   CHECK_GT(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
   2456   CompileRun("Object.defineProperty(a, 'length', { writable: false });");
   2457   CHECK_EQ(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
   2458   // But we should still have an AccessorInfo.
   2459   i::Handle<i::String> name(v8::Utils::OpenHandle(*v8_str("length")));
   2460   i::LookupIterator it(a, name, i::LookupIterator::OWN_SKIP_INTERCEPTOR);
   2461   CHECK_EQ(i::LookupIterator::ACCESSOR, it.state());
   2462   CHECK(it.GetAccessors()->IsAccessorInfo());
   2463 }
   2464 
   2465 
   2466 THREADED_TEST(UndefinedIsNotEnumerable) {
   2467   LocalContext env;
   2468   v8::HandleScope scope(env->GetIsolate());
   2469   v8::Local<Value> result = CompileRun("this.propertyIsEnumerable(undefined)");
   2470   CHECK(result->IsFalse());
   2471 }
   2472 
   2473 
   2474 v8::Local<Script> call_recursively_script;
   2475 static const int kTargetRecursionDepth = 150;  // near maximum
   2476 
   2477 
   2478 static void CallScriptRecursivelyCall(
   2479     const v8::FunctionCallbackInfo<v8::Value>& args) {
   2480   ApiTestFuzzer::Fuzz();
   2481   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   2482   int depth = args.This()
   2483                   ->Get(context, v8_str("depth"))
   2484                   .ToLocalChecked()
   2485                   ->Int32Value(context)
   2486                   .FromJust();
   2487   if (depth == kTargetRecursionDepth) return;
   2488   CHECK(args.This()
   2489             ->Set(context, v8_str("depth"),
   2490                   v8::Integer::New(args.GetIsolate(), depth + 1))
   2491             .FromJust());
   2492   args.GetReturnValue().Set(
   2493       call_recursively_script->Run(context).ToLocalChecked());
   2494 }
   2495 
   2496 
   2497 static void CallFunctionRecursivelyCall(
   2498     const v8::FunctionCallbackInfo<v8::Value>& args) {
   2499   ApiTestFuzzer::Fuzz();
   2500   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   2501   int depth = args.This()
   2502                   ->Get(context, v8_str("depth"))
   2503                   .ToLocalChecked()
   2504                   ->Int32Value(context)
   2505                   .FromJust();
   2506   if (depth == kTargetRecursionDepth) {
   2507     printf("[depth = %d]\n", depth);
   2508     return;
   2509   }
   2510   CHECK(args.This()
   2511             ->Set(context, v8_str("depth"),
   2512                   v8::Integer::New(args.GetIsolate(), depth + 1))
   2513             .FromJust());
   2514   v8::Local<Value> function =
   2515       args.This()
   2516           ->Get(context, v8_str("callFunctionRecursively"))
   2517           .ToLocalChecked();
   2518   args.GetReturnValue().Set(function.As<Function>()
   2519                                 ->Call(context, args.This(), 0, NULL)
   2520                                 .ToLocalChecked());
   2521 }
   2522 
   2523 
   2524 THREADED_TEST(DeepCrossLanguageRecursion) {
   2525   v8::Isolate* isolate = CcTest::isolate();
   2526   v8::HandleScope scope(isolate);
   2527   v8::Local<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
   2528   global->Set(v8_str("callScriptRecursively"),
   2529               v8::FunctionTemplate::New(isolate, CallScriptRecursivelyCall));
   2530   global->Set(v8_str("callFunctionRecursively"),
   2531               v8::FunctionTemplate::New(isolate, CallFunctionRecursivelyCall));
   2532   LocalContext env(NULL, global);
   2533 
   2534   CHECK(env->Global()
   2535             ->Set(env.local(), v8_str("depth"), v8::Integer::New(isolate, 0))
   2536             .FromJust());
   2537   call_recursively_script = v8_compile("callScriptRecursively()");
   2538   call_recursively_script->Run(env.local()).ToLocalChecked();
   2539   call_recursively_script = v8::Local<Script>();
   2540 
   2541   CHECK(env->Global()
   2542             ->Set(env.local(), v8_str("depth"), v8::Integer::New(isolate, 0))
   2543             .FromJust());
   2544   CompileRun("callFunctionRecursively()");
   2545 }
   2546 
   2547 
   2548 static void ThrowingPropertyHandlerGet(
   2549     Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
   2550   // Since this interceptor is used on "with" objects, the runtime will look up
   2551   // @@unscopables.  Punt.
   2552   if (key->IsSymbol()) return;
   2553   ApiTestFuzzer::Fuzz();
   2554   info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
   2555 }
   2556 
   2557 
   2558 static void ThrowingPropertyHandlerSet(
   2559     Local<Name> key, Local<Value>,
   2560     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2561   info.GetIsolate()->ThrowException(key);
   2562   info.GetReturnValue().SetUndefined();  // not the same as empty handle
   2563 }
   2564 
   2565 
   2566 THREADED_TEST(CallbackExceptionRegression) {
   2567   v8::Isolate* isolate = CcTest::isolate();
   2568   v8::HandleScope scope(isolate);
   2569   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
   2570   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(
   2571       ThrowingPropertyHandlerGet, ThrowingPropertyHandlerSet));
   2572   LocalContext env;
   2573   CHECK(env->Global()
   2574             ->Set(env.local(), v8_str("obj"),
   2575                   obj->NewInstance(env.local()).ToLocalChecked())
   2576             .FromJust());
   2577   v8::Local<Value> otto =
   2578       CompileRun("try { with (obj) { otto; } } catch (e) { e; }");
   2579   CHECK(v8_str("otto")->Equals(env.local(), otto).FromJust());
   2580   v8::Local<Value> netto =
   2581       CompileRun("try { with (obj) { netto = 4; } } catch (e) { e; }");
   2582   CHECK(v8_str("netto")->Equals(env.local(), netto).FromJust());
   2583 }
   2584 
   2585 
   2586 THREADED_TEST(FunctionPrototype) {
   2587   v8::Isolate* isolate = CcTest::isolate();
   2588   v8::HandleScope scope(isolate);
   2589   Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(isolate);
   2590   Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
   2591   LocalContext env;
   2592   CHECK(env->Global()
   2593             ->Set(env.local(), v8_str("Foo"),
   2594                   Foo->GetFunction(env.local()).ToLocalChecked())
   2595             .FromJust());
   2596   Local<Script> script = v8_compile("Foo.prototype.plak");
   2597   CHECK_EQ(v8_run_int32value(script), 321);
   2598 }
   2599 
   2600 
   2601 THREADED_TEST(InternalFields) {
   2602   LocalContext env;
   2603   v8::Isolate* isolate = env->GetIsolate();
   2604   v8::HandleScope scope(isolate);
   2605 
   2606   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   2607   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
   2608   instance_templ->SetInternalFieldCount(1);
   2609   Local<v8::Object> obj = templ->GetFunction(env.local())
   2610                               .ToLocalChecked()
   2611                               ->NewInstance(env.local())
   2612                               .ToLocalChecked();
   2613   CHECK_EQ(1, obj->InternalFieldCount());
   2614   CHECK(obj->GetInternalField(0)->IsUndefined());
   2615   obj->SetInternalField(0, v8_num(17));
   2616   CHECK_EQ(17, obj->GetInternalField(0)->Int32Value(env.local()).FromJust());
   2617 }
   2618 
   2619 
   2620 THREADED_TEST(GlobalObjectInternalFields) {
   2621   v8::Isolate* isolate = CcTest::isolate();
   2622   v8::HandleScope scope(isolate);
   2623   Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
   2624   global_template->SetInternalFieldCount(1);
   2625   LocalContext env(NULL, global_template);
   2626   v8::Local<v8::Object> global_proxy = env->Global();
   2627   v8::Local<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
   2628   CHECK_EQ(1, global->InternalFieldCount());
   2629   CHECK(global->GetInternalField(0)->IsUndefined());
   2630   global->SetInternalField(0, v8_num(17));
   2631   CHECK_EQ(17, global->GetInternalField(0)->Int32Value(env.local()).FromJust());
   2632 }
   2633 
   2634 
   2635 THREADED_TEST(GlobalObjectHasRealIndexedProperty) {
   2636   LocalContext env;
   2637   v8::HandleScope scope(CcTest::isolate());
   2638 
   2639   v8::Local<v8::Object> global = env->Global();
   2640   CHECK(global->Set(env.local(), 0, v8_str("value")).FromJust());
   2641   CHECK(global->HasRealIndexedProperty(env.local(), 0).FromJust());
   2642 }
   2643 
   2644 
   2645 static void CheckAlignedPointerInInternalField(Local<v8::Object> obj,
   2646                                                void* value) {
   2647   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
   2648   obj->SetAlignedPointerInInternalField(0, value);
   2649   CcTest::heap()->CollectAllGarbage();
   2650   CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
   2651 }
   2652 
   2653 
   2654 THREADED_TEST(InternalFieldsAlignedPointers) {
   2655   LocalContext env;
   2656   v8::Isolate* isolate = env->GetIsolate();
   2657   v8::HandleScope scope(isolate);
   2658 
   2659   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   2660   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
   2661   instance_templ->SetInternalFieldCount(1);
   2662   Local<v8::Object> obj = templ->GetFunction(env.local())
   2663                               .ToLocalChecked()
   2664                               ->NewInstance(env.local())
   2665                               .ToLocalChecked();
   2666   CHECK_EQ(1, obj->InternalFieldCount());
   2667 
   2668   CheckAlignedPointerInInternalField(obj, NULL);
   2669 
   2670   int* heap_allocated = new int[100];
   2671   CheckAlignedPointerInInternalField(obj, heap_allocated);
   2672   delete[] heap_allocated;
   2673 
   2674   int stack_allocated[100];
   2675   CheckAlignedPointerInInternalField(obj, stack_allocated);
   2676 
   2677   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
   2678   CheckAlignedPointerInInternalField(obj, huge);
   2679 
   2680   v8::Global<v8::Object> persistent(isolate, obj);
   2681   CHECK_EQ(1, Object::InternalFieldCount(persistent));
   2682   CHECK_EQ(huge, Object::GetAlignedPointerFromInternalField(persistent, 0));
   2683 }
   2684 
   2685 
   2686 static void CheckAlignedPointerInEmbedderData(LocalContext* env, int index,
   2687                                               void* value) {
   2688   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
   2689   (*env)->SetAlignedPointerInEmbedderData(index, value);
   2690   CcTest::heap()->CollectAllGarbage();
   2691   CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
   2692 }
   2693 
   2694 
   2695 static void* AlignedTestPointer(int i) {
   2696   return reinterpret_cast<void*>(i * 1234);
   2697 }
   2698 
   2699 
   2700 THREADED_TEST(EmbedderDataAlignedPointers) {
   2701   LocalContext env;
   2702   v8::HandleScope scope(env->GetIsolate());
   2703 
   2704   CheckAlignedPointerInEmbedderData(&env, 0, NULL);
   2705 
   2706   int* heap_allocated = new int[100];
   2707   CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
   2708   delete[] heap_allocated;
   2709 
   2710   int stack_allocated[100];
   2711   CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
   2712 
   2713   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
   2714   CheckAlignedPointerInEmbedderData(&env, 3, huge);
   2715 
   2716   // Test growing of the embedder data's backing store.
   2717   for (int i = 0; i < 100; i++) {
   2718     env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
   2719   }
   2720   CcTest::heap()->CollectAllGarbage();
   2721   for (int i = 0; i < 100; i++) {
   2722     CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
   2723   }
   2724 }
   2725 
   2726 
   2727 static void CheckEmbedderData(LocalContext* env, int index,
   2728                               v8::Local<Value> data) {
   2729   (*env)->SetEmbedderData(index, data);
   2730   CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
   2731 }
   2732 
   2733 
   2734 THREADED_TEST(EmbedderData) {
   2735   LocalContext env;
   2736   v8::Isolate* isolate = env->GetIsolate();
   2737   v8::HandleScope scope(isolate);
   2738 
   2739   CheckEmbedderData(&env, 3, v8_str("The quick brown fox jumps"));
   2740   CheckEmbedderData(&env, 2, v8_str("over the lazy dog."));
   2741   CheckEmbedderData(&env, 1, v8::Number::New(isolate, 1.2345));
   2742   CheckEmbedderData(&env, 0, v8::Boolean::New(isolate, true));
   2743 }
   2744 
   2745 
   2746 THREADED_TEST(IdentityHash) {
   2747   LocalContext env;
   2748   v8::Isolate* isolate = env->GetIsolate();
   2749   v8::HandleScope scope(isolate);
   2750 
   2751   // Ensure that the test starts with an fresh heap to test whether the hash
   2752   // code is based on the address.
   2753   CcTest::heap()->CollectAllGarbage();
   2754   Local<v8::Object> obj = v8::Object::New(isolate);
   2755   int hash = obj->GetIdentityHash();
   2756   int hash1 = obj->GetIdentityHash();
   2757   CHECK_EQ(hash, hash1);
   2758   int hash2 = v8::Object::New(isolate)->GetIdentityHash();
   2759   // Since the identity hash is essentially a random number two consecutive
   2760   // objects should not be assigned the same hash code. If the test below fails
   2761   // the random number generator should be evaluated.
   2762   CHECK_NE(hash, hash2);
   2763   CcTest::heap()->CollectAllGarbage();
   2764   int hash3 = v8::Object::New(isolate)->GetIdentityHash();
   2765   // Make sure that the identity hash is not based on the initial address of
   2766   // the object alone. If the test below fails the random number generator
   2767   // should be evaluated.
   2768   CHECK_NE(hash, hash3);
   2769   int hash4 = obj->GetIdentityHash();
   2770   CHECK_EQ(hash, hash4);
   2771 
   2772   // Check identity hashes behaviour in the presence of JS accessors.
   2773   // Put a getter for 'v8::IdentityHash' on the Object's prototype:
   2774   {
   2775     CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
   2776     Local<v8::Object> o1 = v8::Object::New(isolate);
   2777     Local<v8::Object> o2 = v8::Object::New(isolate);
   2778     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
   2779   }
   2780   {
   2781     CompileRun(
   2782         "function cnst() { return 42; };\n"
   2783         "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
   2784     Local<v8::Object> o1 = v8::Object::New(isolate);
   2785     Local<v8::Object> o2 = v8::Object::New(isolate);
   2786     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
   2787   }
   2788 }
   2789 
   2790 
   2791 void GlobalProxyIdentityHash(bool set_in_js) {
   2792   LocalContext env;
   2793   v8::Isolate* isolate = env->GetIsolate();
   2794   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   2795   v8::HandleScope scope(isolate);
   2796   Local<Object> global_proxy = env->Global();
   2797   i::Handle<i::Object> i_global_proxy = v8::Utils::OpenHandle(*global_proxy);
   2798   CHECK(env->Global()
   2799             ->Set(env.local(), v8_str("global"), global_proxy)
   2800             .FromJust());
   2801   int32_t hash1;
   2802   if (set_in_js) {
   2803     CompileRun("var m = new Set(); m.add(global);");
   2804     i::Object* original_hash = i_global_proxy->GetHash();
   2805     CHECK(original_hash->IsSmi());
   2806     hash1 = i::Smi::cast(original_hash)->value();
   2807   } else {
   2808     hash1 = i::Object::GetOrCreateHash(i_isolate, i_global_proxy)->value();
   2809   }
   2810   // Hash should be retained after being detached.
   2811   env->DetachGlobal();
   2812   int hash2 = global_proxy->GetIdentityHash();
   2813   CHECK_EQ(hash1, hash2);
   2814   {
   2815     // Re-attach global proxy to a new context, hash should stay the same.
   2816     LocalContext env2(NULL, Local<ObjectTemplate>(), global_proxy);
   2817     int hash3 = global_proxy->GetIdentityHash();
   2818     CHECK_EQ(hash1, hash3);
   2819   }
   2820 }
   2821 
   2822 
   2823 THREADED_TEST(GlobalProxyIdentityHash) {
   2824   GlobalProxyIdentityHash(true);
   2825   GlobalProxyIdentityHash(false);
   2826 }
   2827 
   2828 
   2829 TEST(SymbolIdentityHash) {
   2830   LocalContext env;
   2831   v8::Isolate* isolate = env->GetIsolate();
   2832   v8::HandleScope scope(isolate);
   2833 
   2834   {
   2835     Local<v8::Symbol> symbol = v8::Symbol::New(isolate);
   2836     int hash = symbol->GetIdentityHash();
   2837     int hash1 = symbol->GetIdentityHash();
   2838     CHECK_EQ(hash, hash1);
   2839     CcTest::heap()->CollectAllGarbage();
   2840     int hash3 = symbol->GetIdentityHash();
   2841     CHECK_EQ(hash, hash3);
   2842   }
   2843 
   2844   {
   2845     v8::Local<v8::Symbol> js_symbol =
   2846         CompileRun("Symbol('foo')").As<v8::Symbol>();
   2847     int hash = js_symbol->GetIdentityHash();
   2848     int hash1 = js_symbol->GetIdentityHash();
   2849     CHECK_EQ(hash, hash1);
   2850     CcTest::heap()->CollectAllGarbage();
   2851     int hash3 = js_symbol->GetIdentityHash();
   2852     CHECK_EQ(hash, hash3);
   2853   }
   2854 }
   2855 
   2856 
   2857 TEST(StringIdentityHash) {
   2858   LocalContext env;
   2859   v8::Isolate* isolate = env->GetIsolate();
   2860   v8::HandleScope scope(isolate);
   2861 
   2862   Local<v8::String> str = v8_str("str1");
   2863   int hash = str->GetIdentityHash();
   2864   int hash1 = str->GetIdentityHash();
   2865   CHECK_EQ(hash, hash1);
   2866   CcTest::heap()->CollectAllGarbage();
   2867   int hash3 = str->GetIdentityHash();
   2868   CHECK_EQ(hash, hash3);
   2869 
   2870   Local<v8::String> str2 = v8_str("str1");
   2871   int hash4 = str2->GetIdentityHash();
   2872   CHECK_EQ(hash, hash4);
   2873 }
   2874 
   2875 
   2876 THREADED_TEST(SymbolProperties) {
   2877   LocalContext env;
   2878   v8::Isolate* isolate = env->GetIsolate();
   2879   v8::HandleScope scope(isolate);
   2880 
   2881   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   2882   v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
   2883   v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, v8_str("my-symbol"));
   2884   v8::Local<v8::Symbol> sym3 = v8::Symbol::New(isolate, v8_str("sym3"));
   2885 
   2886   CcTest::heap()->CollectAllGarbage();
   2887 
   2888   // Check basic symbol functionality.
   2889   CHECK(sym1->IsSymbol());
   2890   CHECK(sym2->IsSymbol());
   2891   CHECK(!obj->IsSymbol());
   2892 
   2893   CHECK(sym1->Equals(env.local(), sym1).FromJust());
   2894   CHECK(sym2->Equals(env.local(), sym2).FromJust());
   2895   CHECK(!sym1->Equals(env.local(), sym2).FromJust());
   2896   CHECK(!sym2->Equals(env.local(), sym1).FromJust());
   2897   CHECK(sym1->StrictEquals(sym1));
   2898   CHECK(sym2->StrictEquals(sym2));
   2899   CHECK(!sym1->StrictEquals(sym2));
   2900   CHECK(!sym2->StrictEquals(sym1));
   2901 
   2902   CHECK(sym2->Name()->Equals(env.local(), v8_str("my-symbol")).FromJust());
   2903 
   2904   v8::Local<v8::Value> sym_val = sym2;
   2905   CHECK(sym_val->IsSymbol());
   2906   CHECK(sym_val->Equals(env.local(), sym2).FromJust());
   2907   CHECK(sym_val->StrictEquals(sym2));
   2908   CHECK(v8::Symbol::Cast(*sym_val)->Equals(env.local(), sym2).FromJust());
   2909 
   2910   v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
   2911   CHECK(sym_obj->IsSymbolObject());
   2912   CHECK(!sym2->IsSymbolObject());
   2913   CHECK(!obj->IsSymbolObject());
   2914   CHECK(sym_obj->Equals(env.local(), sym2).FromJust());
   2915   CHECK(!sym_obj->StrictEquals(sym2));
   2916   CHECK(v8::SymbolObject::Cast(*sym_obj)
   2917             ->Equals(env.local(), sym_obj)
   2918             .FromJust());
   2919   CHECK(v8::SymbolObject::Cast(*sym_obj)
   2920             ->ValueOf()
   2921             ->Equals(env.local(), sym2)
   2922             .FromJust());
   2923 
   2924   // Make sure delete of a non-existent symbol property works.
   2925   CHECK(obj->Delete(env.local(), sym1).FromJust());
   2926   CHECK(!obj->Has(env.local(), sym1).FromJust());
   2927 
   2928   CHECK(
   2929       obj->Set(env.local(), sym1, v8::Integer::New(isolate, 1503)).FromJust());
   2930   CHECK(obj->Has(env.local(), sym1).FromJust());
   2931   CHECK_EQ(1503, obj->Get(env.local(), sym1)
   2932                      .ToLocalChecked()
   2933                      ->Int32Value(env.local())
   2934                      .FromJust());
   2935   CHECK(
   2936       obj->Set(env.local(), sym1, v8::Integer::New(isolate, 2002)).FromJust());
   2937   CHECK(obj->Has(env.local(), sym1).FromJust());
   2938   CHECK_EQ(2002, obj->Get(env.local(), sym1)
   2939                      .ToLocalChecked()
   2940                      ->Int32Value(env.local())
   2941                      .FromJust());
   2942   CHECK_EQ(v8::None, obj->GetPropertyAttributes(env.local(), sym1).FromJust());
   2943 
   2944   CHECK_EQ(0u,
   2945            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   2946   unsigned num_props =
   2947       obj->GetPropertyNames(env.local()).ToLocalChecked()->Length();
   2948   CHECK(obj->Set(env.local(), v8_str("bla"), v8::Integer::New(isolate, 20))
   2949             .FromJust());
   2950   CHECK_EQ(1u,
   2951            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   2952   CHECK_EQ(num_props + 1,
   2953            obj->GetPropertyNames(env.local()).ToLocalChecked()->Length());
   2954 
   2955   CcTest::heap()->CollectAllGarbage();
   2956 
   2957   CHECK(obj->SetAccessor(env.local(), sym3, SymbolAccessorGetter,
   2958                          SymbolAccessorSetter)
   2959             .FromJust());
   2960   CHECK(obj->Get(env.local(), sym3).ToLocalChecked()->IsUndefined());
   2961   CHECK(obj->Set(env.local(), sym3, v8::Integer::New(isolate, 42)).FromJust());
   2962   CHECK(obj->Get(env.local(), sym3)
   2963             .ToLocalChecked()
   2964             ->Equals(env.local(), v8::Integer::New(isolate, 42))
   2965             .FromJust());
   2966   CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
   2967             .ToLocalChecked()
   2968             ->Equals(env.local(), v8::Integer::New(isolate, 42))
   2969             .FromJust());
   2970 
   2971   // Add another property and delete it afterwards to force the object in
   2972   // slow case.
   2973   CHECK(
   2974       obj->Set(env.local(), sym2, v8::Integer::New(isolate, 2008)).FromJust());
   2975   CHECK_EQ(2002, obj->Get(env.local(), sym1)
   2976                      .ToLocalChecked()
   2977                      ->Int32Value(env.local())
   2978                      .FromJust());
   2979   CHECK_EQ(2008, obj->Get(env.local(), sym2)
   2980                      .ToLocalChecked()
   2981                      ->Int32Value(env.local())
   2982                      .FromJust());
   2983   CHECK_EQ(2002, obj->Get(env.local(), sym1)
   2984                      .ToLocalChecked()
   2985                      ->Int32Value(env.local())
   2986                      .FromJust());
   2987   CHECK_EQ(2u,
   2988            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   2989 
   2990   CHECK(obj->Has(env.local(), sym1).FromJust());
   2991   CHECK(obj->Has(env.local(), sym2).FromJust());
   2992   CHECK(obj->Has(env.local(), sym3).FromJust());
   2993   CHECK(obj->Has(env.local(), v8_str("accessor_sym3")).FromJust());
   2994   CHECK(obj->Delete(env.local(), sym2).FromJust());
   2995   CHECK(obj->Has(env.local(), sym1).FromJust());
   2996   CHECK(!obj->Has(env.local(), sym2).FromJust());
   2997   CHECK(obj->Has(env.local(), sym3).FromJust());
   2998   CHECK(obj->Has(env.local(), v8_str("accessor_sym3")).FromJust());
   2999   CHECK_EQ(2002, obj->Get(env.local(), sym1)
   3000                      .ToLocalChecked()
   3001                      ->Int32Value(env.local())
   3002                      .FromJust());
   3003   CHECK(obj->Get(env.local(), sym3)
   3004             .ToLocalChecked()
   3005             ->Equals(env.local(), v8::Integer::New(isolate, 42))
   3006             .FromJust());
   3007   CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
   3008             .ToLocalChecked()
   3009             ->Equals(env.local(), v8::Integer::New(isolate, 42))
   3010             .FromJust());
   3011   CHECK_EQ(2u,
   3012            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   3013 
   3014   // Symbol properties are inherited.
   3015   v8::Local<v8::Object> child = v8::Object::New(isolate);
   3016   CHECK(child->SetPrototype(env.local(), obj).FromJust());
   3017   CHECK(child->Has(env.local(), sym1).FromJust());
   3018   CHECK_EQ(2002, child->Get(env.local(), sym1)
   3019                      .ToLocalChecked()
   3020                      ->Int32Value(env.local())
   3021                      .FromJust());
   3022   CHECK(obj->Get(env.local(), sym3)
   3023             .ToLocalChecked()
   3024             ->Equals(env.local(), v8::Integer::New(isolate, 42))
   3025             .FromJust());
   3026   CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
   3027             .ToLocalChecked()
   3028             ->Equals(env.local(), v8::Integer::New(isolate, 42))
   3029             .FromJust());
   3030   CHECK_EQ(0u,
   3031            child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   3032 }
   3033 
   3034 
   3035 THREADED_TEST(SymbolTemplateProperties) {
   3036   LocalContext env;
   3037   v8::Isolate* isolate = env->GetIsolate();
   3038   v8::HandleScope scope(isolate);
   3039   v8::Local<v8::FunctionTemplate> foo = v8::FunctionTemplate::New(isolate);
   3040   v8::Local<v8::Name> name = v8::Symbol::New(isolate);
   3041   CHECK(!name.IsEmpty());
   3042   foo->PrototypeTemplate()->Set(name, v8::FunctionTemplate::New(isolate));
   3043   v8::Local<v8::Object> new_instance =
   3044       foo->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
   3045   CHECK(!new_instance.IsEmpty());
   3046   CHECK(new_instance->Has(env.local(), name).FromJust());
   3047 }
   3048 
   3049 
   3050 THREADED_TEST(PrivatePropertiesOnProxies) {
   3051   LocalContext env;
   3052   v8::Isolate* isolate = env->GetIsolate();
   3053   v8::HandleScope scope(isolate);
   3054 
   3055   v8::Local<v8::Object> target = CompileRun("({})").As<v8::Object>();
   3056   v8::Local<v8::Object> handler = CompileRun("({})").As<v8::Object>();
   3057 
   3058   v8::Local<v8::Proxy> proxy =
   3059       v8::Proxy::New(env.local(), target, handler).ToLocalChecked();
   3060 
   3061   v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
   3062   v8::Local<v8::Private> priv2 =
   3063       v8::Private::New(isolate, v8_str("my-private"));
   3064 
   3065   CcTest::heap()->CollectAllGarbage();
   3066 
   3067   CHECK(priv2->Name()
   3068             ->Equals(env.local(),
   3069                      v8::String::NewFromUtf8(isolate, "my-private",
   3070                                              v8::NewStringType::kNormal)
   3071                          .ToLocalChecked())
   3072             .FromJust());
   3073 
   3074   // Make sure delete of a non-existent private symbol property works.
   3075   proxy->DeletePrivate(env.local(), priv1).FromJust();
   3076   CHECK(!proxy->HasPrivate(env.local(), priv1).FromJust());
   3077 
   3078   CHECK(proxy->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 1503))
   3079             .FromJust());
   3080   CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
   3081   CHECK_EQ(1503, proxy->GetPrivate(env.local(), priv1)
   3082                      .ToLocalChecked()
   3083                      ->Int32Value(env.local())
   3084                      .FromJust());
   3085   CHECK(proxy->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 2002))
   3086             .FromJust());
   3087   CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
   3088   CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
   3089                      .ToLocalChecked()
   3090                      ->Int32Value(env.local())
   3091                      .FromJust());
   3092 
   3093   CHECK_EQ(0u,
   3094            proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   3095   unsigned num_props =
   3096       proxy->GetPropertyNames(env.local()).ToLocalChecked()->Length();
   3097   CHECK(proxy->Set(env.local(), v8::String::NewFromUtf8(
   3098                                     isolate, "bla", v8::NewStringType::kNormal)
   3099                                     .ToLocalChecked(),
   3100                    v8::Integer::New(isolate, 20))
   3101             .FromJust());
   3102   CHECK_EQ(1u,
   3103            proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   3104   CHECK_EQ(num_props + 1,
   3105            proxy->GetPropertyNames(env.local()).ToLocalChecked()->Length());
   3106 
   3107   CcTest::heap()->CollectAllGarbage();
   3108 
   3109   // Add another property and delete it afterwards to force the object in
   3110   // slow case.
   3111   CHECK(proxy->SetPrivate(env.local(), priv2, v8::Integer::New(isolate, 2008))
   3112             .FromJust());
   3113   CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
   3114                      .ToLocalChecked()
   3115                      ->Int32Value(env.local())
   3116                      .FromJust());
   3117   CHECK_EQ(2008, proxy->GetPrivate(env.local(), priv2)
   3118                      .ToLocalChecked()
   3119                      ->Int32Value(env.local())
   3120                      .FromJust());
   3121   CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
   3122                      .ToLocalChecked()
   3123                      ->Int32Value(env.local())
   3124                      .FromJust());
   3125   CHECK_EQ(1u,
   3126            proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   3127 
   3128   CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
   3129   CHECK(proxy->HasPrivate(env.local(), priv2).FromJust());
   3130   CHECK(proxy->DeletePrivate(env.local(), priv2).FromJust());
   3131   CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
   3132   CHECK(!proxy->HasPrivate(env.local(), priv2).FromJust());
   3133   CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
   3134                      .ToLocalChecked()
   3135                      ->Int32Value(env.local())
   3136                      .FromJust());
   3137   CHECK_EQ(1u,
   3138            proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   3139 
   3140   // Private properties are not inherited (for the time being).
   3141   v8::Local<v8::Object> child = v8::Object::New(isolate);
   3142   CHECK(child->SetPrototype(env.local(), proxy).FromJust());
   3143   CHECK(!child->HasPrivate(env.local(), priv1).FromJust());
   3144   CHECK_EQ(0u,
   3145            child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   3146 }
   3147 
   3148 
   3149 THREADED_TEST(PrivateProperties) {
   3150   LocalContext env;
   3151   v8::Isolate* isolate = env->GetIsolate();
   3152   v8::HandleScope scope(isolate);
   3153 
   3154   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   3155   v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
   3156   v8::Local<v8::Private> priv2 =
   3157       v8::Private::New(isolate, v8_str("my-private"));
   3158 
   3159   CcTest::heap()->CollectAllGarbage();
   3160 
   3161   CHECK(priv2->Name()
   3162             ->Equals(env.local(),
   3163                      v8::String::NewFromUtf8(isolate, "my-private",
   3164                                              v8::NewStringType::kNormal)
   3165                          .ToLocalChecked())
   3166             .FromJust());
   3167 
   3168   // Make sure delete of a non-existent private symbol property works.
   3169   obj->DeletePrivate(env.local(), priv1).FromJust();
   3170   CHECK(!obj->HasPrivate(env.local(), priv1).FromJust());
   3171 
   3172   CHECK(obj->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 1503))
   3173             .FromJust());
   3174   CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
   3175   CHECK_EQ(1503, obj->GetPrivate(env.local(), priv1)
   3176                      .ToLocalChecked()
   3177                      ->Int32Value(env.local())
   3178                      .FromJust());
   3179   CHECK(obj->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 2002))
   3180             .FromJust());
   3181   CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
   3182   CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
   3183                      .ToLocalChecked()
   3184                      ->Int32Value(env.local())
   3185                      .FromJust());
   3186 
   3187   CHECK_EQ(0u,
   3188            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   3189   unsigned num_props =
   3190       obj->GetPropertyNames(env.local()).ToLocalChecked()->Length();
   3191   CHECK(obj->Set(env.local(), v8::String::NewFromUtf8(
   3192                                   isolate, "bla", v8::NewStringType::kNormal)
   3193                                   .ToLocalChecked(),
   3194                  v8::Integer::New(isolate, 20))
   3195             .FromJust());
   3196   CHECK_EQ(1u,
   3197            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   3198   CHECK_EQ(num_props + 1,
   3199            obj->GetPropertyNames(env.local()).ToLocalChecked()->Length());
   3200 
   3201   CcTest::heap()->CollectAllGarbage();
   3202 
   3203   // Add another property and delete it afterwards to force the object in
   3204   // slow case.
   3205   CHECK(obj->SetPrivate(env.local(), priv2, v8::Integer::New(isolate, 2008))
   3206             .FromJust());
   3207   CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
   3208                      .ToLocalChecked()
   3209                      ->Int32Value(env.local())
   3210                      .FromJust());
   3211   CHECK_EQ(2008, obj->GetPrivate(env.local(), priv2)
   3212                      .ToLocalChecked()
   3213                      ->Int32Value(env.local())
   3214                      .FromJust());
   3215   CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
   3216                      .ToLocalChecked()
   3217                      ->Int32Value(env.local())
   3218                      .FromJust());
   3219   CHECK_EQ(1u,
   3220            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   3221 
   3222   CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
   3223   CHECK(obj->HasPrivate(env.local(), priv2).FromJust());
   3224   CHECK(obj->DeletePrivate(env.local(), priv2).FromJust());
   3225   CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
   3226   CHECK(!obj->HasPrivate(env.local(), priv2).FromJust());
   3227   CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
   3228                      .ToLocalChecked()
   3229                      ->Int32Value(env.local())
   3230                      .FromJust());
   3231   CHECK_EQ(1u,
   3232            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   3233 
   3234   // Private properties are not inherited (for the time being).
   3235   v8::Local<v8::Object> child = v8::Object::New(isolate);
   3236   CHECK(child->SetPrototype(env.local(), obj).FromJust());
   3237   CHECK(!child->HasPrivate(env.local(), priv1).FromJust());
   3238   CHECK_EQ(0u,
   3239            child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   3240 }
   3241 
   3242 
   3243 THREADED_TEST(GlobalSymbols) {
   3244   LocalContext env;
   3245   v8::Isolate* isolate = env->GetIsolate();
   3246   v8::HandleScope scope(isolate);
   3247 
   3248   v8::Local<String> name = v8_str("my-symbol");
   3249   v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name);
   3250   v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name);
   3251   CHECK(glob2->SameValue(glob));
   3252 
   3253   v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name);
   3254   v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name);
   3255   CHECK(glob_api2->SameValue(glob_api));
   3256   CHECK(!glob_api->SameValue(glob));
   3257 
   3258   v8::Local<v8::Symbol> sym = v8::Symbol::New(isolate, name);
   3259   CHECK(!sym->SameValue(glob));
   3260 
   3261   CompileRun("var sym2 = Symbol.for('my-symbol')");
   3262   v8::Local<Value> sym2 =
   3263       env->Global()->Get(env.local(), v8_str("sym2")).ToLocalChecked();
   3264   CHECK(sym2->SameValue(glob));
   3265   CHECK(!sym2->SameValue(glob_api));
   3266 }
   3267 
   3268 
   3269 static void CheckWellKnownSymbol(v8::Local<v8::Symbol>(*getter)(v8::Isolate*),
   3270                                  const char* name) {
   3271   LocalContext env;
   3272   v8::Isolate* isolate = env->GetIsolate();
   3273   v8::HandleScope scope(isolate);
   3274 
   3275   v8::Local<v8::Symbol> symbol = getter(isolate);
   3276   std::string script = std::string("var sym = ") + name;
   3277   CompileRun(script.c_str());
   3278   v8::Local<Value> value =
   3279       env->Global()->Get(env.local(), v8_str("sym")).ToLocalChecked();
   3280 
   3281   CHECK(!value.IsEmpty());
   3282   CHECK(!symbol.IsEmpty());
   3283   CHECK(value->SameValue(symbol));
   3284 }
   3285 
   3286 
   3287 THREADED_TEST(WellKnownSymbols) {
   3288   CheckWellKnownSymbol(v8::Symbol::GetIterator, "Symbol.iterator");
   3289   CheckWellKnownSymbol(v8::Symbol::GetUnscopables, "Symbol.unscopables");
   3290 }
   3291 
   3292 
   3293 THREADED_TEST(GlobalPrivates) {
   3294   i::FLAG_allow_natives_syntax = true;
   3295   LocalContext env;
   3296   v8::Isolate* isolate = env->GetIsolate();
   3297   v8::HandleScope scope(isolate);
   3298 
   3299   v8::Local<String> name = v8_str("my-private");
   3300   v8::Local<v8::Private> glob = v8::Private::ForApi(isolate, name);
   3301   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   3302   CHECK(obj->SetPrivate(env.local(), glob, v8::Integer::New(isolate, 3))
   3303             .FromJust());
   3304 
   3305   v8::Local<v8::Private> glob2 = v8::Private::ForApi(isolate, name);
   3306   CHECK(obj->HasPrivate(env.local(), glob2).FromJust());
   3307 
   3308   v8::Local<v8::Private> priv = v8::Private::New(isolate, name);
   3309   CHECK(!obj->HasPrivate(env.local(), priv).FromJust());
   3310 
   3311   CompileRun("var intern = %CreatePrivateSymbol('my-private')");
   3312   v8::Local<Value> intern =
   3313       env->Global()->Get(env.local(), v8_str("intern")).ToLocalChecked();
   3314   CHECK(!obj->Has(env.local(), intern).FromJust());
   3315 }
   3316 
   3317 
   3318 class ScopedArrayBufferContents {
   3319  public:
   3320   explicit ScopedArrayBufferContents(const v8::ArrayBuffer::Contents& contents)
   3321       : contents_(contents) {}
   3322   ~ScopedArrayBufferContents() { free(contents_.Data()); }
   3323   void* Data() const { return contents_.Data(); }
   3324   size_t ByteLength() const { return contents_.ByteLength(); }
   3325 
   3326  private:
   3327   const v8::ArrayBuffer::Contents contents_;
   3328 };
   3329 
   3330 template <typename T>
   3331 static void CheckInternalFieldsAreZero(v8::Local<T> value) {
   3332   CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
   3333   for (int i = 0; i < value->InternalFieldCount(); i++) {
   3334     CHECK_EQ(0, value->GetInternalField(i)
   3335                     ->Int32Value(CcTest::isolate()->GetCurrentContext())
   3336                     .FromJust());
   3337   }
   3338 }
   3339 
   3340 
   3341 THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
   3342   LocalContext env;
   3343   v8::Isolate* isolate = env->GetIsolate();
   3344   v8::HandleScope handle_scope(isolate);
   3345 
   3346   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 1024);
   3347   CheckInternalFieldsAreZero(ab);
   3348   CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
   3349   CHECK(!ab->IsExternal());
   3350   CcTest::heap()->CollectAllGarbage();
   3351 
   3352   ScopedArrayBufferContents ab_contents(ab->Externalize());
   3353   CHECK(ab->IsExternal());
   3354 
   3355   CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
   3356   uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
   3357   CHECK(data != NULL);
   3358   CHECK(env->Global()->Set(env.local(), v8_str("ab"), ab).FromJust());
   3359 
   3360   v8::Local<v8::Value> result = CompileRun("ab.byteLength");
   3361   CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
   3362 
   3363   result = CompileRun(
   3364       "var u8 = new Uint8Array(ab);"
   3365       "u8[0] = 0xFF;"
   3366       "u8[1] = 0xAA;"
   3367       "u8.length");
   3368   CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
   3369   CHECK_EQ(0xFF, data[0]);
   3370   CHECK_EQ(0xAA, data[1]);
   3371   data[0] = 0xCC;
   3372   data[1] = 0x11;
   3373   result = CompileRun("u8[0] + u8[1]");
   3374   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
   3375 }
   3376 
   3377 
   3378 THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
   3379   LocalContext env;
   3380   v8::Isolate* isolate = env->GetIsolate();
   3381   v8::HandleScope handle_scope(isolate);
   3382 
   3383 
   3384   v8::Local<v8::Value> result = CompileRun(
   3385       "var ab1 = new ArrayBuffer(2);"
   3386       "var u8_a = new Uint8Array(ab1);"
   3387       "u8_a[0] = 0xAA;"
   3388       "u8_a[1] = 0xFF; u8_a.buffer");
   3389   Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
   3390   CheckInternalFieldsAreZero(ab1);
   3391   CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
   3392   CHECK(!ab1->IsExternal());
   3393   ScopedArrayBufferContents ab1_contents(ab1->Externalize());
   3394   CHECK(ab1->IsExternal());
   3395 
   3396   result = CompileRun("ab1.byteLength");
   3397   CHECK_EQ(2, result->Int32Value(env.local()).FromJust());
   3398   result = CompileRun("u8_a[0]");
   3399   CHECK_EQ(0xAA, result->Int32Value(env.local()).FromJust());
   3400   result = CompileRun("u8_a[1]");
   3401   CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
   3402   result = CompileRun(
   3403       "var u8_b = new Uint8Array(ab1);"
   3404       "u8_b[0] = 0xBB;"
   3405       "u8_a[0]");
   3406   CHECK_EQ(0xBB, result->Int32Value(env.local()).FromJust());
   3407   result = CompileRun("u8_b[1]");
   3408   CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
   3409 
   3410   CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
   3411   uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
   3412   CHECK_EQ(0xBB, ab1_data[0]);
   3413   CHECK_EQ(0xFF, ab1_data[1]);
   3414   ab1_data[0] = 0xCC;
   3415   ab1_data[1] = 0x11;
   3416   result = CompileRun("u8_a[0] + u8_a[1]");
   3417   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
   3418 }
   3419 
   3420 
   3421 THREADED_TEST(ArrayBuffer_External) {
   3422   LocalContext env;
   3423   v8::Isolate* isolate = env->GetIsolate();
   3424   v8::HandleScope handle_scope(isolate);
   3425 
   3426   i::ScopedVector<uint8_t> my_data(100);
   3427   memset(my_data.start(), 0, 100);
   3428   Local<v8::ArrayBuffer> ab3 =
   3429       v8::ArrayBuffer::New(isolate, my_data.start(), 100);
   3430   CheckInternalFieldsAreZero(ab3);
   3431   CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
   3432   CHECK(ab3->IsExternal());
   3433 
   3434   CHECK(env->Global()->Set(env.local(), v8_str("ab3"), ab3).FromJust());
   3435 
   3436   v8::Local<v8::Value> result = CompileRun("ab3.byteLength");
   3437   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
   3438 
   3439   result = CompileRun(
   3440       "var u8_b = new Uint8Array(ab3);"
   3441       "u8_b[0] = 0xBB;"
   3442       "u8_b[1] = 0xCC;"
   3443       "u8_b.length");
   3444   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
   3445   CHECK_EQ(0xBB, my_data[0]);
   3446   CHECK_EQ(0xCC, my_data[1]);
   3447   my_data[0] = 0xCC;
   3448   my_data[1] = 0x11;
   3449   result = CompileRun("u8_b[0] + u8_b[1]");
   3450   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
   3451 }
   3452 
   3453 
   3454 THREADED_TEST(ArrayBuffer_DisableNeuter) {
   3455   LocalContext env;
   3456   v8::Isolate* isolate = env->GetIsolate();
   3457   v8::HandleScope handle_scope(isolate);
   3458 
   3459   i::ScopedVector<uint8_t> my_data(100);
   3460   memset(my_data.start(), 0, 100);
   3461   Local<v8::ArrayBuffer> ab =
   3462       v8::ArrayBuffer::New(isolate, my_data.start(), 100);
   3463   CHECK(ab->IsNeuterable());
   3464 
   3465   i::Handle<i::JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
   3466   buf->set_is_neuterable(false);
   3467 
   3468   CHECK(!ab->IsNeuterable());
   3469 }
   3470 
   3471 
   3472 static void CheckDataViewIsNeutered(v8::Local<v8::DataView> dv) {
   3473   CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
   3474   CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
   3475 }
   3476 
   3477 
   3478 static void CheckIsNeutered(v8::Local<v8::TypedArray> ta) {
   3479   CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
   3480   CHECK_EQ(0, static_cast<int>(ta->Length()));
   3481   CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
   3482 }
   3483 
   3484 
   3485 static void CheckIsTypedArrayVarNeutered(const char* name) {
   3486   i::ScopedVector<char> source(1024);
   3487   i::SNPrintF(source,
   3488               "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
   3489               name, name, name);
   3490   CHECK(CompileRun(source.start())->IsTrue());
   3491   v8::Local<v8::TypedArray> ta =
   3492       v8::Local<v8::TypedArray>::Cast(CompileRun(name));
   3493   CheckIsNeutered(ta);
   3494 }
   3495 
   3496 
   3497 template <typename TypedArray, int kElementSize>
   3498 static Local<TypedArray> CreateAndCheck(Local<v8::ArrayBuffer> ab,
   3499                                         int byteOffset, int length) {
   3500   v8::Local<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
   3501   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
   3502   CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
   3503   CHECK_EQ(length, static_cast<int>(ta->Length()));
   3504   CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
   3505   return ta;
   3506 }
   3507 
   3508 
   3509 THREADED_TEST(ArrayBuffer_NeuteringApi) {
   3510   LocalContext env;
   3511   v8::Isolate* isolate = env->GetIsolate();
   3512   v8::HandleScope handle_scope(isolate);
   3513 
   3514   v8::Local<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1024);
   3515 
   3516   v8::Local<v8::Uint8Array> u8a =
   3517       CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
   3518   v8::Local<v8::Uint8ClampedArray> u8c =
   3519       CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
   3520   v8::Local<v8::Int8Array> i8a =
   3521       CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
   3522 
   3523   v8::Local<v8::Uint16Array> u16a =
   3524       CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
   3525   v8::Local<v8::Int16Array> i16a =
   3526       CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
   3527 
   3528   v8::Local<v8::Uint32Array> u32a =
   3529       CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
   3530   v8::Local<v8::Int32Array> i32a =
   3531       CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
   3532 
   3533   v8::Local<v8::Float32Array> f32a =
   3534       CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
   3535   v8::Local<v8::Float64Array> f64a =
   3536       CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
   3537 
   3538   v8::Local<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
   3539   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
   3540   CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
   3541   CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
   3542 
   3543   ScopedArrayBufferContents contents(buffer->Externalize());
   3544   buffer->Neuter();
   3545   CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
   3546   CheckIsNeutered(u8a);
   3547   CheckIsNeutered(u8c);
   3548   CheckIsNeutered(i8a);
   3549   CheckIsNeutered(u16a);
   3550   CheckIsNeutered(i16a);
   3551   CheckIsNeutered(u32a);
   3552   CheckIsNeutered(i32a);
   3553   CheckIsNeutered(f32a);
   3554   CheckIsNeutered(f64a);
   3555   CheckDataViewIsNeutered(dv);
   3556 }
   3557 
   3558 
   3559 THREADED_TEST(ArrayBuffer_NeuteringScript) {
   3560   LocalContext env;
   3561   v8::Isolate* isolate = env->GetIsolate();
   3562   v8::HandleScope handle_scope(isolate);
   3563 
   3564   CompileRun(
   3565       "var ab = new ArrayBuffer(1024);"
   3566       "var u8a = new Uint8Array(ab, 1, 1023);"
   3567       "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
   3568       "var i8a = new Int8Array(ab, 1, 1023);"
   3569       "var u16a = new Uint16Array(ab, 2, 511);"
   3570       "var i16a = new Int16Array(ab, 2, 511);"
   3571       "var u32a = new Uint32Array(ab, 4, 255);"
   3572       "var i32a = new Int32Array(ab, 4, 255);"
   3573       "var f32a = new Float32Array(ab, 4, 255);"
   3574       "var f64a = new Float64Array(ab, 8, 127);"
   3575       "var dv = new DataView(ab, 1, 1023);");
   3576 
   3577   v8::Local<v8::ArrayBuffer> ab =
   3578       Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
   3579 
   3580   v8::Local<v8::DataView> dv = v8::Local<v8::DataView>::Cast(CompileRun("dv"));
   3581 
   3582   ScopedArrayBufferContents contents(ab->Externalize());
   3583   ab->Neuter();
   3584   CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
   3585   CHECK_EQ(0, v8_run_int32value(v8_compile("ab.byteLength")));
   3586 
   3587   CheckIsTypedArrayVarNeutered("u8a");
   3588   CheckIsTypedArrayVarNeutered("u8c");
   3589   CheckIsTypedArrayVarNeutered("i8a");
   3590   CheckIsTypedArrayVarNeutered("u16a");
   3591   CheckIsTypedArrayVarNeutered("i16a");
   3592   CheckIsTypedArrayVarNeutered("u32a");
   3593   CheckIsTypedArrayVarNeutered("i32a");
   3594   CheckIsTypedArrayVarNeutered("f32a");
   3595   CheckIsTypedArrayVarNeutered("f64a");
   3596 
   3597   CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
   3598   CheckDataViewIsNeutered(dv);
   3599 }
   3600 
   3601 
   3602 class ScopedSharedArrayBufferContents {
   3603  public:
   3604   explicit ScopedSharedArrayBufferContents(
   3605       const v8::SharedArrayBuffer::Contents& contents)
   3606       : contents_(contents) {}
   3607   ~ScopedSharedArrayBufferContents() { free(contents_.Data()); }
   3608   void* Data() const { return contents_.Data(); }
   3609   size_t ByteLength() const { return contents_.ByteLength(); }
   3610 
   3611  private:
   3612   const v8::SharedArrayBuffer::Contents contents_;
   3613 };
   3614 
   3615 
   3616 THREADED_TEST(SharedArrayBuffer_ApiInternalToExternal) {
   3617   i::FLAG_harmony_sharedarraybuffer = true;
   3618   LocalContext env;
   3619   v8::Isolate* isolate = env->GetIsolate();
   3620   v8::HandleScope handle_scope(isolate);
   3621 
   3622   Local<v8::SharedArrayBuffer> ab = v8::SharedArrayBuffer::New(isolate, 1024);
   3623   CheckInternalFieldsAreZero(ab);
   3624   CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
   3625   CHECK(!ab->IsExternal());
   3626   CcTest::heap()->CollectAllGarbage();
   3627 
   3628   ScopedSharedArrayBufferContents ab_contents(ab->Externalize());
   3629   CHECK(ab->IsExternal());
   3630 
   3631   CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
   3632   uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
   3633   CHECK(data != NULL);
   3634   CHECK(env->Global()->Set(env.local(), v8_str("ab"), ab).FromJust());
   3635 
   3636   v8::Local<v8::Value> result = CompileRun("ab.byteLength");
   3637   CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
   3638 
   3639   result = CompileRun(
   3640       "var u8 = new Uint8Array(ab);"
   3641       "u8[0] = 0xFF;"
   3642       "u8[1] = 0xAA;"
   3643       "u8.length");
   3644   CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
   3645   CHECK_EQ(0xFF, data[0]);
   3646   CHECK_EQ(0xAA, data[1]);
   3647   data[0] = 0xCC;
   3648   data[1] = 0x11;
   3649   result = CompileRun("u8[0] + u8[1]");
   3650   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
   3651 }
   3652 
   3653 
   3654 THREADED_TEST(SharedArrayBuffer_JSInternalToExternal) {
   3655   i::FLAG_harmony_sharedarraybuffer = true;
   3656   LocalContext env;
   3657   v8::Isolate* isolate = env->GetIsolate();
   3658   v8::HandleScope handle_scope(isolate);
   3659 
   3660 
   3661   v8::Local<v8::Value> result = CompileRun(
   3662       "var ab1 = new SharedArrayBuffer(2);"
   3663       "var u8_a = new Uint8Array(ab1);"
   3664       "u8_a[0] = 0xAA;"
   3665       "u8_a[1] = 0xFF; u8_a.buffer");
   3666   Local<v8::SharedArrayBuffer> ab1 = Local<v8::SharedArrayBuffer>::Cast(result);
   3667   CheckInternalFieldsAreZero(ab1);
   3668   CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
   3669   CHECK(!ab1->IsExternal());
   3670   ScopedSharedArrayBufferContents ab1_contents(ab1->Externalize());
   3671   CHECK(ab1->IsExternal());
   3672 
   3673   result = CompileRun("ab1.byteLength");
   3674   CHECK_EQ(2, result->Int32Value(env.local()).FromJust());
   3675   result = CompileRun("u8_a[0]");
   3676   CHECK_EQ(0xAA, result->Int32Value(env.local()).FromJust());
   3677   result = CompileRun("u8_a[1]");
   3678   CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
   3679   result = CompileRun(
   3680       "var u8_b = new Uint8Array(ab1);"
   3681       "u8_b[0] = 0xBB;"
   3682       "u8_a[0]");
   3683   CHECK_EQ(0xBB, result->Int32Value(env.local()).FromJust());
   3684   result = CompileRun("u8_b[1]");
   3685   CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
   3686 
   3687   CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
   3688   uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
   3689   CHECK_EQ(0xBB, ab1_data[0]);
   3690   CHECK_EQ(0xFF, ab1_data[1]);
   3691   ab1_data[0] = 0xCC;
   3692   ab1_data[1] = 0x11;
   3693   result = CompileRun("u8_a[0] + u8_a[1]");
   3694   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
   3695 }
   3696 
   3697 
   3698 THREADED_TEST(SharedArrayBuffer_External) {
   3699   i::FLAG_harmony_sharedarraybuffer = true;
   3700   LocalContext env;
   3701   v8::Isolate* isolate = env->GetIsolate();
   3702   v8::HandleScope handle_scope(isolate);
   3703 
   3704   i::ScopedVector<uint8_t> my_data(100);
   3705   memset(my_data.start(), 0, 100);
   3706   Local<v8::SharedArrayBuffer> ab3 =
   3707       v8::SharedArrayBuffer::New(isolate, my_data.start(), 100);
   3708   CheckInternalFieldsAreZero(ab3);
   3709   CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
   3710   CHECK(ab3->IsExternal());
   3711 
   3712   CHECK(env->Global()->Set(env.local(), v8_str("ab3"), ab3).FromJust());
   3713 
   3714   v8::Local<v8::Value> result = CompileRun("ab3.byteLength");
   3715   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
   3716 
   3717   result = CompileRun(
   3718       "var u8_b = new Uint8Array(ab3);"
   3719       "u8_b[0] = 0xBB;"
   3720       "u8_b[1] = 0xCC;"
   3721       "u8_b.length");
   3722   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
   3723   CHECK_EQ(0xBB, my_data[0]);
   3724   CHECK_EQ(0xCC, my_data[1]);
   3725   my_data[0] = 0xCC;
   3726   my_data[1] = 0x11;
   3727   result = CompileRun("u8_b[0] + u8_b[1]");
   3728   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
   3729 }
   3730 
   3731 
   3732 THREADED_TEST(HiddenProperties) {
   3733   LocalContext env;
   3734   v8::Isolate* isolate = env->GetIsolate();
   3735   v8::HandleScope scope(isolate);
   3736 
   3737   v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
   3738   v8::Local<v8::Private> key =
   3739       v8::Private::ForApi(isolate, v8_str("api-test::hidden-key"));
   3740   v8::Local<v8::String> empty = v8_str("");
   3741   v8::Local<v8::String> prop_name = v8_str("prop_name");
   3742 
   3743   CcTest::heap()->CollectAllGarbage();
   3744 
   3745   // Make sure delete of a non-existent hidden value works
   3746   obj->DeletePrivate(env.local(), key).FromJust();
   3747 
   3748   CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 1503))
   3749             .FromJust());
   3750   CHECK_EQ(1503, obj->GetPrivate(env.local(), key)
   3751                      .ToLocalChecked()
   3752                      ->Int32Value(env.local())
   3753                      .FromJust());
   3754   CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 2002))
   3755             .FromJust());
   3756   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
   3757                      .ToLocalChecked()
   3758                      ->Int32Value(env.local())
   3759                      .FromJust());
   3760 
   3761   CcTest::heap()->CollectAllGarbage();
   3762 
   3763   // Make sure we do not find the hidden property.
   3764   CHECK(!obj->Has(env.local(), empty).FromJust());
   3765   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
   3766                      .ToLocalChecked()
   3767                      ->Int32Value(env.local())
   3768                      .FromJust());
   3769   CHECK(obj->Get(env.local(), empty).ToLocalChecked()->IsUndefined());
   3770   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
   3771                      .ToLocalChecked()
   3772                      ->Int32Value(env.local())
   3773                      .FromJust());
   3774   CHECK(
   3775       obj->Set(env.local(), empty, v8::Integer::New(isolate, 2003)).FromJust());
   3776   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
   3777                      .ToLocalChecked()
   3778                      ->Int32Value(env.local())
   3779                      .FromJust());
   3780   CHECK_EQ(2003, obj->Get(env.local(), empty)
   3781                      .ToLocalChecked()
   3782                      ->Int32Value(env.local())
   3783                      .FromJust());
   3784 
   3785   CcTest::heap()->CollectAllGarbage();
   3786 
   3787   // Add another property and delete it afterwards to force the object in
   3788   // slow case.
   3789   CHECK(obj->Set(env.local(), prop_name, v8::Integer::New(isolate, 2008))
   3790             .FromJust());
   3791   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
   3792                      .ToLocalChecked()
   3793                      ->Int32Value(env.local())
   3794                      .FromJust());
   3795   CHECK_EQ(2008, obj->Get(env.local(), prop_name)
   3796                      .ToLocalChecked()
   3797                      ->Int32Value(env.local())
   3798                      .FromJust());
   3799   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
   3800                      .ToLocalChecked()
   3801                      ->Int32Value(env.local())
   3802                      .FromJust());
   3803   CHECK(obj->Delete(env.local(), prop_name).FromJust());
   3804   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
   3805                      .ToLocalChecked()
   3806                      ->Int32Value(env.local())
   3807                      .FromJust());
   3808 
   3809   CcTest::heap()->CollectAllGarbage();
   3810 
   3811   CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 2002))
   3812             .FromJust());
   3813   CHECK(obj->DeletePrivate(env.local(), key).FromJust());
   3814   CHECK(!obj->HasPrivate(env.local(), key).FromJust());
   3815 }
   3816 
   3817 
   3818 THREADED_TEST(Regress97784) {
   3819   // Regression test for crbug.com/97784
   3820   // Messing with the Object.prototype should not have effect on
   3821   // hidden properties.
   3822   LocalContext env;
   3823   v8::HandleScope scope(env->GetIsolate());
   3824 
   3825   v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
   3826   v8::Local<v8::Private> key =
   3827       v8::Private::New(env->GetIsolate(), v8_str("hidden"));
   3828 
   3829   CompileRun(
   3830       "set_called = false;"
   3831       "Object.defineProperty("
   3832       "    Object.prototype,"
   3833       "    'hidden',"
   3834       "    {get: function() { return 45; },"
   3835       "     set: function() { set_called = true; }})");
   3836 
   3837   CHECK(!obj->HasPrivate(env.local(), key).FromJust());
   3838   // Make sure that the getter and setter from Object.prototype is not invoked.
   3839   // If it did we would have full access to the hidden properties in
   3840   // the accessor.
   3841   CHECK(
   3842       obj->SetPrivate(env.local(), key, v8::Integer::New(env->GetIsolate(), 42))
   3843           .FromJust());
   3844   ExpectFalse("set_called");
   3845   CHECK_EQ(42, obj->GetPrivate(env.local(), key)
   3846                    .ToLocalChecked()
   3847                    ->Int32Value(env.local())
   3848                    .FromJust());
   3849 }
   3850 
   3851 
   3852 THREADED_TEST(External) {
   3853   v8::HandleScope scope(CcTest::isolate());
   3854   int x = 3;
   3855   Local<v8::External> ext = v8::External::New(CcTest::isolate(), &x);
   3856   LocalContext env;
   3857   CHECK(env->Global()->Set(env.local(), v8_str("ext"), ext).FromJust());
   3858   Local<Value> reext_obj = CompileRun("this.ext");
   3859   v8::Local<v8::External> reext = reext_obj.As<v8::External>();
   3860   int* ptr = static_cast<int*>(reext->Value());
   3861   CHECK_EQ(x, 3);
   3862   *ptr = 10;
   3863   CHECK_EQ(x, 10);
   3864 
   3865   // Make sure unaligned pointers are wrapped properly.
   3866   char* data = i::StrDup("0123456789");
   3867   Local<v8::Value> zero = v8::External::New(CcTest::isolate(), &data[0]);
   3868   Local<v8::Value> one = v8::External::New(CcTest::isolate(), &data[1]);
   3869   Local<v8::Value> two = v8::External::New(CcTest::isolate(), &data[2]);
   3870   Local<v8::Value> three = v8::External::New(CcTest::isolate(), &data[3]);
   3871 
   3872   char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
   3873   CHECK_EQ('0', *char_ptr);
   3874   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
   3875   CHECK_EQ('1', *char_ptr);
   3876   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
   3877   CHECK_EQ('2', *char_ptr);
   3878   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
   3879   CHECK_EQ('3', *char_ptr);
   3880   i::DeleteArray(data);
   3881 }
   3882 
   3883 
   3884 THREADED_TEST(GlobalHandle) {
   3885   v8::Isolate* isolate = CcTest::isolate();
   3886   v8::Persistent<String> global;
   3887   {
   3888     v8::HandleScope scope(isolate);
   3889     global.Reset(isolate, v8_str("str"));
   3890   }
   3891   {
   3892     v8::HandleScope scope(isolate);
   3893     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
   3894   }
   3895   global.Reset();
   3896   {
   3897     v8::HandleScope scope(isolate);
   3898     global.Reset(isolate, v8_str("str"));
   3899   }
   3900   {
   3901     v8::HandleScope scope(isolate);
   3902     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
   3903   }
   3904   global.Reset();
   3905 }
   3906 
   3907 
   3908 THREADED_TEST(ResettingGlobalHandle) {
   3909   v8::Isolate* isolate = CcTest::isolate();
   3910   v8::Persistent<String> global;
   3911   {
   3912     v8::HandleScope scope(isolate);
   3913     global.Reset(isolate, v8_str("str"));
   3914   }
   3915   v8::internal::GlobalHandles* global_handles =
   3916       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
   3917   int initial_handle_count = global_handles->global_handles_count();
   3918   {
   3919     v8::HandleScope scope(isolate);
   3920     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
   3921   }
   3922   {
   3923     v8::HandleScope scope(isolate);
   3924     global.Reset(isolate, v8_str("longer"));
   3925   }
   3926   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
   3927   {
   3928     v8::HandleScope scope(isolate);
   3929     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 6);
   3930   }
   3931   global.Reset();
   3932   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
   3933 }
   3934 
   3935 
   3936 THREADED_TEST(ResettingGlobalHandleToEmpty) {
   3937   v8::Isolate* isolate = CcTest::isolate();
   3938   v8::Persistent<String> global;
   3939   {
   3940     v8::HandleScope scope(isolate);
   3941     global.Reset(isolate, v8_str("str"));
   3942   }
   3943   v8::internal::GlobalHandles* global_handles =
   3944       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
   3945   int initial_handle_count = global_handles->global_handles_count();
   3946   {
   3947     v8::HandleScope scope(isolate);
   3948     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
   3949   }
   3950   {
   3951     v8::HandleScope scope(isolate);
   3952     Local<String> empty;
   3953     global.Reset(isolate, empty);
   3954   }
   3955   CHECK(global.IsEmpty());
   3956   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
   3957 }
   3958 
   3959 
   3960 template <class T>
   3961 static v8::Global<T> PassUnique(v8::Global<T> unique) {
   3962   return unique.Pass();
   3963 }
   3964 
   3965 
   3966 template <class T>
   3967 static v8::Global<T> ReturnUnique(v8::Isolate* isolate,
   3968                                   const v8::Persistent<T>& global) {
   3969   v8::Global<String> unique(isolate, global);
   3970   return unique.Pass();
   3971 }
   3972 
   3973 
   3974 THREADED_TEST(Global) {
   3975   v8::Isolate* isolate = CcTest::isolate();
   3976   v8::Persistent<String> global;
   3977   {
   3978     v8::HandleScope scope(isolate);
   3979     global.Reset(isolate, v8_str("str"));
   3980   }
   3981   v8::internal::GlobalHandles* global_handles =
   3982       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
   3983   int initial_handle_count = global_handles->global_handles_count();
   3984   {
   3985     v8::Global<String> unique(isolate, global);
   3986     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
   3987     // Test assignment via Pass
   3988     {
   3989       v8::Global<String> copy = unique.Pass();
   3990       CHECK(unique.IsEmpty());
   3991       CHECK(copy == global);
   3992       CHECK_EQ(initial_handle_count + 1,
   3993                global_handles->global_handles_count());
   3994       unique = copy.Pass();
   3995     }
   3996     // Test ctor via Pass
   3997     {
   3998       v8::Global<String> copy(unique.Pass());
   3999       CHECK(unique.IsEmpty());
   4000       CHECK(copy == global);
   4001       CHECK_EQ(initial_handle_count + 1,
   4002                global_handles->global_handles_count());
   4003       unique = copy.Pass();
   4004     }
   4005     // Test pass through function call
   4006     {
   4007       v8::Global<String> copy = PassUnique(unique.Pass());
   4008       CHECK(unique.IsEmpty());
   4009       CHECK(copy == global);
   4010       CHECK_EQ(initial_handle_count + 1,
   4011                global_handles->global_handles_count());
   4012       unique = copy.Pass();
   4013     }
   4014     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
   4015   }
   4016   // Test pass from function call
   4017   {
   4018     v8::Global<String> unique = ReturnUnique(isolate, global);
   4019     CHECK(unique == global);
   4020     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
   4021   }
   4022   CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
   4023   global.Reset();
   4024 }
   4025 
   4026 
   4027 namespace {
   4028 
   4029 class TwoPassCallbackData;
   4030 void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
   4031 void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
   4032 
   4033 
   4034 class TwoPassCallbackData {
   4035  public:
   4036   TwoPassCallbackData(v8::Isolate* isolate, int* instance_counter)
   4037       : first_pass_called_(false),
   4038         second_pass_called_(false),
   4039         trigger_gc_(false),
   4040         instance_counter_(instance_counter) {
   4041     HandleScope scope(isolate);
   4042     i::ScopedVector<char> buffer(40);
   4043     i::SNPrintF(buffer, "%p", static_cast<void*>(this));
   4044     auto string =
   4045         v8::String::NewFromUtf8(isolate, buffer.start(),
   4046                                 v8::NewStringType::kNormal).ToLocalChecked();
   4047     cell_.Reset(isolate, string);
   4048     (*instance_counter_)++;
   4049   }
   4050 
   4051   ~TwoPassCallbackData() {
   4052     CHECK(first_pass_called_);
   4053     CHECK(second_pass_called_);
   4054     CHECK(cell_.IsEmpty());
   4055     (*instance_counter_)--;
   4056   }
   4057 
   4058   void FirstPass() {
   4059     CHECK(!first_pass_called_);
   4060     CHECK(!second_pass_called_);
   4061     CHECK(!cell_.IsEmpty());
   4062     cell_.Reset();
   4063     first_pass_called_ = true;
   4064   }
   4065 
   4066   void SecondPass() {
   4067     CHECK(first_pass_called_);
   4068     CHECK(!second_pass_called_);
   4069     CHECK(cell_.IsEmpty());
   4070     second_pass_called_ = true;
   4071     delete this;
   4072   }
   4073 
   4074   void SetWeak() {
   4075     cell_.SetWeak(this, FirstPassCallback, v8::WeakCallbackType::kParameter);
   4076   }
   4077 
   4078   void MarkTriggerGc() { trigger_gc_ = true; }
   4079   bool trigger_gc() { return trigger_gc_; }
   4080 
   4081   int* instance_counter() { return instance_counter_; }
   4082 
   4083  private:
   4084   bool first_pass_called_;
   4085   bool second_pass_called_;
   4086   bool trigger_gc_;
   4087   v8::Global<v8::String> cell_;
   4088   int* instance_counter_;
   4089 };
   4090 
   4091 
   4092 void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
   4093   ApiTestFuzzer::Fuzz();
   4094   bool trigger_gc = data.GetParameter()->trigger_gc();
   4095   int* instance_counter = data.GetParameter()->instance_counter();
   4096   data.GetParameter()->SecondPass();
   4097   if (!trigger_gc) return;
   4098   auto data_2 = new TwoPassCallbackData(data.GetIsolate(), instance_counter);
   4099   data_2->SetWeak();
   4100   CcTest::heap()->CollectAllGarbage();
   4101 }
   4102 
   4103 
   4104 void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
   4105   data.GetParameter()->FirstPass();
   4106   data.SetSecondPassCallback(SecondPassCallback);
   4107 }
   4108 
   4109 }  // namespace
   4110 
   4111 
   4112 TEST(TwoPassPhantomCallbacks) {
   4113   auto isolate = CcTest::isolate();
   4114   const size_t kLength = 20;
   4115   int instance_counter = 0;
   4116   for (size_t i = 0; i < kLength; ++i) {
   4117     auto data = new TwoPassCallbackData(isolate, &instance_counter);
   4118     data->SetWeak();
   4119   }
   4120   CHECK_EQ(static_cast<int>(kLength), instance_counter);
   4121   CcTest::heap()->CollectAllGarbage();
   4122   EmptyMessageQueues(isolate);
   4123   CHECK_EQ(0, instance_counter);
   4124 }
   4125 
   4126 
   4127 TEST(TwoPassPhantomCallbacksNestedGc) {
   4128   auto isolate = CcTest::isolate();
   4129   const size_t kLength = 20;
   4130   TwoPassCallbackData* array[kLength];
   4131   int instance_counter = 0;
   4132   for (size_t i = 0; i < kLength; ++i) {
   4133     array[i] = new TwoPassCallbackData(isolate, &instance_counter);
   4134     array[i]->SetWeak();
   4135   }
   4136   array[5]->MarkTriggerGc();
   4137   array[10]->MarkTriggerGc();
   4138   array[15]->MarkTriggerGc();
   4139   CHECK_EQ(static_cast<int>(kLength), instance_counter);
   4140   CcTest::heap()->CollectAllGarbage();
   4141   EmptyMessageQueues(isolate);
   4142   CHECK_EQ(0, instance_counter);
   4143 }
   4144 
   4145 
   4146 namespace {
   4147 
   4148 void* IntKeyToVoidPointer(int key) { return reinterpret_cast<void*>(key << 1); }
   4149 
   4150 
   4151 Local<v8::Object> NewObjectForIntKey(
   4152     v8::Isolate* isolate, const v8::Global<v8::ObjectTemplate>& templ,
   4153     int key) {
   4154   auto local = Local<v8::ObjectTemplate>::New(isolate, templ);
   4155   auto obj = local->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
   4156   obj->SetAlignedPointerInInternalField(0, IntKeyToVoidPointer(key));
   4157   return obj;
   4158 }
   4159 
   4160 
   4161 template <typename K, typename V>
   4162 class PhantomStdMapTraits : public v8::StdMapTraits<K, V> {
   4163  public:
   4164   typedef typename v8::GlobalValueMap<K, V, PhantomStdMapTraits<K, V>> MapType;
   4165   static const v8::PersistentContainerCallbackType kCallbackType =
   4166       v8::kWeakWithInternalFields;
   4167   struct WeakCallbackDataType {
   4168     MapType* map;
   4169     K key;
   4170   };
   4171   static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key,
   4172                                                      Local<V> value) {
   4173     WeakCallbackDataType* data = new WeakCallbackDataType;
   4174     data->map = map;
   4175     data->key = key;
   4176     return data;
   4177   }
   4178   static MapType* MapFromWeakCallbackInfo(
   4179       const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
   4180     return data.GetParameter()->map;
   4181   }
   4182   static K KeyFromWeakCallbackInfo(
   4183       const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
   4184     return data.GetParameter()->key;
   4185   }
   4186   static void DisposeCallbackData(WeakCallbackDataType* data) { delete data; }
   4187   static void Dispose(v8::Isolate* isolate, v8::Global<V> value, K key) {
   4188     CHECK_EQ(IntKeyToVoidPointer(key),
   4189              v8::Object::GetAlignedPointerFromInternalField(value, 0));
   4190   }
   4191   static void OnWeakCallback(
   4192       const v8::WeakCallbackInfo<WeakCallbackDataType>&) {}
   4193   static void DisposeWeak(
   4194       const v8::WeakCallbackInfo<WeakCallbackDataType>& info) {
   4195     K key = KeyFromWeakCallbackInfo(info);
   4196     CHECK_EQ(IntKeyToVoidPointer(key), info.GetInternalField(0));
   4197     DisposeCallbackData(info.GetParameter());
   4198   }
   4199 };
   4200 
   4201 
   4202 template <typename Map>
   4203 void TestGlobalValueMap() {
   4204   LocalContext env;
   4205   v8::Isolate* isolate = env->GetIsolate();
   4206   v8::Global<ObjectTemplate> templ;
   4207   {
   4208     HandleScope scope(isolate);
   4209     auto t = ObjectTemplate::New(isolate);
   4210     t->SetInternalFieldCount(1);
   4211     templ.Reset(isolate, t);
   4212   }
   4213   Map map(isolate);
   4214   v8::internal::GlobalHandles* global_handles =
   4215       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
   4216   int initial_handle_count = global_handles->global_handles_count();
   4217   CHECK_EQ(0, static_cast<int>(map.Size()));
   4218   {
   4219     HandleScope scope(isolate);
   4220     Local<v8::Object> obj = map.Get(7);
   4221     CHECK(obj.IsEmpty());
   4222     Local<v8::Object> expected = v8::Object::New(isolate);
   4223     map.Set(7, expected);
   4224     CHECK_EQ(1, static_cast<int>(map.Size()));
   4225     obj = map.Get(7);
   4226     CHECK(expected->Equals(env.local(), obj).FromJust());
   4227     {
   4228       typename Map::PersistentValueReference ref = map.GetReference(7);
   4229       CHECK(expected->Equals(env.local(), ref.NewLocal(isolate)).FromJust());
   4230     }
   4231     v8::Global<v8::Object> removed = map.Remove(7);
   4232     CHECK_EQ(0, static_cast<int>(map.Size()));
   4233     CHECK(expected == removed);
   4234     removed = map.Remove(7);
   4235     CHECK(removed.IsEmpty());
   4236     map.Set(8, expected);
   4237     CHECK_EQ(1, static_cast<int>(map.Size()));
   4238     map.Set(8, expected);
   4239     CHECK_EQ(1, static_cast<int>(map.Size()));
   4240     {
   4241       typename Map::PersistentValueReference ref;
   4242       Local<v8::Object> expected2 = NewObjectForIntKey(isolate, templ, 8);
   4243       removed = map.Set(8, v8::Global<v8::Object>(isolate, expected2), &ref);
   4244       CHECK_EQ(1, static_cast<int>(map.Size()));
   4245       CHECK(expected == removed);
   4246       CHECK(expected2->Equals(env.local(), ref.NewLocal(isolate)).FromJust());
   4247     }
   4248   }
   4249   CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
   4250   if (map.IsWeak()) {
   4251     CcTest::i_isolate()->heap()->CollectAllGarbage(
   4252         i::Heap::kAbortIncrementalMarkingMask);
   4253   } else {
   4254     map.Clear();
   4255   }
   4256   CHECK_EQ(0, static_cast<int>(map.Size()));
   4257   CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
   4258   {
   4259     HandleScope scope(isolate);
   4260     Local<v8::Object> value = NewObjectForIntKey(isolate, templ, 9);
   4261     map.Set(9, value);
   4262     map.Clear();
   4263   }
   4264   CHECK_EQ(0, static_cast<int>(map.Size()));
   4265   CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
   4266 }
   4267 
   4268 }  // namespace
   4269 
   4270 
   4271 TEST(GlobalValueMap) {
   4272   // Default case, w/o weak callbacks:
   4273   TestGlobalValueMap<v8::StdGlobalValueMap<int, v8::Object>>();
   4274 
   4275   // Custom traits with weak callbacks:
   4276   typedef v8::GlobalValueMap<int, v8::Object,
   4277                              PhantomStdMapTraits<int, v8::Object>> WeakMap;
   4278   TestGlobalValueMap<WeakMap>();
   4279 }
   4280 
   4281 
   4282 TEST(PersistentValueVector) {
   4283   LocalContext env;
   4284   v8::Isolate* isolate = env->GetIsolate();
   4285   v8::internal::GlobalHandles* global_handles =
   4286       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
   4287   int handle_count = global_handles->global_handles_count();
   4288   HandleScope scope(isolate);
   4289 
   4290   v8::PersistentValueVector<v8::Object> vector(isolate);
   4291 
   4292   Local<v8::Object> obj1 = v8::Object::New(isolate);
   4293   Local<v8::Object> obj2 = v8::Object::New(isolate);
   4294   v8::Global<v8::Object> obj3(isolate, v8::Object::New(isolate));
   4295 
   4296   CHECK(vector.IsEmpty());
   4297   CHECK_EQ(0, static_cast<int>(vector.Size()));
   4298 
   4299   vector.ReserveCapacity(3);
   4300   CHECK(vector.IsEmpty());
   4301 
   4302   vector.Append(obj1);
   4303   vector.Append(obj2);
   4304   vector.Append(obj1);
   4305   vector.Append(obj3.Pass());
   4306   vector.Append(obj1);
   4307 
   4308   CHECK(!vector.IsEmpty());
   4309   CHECK_EQ(5, static_cast<int>(vector.Size()));
   4310   CHECK(obj3.IsEmpty());
   4311   CHECK(obj1->Equals(env.local(), vector.Get(0)).FromJust());
   4312   CHECK(obj1->Equals(env.local(), vector.Get(2)).FromJust());
   4313   CHECK(obj1->Equals(env.local(), vector.Get(4)).FromJust());
   4314   CHECK(obj2->Equals(env.local(), vector.Get(1)).FromJust());
   4315 
   4316   CHECK_EQ(5 + handle_count, global_handles->global_handles_count());
   4317 
   4318   vector.Clear();
   4319   CHECK(vector.IsEmpty());
   4320   CHECK_EQ(0, static_cast<int>(vector.Size()));
   4321   CHECK_EQ(handle_count, global_handles->global_handles_count());
   4322 }
   4323 
   4324 
   4325 THREADED_TEST(GlobalHandleUpcast) {
   4326   v8::Isolate* isolate = CcTest::isolate();
   4327   v8::HandleScope scope(isolate);
   4328   v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
   4329   v8::Persistent<String> global_string(isolate, local);
   4330   v8::Persistent<Value>& global_value =
   4331       v8::Persistent<Value>::Cast(global_string);
   4332   CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
   4333   CHECK(global_string == v8::Persistent<String>::Cast(global_value));
   4334   global_string.Reset();
   4335 }
   4336 
   4337 
   4338 THREADED_TEST(HandleEquality) {
   4339   v8::Isolate* isolate = CcTest::isolate();
   4340   v8::Persistent<String> global1;
   4341   v8::Persistent<String> global2;
   4342   {
   4343     v8::HandleScope scope(isolate);
   4344     global1.Reset(isolate, v8_str("str"));
   4345     global2.Reset(isolate, v8_str("str2"));
   4346   }
   4347   CHECK_EQ(global1 == global1, true);
   4348   CHECK_EQ(global1 != global1, false);
   4349   {
   4350     v8::HandleScope scope(isolate);
   4351     Local<String> local1 = Local<String>::New(isolate, global1);
   4352     Local<String> local2 = Local<String>::New(isolate, global2);
   4353 
   4354     CHECK_EQ(global1 == local1, true);
   4355     CHECK_EQ(global1 != local1, false);
   4356     CHECK_EQ(local1 == global1, true);
   4357     CHECK_EQ(local1 != global1, false);
   4358 
   4359     CHECK_EQ(global1 == local2, false);
   4360     CHECK_EQ(global1 != local2, true);
   4361     CHECK_EQ(local2 == global1, false);
   4362     CHECK_EQ(local2 != global1, true);
   4363 
   4364     CHECK_EQ(local1 == local2, false);
   4365     CHECK_EQ(local1 != local2, true);
   4366 
   4367     Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
   4368     CHECK_EQ(local1 == anotherLocal1, true);
   4369     CHECK_EQ(local1 != anotherLocal1, false);
   4370   }
   4371   global1.Reset();
   4372   global2.Reset();
   4373 }
   4374 
   4375 
   4376 THREADED_TEST(LocalHandle) {
   4377   v8::HandleScope scope(CcTest::isolate());
   4378   v8::Local<String> local =
   4379       v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
   4380   CHECK_EQ(local->Length(), 3);
   4381 }
   4382 
   4383 
   4384 class WeakCallCounter {
   4385  public:
   4386   explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) {}
   4387   int id() { return id_; }
   4388   void increment() { number_of_weak_calls_++; }
   4389   int NumberOfWeakCalls() { return number_of_weak_calls_; }
   4390 
   4391  private:
   4392   int id_;
   4393   int number_of_weak_calls_;
   4394 };
   4395 
   4396 
   4397 template <typename T>
   4398 struct WeakCallCounterAndPersistent {
   4399   explicit WeakCallCounterAndPersistent(WeakCallCounter* counter)
   4400       : counter(counter) {}
   4401   WeakCallCounter* counter;
   4402   v8::Persistent<T> handle;
   4403 };
   4404 
   4405 
   4406 template <typename T>
   4407 static void WeakPointerCallback(
   4408     const v8::WeakCallbackInfo<WeakCallCounterAndPersistent<T>>& data) {
   4409   CHECK_EQ(1234, data.GetParameter()->counter->id());
   4410   data.GetParameter()->counter->increment();
   4411   data.GetParameter()->handle.Reset();
   4412 }
   4413 
   4414 
   4415 template <typename T>
   4416 static UniqueId MakeUniqueId(const Persistent<T>& p) {
   4417   return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
   4418 }
   4419 
   4420 
   4421 THREADED_TEST(ApiObjectGroups) {
   4422   LocalContext env;
   4423   v8::Isolate* iso = env->GetIsolate();
   4424   HandleScope scope(iso);
   4425 
   4426   WeakCallCounter counter(1234);
   4427 
   4428   WeakCallCounterAndPersistent<Value> g1s1(&counter);
   4429   WeakCallCounterAndPersistent<Value> g1s2(&counter);
   4430   WeakCallCounterAndPersistent<Value> g1c1(&counter);
   4431   WeakCallCounterAndPersistent<Value> g2s1(&counter);
   4432   WeakCallCounterAndPersistent<Value> g2s2(&counter);
   4433   WeakCallCounterAndPersistent<Value> g2c1(&counter);
   4434 
   4435   {
   4436     HandleScope scope(iso);
   4437     g1s1.handle.Reset(iso, Object::New(iso));
   4438     g1s2.handle.Reset(iso, Object::New(iso));
   4439     g1c1.handle.Reset(iso, Object::New(iso));
   4440     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
   4441                         v8::WeakCallbackType::kParameter);
   4442     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
   4443                         v8::WeakCallbackType::kParameter);
   4444     g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
   4445                         v8::WeakCallbackType::kParameter);
   4446 
   4447     g2s1.handle.Reset(iso, Object::New(iso));
   4448     g2s2.handle.Reset(iso, Object::New(iso));
   4449     g2c1.handle.Reset(iso, Object::New(iso));
   4450     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
   4451                         v8::WeakCallbackType::kParameter);
   4452     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
   4453                         v8::WeakCallbackType::kParameter);
   4454     g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
   4455                         v8::WeakCallbackType::kParameter);
   4456   }
   4457 
   4458   WeakCallCounterAndPersistent<Value> root(&counter);
   4459   root.handle.Reset(iso, g1s1.handle);  // make a root.
   4460 
   4461   // Connect group 1 and 2, make a cycle.
   4462   {
   4463     HandleScope scope(iso);
   4464     CHECK(Local<Object>::New(iso, g1s2.handle.As<Object>())
   4465               ->Set(env.local(), 0, Local<Value>::New(iso, g2s2.handle))
   4466               .FromJust());
   4467     CHECK(Local<Object>::New(iso, g2s1.handle.As<Object>())
   4468               ->Set(env.local(), 0, Local<Value>::New(iso, g1s1.handle))
   4469               .FromJust());
   4470   }
   4471 
   4472   {
   4473     UniqueId id1 = MakeUniqueId(g1s1.handle);
   4474     UniqueId id2 = MakeUniqueId(g2s2.handle);
   4475     iso->SetObjectGroupId(g1s1.handle, id1);
   4476     iso->SetObjectGroupId(g1s2.handle, id1);
   4477     iso->SetReferenceFromGroup(id1, g1c1.handle);
   4478     iso->SetObjectGroupId(g2s1.handle, id2);
   4479     iso->SetObjectGroupId(g2s2.handle, id2);
   4480     iso->SetReferenceFromGroup(id2, g2c1.handle);
   4481   }
   4482   // Do a single full GC, ensure incremental marking is stopped.
   4483   v8::internal::Heap* heap =
   4484       reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
   4485   heap->CollectAllGarbage();
   4486 
   4487   // All object should be alive.
   4488   CHECK_EQ(0, counter.NumberOfWeakCalls());
   4489 
   4490   // Weaken the root.
   4491   root.handle.SetWeak(&root, &WeakPointerCallback,
   4492                       v8::WeakCallbackType::kParameter);
   4493   // But make children strong roots---all the objects (except for children)
   4494   // should be collectable now.
   4495   g1c1.handle.ClearWeak();
   4496   g2c1.handle.ClearWeak();
   4497 
   4498   // Groups are deleted, rebuild groups.
   4499   {
   4500     UniqueId id1 = MakeUniqueId(g1s1.handle);
   4501     UniqueId id2 = MakeUniqueId(g2s2.handle);
   4502     iso->SetObjectGroupId(g1s1.handle, id1);
   4503     iso->SetObjectGroupId(g1s2.handle, id1);
   4504     iso->SetReferenceFromGroup(id1, g1c1.handle);
   4505     iso->SetObjectGroupId(g2s1.handle, id2);
   4506     iso->SetObjectGroupId(g2s2.handle, id2);
   4507     iso->SetReferenceFromGroup(id2, g2c1.handle);
   4508   }
   4509 
   4510   heap->CollectAllGarbage();
   4511 
   4512   // All objects should be gone. 5 global handles in total.
   4513   CHECK_EQ(5, counter.NumberOfWeakCalls());
   4514 
   4515   // And now make children weak again and collect them.
   4516   g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
   4517                       v8::WeakCallbackType::kParameter);
   4518   g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
   4519                       v8::WeakCallbackType::kParameter);
   4520 
   4521   heap->CollectAllGarbage();
   4522   CHECK_EQ(7, counter.NumberOfWeakCalls());
   4523 }
   4524 
   4525 
   4526 THREADED_TEST(ApiObjectGroupsForSubtypes) {
   4527   LocalContext env;
   4528   v8::Isolate* iso = env->GetIsolate();
   4529   HandleScope scope(iso);
   4530 
   4531   WeakCallCounter counter(1234);
   4532 
   4533   WeakCallCounterAndPersistent<Object> g1s1(&counter);
   4534   WeakCallCounterAndPersistent<String> g1s2(&counter);
   4535   WeakCallCounterAndPersistent<String> g1c1(&counter);
   4536   WeakCallCounterAndPersistent<Object> g2s1(&counter);
   4537   WeakCallCounterAndPersistent<String> g2s2(&counter);
   4538   WeakCallCounterAndPersistent<String> g2c1(&counter);
   4539 
   4540   {
   4541     HandleScope scope(iso);
   4542     g1s1.handle.Reset(iso, Object::New(iso));
   4543     g1s2.handle.Reset(iso, v8_str("foo1"));
   4544     g1c1.handle.Reset(iso, v8_str("foo2"));
   4545     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
   4546                         v8::WeakCallbackType::kParameter);
   4547     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
   4548                         v8::WeakCallbackType::kParameter);
   4549     g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
   4550                         v8::WeakCallbackType::kParameter);
   4551 
   4552     g2s1.handle.Reset(iso, Object::New(iso));
   4553     g2s2.handle.Reset(iso, v8_str("foo3"));
   4554     g2c1.handle.Reset(iso, v8_str("foo4"));
   4555     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
   4556                         v8::WeakCallbackType::kParameter);
   4557     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
   4558                         v8::WeakCallbackType::kParameter);
   4559     g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
   4560                         v8::WeakCallbackType::kParameter);
   4561   }
   4562 
   4563   WeakCallCounterAndPersistent<Value> root(&counter);
   4564   root.handle.Reset(iso, g1s1.handle);  // make a root.
   4565 
   4566   // Connect group 1 and 2, make a cycle.
   4567   {
   4568     HandleScope scope(iso);
   4569     CHECK(Local<Object>::New(iso, g1s1.handle)
   4570               ->Set(env.local(), 0, Local<Object>::New(iso, g2s1.handle))
   4571               .FromJust());
   4572     CHECK(Local<Object>::New(iso, g2s1.handle)
   4573               ->Set(env.local(), 0, Local<Object>::New(iso, g1s1.handle))
   4574               .FromJust());
   4575   }
   4576 
   4577   {
   4578     UniqueId id1 = MakeUniqueId(g1s1.handle);
   4579     UniqueId id2 = MakeUniqueId(g2s2.handle);
   4580     iso->SetObjectGroupId(g1s1.handle, id1);
   4581     iso->SetObjectGroupId(g1s2.handle, id1);
   4582     iso->SetReference(g1s1.handle, g1c1.handle);
   4583     iso->SetObjectGroupId(g2s1.handle, id2);
   4584     iso->SetObjectGroupId(g2s2.handle, id2);
   4585     iso->SetReferenceFromGroup(id2, g2c1.handle);
   4586   }
   4587   // Do a single full GC, ensure incremental marking is stopped.
   4588   v8::internal::Heap* heap =
   4589       reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
   4590   heap->CollectAllGarbage();
   4591 
   4592   // All object should be alive.
   4593   CHECK_EQ(0, counter.NumberOfWeakCalls());
   4594 
   4595   // Weaken the root.
   4596   root.handle.SetWeak(&root, &WeakPointerCallback,
   4597                       v8::WeakCallbackType::kParameter);
   4598   // But make children strong roots---all the objects (except for children)
   4599   // should be collectable now.
   4600   g1c1.handle.ClearWeak();
   4601   g2c1.handle.ClearWeak();
   4602 
   4603   // Groups are deleted, rebuild groups.
   4604   {
   4605     UniqueId id1 = MakeUniqueId(g1s1.handle);
   4606     UniqueId id2 = MakeUniqueId(g2s2.handle);
   4607     iso->SetObjectGroupId(g1s1.handle, id1);
   4608     iso->SetObjectGroupId(g1s2.handle, id1);
   4609     iso->SetReference(g1s1.handle, g1c1.handle);
   4610     iso->SetObjectGroupId(g2s1.handle, id2);
   4611     iso->SetObjectGroupId(g2s2.handle, id2);
   4612     iso->SetReferenceFromGroup(id2, g2c1.handle);
   4613   }
   4614 
   4615   heap->CollectAllGarbage();
   4616 
   4617   // All objects should be gone. 5 global handles in total.
   4618   CHECK_EQ(5, counter.NumberOfWeakCalls());
   4619 
   4620   // And now make children weak again and collect them.
   4621   g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
   4622                       v8::WeakCallbackType::kParameter);
   4623   g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
   4624                       v8::WeakCallbackType::kParameter);
   4625 
   4626   heap->CollectAllGarbage();
   4627   CHECK_EQ(7, counter.NumberOfWeakCalls());
   4628 }
   4629 
   4630 
   4631 THREADED_TEST(ApiObjectGroupsCycle) {
   4632   LocalContext env;
   4633   v8::Isolate* iso = env->GetIsolate();
   4634   HandleScope scope(iso);
   4635 
   4636   WeakCallCounter counter(1234);
   4637 
   4638   WeakCallCounterAndPersistent<Value> g1s1(&counter);
   4639   WeakCallCounterAndPersistent<Value> g1s2(&counter);
   4640   WeakCallCounterAndPersistent<Value> g2s1(&counter);
   4641   WeakCallCounterAndPersistent<Value> g2s2(&counter);
   4642   WeakCallCounterAndPersistent<Value> g3s1(&counter);
   4643   WeakCallCounterAndPersistent<Value> g3s2(&counter);
   4644   WeakCallCounterAndPersistent<Value> g4s1(&counter);
   4645   WeakCallCounterAndPersistent<Value> g4s2(&counter);
   4646 
   4647   {
   4648     HandleScope scope(iso);
   4649     g1s1.handle.Reset(iso, Object::New(iso));
   4650     g1s2.handle.Reset(iso, Object::New(iso));
   4651     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
   4652                         v8::WeakCallbackType::kParameter);
   4653     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
   4654                         v8::WeakCallbackType::kParameter);
   4655     CHECK(g1s1.handle.IsWeak());
   4656     CHECK(g1s2.handle.IsWeak());
   4657 
   4658     g2s1.handle.Reset(iso, Object::New(iso));
   4659     g2s2.handle.Reset(iso, Object::New(iso));
   4660     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
   4661                         v8::WeakCallbackType::kParameter);
   4662     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
   4663                         v8::WeakCallbackType::kParameter);
   4664     CHECK(g2s1.handle.IsWeak());
   4665     CHECK(g2s2.handle.IsWeak());
   4666 
   4667     g3s1.handle.Reset(iso, Object::New(iso));
   4668     g3s2.handle.Reset(iso, Object::New(iso));
   4669     g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback,
   4670                         v8::WeakCallbackType::kParameter);
   4671     g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback,
   4672                         v8::WeakCallbackType::kParameter);
   4673     CHECK(g3s1.handle.IsWeak());
   4674     CHECK(g3s2.handle.IsWeak());
   4675 
   4676     g4s1.handle.Reset(iso, Object::New(iso));
   4677     g4s2.handle.Reset(iso, Object::New(iso));
   4678     g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback,
   4679                         v8::WeakCallbackType::kParameter);
   4680     g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback,
   4681                         v8::WeakCallbackType::kParameter);
   4682     CHECK(g4s1.handle.IsWeak());
   4683     CHECK(g4s2.handle.IsWeak());
   4684   }
   4685 
   4686   WeakCallCounterAndPersistent<Value> root(&counter);
   4687   root.handle.Reset(iso, g1s1.handle);  // make a root.
   4688 
   4689   // Connect groups.  We're building the following cycle:
   4690   // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
   4691   // groups.
   4692   {
   4693     UniqueId id1 = MakeUniqueId(g1s1.handle);
   4694     UniqueId id2 = MakeUniqueId(g2s1.handle);
   4695     UniqueId id3 = MakeUniqueId(g3s1.handle);
   4696     UniqueId id4 = MakeUniqueId(g4s1.handle);
   4697     iso->SetObjectGroupId(g1s1.handle, id1);
   4698     iso->SetObjectGroupId(g1s2.handle, id1);
   4699     iso->SetReferenceFromGroup(id1, g2s1.handle);
   4700     iso->SetObjectGroupId(g2s1.handle, id2);
   4701     iso->SetObjectGroupId(g2s2.handle, id2);
   4702     iso->SetReferenceFromGroup(id2, g3s1.handle);
   4703     iso->SetObjectGroupId(g3s1.handle, id3);
   4704     iso->SetObjectGroupId(g3s2.handle, id3);
   4705     iso->SetReferenceFromGroup(id3, g4s1.handle);
   4706     iso->SetObjectGroupId(g4s1.handle, id4);
   4707     iso->SetObjectGroupId(g4s2.handle, id4);
   4708     iso->SetReferenceFromGroup(id4, g1s1.handle);
   4709   }
   4710   // Do a single full GC
   4711   v8::internal::Heap* heap =
   4712       reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
   4713   heap->CollectAllGarbage();
   4714 
   4715   // All object should be alive.
   4716   CHECK_EQ(0, counter.NumberOfWeakCalls());
   4717 
   4718   // Weaken the root.
   4719   root.handle.SetWeak(&root, &WeakPointerCallback,
   4720                       v8::WeakCallbackType::kParameter);
   4721 
   4722   // Groups are deleted, rebuild groups.
   4723   {
   4724     UniqueId id1 = MakeUniqueId(g1s1.handle);
   4725     UniqueId id2 = MakeUniqueId(g2s1.handle);
   4726     UniqueId id3 = MakeUniqueId(g3s1.handle);
   4727     UniqueId id4 = MakeUniqueId(g4s1.handle);
   4728     iso->SetObjectGroupId(g1s1.handle, id1);
   4729     iso->SetObjectGroupId(g1s2.handle, id1);
   4730     iso->SetReferenceFromGroup(id1, g2s1.handle);
   4731     iso->SetObjectGroupId(g2s1.handle, id2);
   4732     iso->SetObjectGroupId(g2s2.handle, id2);
   4733     iso->SetReferenceFromGroup(id2, g3s1.handle);
   4734     iso->SetObjectGroupId(g3s1.handle, id3);
   4735     iso->SetObjectGroupId(g3s2.handle, id3);
   4736     iso->SetReferenceFromGroup(id3, g4s1.handle);
   4737     iso->SetObjectGroupId(g4s1.handle, id4);
   4738     iso->SetObjectGroupId(g4s2.handle, id4);
   4739     iso->SetReferenceFromGroup(id4, g1s1.handle);
   4740   }
   4741 
   4742   heap->CollectAllGarbage();
   4743 
   4744   // All objects should be gone. 9 global handles in total.
   4745   CHECK_EQ(9, counter.NumberOfWeakCalls());
   4746 }
   4747 
   4748 
   4749 THREADED_TEST(ScriptException) {
   4750   LocalContext env;
   4751   v8::HandleScope scope(env->GetIsolate());
   4752   Local<Script> script = v8_compile("throw 'panama!';");
   4753   v8::TryCatch try_catch(env->GetIsolate());
   4754   v8::MaybeLocal<Value> result = script->Run(env.local());
   4755   CHECK(result.IsEmpty());
   4756   CHECK(try_catch.HasCaught());
   4757   String::Utf8Value exception_value(try_catch.Exception());
   4758   CHECK_EQ(0, strcmp(*exception_value, "panama!"));
   4759 }
   4760 
   4761 
   4762 TEST(TryCatchCustomException) {
   4763   LocalContext env;
   4764   v8::Isolate* isolate = env->GetIsolate();
   4765   v8::HandleScope scope(isolate);
   4766   v8::TryCatch try_catch(isolate);
   4767   CompileRun(
   4768       "function CustomError() { this.a = 'b'; }"
   4769       "(function f() { throw new CustomError(); })();");
   4770   CHECK(try_catch.HasCaught());
   4771   CHECK(try_catch.Exception()
   4772             ->ToObject(env.local())
   4773             .ToLocalChecked()
   4774             ->Get(env.local(), v8_str("a"))
   4775             .ToLocalChecked()
   4776             ->Equals(env.local(), v8_str("b"))
   4777             .FromJust());
   4778 }
   4779 
   4780 
   4781 bool message_received;
   4782 
   4783 
   4784 static void check_message_0(v8::Local<v8::Message> message,
   4785                             v8::Local<Value> data) {
   4786   CHECK_EQ(5.76, data->NumberValue(CcTest::isolate()->GetCurrentContext())
   4787                      .FromJust());
   4788   CHECK_EQ(6.75, message->GetScriptOrigin()
   4789                      .ResourceName()
   4790                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
   4791                      .FromJust());
   4792   CHECK(!message->IsSharedCrossOrigin());
   4793   message_received = true;
   4794 }
   4795 
   4796 
   4797 THREADED_TEST(MessageHandler0) {
   4798   message_received = false;
   4799   v8::HandleScope scope(CcTest::isolate());
   4800   CHECK(!message_received);
   4801   LocalContext context;
   4802   CcTest::isolate()->AddMessageListener(check_message_0, v8_num(5.76));
   4803   v8::Local<v8::Script> script = CompileWithOrigin("throw 'error'", "6.75");
   4804   CHECK(script->Run(context.local()).IsEmpty());
   4805   CHECK(message_received);
   4806   // clear out the message listener
   4807   CcTest::isolate()->RemoveMessageListeners(check_message_0);
   4808 }
   4809 
   4810 
   4811 static void check_message_1(v8::Local<v8::Message> message,
   4812                             v8::Local<Value> data) {
   4813   CHECK(data->IsNumber());
   4814   CHECK_EQ(1337,
   4815            data->Int32Value(CcTest::isolate()->GetCurrentContext()).FromJust());
   4816   CHECK(!message->IsSharedCrossOrigin());
   4817   message_received = true;
   4818 }
   4819 
   4820 
   4821 TEST(MessageHandler1) {
   4822   message_received = false;
   4823   v8::HandleScope scope(CcTest::isolate());
   4824   CHECK(!message_received);
   4825   CcTest::isolate()->AddMessageListener(check_message_1);
   4826   LocalContext context;
   4827   CompileRun("throw 1337;");
   4828   CHECK(message_received);
   4829   // clear out the message listener
   4830   CcTest::isolate()->RemoveMessageListeners(check_message_1);
   4831 }
   4832 
   4833 
   4834 static void check_message_2(v8::Local<v8::Message> message,
   4835                             v8::Local<Value> data) {
   4836   LocalContext context;
   4837   CHECK(data->IsObject());
   4838   v8::Local<v8::Value> hidden_property =
   4839       v8::Object::Cast(*data)
   4840           ->GetPrivate(
   4841               context.local(),
   4842               v8::Private::ForApi(CcTest::isolate(), v8_str("hidden key")))
   4843           .ToLocalChecked();
   4844   CHECK(v8_str("hidden value")
   4845             ->Equals(context.local(), hidden_property)
   4846             .FromJust());
   4847   CHECK(!message->IsSharedCrossOrigin());
   4848   message_received = true;
   4849 }
   4850 
   4851 
   4852 TEST(MessageHandler2) {
   4853   message_received = false;
   4854   v8::HandleScope scope(CcTest::isolate());
   4855   CHECK(!message_received);
   4856   CcTest::isolate()->AddMessageListener(check_message_2);
   4857   LocalContext context;
   4858   v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
   4859   v8::Object::Cast(*error)
   4860       ->SetPrivate(context.local(),
   4861                    v8::Private::ForApi(CcTest::isolate(), v8_str("hidden key")),
   4862                    v8_str("hidden value"))
   4863       .FromJust();
   4864   CHECK(context->Global()
   4865             ->Set(context.local(), v8_str("error"), error)
   4866             .FromJust());
   4867   CompileRun("throw error;");
   4868   CHECK(message_received);
   4869   // clear out the message listener
   4870   CcTest::isolate()->RemoveMessageListeners(check_message_2);
   4871 }
   4872 
   4873 
   4874 static void check_message_3(v8::Local<v8::Message> message,
   4875                             v8::Local<Value> data) {
   4876   CHECK(message->IsSharedCrossOrigin());
   4877   CHECK(message->GetScriptOrigin().Options().IsSharedCrossOrigin());
   4878   CHECK(message->GetScriptOrigin().Options().IsEmbedderDebugScript());
   4879   CHECK(message->GetScriptOrigin().Options().IsOpaque());
   4880   CHECK_EQ(6.75, message->GetScriptOrigin()
   4881                      .ResourceName()
   4882                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
   4883                      .FromJust());
   4884   CHECK_EQ(7.40, message->GetScriptOrigin()
   4885                      .SourceMapUrl()
   4886                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
   4887                      .FromJust());
   4888   message_received = true;
   4889 }
   4890 
   4891 
   4892 TEST(MessageHandler3) {
   4893   message_received = false;
   4894   v8::Isolate* isolate = CcTest::isolate();
   4895   v8::HandleScope scope(isolate);
   4896   CHECK(!message_received);
   4897   isolate->AddMessageListener(check_message_3);
   4898   LocalContext context;
   4899   v8::ScriptOrigin origin = v8::ScriptOrigin(
   4900       v8_str("6.75"), v8::Integer::New(isolate, 1),
   4901       v8::Integer::New(isolate, 2), v8::True(isolate), Local<v8::Integer>(),
   4902       v8::True(isolate), v8_str("7.40"), v8::True(isolate));
   4903   v8::Local<v8::Script> script =
   4904       Script::Compile(context.local(), v8_str("throw 'error'"), &origin)
   4905           .ToLocalChecked();
   4906   CHECK(script->Run(context.local()).IsEmpty());
   4907   CHECK(message_received);
   4908   // clear out the message listener
   4909   isolate->RemoveMessageListeners(check_message_3);
   4910 }
   4911 
   4912 
   4913 static void check_message_4(v8::Local<v8::Message> message,
   4914                             v8::Local<Value> data) {
   4915   CHECK(!message->IsSharedCrossOrigin());
   4916   CHECK_EQ(6.75, message->GetScriptOrigin()
   4917                      .ResourceName()
   4918                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
   4919                      .FromJust());
   4920   message_received = true;
   4921 }
   4922 
   4923 
   4924 TEST(MessageHandler4) {
   4925   message_received = false;
   4926   v8::Isolate* isolate = CcTest::isolate();
   4927   v8::HandleScope scope(isolate);
   4928   CHECK(!message_received);
   4929   isolate->AddMessageListener(check_message_4);
   4930   LocalContext context;
   4931   v8::ScriptOrigin origin =
   4932       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
   4933                        v8::Integer::New(isolate, 2), v8::False(isolate));
   4934   v8::Local<v8::Script> script =
   4935       Script::Compile(context.local(), v8_str("throw 'error'"), &origin)
   4936           .ToLocalChecked();
   4937   CHECK(script->Run(context.local()).IsEmpty());
   4938   CHECK(message_received);
   4939   // clear out the message listener
   4940   isolate->RemoveMessageListeners(check_message_4);
   4941 }
   4942 
   4943 
   4944 static void check_message_5a(v8::Local<v8::Message> message,
   4945                              v8::Local<Value> data) {
   4946   CHECK(message->IsSharedCrossOrigin());
   4947   CHECK_EQ(6.75, message->GetScriptOrigin()
   4948                      .ResourceName()
   4949                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
   4950                      .FromJust());
   4951   message_received = true;
   4952 }
   4953 
   4954 
   4955 static void check_message_5b(v8::Local<v8::Message> message,
   4956                              v8::Local<Value> data) {
   4957   CHECK(!message->IsSharedCrossOrigin());
   4958   CHECK_EQ(6.75, message->GetScriptOrigin()
   4959                      .ResourceName()
   4960                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
   4961                      .FromJust());
   4962   message_received = true;
   4963 }
   4964 
   4965 
   4966 TEST(MessageHandler5) {
   4967   message_received = false;
   4968   v8::Isolate* isolate = CcTest::isolate();
   4969   v8::HandleScope scope(isolate);
   4970   CHECK(!message_received);
   4971   isolate->AddMessageListener(check_message_5a);
   4972   LocalContext context;
   4973   v8::ScriptOrigin origin1 =
   4974       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
   4975                        v8::Integer::New(isolate, 2), v8::True(isolate));
   4976   v8::Local<v8::Script> script =
   4977       Script::Compile(context.local(), v8_str("throw 'error'"), &origin1)
   4978           .ToLocalChecked();
   4979   CHECK(script->Run(context.local()).IsEmpty());
   4980   CHECK(message_received);
   4981   // clear out the message listener
   4982   isolate->RemoveMessageListeners(check_message_5a);
   4983 
   4984   message_received = false;
   4985   isolate->AddMessageListener(check_message_5b);
   4986   v8::ScriptOrigin origin2 =
   4987       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
   4988                        v8::Integer::New(isolate, 2), v8::False(isolate));
   4989   script = Script::Compile(context.local(), v8_str("throw 'error'"), &origin2)
   4990                .ToLocalChecked();
   4991   CHECK(script->Run(context.local()).IsEmpty());
   4992   CHECK(message_received);
   4993   // clear out the message listener
   4994   isolate->RemoveMessageListeners(check_message_5b);
   4995 }
   4996 
   4997 
   4998 TEST(NativeWeakMap) {
   4999   v8::Isolate* isolate = CcTest::isolate();
   5000   HandleScope scope(isolate);
   5001   Local<v8::NativeWeakMap> weak_map(v8::NativeWeakMap::New(isolate));
   5002   CHECK(!weak_map.IsEmpty());
   5003 
   5004   LocalContext env;
   5005   Local<Object> value = v8::Object::New(isolate);
   5006 
   5007   Local<Object> local1 = v8::Object::New(isolate);
   5008   CHECK(!weak_map->Has(local1));
   5009   CHECK(weak_map->Get(local1)->IsUndefined());
   5010   weak_map->Set(local1, value);
   5011   CHECK(weak_map->Has(local1));
   5012   CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
   5013 
   5014   WeakCallCounter counter(1234);
   5015   WeakCallCounterAndPersistent<Value> o1(&counter);
   5016   WeakCallCounterAndPersistent<Value> o2(&counter);
   5017   WeakCallCounterAndPersistent<Value> s1(&counter);
   5018   {
   5019     HandleScope scope(isolate);
   5020     Local<v8::Object> obj1 = v8::Object::New(isolate);
   5021     Local<v8::Object> obj2 = v8::Object::New(isolate);
   5022     Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
   5023 
   5024     weak_map->Set(obj1, value);
   5025     weak_map->Set(obj2, value);
   5026     weak_map->Set(sym1, value);
   5027 
   5028     o1.handle.Reset(isolate, obj1);
   5029     o2.handle.Reset(isolate, obj2);
   5030     s1.handle.Reset(isolate, sym1);
   5031 
   5032     CHECK(weak_map->Has(local1));
   5033     CHECK(weak_map->Has(obj1));
   5034     CHECK(weak_map->Has(obj2));
   5035     CHECK(weak_map->Has(sym1));
   5036 
   5037     CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
   5038     CHECK(value->Equals(env.local(), weak_map->Get(obj1)).FromJust());
   5039     CHECK(value->Equals(env.local(), weak_map->Get(obj2)).FromJust());
   5040     CHECK(value->Equals(env.local(), weak_map->Get(sym1)).FromJust());
   5041   }
   5042   CcTest::heap()->CollectAllGarbage();
   5043   {
   5044     HandleScope scope(isolate);
   5045     CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
   5046     CHECK(value->Equals(env.local(),
   5047                         weak_map->Get(Local<Value>::New(isolate, o1.handle)))
   5048               .FromJust());
   5049     CHECK(value->Equals(env.local(),
   5050                         weak_map->Get(Local<Value>::New(isolate, o2.handle)))
   5051               .FromJust());
   5052     CHECK(value->Equals(env.local(),
   5053                         weak_map->Get(Local<Value>::New(isolate, s1.handle)))
   5054               .FromJust());
   5055   }
   5056 
   5057   o1.handle.SetWeak(&o1, &WeakPointerCallback,
   5058                     v8::WeakCallbackType::kParameter);
   5059   o2.handle.SetWeak(&o2, &WeakPointerCallback,
   5060                     v8::WeakCallbackType::kParameter);
   5061   s1.handle.SetWeak(&s1, &WeakPointerCallback,
   5062                     v8::WeakCallbackType::kParameter);
   5063 
   5064   CcTest::heap()->CollectAllGarbage();
   5065   CHECK_EQ(3, counter.NumberOfWeakCalls());
   5066 
   5067   CHECK(o1.handle.IsEmpty());
   5068   CHECK(o2.handle.IsEmpty());
   5069   CHECK(s1.handle.IsEmpty());
   5070 
   5071   CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
   5072   CHECK(weak_map->Delete(local1));
   5073   CHECK(!weak_map->Has(local1));
   5074   CHECK(weak_map->Get(local1)->IsUndefined());
   5075 }
   5076 
   5077 
   5078 THREADED_TEST(GetSetProperty) {
   5079   LocalContext context;
   5080   v8::Isolate* isolate = context->GetIsolate();
   5081   v8::HandleScope scope(isolate);
   5082   CHECK(context->Global()
   5083             ->Set(context.local(), v8_str("foo"), v8_num(14))
   5084             .FromJust());
   5085   CHECK(context->Global()
   5086             ->Set(context.local(), v8_str("12"), v8_num(92))
   5087             .FromJust());
   5088   CHECK(context->Global()
   5089             ->Set(context.local(), v8::Integer::New(isolate, 16), v8_num(32))
   5090             .FromJust());
   5091   CHECK(context->Global()
   5092             ->Set(context.local(), v8_num(13), v8_num(56))
   5093             .FromJust());
   5094   Local<Value> foo = CompileRun("this.foo");
   5095   CHECK_EQ(14, foo->Int32Value(context.local()).FromJust());
   5096   Local<Value> twelve = CompileRun("this[12]");
   5097   CHECK_EQ(92, twelve->Int32Value(context.local()).FromJust());
   5098   Local<Value> sixteen = CompileRun("this[16]");
   5099   CHECK_EQ(32, sixteen->Int32Value(context.local()).FromJust());
   5100   Local<Value> thirteen = CompileRun("this[13]");
   5101   CHECK_EQ(56, thirteen->Int32Value(context.local()).FromJust());
   5102   CHECK_EQ(92, context->Global()
   5103                    ->Get(context.local(), v8::Integer::New(isolate, 12))
   5104                    .ToLocalChecked()
   5105                    ->Int32Value(context.local())
   5106                    .FromJust());
   5107   CHECK_EQ(92, context->Global()
   5108                    ->Get(context.local(), v8_str("12"))
   5109                    .ToLocalChecked()
   5110                    ->Int32Value(context.local())
   5111                    .FromJust());
   5112   CHECK_EQ(92, context->Global()
   5113                    ->Get(context.local(), v8_num(12))
   5114                    .ToLocalChecked()
   5115                    ->Int32Value(context.local())
   5116                    .FromJust());
   5117   CHECK_EQ(32, context->Global()
   5118                    ->Get(context.local(), v8::Integer::New(isolate, 16))
   5119                    .ToLocalChecked()
   5120                    ->Int32Value(context.local())
   5121                    .FromJust());
   5122   CHECK_EQ(32, context->Global()
   5123                    ->Get(context.local(), v8_str("16"))
   5124                    .ToLocalChecked()
   5125                    ->Int32Value(context.local())
   5126                    .FromJust());
   5127   CHECK_EQ(32, context->Global()
   5128                    ->Get(context.local(), v8_num(16))
   5129                    .ToLocalChecked()
   5130                    ->Int32Value(context.local())
   5131                    .FromJust());
   5132   CHECK_EQ(56, context->Global()
   5133                    ->Get(context.local(), v8::Integer::New(isolate, 13))
   5134                    .ToLocalChecked()
   5135                    ->Int32Value(context.local())
   5136                    .FromJust());
   5137   CHECK_EQ(56, context->Global()
   5138                    ->Get(context.local(), v8_str("13"))
   5139                    .ToLocalChecked()
   5140                    ->Int32Value(context.local())
   5141                    .FromJust());
   5142   CHECK_EQ(56, context->Global()
   5143                    ->Get(context.local(), v8_num(13))
   5144                    .ToLocalChecked()
   5145                    ->Int32Value(context.local())
   5146                    .FromJust());
   5147 }
   5148 
   5149 
   5150 THREADED_TEST(PropertyAttributes) {
   5151   LocalContext context;
   5152   v8::HandleScope scope(context->GetIsolate());
   5153   // none
   5154   Local<String> prop = v8_str("none");
   5155   CHECK(context->Global()->Set(context.local(), prop, v8_num(7)).FromJust());
   5156   CHECK_EQ(v8::None, context->Global()
   5157                          ->GetPropertyAttributes(context.local(), prop)
   5158                          .FromJust());
   5159   // read-only
   5160   prop = v8_str("read_only");
   5161   context->Global()
   5162       ->DefineOwnProperty(context.local(), prop, v8_num(7), v8::ReadOnly)
   5163       .FromJust();
   5164   CHECK_EQ(7, context->Global()
   5165                   ->Get(context.local(), prop)
   5166                   .ToLocalChecked()
   5167                   ->Int32Value(context.local())
   5168                   .FromJust());
   5169   CHECK_EQ(v8::ReadOnly, context->Global()
   5170                              ->GetPropertyAttributes(context.local(), prop)
   5171                              .FromJust());
   5172   CompileRun("read_only = 9");
   5173   CHECK_EQ(7, context->Global()
   5174                   ->Get(context.local(), prop)
   5175                   .ToLocalChecked()
   5176                   ->Int32Value(context.local())
   5177                   .FromJust());
   5178   CHECK(context->Global()->Set(context.local(), prop, v8_num(10)).FromJust());
   5179   CHECK_EQ(7, context->Global()
   5180                   ->Get(context.local(), prop)
   5181                   .ToLocalChecked()
   5182                   ->Int32Value(context.local())
   5183                   .FromJust());
   5184   // dont-delete
   5185   prop = v8_str("dont_delete");
   5186   context->Global()
   5187       ->DefineOwnProperty(context.local(), prop, v8_num(13), v8::DontDelete)
   5188       .FromJust();
   5189   CHECK_EQ(13, context->Global()
   5190                    ->Get(context.local(), prop)
   5191                    .ToLocalChecked()
   5192                    ->Int32Value(context.local())
   5193                    .FromJust());
   5194   CompileRun("delete dont_delete");
   5195   CHECK_EQ(13, context->Global()
   5196                    ->Get(context.local(), prop)
   5197                    .ToLocalChecked()
   5198                    ->Int32Value(context.local())
   5199                    .FromJust());
   5200   CHECK_EQ(v8::DontDelete, context->Global()
   5201                                ->GetPropertyAttributes(context.local(), prop)
   5202                                .FromJust());
   5203   // dont-enum
   5204   prop = v8_str("dont_enum");
   5205   context->Global()
   5206       ->DefineOwnProperty(context.local(), prop, v8_num(28), v8::DontEnum)
   5207       .FromJust();
   5208   CHECK_EQ(v8::DontEnum, context->Global()
   5209                              ->GetPropertyAttributes(context.local(), prop)
   5210                              .FromJust());
   5211   // absent
   5212   prop = v8_str("absent");
   5213   CHECK_EQ(v8::None, context->Global()
   5214                          ->GetPropertyAttributes(context.local(), prop)
   5215                          .FromJust());
   5216   Local<Value> fake_prop = v8_num(1);
   5217   CHECK_EQ(v8::None, context->Global()
   5218                          ->GetPropertyAttributes(context.local(), fake_prop)
   5219                          .FromJust());
   5220   // exception
   5221   TryCatch try_catch(context->GetIsolate());
   5222   Local<Value> exception =
   5223       CompileRun("({ toString: function() { throw 'exception';} })");
   5224   CHECK(context->Global()
   5225             ->GetPropertyAttributes(context.local(), exception)
   5226             .IsNothing());
   5227   CHECK(try_catch.HasCaught());
   5228   String::Utf8Value exception_value(try_catch.Exception());
   5229   CHECK_EQ(0, strcmp("exception", *exception_value));
   5230   try_catch.Reset();
   5231 }
   5232 
   5233 
   5234 THREADED_TEST(Array) {
   5235   LocalContext context;
   5236   v8::HandleScope scope(context->GetIsolate());
   5237   Local<v8::Array> array = v8::Array::New(context->GetIsolate());
   5238   CHECK_EQ(0u, array->Length());
   5239   CHECK(array->Get(context.local(), 0).ToLocalChecked()->IsUndefined());
   5240   CHECK(!array->Has(context.local(), 0).FromJust());
   5241   CHECK(array->Get(context.local(), 100).ToLocalChecked()->IsUndefined());
   5242   CHECK(!array->Has(context.local(), 100).FromJust());
   5243   CHECK(array->Set(context.local(), 2, v8_num(7)).FromJust());
   5244   CHECK_EQ(3u, array->Length());
   5245   CHECK(!array->Has(context.local(), 0).FromJust());
   5246   CHECK(!array->Has(context.local(), 1).FromJust());
   5247   CHECK(array->Has(context.local(), 2).FromJust());
   5248   CHECK_EQ(7, array->Get(context.local(), 2)
   5249                   .ToLocalChecked()
   5250                   ->Int32Value(context.local())
   5251                   .FromJust());
   5252   Local<Value> obj = CompileRun("[1, 2, 3]");
   5253   Local<v8::Array> arr = obj.As<v8::Array>();
   5254   CHECK_EQ(3u, arr->Length());
   5255   CHECK_EQ(1, arr->Get(context.local(), 0)
   5256                   .ToLocalChecked()
   5257                   ->Int32Value(context.local())
   5258                   .FromJust());
   5259   CHECK_EQ(2, arr->Get(context.local(), 1)
   5260                   .ToLocalChecked()
   5261                   ->Int32Value(context.local())
   5262                   .FromJust());
   5263   CHECK_EQ(3, arr->Get(context.local(), 2)
   5264                   .ToLocalChecked()
   5265                   ->Int32Value(context.local())
   5266                   .FromJust());
   5267   array = v8::Array::New(context->GetIsolate(), 27);
   5268   CHECK_EQ(27u, array->Length());
   5269   array = v8::Array::New(context->GetIsolate(), -27);
   5270   CHECK_EQ(0u, array->Length());
   5271 }
   5272 
   5273 
   5274 void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
   5275   v8::EscapableHandleScope scope(args.GetIsolate());
   5276   ApiTestFuzzer::Fuzz();
   5277   Local<v8::Array> result = v8::Array::New(args.GetIsolate(), args.Length());
   5278   for (int i = 0; i < args.Length(); i++) {
   5279     CHECK(result->Set(CcTest::isolate()->GetCurrentContext(), i, args[i])
   5280               .FromJust());
   5281   }
   5282   args.GetReturnValue().Set(scope.Escape(result));
   5283 }
   5284 
   5285 
   5286 THREADED_TEST(Vector) {
   5287   v8::Isolate* isolate = CcTest::isolate();
   5288   v8::HandleScope scope(isolate);
   5289   Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
   5290   global->Set(v8_str("f"), v8::FunctionTemplate::New(isolate, HandleF));
   5291   LocalContext context(0, global);
   5292 
   5293   const char* fun = "f()";
   5294   Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
   5295   CHECK_EQ(0u, a0->Length());
   5296 
   5297   const char* fun2 = "f(11)";
   5298   Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
   5299   CHECK_EQ(1u, a1->Length());
   5300   CHECK_EQ(11, a1->Get(context.local(), 0)
   5301                    .ToLocalChecked()
   5302                    ->Int32Value(context.local())
   5303                    .FromJust());
   5304 
   5305   const char* fun3 = "f(12, 13)";
   5306   Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
   5307   CHECK_EQ(2u, a2->Length());
   5308   CHECK_EQ(12, a2->Get(context.local(), 0)
   5309                    .ToLocalChecked()
   5310                    ->Int32Value(context.local())
   5311                    .FromJust());
   5312   CHECK_EQ(13, a2->Get(context.local(), 1)
   5313                    .ToLocalChecked()
   5314                    ->Int32Value(context.local())
   5315                    .FromJust());
   5316 
   5317   const char* fun4 = "f(14, 15, 16)";
   5318   Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
   5319   CHECK_EQ(3u, a3->Length());
   5320   CHECK_EQ(14, a3->Get(context.local(), 0)
   5321                    .ToLocalChecked()
   5322                    ->Int32Value(context.local())
   5323                    .FromJust());
   5324   CHECK_EQ(15, a3->Get(context.local(), 1)
   5325                    .ToLocalChecked()
   5326                    ->Int32Value(context.local())
   5327                    .FromJust());
   5328   CHECK_EQ(16, a3->Get(context.local(), 2)
   5329                    .ToLocalChecked()
   5330                    ->Int32Value(context.local())
   5331                    .FromJust());
   5332 
   5333   const char* fun5 = "f(17, 18, 19, 20)";
   5334   Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
   5335   CHECK_EQ(4u, a4->Length());
   5336   CHECK_EQ(17, a4->Get(context.local(), 0)
   5337                    .ToLocalChecked()
   5338                    ->Int32Value(context.local())
   5339                    .FromJust());
   5340   CHECK_EQ(18, a4->Get(context.local(), 1)
   5341                    .ToLocalChecked()
   5342                    ->Int32Value(context.local())
   5343                    .FromJust());
   5344   CHECK_EQ(19, a4->Get(context.local(), 2)
   5345                    .ToLocalChecked()
   5346                    ->Int32Value(context.local())
   5347                    .FromJust());
   5348   CHECK_EQ(20, a4->Get(context.local(), 3)
   5349                    .ToLocalChecked()
   5350                    ->Int32Value(context.local())
   5351                    .FromJust());
   5352 }
   5353 
   5354 
   5355 THREADED_TEST(FunctionCall) {
   5356   LocalContext context;
   5357   v8::Isolate* isolate = context->GetIsolate();
   5358   v8::HandleScope scope(isolate);
   5359   CompileRun(
   5360       "function Foo() {"
   5361       "  var result = [];"
   5362       "  for (var i = 0; i < arguments.length; i++) {"
   5363       "    result.push(arguments[i]);"
   5364       "  }"
   5365       "  return result;"
   5366       "}"
   5367       "function ReturnThisSloppy() {"
   5368       "  return this;"
   5369       "}"
   5370       "function ReturnThisStrict() {"
   5371       "  'use strict';"
   5372       "  return this;"
   5373       "}");
   5374   Local<Function> Foo = Local<Function>::Cast(
   5375       context->Global()->Get(context.local(), v8_str("Foo")).ToLocalChecked());
   5376   Local<Function> ReturnThisSloppy = Local<Function>::Cast(
   5377       context->Global()
   5378           ->Get(context.local(), v8_str("ReturnThisSloppy"))
   5379           .ToLocalChecked());
   5380   Local<Function> ReturnThisStrict = Local<Function>::Cast(
   5381       context->Global()
   5382           ->Get(context.local(), v8_str("ReturnThisStrict"))
   5383           .ToLocalChecked());
   5384 
   5385   v8::Local<Value>* args0 = NULL;
   5386   Local<v8::Array> a0 = Local<v8::Array>::Cast(
   5387       Foo->Call(context.local(), Foo, 0, args0).ToLocalChecked());
   5388   CHECK_EQ(0u, a0->Length());
   5389 
   5390   v8::Local<Value> args1[] = {v8_num(1.1)};
   5391   Local<v8::Array> a1 = Local<v8::Array>::Cast(
   5392       Foo->Call(context.local(), Foo, 1, args1).ToLocalChecked());
   5393   CHECK_EQ(1u, a1->Length());
   5394   CHECK_EQ(1.1, a1->Get(context.local(), v8::Integer::New(isolate, 0))
   5395                     .ToLocalChecked()
   5396                     ->NumberValue(context.local())
   5397                     .FromJust());
   5398 
   5399   v8::Local<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
   5400   Local<v8::Array> a2 = Local<v8::Array>::Cast(
   5401       Foo->Call(context.local(), Foo, 2, args2).ToLocalChecked());
   5402   CHECK_EQ(2u, a2->Length());
   5403   CHECK_EQ(2.2, a2->Get(context.local(), v8::Integer::New(isolate, 0))
   5404                     .ToLocalChecked()
   5405                     ->NumberValue(context.local())
   5406                     .FromJust());
   5407   CHECK_EQ(3.3, a2->Get(context.local(), v8::Integer::New(isolate, 1))
   5408                     .ToLocalChecked()
   5409                     ->NumberValue(context.local())
   5410                     .FromJust());
   5411 
   5412   v8::Local<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
   5413   Local<v8::Array> a3 = Local<v8::Array>::Cast(
   5414       Foo->Call(context.local(), Foo, 3, args3).ToLocalChecked());
   5415   CHECK_EQ(3u, a3->Length());
   5416   CHECK_EQ(4.4, a3->Get(context.local(), v8::Integer::New(isolate, 0))
   5417                     .ToLocalChecked()
   5418                     ->NumberValue(context.local())
   5419                     .FromJust());
   5420   CHECK_EQ(5.5, a3->Get(context.local(), v8::Integer::New(isolate, 1))
   5421                     .ToLocalChecked()
   5422                     ->NumberValue(context.local())
   5423                     .FromJust());
   5424   CHECK_EQ(6.6, a3->Get(context.local(), v8::Integer::New(isolate, 2))
   5425                     .ToLocalChecked()
   5426                     ->NumberValue(context.local())
   5427                     .FromJust());
   5428 
   5429   v8::Local<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
   5430                               v8_num(10.11)};
   5431   Local<v8::Array> a4 = Local<v8::Array>::Cast(
   5432       Foo->Call(context.local(), Foo, 4, args4).ToLocalChecked());
   5433   CHECK_EQ(4u, a4->Length());
   5434   CHECK_EQ(7.7, a4->Get(context.local(), v8::Integer::New(isolate, 0))
   5435                     .ToLocalChecked()
   5436                     ->NumberValue(context.local())
   5437                     .FromJust());
   5438   CHECK_EQ(8.8, a4->Get(context.local(), v8::Integer::New(isolate, 1))
   5439                     .ToLocalChecked()
   5440                     ->NumberValue(context.local())
   5441                     .FromJust());
   5442   CHECK_EQ(9.9, a4->Get(context.local(), v8::Integer::New(isolate, 2))
   5443                     .ToLocalChecked()
   5444                     ->NumberValue(context.local())
   5445                     .FromJust());
   5446   CHECK_EQ(10.11, a4->Get(context.local(), v8::Integer::New(isolate, 3))
   5447                       .ToLocalChecked()
   5448                       ->NumberValue(context.local())
   5449                       .FromJust());
   5450 
   5451   Local<v8::Value> r1 =
   5452       ReturnThisSloppy->Call(context.local(), v8::Undefined(isolate), 0, NULL)
   5453           .ToLocalChecked();
   5454   CHECK(r1->StrictEquals(context->Global()));
   5455   Local<v8::Value> r2 =
   5456       ReturnThisSloppy->Call(context.local(), v8::Null(isolate), 0, NULL)
   5457           .ToLocalChecked();
   5458   CHECK(r2->StrictEquals(context->Global()));
   5459   Local<v8::Value> r3 =
   5460       ReturnThisSloppy->Call(context.local(), v8_num(42), 0, NULL)
   5461           .ToLocalChecked();
   5462   CHECK(r3->IsNumberObject());
   5463   CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
   5464   Local<v8::Value> r4 =
   5465       ReturnThisSloppy->Call(context.local(), v8_str("hello"), 0, NULL)
   5466           .ToLocalChecked();
   5467   CHECK(r4->IsStringObject());
   5468   CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
   5469   Local<v8::Value> r5 =
   5470       ReturnThisSloppy->Call(context.local(), v8::True(isolate), 0, NULL)
   5471           .ToLocalChecked();
   5472   CHECK(r5->IsBooleanObject());
   5473   CHECK(r5.As<v8::BooleanObject>()->ValueOf());
   5474 
   5475   Local<v8::Value> r6 =
   5476       ReturnThisStrict->Call(context.local(), v8::Undefined(isolate), 0, NULL)
   5477           .ToLocalChecked();
   5478   CHECK(r6->IsUndefined());
   5479   Local<v8::Value> r7 =
   5480       ReturnThisStrict->Call(context.local(), v8::Null(isolate), 0, NULL)
   5481           .ToLocalChecked();
   5482   CHECK(r7->IsNull());
   5483   Local<v8::Value> r8 =
   5484       ReturnThisStrict->Call(context.local(), v8_num(42), 0, NULL)
   5485           .ToLocalChecked();
   5486   CHECK(r8->StrictEquals(v8_num(42)));
   5487   Local<v8::Value> r9 =
   5488       ReturnThisStrict->Call(context.local(), v8_str("hello"), 0, NULL)
   5489           .ToLocalChecked();
   5490   CHECK(r9->StrictEquals(v8_str("hello")));
   5491   Local<v8::Value> r10 =
   5492       ReturnThisStrict->Call(context.local(), v8::True(isolate), 0, NULL)
   5493           .ToLocalChecked();
   5494   CHECK(r10->StrictEquals(v8::True(isolate)));
   5495 }
   5496 
   5497 
   5498 THREADED_TEST(ConstructCall) {
   5499   LocalContext context;
   5500   v8::Isolate* isolate = context->GetIsolate();
   5501   v8::HandleScope scope(isolate);
   5502   CompileRun(
   5503       "function Foo() {"
   5504       "  var result = [];"
   5505       "  for (var i = 0; i < arguments.length; i++) {"
   5506       "    result.push(arguments[i]);"
   5507       "  }"
   5508       "  return result;"
   5509       "}");
   5510   Local<Function> Foo = Local<Function>::Cast(
   5511       context->Global()->Get(context.local(), v8_str("Foo")).ToLocalChecked());
   5512 
   5513   v8::Local<Value>* args0 = NULL;
   5514   Local<v8::Array> a0 = Local<v8::Array>::Cast(
   5515       Foo->NewInstance(context.local(), 0, args0).ToLocalChecked());
   5516   CHECK_EQ(0u, a0->Length());
   5517 
   5518   v8::Local<Value> args1[] = {v8_num(1.1)};
   5519   Local<v8::Array> a1 = Local<v8::Array>::Cast(
   5520       Foo->NewInstance(context.local(), 1, args1).ToLocalChecked());
   5521   CHECK_EQ(1u, a1->Length());
   5522   CHECK_EQ(1.1, a1->Get(context.local(), v8::Integer::New(isolate, 0))
   5523                     .ToLocalChecked()
   5524                     ->NumberValue(context.local())
   5525                     .FromJust());
   5526 
   5527   v8::Local<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
   5528   Local<v8::Array> a2 = Local<v8::Array>::Cast(
   5529       Foo->NewInstance(context.local(), 2, args2).ToLocalChecked());
   5530   CHECK_EQ(2u, a2->Length());
   5531   CHECK_EQ(2.2, a2->Get(context.local(), v8::Integer::New(isolate, 0))
   5532                     .ToLocalChecked()
   5533                     ->NumberValue(context.local())
   5534                     .FromJust());
   5535   CHECK_EQ(3.3, a2->Get(context.local(), v8::Integer::New(isolate, 1))
   5536                     .ToLocalChecked()
   5537                     ->NumberValue(context.local())
   5538                     .FromJust());
   5539 
   5540   v8::Local<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
   5541   Local<v8::Array> a3 = Local<v8::Array>::Cast(
   5542       Foo->NewInstance(context.local(), 3, args3).ToLocalChecked());
   5543   CHECK_EQ(3u, a3->Length());
   5544   CHECK_EQ(4.4, a3->Get(context.local(), v8::Integer::New(isolate, 0))
   5545                     .ToLocalChecked()
   5546                     ->NumberValue(context.local())
   5547                     .FromJust());
   5548   CHECK_EQ(5.5, a3->Get(context.local(), v8::Integer::New(isolate, 1))
   5549                     .ToLocalChecked()
   5550                     ->NumberValue(context.local())
   5551                     .FromJust());
   5552   CHECK_EQ(6.6, a3->Get(context.local(), v8::Integer::New(isolate, 2))
   5553                     .ToLocalChecked()
   5554                     ->NumberValue(context.local())
   5555                     .FromJust());
   5556 
   5557   v8::Local<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
   5558                               v8_num(10.11)};
   5559   Local<v8::Array> a4 = Local<v8::Array>::Cast(
   5560       Foo->NewInstance(context.local(), 4, args4).ToLocalChecked());
   5561   CHECK_EQ(4u, a4->Length());
   5562   CHECK_EQ(7.7, a4->Get(context.local(), v8::Integer::New(isolate, 0))
   5563                     .ToLocalChecked()
   5564                     ->NumberValue(context.local())
   5565                     .FromJust());
   5566   CHECK_EQ(8.8, a4->Get(context.local(), v8::Integer::New(isolate, 1))
   5567                     .ToLocalChecked()
   5568                     ->NumberValue(context.local())
   5569                     .FromJust());
   5570   CHECK_EQ(9.9, a4->Get(context.local(), v8::Integer::New(isolate, 2))
   5571                     .ToLocalChecked()
   5572                     ->NumberValue(context.local())
   5573                     .FromJust());
   5574   CHECK_EQ(10.11, a4->Get(context.local(), v8::Integer::New(isolate, 3))
   5575                       .ToLocalChecked()
   5576                       ->NumberValue(context.local())
   5577                       .FromJust());
   5578 }
   5579 
   5580 
   5581 THREADED_TEST(ConversionNumber) {
   5582   LocalContext env;
   5583   v8::Isolate* isolate = env->GetIsolate();
   5584   v8::HandleScope scope(isolate);
   5585   // Very large number.
   5586   CompileRun("var obj = Math.pow(2,32) * 1237;");
   5587   Local<Value> obj =
   5588       env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5589   CHECK_EQ(5312874545152.0,
   5590            obj->ToNumber(env.local()).ToLocalChecked()->Value());
   5591   CHECK_EQ(0, obj->ToInt32(env.local()).ToLocalChecked()->Value());
   5592   CHECK(0u ==
   5593         obj->ToUint32(env.local())
   5594             .ToLocalChecked()
   5595             ->Value());  // NOLINT - no CHECK_EQ for unsigned.
   5596   // Large number.
   5597   CompileRun("var obj = -1234567890123;");
   5598   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5599   CHECK_EQ(-1234567890123.0,
   5600            obj->ToNumber(env.local()).ToLocalChecked()->Value());
   5601   CHECK_EQ(-1912276171, obj->ToInt32(env.local()).ToLocalChecked()->Value());
   5602   CHECK(2382691125u ==
   5603         obj->ToUint32(env.local()).ToLocalChecked()->Value());  // NOLINT
   5604   // Small positive integer.
   5605   CompileRun("var obj = 42;");
   5606   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5607   CHECK_EQ(42.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
   5608   CHECK_EQ(42, obj->ToInt32(env.local()).ToLocalChecked()->Value());
   5609   CHECK(42u == obj->ToUint32(env.local()).ToLocalChecked()->Value());  // NOLINT
   5610   // Negative integer.
   5611   CompileRun("var obj = -37;");
   5612   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5613   CHECK_EQ(-37.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
   5614   CHECK_EQ(-37, obj->ToInt32(env.local()).ToLocalChecked()->Value());
   5615   CHECK(4294967259u ==
   5616         obj->ToUint32(env.local()).ToLocalChecked()->Value());  // NOLINT
   5617   // Positive non-int32 integer.
   5618   CompileRun("var obj = 0x81234567;");
   5619   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5620   CHECK_EQ(2166572391.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
   5621   CHECK_EQ(-2128394905, obj->ToInt32(env.local()).ToLocalChecked()->Value());
   5622   CHECK(2166572391u ==
   5623         obj->ToUint32(env.local()).ToLocalChecked()->Value());  // NOLINT
   5624   // Fraction.
   5625   CompileRun("var obj = 42.3;");
   5626   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5627   CHECK_EQ(42.3, obj->ToNumber(env.local()).ToLocalChecked()->Value());
   5628   CHECK_EQ(42, obj->ToInt32(env.local()).ToLocalChecked()->Value());
   5629   CHECK(42u == obj->ToUint32(env.local()).ToLocalChecked()->Value());  // NOLINT
   5630   // Large negative fraction.
   5631   CompileRun("var obj = -5726623061.75;");
   5632   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5633   CHECK_EQ(-5726623061.75,
   5634            obj->ToNumber(env.local()).ToLocalChecked()->Value());
   5635   CHECK_EQ(-1431655765, obj->ToInt32(env.local()).ToLocalChecked()->Value());
   5636   CHECK(2863311531u ==
   5637         obj->ToUint32(env.local()).ToLocalChecked()->Value());  // NOLINT
   5638 }
   5639 
   5640 
   5641 THREADED_TEST(isNumberType) {
   5642   LocalContext env;
   5643   v8::HandleScope scope(env->GetIsolate());
   5644   // Very large number.
   5645   CompileRun("var obj = Math.pow(2,32) * 1237;");
   5646   Local<Value> obj =
   5647       env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5648   CHECK(!obj->IsInt32());
   5649   CHECK(!obj->IsUint32());
   5650   // Large negative number.
   5651   CompileRun("var obj = -1234567890123;");
   5652   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5653   CHECK(!obj->IsInt32());
   5654   CHECK(!obj->IsUint32());
   5655   // Small positive integer.
   5656   CompileRun("var obj = 42;");
   5657   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5658   CHECK(obj->IsInt32());
   5659   CHECK(obj->IsUint32());
   5660   // Negative integer.
   5661   CompileRun("var obj = -37;");
   5662   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5663   CHECK(obj->IsInt32());
   5664   CHECK(!obj->IsUint32());
   5665   // Positive non-int32 integer.
   5666   CompileRun("var obj = 0x81234567;");
   5667   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5668   CHECK(!obj->IsInt32());
   5669   CHECK(obj->IsUint32());
   5670   // Fraction.
   5671   CompileRun("var obj = 42.3;");
   5672   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5673   CHECK(!obj->IsInt32());
   5674   CHECK(!obj->IsUint32());
   5675   // Large negative fraction.
   5676   CompileRun("var obj = -5726623061.75;");
   5677   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5678   CHECK(!obj->IsInt32());
   5679   CHECK(!obj->IsUint32());
   5680   // Positive zero
   5681   CompileRun("var obj = 0.0;");
   5682   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5683   CHECK(obj->IsInt32());
   5684   CHECK(obj->IsUint32());
   5685   // Positive zero
   5686   CompileRun("var obj = -0.0;");
   5687   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5688   CHECK(!obj->IsInt32());
   5689   CHECK(!obj->IsUint32());
   5690 }
   5691 
   5692 
   5693 static void CheckUncle(v8::TryCatch* try_catch) {
   5694   CHECK(try_catch->HasCaught());
   5695   String::Utf8Value str_value(try_catch->Exception());
   5696   CHECK_EQ(0, strcmp(*str_value, "uncle?"));
   5697   try_catch->Reset();
   5698 }
   5699 
   5700 
   5701 THREADED_TEST(ConversionException) {
   5702   LocalContext env;
   5703   v8::Isolate* isolate = env->GetIsolate();
   5704   v8::HandleScope scope(isolate);
   5705   CompileRun(
   5706       "function TestClass() { };"
   5707       "TestClass.prototype.toString = function () { throw 'uncle?'; };"
   5708       "var obj = new TestClass();");
   5709   Local<Value> obj =
   5710       env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5711 
   5712   v8::TryCatch try_catch(isolate);
   5713 
   5714   CHECK(obj->ToString(env.local()).IsEmpty());
   5715   CheckUncle(&try_catch);
   5716 
   5717   CHECK(obj->ToNumber(env.local()).IsEmpty());
   5718   CheckUncle(&try_catch);
   5719 
   5720   CHECK(obj->ToInteger(env.local()).IsEmpty());
   5721   CheckUncle(&try_catch);
   5722 
   5723   CHECK(obj->ToUint32(env.local()).IsEmpty());
   5724   CheckUncle(&try_catch);
   5725 
   5726   CHECK(obj->ToInt32(env.local()).IsEmpty());
   5727   CheckUncle(&try_catch);
   5728 
   5729   CHECK(v8::Undefined(isolate)->ToObject(env.local()).IsEmpty());
   5730   CHECK(try_catch.HasCaught());
   5731   try_catch.Reset();
   5732 
   5733   CHECK(obj->Int32Value(env.local()).IsNothing());
   5734   CheckUncle(&try_catch);
   5735 
   5736   CHECK(obj->Uint32Value(env.local()).IsNothing());
   5737   CheckUncle(&try_catch);
   5738 
   5739   CHECK(obj->NumberValue(env.local()).IsNothing());
   5740   CheckUncle(&try_catch);
   5741 
   5742   CHECK(obj->IntegerValue(env.local()).IsNothing());
   5743   CheckUncle(&try_catch);
   5744 }
   5745 
   5746 
   5747 void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
   5748   ApiTestFuzzer::Fuzz();
   5749   args.GetIsolate()->ThrowException(v8_str("konto"));
   5750 }
   5751 
   5752 
   5753 void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
   5754   if (args.Length() < 1) {
   5755     args.GetReturnValue().Set(false);
   5756     return;
   5757   }
   5758   v8::HandleScope scope(args.GetIsolate());
   5759   v8::TryCatch try_catch(args.GetIsolate());
   5760   Local<Value> result =
   5761       CompileRun(args[0]
   5762                      ->ToString(args.GetIsolate()->GetCurrentContext())
   5763                      .ToLocalChecked());
   5764   CHECK(!try_catch.HasCaught() || result.IsEmpty());
   5765   args.GetReturnValue().Set(try_catch.HasCaught());
   5766 }
   5767 
   5768 
   5769 THREADED_TEST(APICatch) {
   5770   v8::Isolate* isolate = CcTest::isolate();
   5771   v8::HandleScope scope(isolate);
   5772   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5773   templ->Set(v8_str("ThrowFromC"),
   5774              v8::FunctionTemplate::New(isolate, ThrowFromC));
   5775   LocalContext context(0, templ);
   5776   CompileRun(
   5777       "var thrown = false;"
   5778       "try {"
   5779       "  ThrowFromC();"
   5780       "} catch (e) {"
   5781       "  thrown = true;"
   5782       "}");
   5783   Local<Value> thrown = context->Global()
   5784                             ->Get(context.local(), v8_str("thrown"))
   5785                             .ToLocalChecked();
   5786   CHECK(thrown->BooleanValue(context.local()).FromJust());
   5787 }
   5788 
   5789 
   5790 THREADED_TEST(APIThrowTryCatch) {
   5791   v8::Isolate* isolate = CcTest::isolate();
   5792   v8::HandleScope scope(isolate);
   5793   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5794   templ->Set(v8_str("ThrowFromC"),
   5795              v8::FunctionTemplate::New(isolate, ThrowFromC));
   5796   LocalContext context(0, templ);
   5797   v8::TryCatch try_catch(isolate);
   5798   CompileRun("ThrowFromC();");
   5799   CHECK(try_catch.HasCaught());
   5800 }
   5801 
   5802 
   5803 // Test that a try-finally block doesn't shadow a try-catch block
   5804 // when setting up an external handler.
   5805 //
   5806 // BUG(271): Some of the exception propagation does not work on the
   5807 // ARM simulator because the simulator separates the C++ stack and the
   5808 // JS stack.  This test therefore fails on the simulator.  The test is
   5809 // not threaded to allow the threading tests to run on the simulator.
   5810 TEST(TryCatchInTryFinally) {
   5811   v8::Isolate* isolate = CcTest::isolate();
   5812   v8::HandleScope scope(isolate);
   5813   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5814   templ->Set(v8_str("CCatcher"), v8::FunctionTemplate::New(isolate, CCatcher));
   5815   LocalContext context(0, templ);
   5816   Local<Value> result = CompileRun(
   5817       "try {"
   5818       "  try {"
   5819       "    CCatcher('throw 7;');"
   5820       "  } finally {"
   5821       "  }"
   5822       "} catch (e) {"
   5823       "}");
   5824   CHECK(result->IsTrue());
   5825 }
   5826 
   5827 
   5828 static void check_custom_error_tostring(v8::Local<v8::Message> message,
   5829                                         v8::Local<v8::Value> data) {
   5830   const char* uncaught_error = "Uncaught MyError toString";
   5831   CHECK(message->Get()
   5832             ->Equals(CcTest::isolate()->GetCurrentContext(),
   5833                      v8_str(uncaught_error))
   5834             .FromJust());
   5835 }
   5836 
   5837 
   5838 TEST(CustomErrorToString) {
   5839   LocalContext context;
   5840   v8::HandleScope scope(context->GetIsolate());
   5841   context->GetIsolate()->AddMessageListener(check_custom_error_tostring);
   5842   CompileRun(
   5843       "function MyError(name, message) {                   "
   5844       "  this.name = name;                                 "
   5845       "  this.message = message;                           "
   5846       "}                                                   "
   5847       "MyError.prototype = Object.create(Error.prototype); "
   5848       "MyError.prototype.toString = function() {           "
   5849       "  return 'MyError toString';                        "
   5850       "};                                                  "
   5851       "throw new MyError('my name', 'my message');         ");
   5852   context->GetIsolate()->RemoveMessageListeners(check_custom_error_tostring);
   5853 }
   5854 
   5855 
   5856 static void check_custom_error_message(v8::Local<v8::Message> message,
   5857                                        v8::Local<v8::Value> data) {
   5858   const char* uncaught_error = "Uncaught MyError: my message";
   5859   printf("%s\n", *v8::String::Utf8Value(message->Get()));
   5860   CHECK(message->Get()
   5861             ->Equals(CcTest::isolate()->GetCurrentContext(),
   5862                      v8_str(uncaught_error))
   5863             .FromJust());
   5864 }
   5865 
   5866 
   5867 TEST(CustomErrorMessage) {
   5868   LocalContext context;
   5869   v8::HandleScope scope(context->GetIsolate());
   5870   context->GetIsolate()->AddMessageListener(check_custom_error_message);
   5871 
   5872   // Handlebars.
   5873   CompileRun(
   5874       "function MyError(msg) {                             "
   5875       "  this.name = 'MyError';                            "
   5876       "  this.message = msg;                               "
   5877       "}                                                   "
   5878       "MyError.prototype = new Error();                    "
   5879       "throw new MyError('my message');                    ");
   5880 
   5881   // Closure.
   5882   CompileRun(
   5883       "function MyError(msg) {                             "
   5884       "  this.name = 'MyError';                            "
   5885       "  this.message = msg;                               "
   5886       "}                                                   "
   5887       "inherits = function(childCtor, parentCtor) {        "
   5888       "    function tempCtor() {};                         "
   5889       "    tempCtor.prototype = parentCtor.prototype;      "
   5890       "    childCtor.superClass_ = parentCtor.prototype;   "
   5891       "    childCtor.prototype = new tempCtor();           "
   5892       "    childCtor.prototype.constructor = childCtor;    "
   5893       "};                                                  "
   5894       "inherits(MyError, Error);                           "
   5895       "throw new MyError('my message');                    ");
   5896 
   5897   // Object.create.
   5898   CompileRun(
   5899       "function MyError(msg) {                             "
   5900       "  this.name = 'MyError';                            "
   5901       "  this.message = msg;                               "
   5902       "}                                                   "
   5903       "MyError.prototype = Object.create(Error.prototype); "
   5904       "throw new MyError('my message');                    ");
   5905 
   5906   context->GetIsolate()->RemoveMessageListeners(check_custom_error_message);
   5907 }
   5908 
   5909 
   5910 static void check_custom_rethrowing_message(v8::Local<v8::Message> message,
   5911                                             v8::Local<v8::Value> data) {
   5912   const char* uncaught_error = "Uncaught exception";
   5913   CHECK(message->Get()
   5914             ->Equals(CcTest::isolate()->GetCurrentContext(),
   5915                      v8_str(uncaught_error))
   5916             .FromJust());
   5917 }
   5918 
   5919 
   5920 TEST(CustomErrorRethrowsOnToString) {
   5921   LocalContext context;
   5922   v8::HandleScope scope(context->GetIsolate());
   5923   context->GetIsolate()->AddMessageListener(check_custom_rethrowing_message);
   5924 
   5925   CompileRun(
   5926       "var e = { toString: function() { throw e; } };"
   5927       "try { throw e; } finally {}");
   5928 
   5929   context->GetIsolate()->RemoveMessageListeners(
   5930       check_custom_rethrowing_message);
   5931 }
   5932 
   5933 
   5934 static void receive_message(v8::Local<v8::Message> message,
   5935                             v8::Local<v8::Value> data) {
   5936   message->Get();
   5937   message_received = true;
   5938 }
   5939 
   5940 
   5941 TEST(APIThrowMessage) {
   5942   message_received = false;
   5943   v8::Isolate* isolate = CcTest::isolate();
   5944   v8::HandleScope scope(isolate);
   5945   isolate->AddMessageListener(receive_message);
   5946   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5947   templ->Set(v8_str("ThrowFromC"),
   5948              v8::FunctionTemplate::New(isolate, ThrowFromC));
   5949   LocalContext context(0, templ);
   5950   CompileRun("ThrowFromC();");
   5951   CHECK(message_received);
   5952   isolate->RemoveMessageListeners(receive_message);
   5953 }
   5954 
   5955 
   5956 TEST(APIThrowMessageAndVerboseTryCatch) {
   5957   message_received = false;
   5958   v8::Isolate* isolate = CcTest::isolate();
   5959   v8::HandleScope scope(isolate);
   5960   isolate->AddMessageListener(receive_message);
   5961   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5962   templ->Set(v8_str("ThrowFromC"),
   5963              v8::FunctionTemplate::New(isolate, ThrowFromC));
   5964   LocalContext context(0, templ);
   5965   v8::TryCatch try_catch(isolate);
   5966   try_catch.SetVerbose(true);
   5967   Local<Value> result = CompileRun("ThrowFromC();");
   5968   CHECK(try_catch.HasCaught());
   5969   CHECK(result.IsEmpty());
   5970   CHECK(message_received);
   5971   isolate->RemoveMessageListeners(receive_message);
   5972 }
   5973 
   5974 
   5975 TEST(APIStackOverflowAndVerboseTryCatch) {
   5976   message_received = false;
   5977   LocalContext context;
   5978   v8::HandleScope scope(context->GetIsolate());
   5979   context->GetIsolate()->AddMessageListener(receive_message);
   5980   v8::TryCatch try_catch(context->GetIsolate());
   5981   try_catch.SetVerbose(true);
   5982   Local<Value> result = CompileRun("function foo() { foo(); } foo();");
   5983   CHECK(try_catch.HasCaught());
   5984   CHECK(result.IsEmpty());
   5985   CHECK(message_received);
   5986   context->GetIsolate()->RemoveMessageListeners(receive_message);
   5987 }
   5988 
   5989 
   5990 THREADED_TEST(ExternalScriptException) {
   5991   v8::Isolate* isolate = CcTest::isolate();
   5992   v8::HandleScope scope(isolate);
   5993   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5994   templ->Set(v8_str("ThrowFromC"),
   5995              v8::FunctionTemplate::New(isolate, ThrowFromC));
   5996   LocalContext context(0, templ);
   5997 
   5998   v8::TryCatch try_catch(isolate);
   5999   Local<Value> result = CompileRun("ThrowFromC(); throw 'panama';");
   6000   CHECK(result.IsEmpty());
   6001   CHECK(try_catch.HasCaught());
   6002   String::Utf8Value exception_value(try_catch.Exception());
   6003   CHECK_EQ(0, strcmp("konto", *exception_value));
   6004 }
   6005 
   6006 
   6007 void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
   6008   ApiTestFuzzer::Fuzz();
   6009   CHECK_EQ(4, args.Length());
   6010   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   6011   int count = args[0]->Int32Value(context).FromJust();
   6012   int cInterval = args[2]->Int32Value(context).FromJust();
   6013   if (count == 0) {
   6014     args.GetIsolate()->ThrowException(v8_str("FromC"));
   6015     return;
   6016   } else {
   6017     Local<v8::Object> global = context->Global();
   6018     Local<Value> fun =
   6019         global->Get(context, v8_str("JSThrowCountDown")).ToLocalChecked();
   6020     v8::Local<Value> argv[] = {v8_num(count - 1), args[1], args[2], args[3]};
   6021     if (count % cInterval == 0) {
   6022       v8::TryCatch try_catch(args.GetIsolate());
   6023       Local<Value> result = fun.As<Function>()
   6024                                 ->Call(context, global, 4, argv)
   6025                                 .FromMaybe(Local<Value>());
   6026       int expected = args[3]->Int32Value(context).FromJust();
   6027       if (try_catch.HasCaught()) {
   6028         CHECK_EQ(expected, count);
   6029         CHECK(result.IsEmpty());
   6030         CHECK(!CcTest::i_isolate()->has_scheduled_exception());
   6031       } else {
   6032         CHECK_NE(expected, count);
   6033       }
   6034       args.GetReturnValue().Set(result);
   6035       return;
   6036     } else {
   6037       args.GetReturnValue().Set(fun.As<Function>()
   6038                                     ->Call(context, global, 4, argv)
   6039                                     .FromMaybe(v8::Local<v8::Value>()));
   6040       return;
   6041     }
   6042   }
   6043 }
   6044 
   6045 
   6046 void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
   6047   ApiTestFuzzer::Fuzz();
   6048   CHECK_EQ(3, args.Length());
   6049   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   6050   bool equality = args[0]->BooleanValue(context).FromJust();
   6051   int count = args[1]->Int32Value(context).FromJust();
   6052   int expected = args[2]->Int32Value(context).FromJust();
   6053   if (equality) {
   6054     CHECK_EQ(count, expected);
   6055   } else {
   6056     CHECK_NE(count, expected);
   6057   }
   6058 }
   6059 
   6060 
   6061 THREADED_TEST(EvalInTryFinally) {
   6062   LocalContext context;
   6063   v8::HandleScope scope(context->GetIsolate());
   6064   v8::TryCatch try_catch(context->GetIsolate());
   6065   CompileRun(
   6066       "(function() {"
   6067       "  try {"
   6068       "    eval('asldkf (*&^&*^');"
   6069       "  } finally {"
   6070       "    return;"
   6071       "  }"
   6072       "})()");
   6073   CHECK(!try_catch.HasCaught());
   6074 }
   6075 
   6076 
   6077 // This test works by making a stack of alternating JavaScript and C
   6078 // activations.  These activations set up exception handlers with regular
   6079 // intervals, one interval for C activations and another for JavaScript
   6080 // activations.  When enough activations have been created an exception is
   6081 // thrown and we check that the right activation catches the exception and that
   6082 // no other activations do.  The right activation is always the topmost one with
   6083 // a handler, regardless of whether it is in JavaScript or C.
   6084 //
   6085 // The notation used to describe a test case looks like this:
   6086 //
   6087 //    *JS[4] *C[3] @JS[2] C[1] JS[0]
   6088 //
   6089 // Each entry is an activation, either JS or C.  The index is the count at that
   6090 // level.  Stars identify activations with exception handlers, the @ identifies
   6091 // the exception handler that should catch the exception.
   6092 //
   6093 // BUG(271): Some of the exception propagation does not work on the
   6094 // ARM simulator because the simulator separates the C++ stack and the
   6095 // JS stack.  This test therefore fails on the simulator.  The test is
   6096 // not threaded to allow the threading tests to run on the simulator.
   6097 TEST(ExceptionOrder) {
   6098   v8::Isolate* isolate = CcTest::isolate();
   6099   v8::HandleScope scope(isolate);
   6100   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6101   templ->Set(v8_str("check"), v8::FunctionTemplate::New(isolate, JSCheck));
   6102   templ->Set(v8_str("CThrowCountDown"),
   6103              v8::FunctionTemplate::New(isolate, CThrowCountDown));
   6104   LocalContext context(0, templ);
   6105   CompileRun(
   6106       "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
   6107       "  if (count == 0) throw 'FromJS';"
   6108       "  if (count % jsInterval == 0) {"
   6109       "    try {"
   6110       "      var value = CThrowCountDown(count - 1,"
   6111       "                                  jsInterval,"
   6112       "                                  cInterval,"
   6113       "                                  expected);"
   6114       "      check(false, count, expected);"
   6115       "      return value;"
   6116       "    } catch (e) {"
   6117       "      check(true, count, expected);"
   6118       "    }"
   6119       "  } else {"
   6120       "    return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
   6121       "  }"
   6122       "}");
   6123   Local<Function> fun = Local<Function>::Cast(
   6124       context->Global()
   6125           ->Get(context.local(), v8_str("JSThrowCountDown"))
   6126           .ToLocalChecked());
   6127 
   6128   const int argc = 4;
   6129   //                             count      jsInterval cInterval  expected
   6130 
   6131   // *JS[4] *C[3] @JS[2] C[1] JS[0]
   6132   v8::Local<Value> a0[argc] = {v8_num(4), v8_num(2), v8_num(3), v8_num(2)};
   6133   fun->Call(context.local(), fun, argc, a0).ToLocalChecked();
   6134 
   6135   // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
   6136   v8::Local<Value> a1[argc] = {v8_num(5), v8_num(6), v8_num(1), v8_num(2)};
   6137   fun->Call(context.local(), fun, argc, a1).ToLocalChecked();
   6138 
   6139   // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
   6140   v8::Local<Value> a2[argc] = {v8_num(6), v8_num(7), v8_num(5), v8_num(5)};
   6141   fun->Call(context.local(), fun, argc, a2).ToLocalChecked();
   6142 
   6143   // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
   6144   v8::Local<Value> a3[argc] = {v8_num(6), v8_num(6), v8_num(7), v8_num(6)};
   6145   fun->Call(context.local(), fun, argc, a3).ToLocalChecked();
   6146 
   6147   // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
   6148   v8::Local<Value> a4[argc] = {v8_num(6), v8_num(4), v8_num(5), v8_num(4)};
   6149   fun->Call(context.local(), fun, argc, a4).ToLocalChecked();
   6150 
   6151   // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
   6152   v8::Local<Value> a5[argc] = {v8_num(6), v8_num(4), v8_num(3), v8_num(3)};
   6153   fun->Call(context.local(), fun, argc, a5).ToLocalChecked();
   6154 }
   6155 
   6156 
   6157 void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
   6158   ApiTestFuzzer::Fuzz();
   6159   CHECK_EQ(1, args.Length());
   6160   args.GetIsolate()->ThrowException(args[0]);
   6161 }
   6162 
   6163 
   6164 THREADED_TEST(ThrowValues) {
   6165   v8::Isolate* isolate = CcTest::isolate();
   6166   v8::HandleScope scope(isolate);
   6167   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6168   templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(isolate, ThrowValue));
   6169   LocalContext context(0, templ);
   6170   v8::Local<v8::Array> result = v8::Local<v8::Array>::Cast(
   6171       CompileRun("function Run(obj) {"
   6172                  "  try {"
   6173                  "    Throw(obj);"
   6174                  "  } catch (e) {"
   6175                  "    return e;"
   6176                  "  }"
   6177                  "  return 'no exception';"
   6178                  "}"
   6179                  "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
   6180   CHECK_EQ(5u, result->Length());
   6181   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 0))
   6182             .ToLocalChecked()
   6183             ->IsString());
   6184   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 1))
   6185             .ToLocalChecked()
   6186             ->IsNumber());
   6187   CHECK_EQ(1, result->Get(context.local(), v8::Integer::New(isolate, 1))
   6188                   .ToLocalChecked()
   6189                   ->Int32Value(context.local())
   6190                   .FromJust());
   6191   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 2))
   6192             .ToLocalChecked()
   6193             ->IsNumber());
   6194   CHECK_EQ(0, result->Get(context.local(), v8::Integer::New(isolate, 2))
   6195                   .ToLocalChecked()
   6196                   ->Int32Value(context.local())
   6197                   .FromJust());
   6198   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 3))
   6199             .ToLocalChecked()
   6200             ->IsNull());
   6201   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 4))
   6202             .ToLocalChecked()
   6203             ->IsUndefined());
   6204 }
   6205 
   6206 
   6207 THREADED_TEST(CatchZero) {
   6208   LocalContext context;
   6209   v8::HandleScope scope(context->GetIsolate());
   6210   v8::TryCatch try_catch(context->GetIsolate());
   6211   CHECK(!try_catch.HasCaught());
   6212   CompileRun("throw 10");
   6213   CHECK(try_catch.HasCaught());
   6214   CHECK_EQ(10, try_catch.Exception()->Int32Value(context.local()).FromJust());
   6215   try_catch.Reset();
   6216   CHECK(!try_catch.HasCaught());
   6217   CompileRun("throw 0");
   6218   CHECK(try_catch.HasCaught());
   6219   CHECK_EQ(0, try_catch.Exception()->Int32Value(context.local()).FromJust());
   6220 }
   6221 
   6222 
   6223 THREADED_TEST(CatchExceptionFromWith) {
   6224   LocalContext context;
   6225   v8::HandleScope scope(context->GetIsolate());
   6226   v8::TryCatch try_catch(context->GetIsolate());
   6227   CHECK(!try_catch.HasCaught());
   6228   CompileRun("var o = {}; with (o) { throw 42; }");
   6229   CHECK(try_catch.HasCaught());
   6230 }
   6231 
   6232 
   6233 THREADED_TEST(TryCatchAndFinallyHidingException) {
   6234   LocalContext context;
   6235   v8::HandleScope scope(context->GetIsolate());
   6236   v8::TryCatch try_catch(context->GetIsolate());
   6237   CHECK(!try_catch.HasCaught());
   6238   CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
   6239   CompileRun("f({toString: function() { throw 42; }});");
   6240   CHECK(!try_catch.HasCaught());
   6241 }
   6242 
   6243 
   6244 void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
   6245   v8::TryCatch try_catch(args.GetIsolate());
   6246 }
   6247 
   6248 
   6249 THREADED_TEST(TryCatchAndFinally) {
   6250   LocalContext context;
   6251   v8::Isolate* isolate = context->GetIsolate();
   6252   v8::HandleScope scope(isolate);
   6253   CHECK(context->Global()
   6254             ->Set(context.local(), v8_str("native_with_try_catch"),
   6255                   v8::FunctionTemplate::New(isolate, WithTryCatch)
   6256                       ->GetFunction(context.local())
   6257                       .ToLocalChecked())
   6258             .FromJust());
   6259   v8::TryCatch try_catch(isolate);
   6260   CHECK(!try_catch.HasCaught());
   6261   CompileRun(
   6262       "try {\n"
   6263       "  throw new Error('a');\n"
   6264       "} finally {\n"
   6265       "  native_with_try_catch();\n"
   6266       "}\n");
   6267   CHECK(try_catch.HasCaught());
   6268 }
   6269 
   6270 
   6271 static void TryCatchNested1Helper(int depth) {
   6272   if (depth > 0) {
   6273     v8::TryCatch try_catch(CcTest::isolate());
   6274     try_catch.SetVerbose(true);
   6275     TryCatchNested1Helper(depth - 1);
   6276     CHECK(try_catch.HasCaught());
   6277     try_catch.ReThrow();
   6278   } else {
   6279     CcTest::isolate()->ThrowException(v8_str("E1"));
   6280   }
   6281 }
   6282 
   6283 
   6284 static void TryCatchNested2Helper(int depth) {
   6285   if (depth > 0) {
   6286     v8::TryCatch try_catch(CcTest::isolate());
   6287     try_catch.SetVerbose(true);
   6288     TryCatchNested2Helper(depth - 1);
   6289     CHECK(try_catch.HasCaught());
   6290     try_catch.ReThrow();
   6291   } else {
   6292     CompileRun("throw 'E2';");
   6293   }
   6294 }
   6295 
   6296 
   6297 TEST(TryCatchNested) {
   6298   v8::V8::Initialize();
   6299   LocalContext context;
   6300   v8::HandleScope scope(context->GetIsolate());
   6301 
   6302   {
   6303     // Test nested try-catch with a native throw in the end.
   6304     v8::TryCatch try_catch(context->GetIsolate());
   6305     TryCatchNested1Helper(5);
   6306     CHECK(try_catch.HasCaught());
   6307     CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E1"));
   6308   }
   6309 
   6310   {
   6311     // Test nested try-catch with a JavaScript throw in the end.
   6312     v8::TryCatch try_catch(context->GetIsolate());
   6313     TryCatchNested2Helper(5);
   6314     CHECK(try_catch.HasCaught());
   6315     CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E2"));
   6316   }
   6317 }
   6318 
   6319 
   6320 void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
   6321   CHECK(try_catch->HasCaught());
   6322   Local<Message> message = try_catch->Message();
   6323   Local<Value> resource = message->GetScriptOrigin().ResourceName();
   6324   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
   6325   CHECK_EQ(0,
   6326            strcmp(*v8::String::Utf8Value(message->Get()), "Uncaught Error: a"));
   6327   CHECK_EQ(1, message->GetLineNumber(CcTest::isolate()->GetCurrentContext())
   6328                   .FromJust());
   6329   CHECK_EQ(0, message->GetStartColumn(CcTest::isolate()->GetCurrentContext())
   6330                   .FromJust());
   6331 }
   6332 
   6333 
   6334 void TryCatchMixedNestingHelper(
   6335     const v8::FunctionCallbackInfo<v8::Value>& args) {
   6336   ApiTestFuzzer::Fuzz();
   6337   v8::TryCatch try_catch(args.GetIsolate());
   6338   CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
   6339   CHECK(try_catch.HasCaught());
   6340   TryCatchMixedNestingCheck(&try_catch);
   6341   try_catch.ReThrow();
   6342 }
   6343 
   6344 
   6345 // This test ensures that an outer TryCatch in the following situation:
   6346 //   C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
   6347 // does not clobber the Message object generated for the inner TryCatch.
   6348 // This exercises the ability of TryCatch.ReThrow() to restore the
   6349 // inner pending Message before throwing the exception again.
   6350 TEST(TryCatchMixedNesting) {
   6351   v8::Isolate* isolate = CcTest::isolate();
   6352   v8::HandleScope scope(isolate);
   6353   v8::V8::Initialize();
   6354   v8::TryCatch try_catch(isolate);
   6355   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6356   templ->Set(v8_str("TryCatchMixedNestingHelper"),
   6357              v8::FunctionTemplate::New(isolate, TryCatchMixedNestingHelper));
   6358   LocalContext context(0, templ);
   6359   CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
   6360   TryCatchMixedNestingCheck(&try_catch);
   6361 }
   6362 
   6363 
   6364 void TryCatchNativeHelper(const v8::FunctionCallbackInfo<v8::Value>& args) {
   6365   ApiTestFuzzer::Fuzz();
   6366   v8::TryCatch try_catch(args.GetIsolate());
   6367   args.GetIsolate()->ThrowException(v8_str("boom"));
   6368   CHECK(try_catch.HasCaught());
   6369 }
   6370 
   6371 
   6372 TEST(TryCatchNative) {
   6373   v8::Isolate* isolate = CcTest::isolate();
   6374   v8::HandleScope scope(isolate);
   6375   v8::V8::Initialize();
   6376   v8::TryCatch try_catch(isolate);
   6377   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6378   templ->Set(v8_str("TryCatchNativeHelper"),
   6379              v8::FunctionTemplate::New(isolate, TryCatchNativeHelper));
   6380   LocalContext context(0, templ);
   6381   CompileRun("TryCatchNativeHelper();");
   6382   CHECK(!try_catch.HasCaught());
   6383 }
   6384 
   6385 
   6386 void TryCatchNativeResetHelper(
   6387     const v8::FunctionCallbackInfo<v8::Value>& args) {
   6388   ApiTestFuzzer::Fuzz();
   6389   v8::TryCatch try_catch(args.GetIsolate());
   6390   args.GetIsolate()->ThrowException(v8_str("boom"));
   6391   CHECK(try_catch.HasCaught());
   6392   try_catch.Reset();
   6393   CHECK(!try_catch.HasCaught());
   6394 }
   6395 
   6396 
   6397 TEST(TryCatchNativeReset) {
   6398   v8::Isolate* isolate = CcTest::isolate();
   6399   v8::HandleScope scope(isolate);
   6400   v8::V8::Initialize();
   6401   v8::TryCatch try_catch(isolate);
   6402   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6403   templ->Set(v8_str("TryCatchNativeResetHelper"),
   6404              v8::FunctionTemplate::New(isolate, TryCatchNativeResetHelper));
   6405   LocalContext context(0, templ);
   6406   CompileRun("TryCatchNativeResetHelper();");
   6407   CHECK(!try_catch.HasCaught());
   6408 }
   6409 
   6410 
   6411 THREADED_TEST(Equality) {
   6412   LocalContext context;
   6413   v8::Isolate* isolate = context->GetIsolate();
   6414   v8::HandleScope scope(context->GetIsolate());
   6415   // Check that equality works at all before relying on CHECK_EQ
   6416   CHECK(v8_str("a")->Equals(context.local(), v8_str("a")).FromJust());
   6417   CHECK(!v8_str("a")->Equals(context.local(), v8_str("b")).FromJust());
   6418 
   6419   CHECK(v8_str("a")->Equals(context.local(), v8_str("a")).FromJust());
   6420   CHECK(!v8_str("a")->Equals(context.local(), v8_str("b")).FromJust());
   6421   CHECK(v8_num(1)->Equals(context.local(), v8_num(1)).FromJust());
   6422   CHECK(v8_num(1.00)->Equals(context.local(), v8_num(1)).FromJust());
   6423   CHECK(!v8_num(1)->Equals(context.local(), v8_num(2)).FromJust());
   6424 
   6425   // Assume String is not internalized.
   6426   CHECK(v8_str("a")->StrictEquals(v8_str("a")));
   6427   CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
   6428   CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
   6429   CHECK(v8_num(1)->StrictEquals(v8_num(1)));
   6430   CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
   6431   CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
   6432   Local<Value> not_a_number = v8_num(std::numeric_limits<double>::quiet_NaN());
   6433   CHECK(!not_a_number->StrictEquals(not_a_number));
   6434   CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
   6435   CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
   6436 
   6437   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   6438   v8::Persistent<v8::Object> alias(isolate, obj);
   6439   CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
   6440   alias.Reset();
   6441 
   6442   CHECK(v8_str("a")->SameValue(v8_str("a")));
   6443   CHECK(!v8_str("a")->SameValue(v8_str("b")));
   6444   CHECK(!v8_str("5")->SameValue(v8_num(5)));
   6445   CHECK(v8_num(1)->SameValue(v8_num(1)));
   6446   CHECK(!v8_num(1)->SameValue(v8_num(2)));
   6447   CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
   6448   CHECK(not_a_number->SameValue(not_a_number));
   6449   CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
   6450   CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
   6451 }
   6452 
   6453 THREADED_TEST(TypeOf) {
   6454   LocalContext context;
   6455   v8::Isolate* isolate = context->GetIsolate();
   6456   v8::HandleScope scope(context->GetIsolate());
   6457 
   6458   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   6459   Local<v8::Function> fun = t1->GetFunction(context.local()).ToLocalChecked();
   6460 
   6461   CHECK(v8::Undefined(isolate)
   6462             ->TypeOf(isolate)
   6463             ->Equals(context.local(), v8_str("undefined"))
   6464             .FromJust());
   6465   CHECK(v8::Null(isolate)
   6466             ->TypeOf(isolate)
   6467             ->Equals(context.local(), v8_str("object"))
   6468             .FromJust());
   6469   CHECK(v8_str("str")
   6470             ->TypeOf(isolate)
   6471             ->Equals(context.local(), v8_str("string"))
   6472             .FromJust());
   6473   CHECK(v8_num(0.0)
   6474             ->TypeOf(isolate)
   6475             ->Equals(context.local(), v8_str("number"))
   6476             .FromJust());
   6477   CHECK(v8_num(1)
   6478             ->TypeOf(isolate)
   6479             ->Equals(context.local(), v8_str("number"))
   6480             .FromJust());
   6481   CHECK(v8::Object::New(isolate)
   6482             ->TypeOf(isolate)
   6483             ->Equals(context.local(), v8_str("object"))
   6484             .FromJust());
   6485   CHECK(v8::Boolean::New(isolate, true)
   6486             ->TypeOf(isolate)
   6487             ->Equals(context.local(), v8_str("boolean"))
   6488             .FromJust());
   6489   CHECK(fun->TypeOf(isolate)
   6490             ->Equals(context.local(), v8_str("function"))
   6491             .FromJust());
   6492 }
   6493 
   6494 THREADED_TEST(MultiRun) {
   6495   LocalContext context;
   6496   v8::HandleScope scope(context->GetIsolate());
   6497   Local<Script> script = v8_compile("x");
   6498   for (int i = 0; i < 10; i++) {
   6499     script->Run(context.local()).IsEmpty();
   6500   }
   6501 }
   6502 
   6503 
   6504 static void GetXValue(Local<Name> name,
   6505                       const v8::PropertyCallbackInfo<v8::Value>& info) {
   6506   ApiTestFuzzer::Fuzz();
   6507   CHECK(info.Data()
   6508             ->Equals(CcTest::isolate()->GetCurrentContext(), v8_str("donut"))
   6509             .FromJust());
   6510   CHECK(name->Equals(CcTest::isolate()->GetCurrentContext(), v8_str("x"))
   6511             .FromJust());
   6512   info.GetReturnValue().Set(name);
   6513 }
   6514 
   6515 
   6516 THREADED_TEST(SimplePropertyRead) {
   6517   LocalContext context;
   6518   v8::Isolate* isolate = context->GetIsolate();
   6519   v8::HandleScope scope(isolate);
   6520   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6521   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
   6522   CHECK(context->Global()
   6523             ->Set(context.local(), v8_str("obj"),
   6524                   templ->NewInstance(context.local()).ToLocalChecked())
   6525             .FromJust());
   6526   Local<Script> script = v8_compile("obj.x");
   6527   for (int i = 0; i < 10; i++) {
   6528     Local<Value> result = script->Run(context.local()).ToLocalChecked();
   6529     CHECK(result->Equals(context.local(), v8_str("x")).FromJust());
   6530   }
   6531 }
   6532 
   6533 
   6534 THREADED_TEST(DefinePropertyOnAPIAccessor) {
   6535   LocalContext context;
   6536   v8::Isolate* isolate = context->GetIsolate();
   6537   v8::HandleScope scope(isolate);
   6538   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6539   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
   6540   CHECK(context->Global()
   6541             ->Set(context.local(), v8_str("obj"),
   6542                   templ->NewInstance(context.local()).ToLocalChecked())
   6543             .FromJust());
   6544 
   6545   // Uses getOwnPropertyDescriptor to check the configurable status
   6546   Local<Script> script_desc = v8_compile(
   6547       "var prop = Object.getOwnPropertyDescriptor( "
   6548       "obj, 'x');"
   6549       "prop.configurable;");
   6550   Local<Value> result = script_desc->Run(context.local()).ToLocalChecked();
   6551   CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
   6552 
   6553   // Redefine get - but still configurable
   6554   Local<Script> script_define = v8_compile(
   6555       "var desc = { get: function(){return 42; },"
   6556       "            configurable: true };"
   6557       "Object.defineProperty(obj, 'x', desc);"
   6558       "obj.x");
   6559   result = script_define->Run(context.local()).ToLocalChecked();
   6560   CHECK(result->Equals(context.local(), v8_num(42)).FromJust());
   6561 
   6562   // Check that the accessor is still configurable
   6563   result = script_desc->Run(context.local()).ToLocalChecked();
   6564   CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
   6565 
   6566   // Redefine to a non-configurable
   6567   script_define = v8_compile(
   6568       "var desc = { get: function(){return 43; },"
   6569       "             configurable: false };"
   6570       "Object.defineProperty(obj, 'x', desc);"
   6571       "obj.x");
   6572   result = script_define->Run(context.local()).ToLocalChecked();
   6573   CHECK(result->Equals(context.local(), v8_num(43)).FromJust());
   6574   result = script_desc->Run(context.local()).ToLocalChecked();
   6575   CHECK_EQ(result->BooleanValue(context.local()).FromJust(), false);
   6576 
   6577   // Make sure that it is not possible to redefine again
   6578   v8::TryCatch try_catch(isolate);
   6579   CHECK(script_define->Run(context.local()).IsEmpty());
   6580   CHECK(try_catch.HasCaught());
   6581   String::Utf8Value exception_value(try_catch.Exception());
   6582   CHECK_EQ(0,
   6583            strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
   6584 }
   6585 
   6586 
   6587 THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
   6588   v8::Isolate* isolate = CcTest::isolate();
   6589   v8::HandleScope scope(isolate);
   6590   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6591   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
   6592   LocalContext context;
   6593   CHECK(context->Global()
   6594             ->Set(context.local(), v8_str("obj"),
   6595                   templ->NewInstance(context.local()).ToLocalChecked())
   6596             .FromJust());
   6597 
   6598   Local<Script> script_desc = v8_compile(
   6599       "var prop ="
   6600       "Object.getOwnPropertyDescriptor( "
   6601       "obj, 'x');"
   6602       "prop.configurable;");
   6603   Local<Value> result = script_desc->Run(context.local()).ToLocalChecked();
   6604   CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
   6605 
   6606   Local<Script> script_define = v8_compile(
   6607       "var desc = {get: function(){return 42; },"
   6608       "            configurable: true };"
   6609       "Object.defineProperty(obj, 'x', desc);"
   6610       "obj.x");
   6611   result = script_define->Run(context.local()).ToLocalChecked();
   6612   CHECK(result->Equals(context.local(), v8_num(42)).FromJust());
   6613 
   6614   result = script_desc->Run(context.local()).ToLocalChecked();
   6615   CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
   6616 
   6617   script_define = v8_compile(
   6618       "var desc = {get: function(){return 43; },"
   6619       "            configurable: false };"
   6620       "Object.defineProperty(obj, 'x', desc);"
   6621       "obj.x");
   6622   result = script_define->Run(context.local()).ToLocalChecked();
   6623   CHECK(result->Equals(context.local(), v8_num(43)).FromJust());
   6624 
   6625   result = script_desc->Run(context.local()).ToLocalChecked();
   6626   CHECK_EQ(result->BooleanValue(context.local()).FromJust(), false);
   6627 
   6628   v8::TryCatch try_catch(isolate);
   6629   CHECK(script_define->Run(context.local()).IsEmpty());
   6630   CHECK(try_catch.HasCaught());
   6631   String::Utf8Value exception_value(try_catch.Exception());
   6632   CHECK_EQ(0,
   6633            strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
   6634 }
   6635 
   6636 
   6637 static v8::Local<v8::Object> GetGlobalProperty(LocalContext* context,
   6638                                                char const* name) {
   6639   return v8::Local<v8::Object>::Cast(
   6640       (*context)
   6641           ->Global()
   6642           ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name))
   6643           .ToLocalChecked());
   6644 }
   6645 
   6646 
   6647 THREADED_TEST(DefineAPIAccessorOnObject) {
   6648   v8::Isolate* isolate = CcTest::isolate();
   6649   v8::HandleScope scope(isolate);
   6650   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6651   LocalContext context;
   6652 
   6653   CHECK(context->Global()
   6654             ->Set(context.local(), v8_str("obj1"),
   6655                   templ->NewInstance(context.local()).ToLocalChecked())
   6656             .FromJust());
   6657   CompileRun("var obj2 = {};");
   6658 
   6659   CHECK(CompileRun("obj1.x")->IsUndefined());
   6660   CHECK(CompileRun("obj2.x")->IsUndefined());
   6661 
   6662   CHECK(GetGlobalProperty(&context, "obj1")
   6663             ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
   6664                           v8_str("donut"))
   6665             .FromJust());
   6666 
   6667   ExpectString("obj1.x", "x");
   6668   CHECK(CompileRun("obj2.x")->IsUndefined());
   6669 
   6670   CHECK(GetGlobalProperty(&context, "obj2")
   6671             ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
   6672                           v8_str("donut"))
   6673             .FromJust());
   6674 
   6675   ExpectString("obj1.x", "x");
   6676   ExpectString("obj2.x", "x");
   6677 
   6678   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   6679   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   6680 
   6681   CompileRun(
   6682       "Object.defineProperty(obj1, 'x',"
   6683       "{ get: function() { return 'y'; }, configurable: true })");
   6684 
   6685   ExpectString("obj1.x", "y");
   6686   ExpectString("obj2.x", "x");
   6687 
   6688   CompileRun(
   6689       "Object.defineProperty(obj2, 'x',"
   6690       "{ get: function() { return 'y'; }, configurable: true })");
   6691 
   6692   ExpectString("obj1.x", "y");
   6693   ExpectString("obj2.x", "y");
   6694 
   6695   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   6696   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   6697 
   6698   CHECK(GetGlobalProperty(&context, "obj1")
   6699             ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
   6700                           v8_str("donut"))
   6701             .FromJust());
   6702   CHECK(GetGlobalProperty(&context, "obj2")
   6703             ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
   6704                           v8_str("donut"))
   6705             .FromJust());
   6706 
   6707   ExpectString("obj1.x", "x");
   6708   ExpectString("obj2.x", "x");
   6709 
   6710   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   6711   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   6712 
   6713   // Define getters/setters, but now make them not configurable.
   6714   CompileRun(
   6715       "Object.defineProperty(obj1, 'x',"
   6716       "{ get: function() { return 'z'; }, configurable: false })");
   6717   CompileRun(
   6718       "Object.defineProperty(obj2, 'x',"
   6719       "{ get: function() { return 'z'; }, configurable: false })");
   6720   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   6721   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   6722 
   6723   ExpectString("obj1.x", "z");
   6724   ExpectString("obj2.x", "z");
   6725 
   6726   CHECK(GetGlobalProperty(&context, "obj1")
   6727             ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
   6728                           v8_str("donut"))
   6729             .IsNothing());
   6730   CHECK(GetGlobalProperty(&context, "obj2")
   6731             ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
   6732                           v8_str("donut"))
   6733             .IsNothing());
   6734 
   6735   ExpectString("obj1.x", "z");
   6736   ExpectString("obj2.x", "z");
   6737 }
   6738 
   6739 
   6740 THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
   6741   v8::Isolate* isolate = CcTest::isolate();
   6742   v8::HandleScope scope(isolate);
   6743   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6744   LocalContext context;
   6745 
   6746   CHECK(context->Global()
   6747             ->Set(context.local(), v8_str("obj1"),
   6748                   templ->NewInstance(context.local()).ToLocalChecked())
   6749             .FromJust());
   6750   CompileRun("var obj2 = {};");
   6751 
   6752   CHECK(GetGlobalProperty(&context, "obj1")
   6753             ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
   6754                           v8_str("donut"), v8::DEFAULT, v8::DontDelete)
   6755             .FromJust());
   6756   CHECK(GetGlobalProperty(&context, "obj2")
   6757             ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
   6758                           v8_str("donut"), v8::DEFAULT, v8::DontDelete)
   6759             .FromJust());
   6760 
   6761   ExpectString("obj1.x", "x");
   6762   ExpectString("obj2.x", "x");
   6763 
   6764   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   6765   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   6766 
   6767   CHECK(GetGlobalProperty(&context, "obj1")
   6768             ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
   6769                           v8_str("donut"))
   6770             .IsNothing());
   6771   CHECK(GetGlobalProperty(&context, "obj2")
   6772             ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
   6773                           v8_str("donut"))
   6774             .IsNothing());
   6775 
   6776   {
   6777     v8::TryCatch try_catch(isolate);
   6778     CompileRun(
   6779         "Object.defineProperty(obj1, 'x',"
   6780         "{get: function() { return 'func'; }})");
   6781     CHECK(try_catch.HasCaught());
   6782     String::Utf8Value exception_value(try_catch.Exception());
   6783     CHECK_EQ(
   6784         0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
   6785   }
   6786   {
   6787     v8::TryCatch try_catch(isolate);
   6788     CompileRun(
   6789         "Object.defineProperty(obj2, 'x',"
   6790         "{get: function() { return 'func'; }})");
   6791     CHECK(try_catch.HasCaught());
   6792     String::Utf8Value exception_value(try_catch.Exception());
   6793     CHECK_EQ(
   6794         0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
   6795   }
   6796 }
   6797 
   6798 
   6799 static void Get239Value(Local<Name> name,
   6800                         const v8::PropertyCallbackInfo<v8::Value>& info) {
   6801   ApiTestFuzzer::Fuzz();
   6802   CHECK(info.Data()
   6803             ->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("donut"))
   6804             .FromJust());
   6805   CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("239"))
   6806             .FromJust());
   6807   info.GetReturnValue().Set(name);
   6808 }
   6809 
   6810 
   6811 THREADED_TEST(ElementAPIAccessor) {
   6812   v8::Isolate* isolate = CcTest::isolate();
   6813   v8::HandleScope scope(isolate);
   6814   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6815   LocalContext context;
   6816 
   6817   CHECK(context->Global()
   6818             ->Set(context.local(), v8_str("obj1"),
   6819                   templ->NewInstance(context.local()).ToLocalChecked())
   6820             .FromJust());
   6821   CompileRun("var obj2 = {};");
   6822 
   6823   CHECK(GetGlobalProperty(&context, "obj1")
   6824             ->SetAccessor(context.local(), v8_str("239"), Get239Value, NULL,
   6825                           v8_str("donut"))
   6826             .FromJust());
   6827   CHECK(GetGlobalProperty(&context, "obj2")
   6828             ->SetAccessor(context.local(), v8_str("239"), Get239Value, NULL,
   6829                           v8_str("donut"))
   6830             .FromJust());
   6831 
   6832   ExpectString("obj1[239]", "239");
   6833   ExpectString("obj2[239]", "239");
   6834   ExpectString("obj1['239']", "239");
   6835   ExpectString("obj2['239']", "239");
   6836 }
   6837 
   6838 
   6839 v8::Persistent<Value> xValue;
   6840 
   6841 
   6842 static void SetXValue(Local<Name> name, Local<Value> value,
   6843                       const v8::PropertyCallbackInfo<void>& info) {
   6844   Local<Context> context = info.GetIsolate()->GetCurrentContext();
   6845   CHECK(value->Equals(context, v8_num(4)).FromJust());
   6846   CHECK(info.Data()->Equals(context, v8_str("donut")).FromJust());
   6847   CHECK(name->Equals(context, v8_str("x")).FromJust());
   6848   CHECK(xValue.IsEmpty());
   6849   xValue.Reset(info.GetIsolate(), value);
   6850 }
   6851 
   6852 
   6853 THREADED_TEST(SimplePropertyWrite) {
   6854   v8::Isolate* isolate = CcTest::isolate();
   6855   v8::HandleScope scope(isolate);
   6856   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6857   templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
   6858   LocalContext context;
   6859   CHECK(context->Global()
   6860             ->Set(context.local(), v8_str("obj"),
   6861                   templ->NewInstance(context.local()).ToLocalChecked())
   6862             .FromJust());
   6863   Local<Script> script = v8_compile("obj.x = 4");
   6864   for (int i = 0; i < 10; i++) {
   6865     CHECK(xValue.IsEmpty());
   6866     script->Run(context.local()).ToLocalChecked();
   6867     CHECK(v8_num(4)
   6868               ->Equals(context.local(),
   6869                        Local<Value>::New(CcTest::isolate(), xValue))
   6870               .FromJust());
   6871     xValue.Reset();
   6872   }
   6873 }
   6874 
   6875 
   6876 THREADED_TEST(SetterOnly) {
   6877   v8::Isolate* isolate = CcTest::isolate();
   6878   v8::HandleScope scope(isolate);
   6879   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6880   templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
   6881   LocalContext context;
   6882   CHECK(context->Global()
   6883             ->Set(context.local(), v8_str("obj"),
   6884                   templ->NewInstance(context.local()).ToLocalChecked())
   6885             .FromJust());
   6886   Local<Script> script = v8_compile("obj.x = 4; obj.x");
   6887   for (int i = 0; i < 10; i++) {
   6888     CHECK(xValue.IsEmpty());
   6889     script->Run(context.local()).ToLocalChecked();
   6890     CHECK(v8_num(4)
   6891               ->Equals(context.local(),
   6892                        Local<Value>::New(CcTest::isolate(), xValue))
   6893               .FromJust());
   6894     xValue.Reset();
   6895   }
   6896 }
   6897 
   6898 
   6899 THREADED_TEST(NoAccessors) {
   6900   v8::Isolate* isolate = CcTest::isolate();
   6901   v8::HandleScope scope(isolate);
   6902   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6903   templ->SetAccessor(v8_str("x"), static_cast<v8::AccessorGetterCallback>(NULL),
   6904                      NULL, v8_str("donut"));
   6905   LocalContext context;
   6906   CHECK(context->Global()
   6907             ->Set(context.local(), v8_str("obj"),
   6908                   templ->NewInstance(context.local()).ToLocalChecked())
   6909             .FromJust());
   6910   Local<Script> script = v8_compile("obj.x = 4; obj.x");
   6911   for (int i = 0; i < 10; i++) {
   6912     script->Run(context.local()).ToLocalChecked();
   6913   }
   6914 }
   6915 
   6916 
   6917 THREADED_TEST(MultiContexts) {
   6918   v8::Isolate* isolate = CcTest::isolate();
   6919   v8::HandleScope scope(isolate);
   6920   v8::Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6921   templ->Set(v8_str("dummy"),
   6922              v8::FunctionTemplate::New(isolate, DummyCallHandler));
   6923 
   6924   Local<String> password = v8_str("Password");
   6925 
   6926   // Create an environment
   6927   LocalContext context0(0, templ);
   6928   context0->SetSecurityToken(password);
   6929   v8::Local<v8::Object> global0 = context0->Global();
   6930   CHECK(global0->Set(context0.local(), v8_str("custom"), v8_num(1234))
   6931             .FromJust());
   6932   CHECK_EQ(1234, global0->Get(context0.local(), v8_str("custom"))
   6933                      .ToLocalChecked()
   6934                      ->Int32Value(context0.local())
   6935                      .FromJust());
   6936 
   6937   // Create an independent environment
   6938   LocalContext context1(0, templ);
   6939   context1->SetSecurityToken(password);
   6940   v8::Local<v8::Object> global1 = context1->Global();
   6941   CHECK(global1->Set(context1.local(), v8_str("custom"), v8_num(1234))
   6942             .FromJust());
   6943   CHECK(!global0->Equals(context1.local(), global1).FromJust());
   6944   CHECK_EQ(1234, global0->Get(context1.local(), v8_str("custom"))
   6945                      .ToLocalChecked()
   6946                      ->Int32Value(context0.local())
   6947                      .FromJust());
   6948   CHECK_EQ(1234, global1->Get(context1.local(), v8_str("custom"))
   6949                      .ToLocalChecked()
   6950                      ->Int32Value(context1.local())
   6951                      .FromJust());
   6952 
   6953   // Now create a new context with the old global
   6954   LocalContext context2(0, templ, global1);
   6955   context2->SetSecurityToken(password);
   6956   v8::Local<v8::Object> global2 = context2->Global();
   6957   CHECK(global1->Equals(context2.local(), global2).FromJust());
   6958   CHECK_EQ(0, global1->Get(context2.local(), v8_str("custom"))
   6959                   .ToLocalChecked()
   6960                   ->Int32Value(context1.local())
   6961                   .FromJust());
   6962   CHECK_EQ(0, global2->Get(context2.local(), v8_str("custom"))
   6963                   .ToLocalChecked()
   6964                   ->Int32Value(context2.local())
   6965                   .FromJust());
   6966 }
   6967 
   6968 
   6969 THREADED_TEST(FunctionPrototypeAcrossContexts) {
   6970   // Make sure that functions created by cloning boilerplates cannot
   6971   // communicate through their __proto__ field.
   6972 
   6973   v8::HandleScope scope(CcTest::isolate());
   6974 
   6975   LocalContext env0;
   6976   v8::Local<v8::Object> global0 = env0->Global();
   6977   v8::Local<v8::Object> object0 = global0->Get(env0.local(), v8_str("Object"))
   6978                                       .ToLocalChecked()
   6979                                       .As<v8::Object>();
   6980   v8::Local<v8::Object> tostring0 =
   6981       object0->Get(env0.local(), v8_str("toString"))
   6982           .ToLocalChecked()
   6983           .As<v8::Object>();
   6984   v8::Local<v8::Object> proto0 =
   6985       tostring0->Get(env0.local(), v8_str("__proto__"))
   6986           .ToLocalChecked()
   6987           .As<v8::Object>();
   6988   CHECK(proto0->Set(env0.local(), v8_str("custom"), v8_num(1234)).FromJust());
   6989 
   6990   LocalContext env1;
   6991   v8::Local<v8::Object> global1 = env1->Global();
   6992   v8::Local<v8::Object> object1 = global1->Get(env1.local(), v8_str("Object"))
   6993                                       .ToLocalChecked()
   6994                                       .As<v8::Object>();
   6995   v8::Local<v8::Object> tostring1 =
   6996       object1->Get(env1.local(), v8_str("toString"))
   6997           .ToLocalChecked()
   6998           .As<v8::Object>();
   6999   v8::Local<v8::Object> proto1 =
   7000       tostring1->Get(env1.local(), v8_str("__proto__"))
   7001           .ToLocalChecked()
   7002           .As<v8::Object>();
   7003   CHECK(!proto1->Has(env1.local(), v8_str("custom")).FromJust());
   7004 }
   7005 
   7006 
   7007 THREADED_TEST(Regress892105) {
   7008   // Make sure that object and array literals created by cloning
   7009   // boilerplates cannot communicate through their __proto__
   7010   // field. This is rather difficult to check, but we try to add stuff
   7011   // to Object.prototype and Array.prototype and create a new
   7012   // environment. This should succeed.
   7013 
   7014   v8::HandleScope scope(CcTest::isolate());
   7015 
   7016   Local<String> source = v8_str(
   7017       "Object.prototype.obj = 1234;"
   7018       "Array.prototype.arr = 4567;"
   7019       "8901");
   7020 
   7021   LocalContext env0;
   7022   Local<Script> script0 = v8_compile(source);
   7023   CHECK_EQ(8901.0, script0->Run(env0.local())
   7024                        .ToLocalChecked()
   7025                        ->NumberValue(env0.local())
   7026                        .FromJust());
   7027 
   7028   LocalContext env1;
   7029   Local<Script> script1 = v8_compile(source);
   7030   CHECK_EQ(8901.0, script1->Run(env1.local())
   7031                        .ToLocalChecked()
   7032                        ->NumberValue(env1.local())
   7033                        .FromJust());
   7034 }
   7035 
   7036 
   7037 THREADED_TEST(UndetectableObject) {
   7038   LocalContext env;
   7039   v8::HandleScope scope(env->GetIsolate());
   7040 
   7041   Local<v8::FunctionTemplate> desc =
   7042       v8::FunctionTemplate::New(env->GetIsolate());
   7043   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   7044 
   7045   Local<v8::Object> obj = desc->GetFunction(env.local())
   7046                               .ToLocalChecked()
   7047                               ->NewInstance(env.local())
   7048                               .ToLocalChecked();
   7049   CHECK(
   7050       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
   7051 
   7052   ExpectString("undetectable.toString()", "[object Object]");
   7053   ExpectString("typeof undetectable", "undefined");
   7054   ExpectString("typeof(undetectable)", "undefined");
   7055   ExpectBoolean("typeof undetectable == 'undefined'", true);
   7056   ExpectBoolean("typeof undetectable == 'object'", false);
   7057   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
   7058   ExpectBoolean("!undetectable", true);
   7059 
   7060   ExpectObject("true&&undetectable", obj);
   7061   ExpectBoolean("false&&undetectable", false);
   7062   ExpectBoolean("true||undetectable", true);
   7063   ExpectObject("false||undetectable", obj);
   7064 
   7065   ExpectObject("undetectable&&true", obj);
   7066   ExpectObject("undetectable&&false", obj);
   7067   ExpectBoolean("undetectable||true", true);
   7068   ExpectBoolean("undetectable||false", false);
   7069 
   7070   ExpectBoolean("undetectable==null", true);
   7071   ExpectBoolean("null==undetectable", true);
   7072   ExpectBoolean("undetectable==undefined", true);
   7073   ExpectBoolean("undefined==undetectable", true);
   7074   ExpectBoolean("undetectable==undetectable", true);
   7075 
   7076 
   7077   ExpectBoolean("undetectable===null", false);
   7078   ExpectBoolean("null===undetectable", false);
   7079   ExpectBoolean("undetectable===undefined", false);
   7080   ExpectBoolean("undefined===undetectable", false);
   7081   ExpectBoolean("undetectable===undetectable", true);
   7082 }
   7083 
   7084 
   7085 THREADED_TEST(VoidLiteral) {
   7086   LocalContext env;
   7087   v8::Isolate* isolate = env->GetIsolate();
   7088   v8::HandleScope scope(isolate);
   7089 
   7090   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
   7091   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   7092 
   7093   Local<v8::Object> obj = desc->GetFunction(env.local())
   7094                               .ToLocalChecked()
   7095                               ->NewInstance(env.local())
   7096                               .ToLocalChecked();
   7097   CHECK(
   7098       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
   7099 
   7100   ExpectBoolean("undefined == void 0", true);
   7101   ExpectBoolean("undetectable == void 0", true);
   7102   ExpectBoolean("null == void 0", true);
   7103   ExpectBoolean("undefined === void 0", true);
   7104   ExpectBoolean("undetectable === void 0", false);
   7105   ExpectBoolean("null === void 0", false);
   7106 
   7107   ExpectBoolean("void 0 == undefined", true);
   7108   ExpectBoolean("void 0 == undetectable", true);
   7109   ExpectBoolean("void 0 == null", true);
   7110   ExpectBoolean("void 0 === undefined", true);
   7111   ExpectBoolean("void 0 === undetectable", false);
   7112   ExpectBoolean("void 0 === null", false);
   7113 
   7114   ExpectString(
   7115       "(function() {"
   7116       "  try {"
   7117       "    return x === void 0;"
   7118       "  } catch(e) {"
   7119       "    return e.toString();"
   7120       "  }"
   7121       "})()",
   7122       "ReferenceError: x is not defined");
   7123   ExpectString(
   7124       "(function() {"
   7125       "  try {"
   7126       "    return void 0 === x;"
   7127       "  } catch(e) {"
   7128       "    return e.toString();"
   7129       "  }"
   7130       "})()",
   7131       "ReferenceError: x is not defined");
   7132 }
   7133 
   7134 
   7135 THREADED_TEST(ExtensibleOnUndetectable) {
   7136   LocalContext env;
   7137   v8::Isolate* isolate = env->GetIsolate();
   7138   v8::HandleScope scope(isolate);
   7139 
   7140   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
   7141   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   7142 
   7143   Local<v8::Object> obj = desc->GetFunction(env.local())
   7144                               .ToLocalChecked()
   7145                               ->NewInstance(env.local())
   7146                               .ToLocalChecked();
   7147   CHECK(
   7148       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
   7149 
   7150   Local<String> source = v8_str(
   7151       "undetectable.x = 42;"
   7152       "undetectable.x");
   7153 
   7154   Local<Script> script = v8_compile(source);
   7155 
   7156   CHECK(v8::Integer::New(isolate, 42)
   7157             ->Equals(env.local(), script->Run(env.local()).ToLocalChecked())
   7158             .FromJust());
   7159 
   7160   ExpectBoolean("Object.isExtensible(undetectable)", true);
   7161 
   7162   source = v8_str("Object.preventExtensions(undetectable);");
   7163   script = v8_compile(source);
   7164   script->Run(env.local()).ToLocalChecked();
   7165   ExpectBoolean("Object.isExtensible(undetectable)", false);
   7166 
   7167   source = v8_str("undetectable.y = 2000;");
   7168   script = v8_compile(source);
   7169   script->Run(env.local()).ToLocalChecked();
   7170   ExpectBoolean("undetectable.y == undefined", true);
   7171 }
   7172 
   7173 
   7174 // The point of this test is type checking. We run it only so compilers
   7175 // don't complain about an unused function.
   7176 TEST(PersistentHandles) {
   7177   LocalContext env;
   7178   v8::Isolate* isolate = CcTest::isolate();
   7179   v8::HandleScope scope(isolate);
   7180   Local<String> str = v8_str("foo");
   7181   v8::Persistent<String> p_str(isolate, str);
   7182   p_str.Reset();
   7183   Local<Script> scr = v8_compile("");
   7184   v8::Persistent<Script> p_scr(isolate, scr);
   7185   p_scr.Reset();
   7186   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   7187   v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
   7188   p_templ.Reset();
   7189 }
   7190 
   7191 
   7192 static void HandleLogDelegator(
   7193     const v8::FunctionCallbackInfo<v8::Value>& args) {
   7194   ApiTestFuzzer::Fuzz();
   7195 }
   7196 
   7197 
   7198 THREADED_TEST(GlobalObjectTemplate) {
   7199   v8::Isolate* isolate = CcTest::isolate();
   7200   v8::HandleScope handle_scope(isolate);
   7201   Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
   7202   global_template->Set(v8_str("JSNI_Log"),
   7203                        v8::FunctionTemplate::New(isolate, HandleLogDelegator));
   7204   v8::Local<Context> context = Context::New(isolate, 0, global_template);
   7205   Context::Scope context_scope(context);
   7206   CompileRun("JSNI_Log('LOG')");
   7207 }
   7208 
   7209 
   7210 static const char* kSimpleExtensionSource =
   7211     "function Foo() {"
   7212     "  return 4;"
   7213     "}";
   7214 
   7215 
   7216 TEST(SimpleExtensions) {
   7217   v8::HandleScope handle_scope(CcTest::isolate());
   7218   v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
   7219   const char* extension_names[] = {"simpletest"};
   7220   v8::ExtensionConfiguration extensions(1, extension_names);
   7221   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7222   Context::Scope lock(context);
   7223   v8::Local<Value> result = CompileRun("Foo()");
   7224   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
   7225             .FromJust());
   7226 }
   7227 
   7228 
   7229 static const char* kStackTraceFromExtensionSource =
   7230     "function foo() {"
   7231     "  throw new Error();"
   7232     "}"
   7233     "function bar() {"
   7234     "  foo();"
   7235     "}";
   7236 
   7237 
   7238 TEST(StackTraceInExtension) {
   7239   v8::HandleScope handle_scope(CcTest::isolate());
   7240   v8::RegisterExtension(
   7241       new Extension("stacktracetest", kStackTraceFromExtensionSource));
   7242   const char* extension_names[] = {"stacktracetest"};
   7243   v8::ExtensionConfiguration extensions(1, extension_names);
   7244   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7245   Context::Scope lock(context);
   7246   CompileRun(
   7247       "function user() { bar(); }"
   7248       "var error;"
   7249       "try{ user(); } catch (e) { error = e; }");
   7250   CHECK_EQ(-1, v8_run_int32value(v8_compile("error.stack.indexOf('foo')")));
   7251   CHECK_EQ(-1, v8_run_int32value(v8_compile("error.stack.indexOf('bar')")));
   7252   CHECK_NE(-1, v8_run_int32value(v8_compile("error.stack.indexOf('user')")));
   7253 }
   7254 
   7255 
   7256 TEST(NullExtensions) {
   7257   v8::HandleScope handle_scope(CcTest::isolate());
   7258   v8::RegisterExtension(new Extension("nulltest", NULL));
   7259   const char* extension_names[] = {"nulltest"};
   7260   v8::ExtensionConfiguration extensions(1, extension_names);
   7261   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7262   Context::Scope lock(context);
   7263   v8::Local<Value> result = CompileRun("1+3");
   7264   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
   7265             .FromJust());
   7266 }
   7267 
   7268 
   7269 static const char* kEmbeddedExtensionSource =
   7270     "function Ret54321(){return 54321;}~~@@$"
   7271     "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
   7272 static const int kEmbeddedExtensionSourceValidLen = 34;
   7273 
   7274 
   7275 TEST(ExtensionMissingSourceLength) {
   7276   v8::HandleScope handle_scope(CcTest::isolate());
   7277   v8::RegisterExtension(
   7278       new Extension("srclentest_fail", kEmbeddedExtensionSource));
   7279   const char* extension_names[] = {"srclentest_fail"};
   7280   v8::ExtensionConfiguration extensions(1, extension_names);
   7281   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7282   CHECK(0 == *context);
   7283 }
   7284 
   7285 
   7286 TEST(ExtensionWithSourceLength) {
   7287   for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
   7288        source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
   7289     v8::HandleScope handle_scope(CcTest::isolate());
   7290     i::ScopedVector<char> extension_name(32);
   7291     i::SNPrintF(extension_name, "ext #%d", source_len);
   7292     v8::RegisterExtension(new Extension(
   7293         extension_name.start(), kEmbeddedExtensionSource, 0, 0, source_len));
   7294     const char* extension_names[1] = {extension_name.start()};
   7295     v8::ExtensionConfiguration extensions(1, extension_names);
   7296     v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7297     if (source_len == kEmbeddedExtensionSourceValidLen) {
   7298       Context::Scope lock(context);
   7299       v8::Local<Value> result = CompileRun("Ret54321()");
   7300       CHECK(v8::Integer::New(CcTest::isolate(), 54321)
   7301                 ->Equals(context, result)
   7302                 .FromJust());
   7303     } else {
   7304       // Anything but exactly the right length should fail to compile.
   7305       CHECK(0 == *context);
   7306     }
   7307   }
   7308 }
   7309 
   7310 
   7311 static const char* kEvalExtensionSource1 =
   7312     "function UseEval1() {"
   7313     "  var x = 42;"
   7314     "  return eval('x');"
   7315     "}";
   7316 
   7317 
   7318 static const char* kEvalExtensionSource2 =
   7319     "(function() {"
   7320     "  var x = 42;"
   7321     "  function e() {"
   7322     "    return eval('x');"
   7323     "  }"
   7324     "  this.UseEval2 = e;"
   7325     "})()";
   7326 
   7327 
   7328 TEST(UseEvalFromExtension) {
   7329   v8::HandleScope handle_scope(CcTest::isolate());
   7330   v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
   7331   v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
   7332   const char* extension_names[] = {"evaltest1", "evaltest2"};
   7333   v8::ExtensionConfiguration extensions(2, extension_names);
   7334   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7335   Context::Scope lock(context);
   7336   v8::Local<Value> result = CompileRun("UseEval1()");
   7337   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
   7338             .FromJust());
   7339   result = CompileRun("UseEval2()");
   7340   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
   7341             .FromJust());
   7342 }
   7343 
   7344 
   7345 static const char* kWithExtensionSource1 =
   7346     "function UseWith1() {"
   7347     "  var x = 42;"
   7348     "  with({x:87}) { return x; }"
   7349     "}";
   7350 
   7351 
   7352 static const char* kWithExtensionSource2 =
   7353     "(function() {"
   7354     "  var x = 42;"
   7355     "  function e() {"
   7356     "    with ({x:87}) { return x; }"
   7357     "  }"
   7358     "  this.UseWith2 = e;"
   7359     "})()";
   7360 
   7361 
   7362 TEST(UseWithFromExtension) {
   7363   v8::HandleScope handle_scope(CcTest::isolate());
   7364   v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
   7365   v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
   7366   const char* extension_names[] = {"withtest1", "withtest2"};
   7367   v8::ExtensionConfiguration extensions(2, extension_names);
   7368   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7369   Context::Scope lock(context);
   7370   v8::Local<Value> result = CompileRun("UseWith1()");
   7371   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 87))
   7372             .FromJust());
   7373   result = CompileRun("UseWith2()");
   7374   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 87))
   7375             .FromJust());
   7376 }
   7377 
   7378 
   7379 TEST(AutoExtensions) {
   7380   v8::HandleScope handle_scope(CcTest::isolate());
   7381   Extension* extension = new Extension("autotest", kSimpleExtensionSource);
   7382   extension->set_auto_enable(true);
   7383   v8::RegisterExtension(extension);
   7384   v8::Local<Context> context = Context::New(CcTest::isolate());
   7385   Context::Scope lock(context);
   7386   v8::Local<Value> result = CompileRun("Foo()");
   7387   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
   7388             .FromJust());
   7389 }
   7390 
   7391 
   7392 static const char* kSyntaxErrorInExtensionSource = "[";
   7393 
   7394 
   7395 // Test that a syntax error in an extension does not cause a fatal
   7396 // error but results in an empty context.
   7397 TEST(SyntaxErrorExtensions) {
   7398   v8::HandleScope handle_scope(CcTest::isolate());
   7399   v8::RegisterExtension(
   7400       new Extension("syntaxerror", kSyntaxErrorInExtensionSource));
   7401   const char* extension_names[] = {"syntaxerror"};
   7402   v8::ExtensionConfiguration extensions(1, extension_names);
   7403   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7404   CHECK(context.IsEmpty());
   7405 }
   7406 
   7407 
   7408 static const char* kExceptionInExtensionSource = "throw 42";
   7409 
   7410 
   7411 // Test that an exception when installing an extension does not cause
   7412 // a fatal error but results in an empty context.
   7413 TEST(ExceptionExtensions) {
   7414   v8::HandleScope handle_scope(CcTest::isolate());
   7415   v8::RegisterExtension(
   7416       new Extension("exception", kExceptionInExtensionSource));
   7417   const char* extension_names[] = {"exception"};
   7418   v8::ExtensionConfiguration extensions(1, extension_names);
   7419   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7420   CHECK(context.IsEmpty());
   7421 }
   7422 
   7423 
   7424 static const char* kNativeCallInExtensionSource =
   7425     "function call_runtime_last_index_of(x) {"
   7426     "  return %StringLastIndexOf(x, 'bob', 10);"
   7427     "}";
   7428 
   7429 
   7430 static const char* kNativeCallTest =
   7431     "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
   7432 
   7433 // Test that a native runtime calls are supported in extensions.
   7434 TEST(NativeCallInExtensions) {
   7435   v8::HandleScope handle_scope(CcTest::isolate());
   7436   v8::RegisterExtension(
   7437       new Extension("nativecall", kNativeCallInExtensionSource));
   7438   const char* extension_names[] = {"nativecall"};
   7439   v8::ExtensionConfiguration extensions(1, extension_names);
   7440   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7441   Context::Scope lock(context);
   7442   v8::Local<Value> result = CompileRun(kNativeCallTest);
   7443   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 3))
   7444             .FromJust());
   7445 }
   7446 
   7447 
   7448 class NativeFunctionExtension : public Extension {
   7449  public:
   7450   NativeFunctionExtension(const char* name, const char* source,
   7451                           v8::FunctionCallback fun = &Echo)
   7452       : Extension(name, source), function_(fun) {}
   7453 
   7454   virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
   7455       v8::Isolate* isolate, v8::Local<v8::String> name) {
   7456     return v8::FunctionTemplate::New(isolate, function_);
   7457   }
   7458 
   7459   static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
   7460     if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
   7461   }
   7462 
   7463  private:
   7464   v8::FunctionCallback function_;
   7465 };
   7466 
   7467 
   7468 TEST(NativeFunctionDeclaration) {
   7469   v8::HandleScope handle_scope(CcTest::isolate());
   7470   const char* name = "nativedecl";
   7471   v8::RegisterExtension(
   7472       new NativeFunctionExtension(name, "native function foo();"));
   7473   const char* extension_names[] = {name};
   7474   v8::ExtensionConfiguration extensions(1, extension_names);
   7475   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7476   Context::Scope lock(context);
   7477   v8::Local<Value> result = CompileRun("foo(42);");
   7478   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
   7479             .FromJust());
   7480 }
   7481 
   7482 
   7483 TEST(NativeFunctionDeclarationError) {
   7484   v8::HandleScope handle_scope(CcTest::isolate());
   7485   const char* name = "nativedeclerr";
   7486   // Syntax error in extension code.
   7487   v8::RegisterExtension(
   7488       new NativeFunctionExtension(name, "native\nfunction foo();"));
   7489   const char* extension_names[] = {name};
   7490   v8::ExtensionConfiguration extensions(1, extension_names);
   7491   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7492   CHECK(context.IsEmpty());
   7493 }
   7494 
   7495 
   7496 TEST(NativeFunctionDeclarationErrorEscape) {
   7497   v8::HandleScope handle_scope(CcTest::isolate());
   7498   const char* name = "nativedeclerresc";
   7499   // Syntax error in extension code - escape code in "native" means that
   7500   // it's not treated as a keyword.
   7501   v8::RegisterExtension(
   7502       new NativeFunctionExtension(name, "nativ\\u0065 function foo();"));
   7503   const char* extension_names[] = {name};
   7504   v8::ExtensionConfiguration extensions(1, extension_names);
   7505   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7506   CHECK(context.IsEmpty());
   7507 }
   7508 
   7509 
   7510 static void CheckDependencies(const char* name, const char* expected) {
   7511   v8::HandleScope handle_scope(CcTest::isolate());
   7512   v8::ExtensionConfiguration config(1, &name);
   7513   LocalContext context(&config);
   7514   CHECK(
   7515       v8_str(expected)
   7516           ->Equals(context.local(), context->Global()
   7517                                         ->Get(context.local(), v8_str("loaded"))
   7518                                         .ToLocalChecked())
   7519           .FromJust());
   7520 }
   7521 
   7522 
   7523 /*
   7524  * Configuration:
   7525  *
   7526  *     /-- B <--\
   7527  * A <-          -- D <-- E
   7528  *     \-- C <--/
   7529  */
   7530 THREADED_TEST(ExtensionDependency) {
   7531   static const char* kEDeps[] = {"D"};
   7532   v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
   7533   static const char* kDDeps[] = {"B", "C"};
   7534   v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
   7535   static const char* kBCDeps[] = {"A"};
   7536   v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
   7537   v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
   7538   v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
   7539   CheckDependencies("A", "undefinedA");
   7540   CheckDependencies("B", "undefinedAB");
   7541   CheckDependencies("C", "undefinedAC");
   7542   CheckDependencies("D", "undefinedABCD");
   7543   CheckDependencies("E", "undefinedABCDE");
   7544   v8::HandleScope handle_scope(CcTest::isolate());
   7545   static const char* exts[2] = {"C", "E"};
   7546   v8::ExtensionConfiguration config(2, exts);
   7547   LocalContext context(&config);
   7548   CHECK(
   7549       v8_str("undefinedACBDE")
   7550           ->Equals(context.local(), context->Global()
   7551                                         ->Get(context.local(), v8_str("loaded"))
   7552                                         .ToLocalChecked())
   7553           .FromJust());
   7554 }
   7555 
   7556 
   7557 static const char* kExtensionTestScript =
   7558     "native function A();"
   7559     "native function B();"
   7560     "native function C();"
   7561     "function Foo(i) {"
   7562     "  if (i == 0) return A();"
   7563     "  if (i == 1) return B();"
   7564     "  if (i == 2) return C();"
   7565     "}";
   7566 
   7567 
   7568 static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
   7569   ApiTestFuzzer::Fuzz();
   7570   if (args.IsConstructCall()) {
   7571     CHECK(args.This()
   7572               ->Set(args.GetIsolate()->GetCurrentContext(), v8_str("data"),
   7573                     args.Data())
   7574               .FromJust());
   7575     args.GetReturnValue().SetNull();
   7576     return;
   7577   }
   7578   args.GetReturnValue().Set(args.Data());
   7579 }
   7580 
   7581 
   7582 class FunctionExtension : public Extension {
   7583  public:
   7584   FunctionExtension() : Extension("functiontest", kExtensionTestScript) {}
   7585   virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
   7586       v8::Isolate* isolate, v8::Local<String> name);
   7587 };
   7588 
   7589 
   7590 static int lookup_count = 0;
   7591 v8::Local<v8::FunctionTemplate> FunctionExtension::GetNativeFunctionTemplate(
   7592     v8::Isolate* isolate, v8::Local<String> name) {
   7593   lookup_count++;
   7594   if (name->Equals(isolate->GetCurrentContext(), v8_str("A")).FromJust()) {
   7595     return v8::FunctionTemplate::New(isolate, CallFun,
   7596                                      v8::Integer::New(isolate, 8));
   7597   } else if (name->Equals(isolate->GetCurrentContext(), v8_str("B"))
   7598                  .FromJust()) {
   7599     return v8::FunctionTemplate::New(isolate, CallFun,
   7600                                      v8::Integer::New(isolate, 7));
   7601   } else if (name->Equals(isolate->GetCurrentContext(), v8_str("C"))
   7602                  .FromJust()) {
   7603     return v8::FunctionTemplate::New(isolate, CallFun,
   7604                                      v8::Integer::New(isolate, 6));
   7605   } else {
   7606     return v8::Local<v8::FunctionTemplate>();
   7607   }
   7608 }
   7609 
   7610 
   7611 THREADED_TEST(FunctionLookup) {
   7612   v8::RegisterExtension(new FunctionExtension());
   7613   v8::HandleScope handle_scope(CcTest::isolate());
   7614   static const char* exts[1] = {"functiontest"};
   7615   v8::ExtensionConfiguration config(1, exts);
   7616   LocalContext context(&config);
   7617   CHECK_EQ(3, lookup_count);
   7618   CHECK(v8::Integer::New(CcTest::isolate(), 8)
   7619             ->Equals(context.local(), CompileRun("Foo(0)"))
   7620             .FromJust());
   7621   CHECK(v8::Integer::New(CcTest::isolate(), 7)
   7622             ->Equals(context.local(), CompileRun("Foo(1)"))
   7623             .FromJust());
   7624   CHECK(v8::Integer::New(CcTest::isolate(), 6)
   7625             ->Equals(context.local(), CompileRun("Foo(2)"))
   7626             .FromJust());
   7627 }
   7628 
   7629 
   7630 THREADED_TEST(NativeFunctionConstructCall) {
   7631   v8::RegisterExtension(new FunctionExtension());
   7632   v8::HandleScope handle_scope(CcTest::isolate());
   7633   static const char* exts[1] = {"functiontest"};
   7634   v8::ExtensionConfiguration config(1, exts);
   7635   LocalContext context(&config);
   7636   for (int i = 0; i < 10; i++) {
   7637     // Run a few times to ensure that allocation of objects doesn't
   7638     // change behavior of a constructor function.
   7639     CHECK(v8::Integer::New(CcTest::isolate(), 8)
   7640               ->Equals(context.local(), CompileRun("(new A()).data"))
   7641               .FromJust());
   7642     CHECK(v8::Integer::New(CcTest::isolate(), 7)
   7643               ->Equals(context.local(), CompileRun("(new B()).data"))
   7644               .FromJust());
   7645     CHECK(v8::Integer::New(CcTest::isolate(), 6)
   7646               ->Equals(context.local(), CompileRun("(new C()).data"))
   7647               .FromJust());
   7648   }
   7649 }
   7650 
   7651 
   7652 static const char* last_location;
   7653 static const char* last_message;
   7654 void StoringErrorCallback(const char* location, const char* message) {
   7655   if (last_location == NULL) {
   7656     last_location = location;
   7657     last_message = message;
   7658   }
   7659 }
   7660 
   7661 
   7662 // ErrorReporting creates a circular extensions configuration and
   7663 // tests that the fatal error handler gets called.  This renders V8
   7664 // unusable and therefore this test cannot be run in parallel.
   7665 TEST(ErrorReporting) {
   7666   CcTest::isolate()->SetFatalErrorHandler(StoringErrorCallback);
   7667   static const char* aDeps[] = {"B"};
   7668   v8::RegisterExtension(new Extension("A", "", 1, aDeps));
   7669   static const char* bDeps[] = {"A"};
   7670   v8::RegisterExtension(new Extension("B", "", 1, bDeps));
   7671   last_location = NULL;
   7672   v8::ExtensionConfiguration config(1, bDeps);
   7673   v8::Local<Context> context = Context::New(CcTest::isolate(), &config);
   7674   CHECK(context.IsEmpty());
   7675   CHECK(last_location);
   7676 }
   7677 
   7678 
   7679 static void MissingScriptInfoMessageListener(v8::Local<v8::Message> message,
   7680                                              v8::Local<Value> data) {
   7681   v8::Isolate* isolate = CcTest::isolate();
   7682   Local<Context> context = isolate->GetCurrentContext();
   7683   CHECK(message->GetScriptOrigin().ResourceName()->IsUndefined());
   7684   CHECK(v8::Undefined(isolate)
   7685             ->Equals(context, message->GetScriptOrigin().ResourceName())
   7686             .FromJust());
   7687   message->GetLineNumber(context).FromJust();
   7688   message->GetSourceLine(context).ToLocalChecked();
   7689 }
   7690 
   7691 
   7692 THREADED_TEST(ErrorWithMissingScriptInfo) {
   7693   LocalContext context;
   7694   v8::HandleScope scope(context->GetIsolate());
   7695   context->GetIsolate()->AddMessageListener(MissingScriptInfoMessageListener);
   7696   CompileRun("throw Error()");
   7697   context->GetIsolate()->RemoveMessageListeners(
   7698       MissingScriptInfoMessageListener);
   7699 }
   7700 
   7701 
   7702 struct FlagAndPersistent {
   7703   bool flag;
   7704   v8::Global<v8::Object> handle;
   7705 };
   7706 
   7707 
   7708 static void SetFlag(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
   7709   data.GetParameter()->flag = true;
   7710   data.GetParameter()->handle.Reset();
   7711 }
   7712 
   7713 
   7714 static void IndependentWeakHandle(bool global_gc, bool interlinked) {
   7715   v8::Isolate* iso = CcTest::isolate();
   7716   v8::HandleScope scope(iso);
   7717   v8::Local<Context> context = Context::New(iso);
   7718   Context::Scope context_scope(context);
   7719 
   7720   FlagAndPersistent object_a, object_b;
   7721 
   7722   intptr_t big_heap_size;
   7723 
   7724   {
   7725     v8::HandleScope handle_scope(iso);
   7726     Local<Object> a(v8::Object::New(iso));
   7727     Local<Object> b(v8::Object::New(iso));
   7728     object_a.handle.Reset(iso, a);
   7729     object_b.handle.Reset(iso, b);
   7730     if (interlinked) {
   7731       a->Set(context, v8_str("x"), b).FromJust();
   7732       b->Set(context, v8_str("x"), a).FromJust();
   7733     }
   7734     if (global_gc) {
   7735       CcTest::heap()->CollectAllGarbage();
   7736     } else {
   7737       CcTest::heap()->CollectGarbage(i::NEW_SPACE);
   7738     }
   7739     // We are relying on this creating a big flag array and reserving the space
   7740     // up front.
   7741     v8::Local<Value> big_array = CompileRun("new Array(5000)");
   7742     a->Set(context, v8_str("y"), big_array).FromJust();
   7743     big_heap_size = CcTest::heap()->SizeOfObjects();
   7744   }
   7745 
   7746   object_a.flag = false;
   7747   object_b.flag = false;
   7748   object_a.handle.SetWeak(&object_a, &SetFlag,
   7749                           v8::WeakCallbackType::kParameter);
   7750   object_b.handle.SetWeak(&object_b, &SetFlag,
   7751                           v8::WeakCallbackType::kParameter);
   7752   CHECK(!object_b.handle.IsIndependent());
   7753   object_a.handle.MarkIndependent();
   7754   object_b.handle.MarkIndependent();
   7755   CHECK(object_b.handle.IsIndependent());
   7756   if (global_gc) {
   7757     CcTest::heap()->CollectAllGarbage();
   7758   } else {
   7759     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
   7760   }
   7761   // A single GC should be enough to reclaim the memory, since we are using
   7762   // phantom handles.
   7763   CHECK_LT(CcTest::heap()->SizeOfObjects(), big_heap_size - 20000);
   7764   CHECK(object_a.flag);
   7765   CHECK(object_b.flag);
   7766 }
   7767 
   7768 
   7769 TEST(IndependentWeakHandle) {
   7770   IndependentWeakHandle(false, false);
   7771   IndependentWeakHandle(false, true);
   7772   IndependentWeakHandle(true, false);
   7773   IndependentWeakHandle(true, true);
   7774 }
   7775 
   7776 
   7777 class Trivial {
   7778  public:
   7779   explicit Trivial(int x) : x_(x) {}
   7780 
   7781   int x() { return x_; }
   7782   void set_x(int x) { x_ = x; }
   7783 
   7784  private:
   7785   int x_;
   7786 };
   7787 
   7788 
   7789 class Trivial2 {
   7790  public:
   7791   Trivial2(int x, int y) : y_(y), x_(x) {}
   7792 
   7793   int x() { return x_; }
   7794   void set_x(int x) { x_ = x; }
   7795 
   7796   int y() { return y_; }
   7797   void set_y(int y) { y_ = y; }
   7798 
   7799  private:
   7800   int y_;
   7801   int x_;
   7802 };
   7803 
   7804 
   7805 void CheckInternalFields(
   7806     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   7807   v8::Persistent<v8::Object>* handle = data.GetParameter();
   7808   handle->Reset();
   7809   Trivial* t1 = reinterpret_cast<Trivial*>(data.GetInternalField(0));
   7810   Trivial2* t2 = reinterpret_cast<Trivial2*>(data.GetInternalField(1));
   7811   CHECK_EQ(42, t1->x());
   7812   CHECK_EQ(103, t2->x());
   7813   t1->set_x(1729);
   7814   t2->set_x(33550336);
   7815 }
   7816 
   7817 
   7818 void InternalFieldCallback(bool global_gc) {
   7819   LocalContext env;
   7820   v8::Isolate* isolate = env->GetIsolate();
   7821   v8::HandleScope scope(isolate);
   7822 
   7823   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   7824   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
   7825   Trivial* t1;
   7826   Trivial2* t2;
   7827   instance_templ->SetInternalFieldCount(2);
   7828   {
   7829     v8::HandleScope scope(isolate);
   7830     Local<v8::Object> obj = templ->GetFunction(env.local())
   7831                                 .ToLocalChecked()
   7832                                 ->NewInstance(env.local())
   7833                                 .ToLocalChecked();
   7834     v8::Persistent<v8::Object> handle(isolate, obj);
   7835     CHECK_EQ(2, obj->InternalFieldCount());
   7836     CHECK(obj->GetInternalField(0)->IsUndefined());
   7837     t1 = new Trivial(42);
   7838     t2 = new Trivial2(103, 9);
   7839 
   7840     obj->SetAlignedPointerInInternalField(0, t1);
   7841     t1 = reinterpret_cast<Trivial*>(obj->GetAlignedPointerFromInternalField(0));
   7842     CHECK_EQ(42, t1->x());
   7843 
   7844     obj->SetAlignedPointerInInternalField(1, t2);
   7845     t2 =
   7846         reinterpret_cast<Trivial2*>(obj->GetAlignedPointerFromInternalField(1));
   7847     CHECK_EQ(103, t2->x());
   7848 
   7849     handle.SetWeak<v8::Persistent<v8::Object>>(
   7850         &handle, CheckInternalFields, v8::WeakCallbackType::kInternalFields);
   7851     if (!global_gc) {
   7852       handle.MarkIndependent();
   7853     }
   7854   }
   7855   if (global_gc) {
   7856     CcTest::heap()->CollectAllGarbage();
   7857   } else {
   7858     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
   7859   }
   7860 
   7861   CHECK_EQ(1729, t1->x());
   7862   CHECK_EQ(33550336, t2->x());
   7863 
   7864   delete t1;
   7865   delete t2;
   7866 }
   7867 
   7868 
   7869 THREADED_TEST(InternalFieldCallback) {
   7870   InternalFieldCallback(false);
   7871   InternalFieldCallback(true);
   7872 }
   7873 
   7874 
   7875 static void ResetUseValueAndSetFlag(
   7876     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
   7877   // Blink will reset the handle, and then use the other handle, so they
   7878   // can't use the same backing slot.
   7879   data.GetParameter()->handle.Reset();
   7880   data.GetParameter()->flag = true;
   7881 }
   7882 
   7883 
   7884 void v8::internal::HeapTester::ResetWeakHandle(bool global_gc) {
   7885   using v8::Context;
   7886   using v8::Local;
   7887   using v8::Object;
   7888 
   7889   v8::Isolate* iso = CcTest::isolate();
   7890   v8::HandleScope scope(iso);
   7891   v8::Local<Context> context = Context::New(iso);
   7892   Context::Scope context_scope(context);
   7893 
   7894   FlagAndPersistent object_a, object_b;
   7895 
   7896   {
   7897     v8::HandleScope handle_scope(iso);
   7898     Local<Object> a(v8::Object::New(iso));
   7899     Local<Object> b(v8::Object::New(iso));
   7900     object_a.handle.Reset(iso, a);
   7901     object_b.handle.Reset(iso, b);
   7902     if (global_gc) {
   7903       CcTest::heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
   7904     } else {
   7905       CcTest::heap()->CollectGarbage(i::NEW_SPACE);
   7906     }
   7907   }
   7908 
   7909   object_a.flag = false;
   7910   object_b.flag = false;
   7911   object_a.handle.SetWeak(&object_a, &ResetUseValueAndSetFlag,
   7912                           v8::WeakCallbackType::kParameter);
   7913   object_b.handle.SetWeak(&object_b, &ResetUseValueAndSetFlag,
   7914                           v8::WeakCallbackType::kParameter);
   7915   if (!global_gc) {
   7916     object_a.handle.MarkIndependent();
   7917     object_b.handle.MarkIndependent();
   7918     CHECK(object_b.handle.IsIndependent());
   7919   }
   7920   if (global_gc) {
   7921     CcTest::heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
   7922   } else {
   7923     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
   7924   }
   7925   CHECK(object_a.flag);
   7926   CHECK(object_b.flag);
   7927 }
   7928 
   7929 
   7930 THREADED_HEAP_TEST(ResetWeakHandle) {
   7931   v8::internal::HeapTester::ResetWeakHandle(false);
   7932   v8::internal::HeapTester::ResetWeakHandle(true);
   7933 }
   7934 
   7935 
   7936 static void InvokeScavenge() { CcTest::heap()->CollectGarbage(i::NEW_SPACE); }
   7937 
   7938 
   7939 static void InvokeMarkSweep() { CcTest::heap()->CollectAllGarbage(); }
   7940 
   7941 
   7942 static void ForceScavenge2(
   7943     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
   7944   data.GetParameter()->flag = true;
   7945   InvokeScavenge();
   7946 }
   7947 
   7948 static void ForceScavenge1(
   7949     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
   7950   data.GetParameter()->handle.Reset();
   7951   data.SetSecondPassCallback(ForceScavenge2);
   7952 }
   7953 
   7954 
   7955 static void ForceMarkSweep2(
   7956     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
   7957   data.GetParameter()->flag = true;
   7958   InvokeMarkSweep();
   7959 }
   7960 
   7961 static void ForceMarkSweep1(
   7962     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
   7963   data.GetParameter()->handle.Reset();
   7964   data.SetSecondPassCallback(ForceMarkSweep2);
   7965 }
   7966 
   7967 
   7968 THREADED_TEST(GCFromWeakCallbacks) {
   7969   v8::Isolate* isolate = CcTest::isolate();
   7970   v8::Locker locker(CcTest::isolate());
   7971   v8::HandleScope scope(isolate);
   7972   v8::Local<Context> context = Context::New(isolate);
   7973   Context::Scope context_scope(context);
   7974 
   7975   static const int kNumberOfGCTypes = 2;
   7976   typedef v8::WeakCallbackInfo<FlagAndPersistent>::Callback Callback;
   7977   Callback gc_forcing_callback[kNumberOfGCTypes] = {&ForceScavenge1,
   7978                                                     &ForceMarkSweep1};
   7979 
   7980   typedef void (*GCInvoker)();
   7981   GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
   7982 
   7983   for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
   7984     for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
   7985       FlagAndPersistent object;
   7986       {
   7987         v8::HandleScope handle_scope(isolate);
   7988         object.handle.Reset(isolate, v8::Object::New(isolate));
   7989       }
   7990       object.flag = false;
   7991       object.handle.SetWeak(&object, gc_forcing_callback[inner_gc],
   7992                             v8::WeakCallbackType::kParameter);
   7993       object.handle.MarkIndependent();
   7994       invoke_gc[outer_gc]();
   7995       EmptyMessageQueues(isolate);
   7996       CHECK(object.flag);
   7997     }
   7998   }
   7999 }
   8000 
   8001 
   8002 v8::Local<Function> args_fun;
   8003 
   8004 
   8005 static void ArgumentsTestCallback(
   8006     const v8::FunctionCallbackInfo<v8::Value>& args) {
   8007   ApiTestFuzzer::Fuzz();
   8008   v8::Isolate* isolate = args.GetIsolate();
   8009   Local<Context> context = isolate->GetCurrentContext();
   8010   CHECK_EQ(3, args.Length());
   8011   CHECK(v8::Integer::New(isolate, 1)->Equals(context, args[0]).FromJust());
   8012   CHECK(v8::Integer::New(isolate, 2)->Equals(context, args[1]).FromJust());
   8013   CHECK(v8::Integer::New(isolate, 3)->Equals(context, args[2]).FromJust());
   8014   CHECK(v8::Undefined(isolate)->Equals(context, args[3]).FromJust());
   8015   v8::HandleScope scope(args.GetIsolate());
   8016   CcTest::heap()->CollectAllGarbage();
   8017 }
   8018 
   8019 
   8020 THREADED_TEST(Arguments) {
   8021   v8::Isolate* isolate = CcTest::isolate();
   8022   v8::HandleScope scope(isolate);
   8023   v8::Local<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
   8024   global->Set(v8_str("f"),
   8025               v8::FunctionTemplate::New(isolate, ArgumentsTestCallback));
   8026   LocalContext context(NULL, global);
   8027   args_fun = context->Global()
   8028                  ->Get(context.local(), v8_str("f"))
   8029                  .ToLocalChecked()
   8030                  .As<Function>();
   8031   v8_compile("f(1, 2, 3)")->Run(context.local()).ToLocalChecked();
   8032 }
   8033 
   8034 
   8035 static int p_getter_count;
   8036 static int p_getter_count2;
   8037 
   8038 
   8039 static void PGetter(Local<Name> name,
   8040                     const v8::PropertyCallbackInfo<v8::Value>& info) {
   8041   ApiTestFuzzer::Fuzz();
   8042   p_getter_count++;
   8043   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
   8044   v8::Local<v8::Object> global = context->Global();
   8045   CHECK(
   8046       info.Holder()
   8047           ->Equals(context, global->Get(context, v8_str("o1")).ToLocalChecked())
   8048           .FromJust());
   8049   if (name->Equals(context, v8_str("p1")).FromJust()) {
   8050     CHECK(info.This()
   8051               ->Equals(context,
   8052                        global->Get(context, v8_str("o1")).ToLocalChecked())
   8053               .FromJust());
   8054   } else if (name->Equals(context, v8_str("p2")).FromJust()) {
   8055     CHECK(info.This()
   8056               ->Equals(context,
   8057                        global->Get(context, v8_str("o2")).ToLocalChecked())
   8058               .FromJust());
   8059   } else if (name->Equals(context, v8_str("p3")).FromJust()) {
   8060     CHECK(info.This()
   8061               ->Equals(context,
   8062                        global->Get(context, v8_str("o3")).ToLocalChecked())
   8063               .FromJust());
   8064   } else if (name->Equals(context, v8_str("p4")).FromJust()) {
   8065     CHECK(info.This()
   8066               ->Equals(context,
   8067                        global->Get(context, v8_str("o4")).ToLocalChecked())
   8068               .FromJust());
   8069   }
   8070 }
   8071 
   8072 
   8073 static void RunHolderTest(v8::Local<v8::ObjectTemplate> obj) {
   8074   ApiTestFuzzer::Fuzz();
   8075   LocalContext context;
   8076   CHECK(context->Global()
   8077             ->Set(context.local(), v8_str("o1"),
   8078                   obj->NewInstance(context.local()).ToLocalChecked())
   8079             .FromJust());
   8080   CompileRun(
   8081     "o1.__proto__ = { };"
   8082     "var o2 = { __proto__: o1 };"
   8083     "var o3 = { __proto__: o2 };"
   8084     "var o4 = { __proto__: o3 };"
   8085     "for (var i = 0; i < 10; i++) o4.p4;"
   8086     "for (var i = 0; i < 10; i++) o3.p3;"
   8087     "for (var i = 0; i < 10; i++) o2.p2;"
   8088     "for (var i = 0; i < 10; i++) o1.p1;");
   8089 }
   8090 
   8091 
   8092 static void PGetter2(Local<Name> name,
   8093                      const v8::PropertyCallbackInfo<v8::Value>& info) {
   8094   ApiTestFuzzer::Fuzz();
   8095   p_getter_count2++;
   8096   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
   8097   v8::Local<v8::Object> global = context->Global();
   8098   CHECK(
   8099       info.Holder()
   8100           ->Equals(context, global->Get(context, v8_str("o1")).ToLocalChecked())
   8101           .FromJust());
   8102   if (name->Equals(context, v8_str("p1")).FromJust()) {
   8103     CHECK(info.This()
   8104               ->Equals(context,
   8105                        global->Get(context, v8_str("o1")).ToLocalChecked())
   8106               .FromJust());
   8107   } else if (name->Equals(context, v8_str("p2")).FromJust()) {
   8108     CHECK(info.This()
   8109               ->Equals(context,
   8110                        global->Get(context, v8_str("o2")).ToLocalChecked())
   8111               .FromJust());
   8112   } else if (name->Equals(context, v8_str("p3")).FromJust()) {
   8113     CHECK(info.This()
   8114               ->Equals(context,
   8115                        global->Get(context, v8_str("o3")).ToLocalChecked())
   8116               .FromJust());
   8117   } else if (name->Equals(context, v8_str("p4")).FromJust()) {
   8118     CHECK(info.This()
   8119               ->Equals(context,
   8120                        global->Get(context, v8_str("o4")).ToLocalChecked())
   8121               .FromJust());
   8122   }
   8123 }
   8124 
   8125 
   8126 THREADED_TEST(GetterHolders) {
   8127   v8::Isolate* isolate = CcTest::isolate();
   8128   v8::HandleScope scope(isolate);
   8129   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
   8130   obj->SetAccessor(v8_str("p1"), PGetter);
   8131   obj->SetAccessor(v8_str("p2"), PGetter);
   8132   obj->SetAccessor(v8_str("p3"), PGetter);
   8133   obj->SetAccessor(v8_str("p4"), PGetter);
   8134   p_getter_count = 0;
   8135   RunHolderTest(obj);
   8136   CHECK_EQ(40, p_getter_count);
   8137 }
   8138 
   8139 
   8140 THREADED_TEST(PreInterceptorHolders) {
   8141   v8::Isolate* isolate = CcTest::isolate();
   8142   v8::HandleScope scope(isolate);
   8143   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
   8144   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(PGetter2));
   8145   p_getter_count2 = 0;
   8146   RunHolderTest(obj);
   8147   CHECK_EQ(40, p_getter_count2);
   8148 }
   8149 
   8150 
   8151 THREADED_TEST(ObjectInstantiation) {
   8152   v8::Isolate* isolate = CcTest::isolate();
   8153   v8::HandleScope scope(isolate);
   8154   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   8155   templ->SetAccessor(v8_str("t"), PGetter2);
   8156   LocalContext context;
   8157   CHECK(context->Global()
   8158             ->Set(context.local(), v8_str("o"),
   8159                   templ->NewInstance(context.local()).ToLocalChecked())
   8160             .FromJust());
   8161   for (int i = 0; i < 100; i++) {
   8162     v8::HandleScope inner_scope(CcTest::isolate());
   8163     v8::Local<v8::Object> obj =
   8164         templ->NewInstance(context.local()).ToLocalChecked();
   8165     CHECK(!obj->Equals(context.local(), context->Global()
   8166                                             ->Get(context.local(), v8_str("o"))
   8167                                             .ToLocalChecked())
   8168                .FromJust());
   8169     CHECK(
   8170         context->Global()->Set(context.local(), v8_str("o2"), obj).FromJust());
   8171     v8::Local<Value> value = CompileRun("o.__proto__ === o2.__proto__");
   8172     CHECK(v8::True(isolate)->Equals(context.local(), value).FromJust());
   8173     CHECK(context->Global()->Set(context.local(), v8_str("o"), obj).FromJust());
   8174   }
   8175 }
   8176 
   8177 
   8178 static int StrCmp16(uint16_t* a, uint16_t* b) {
   8179   while (true) {
   8180     if (*a == 0 && *b == 0) return 0;
   8181     if (*a != *b) return 0 + *a - *b;
   8182     a++;
   8183     b++;
   8184   }
   8185 }
   8186 
   8187 
   8188 static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
   8189   while (true) {
   8190     if (n-- == 0) return 0;
   8191     if (*a == 0 && *b == 0) return 0;
   8192     if (*a != *b) return 0 + *a - *b;
   8193     a++;
   8194     b++;
   8195   }
   8196 }
   8197 
   8198 
   8199 int GetUtf8Length(Local<String> str) {
   8200   int len = str->Utf8Length();
   8201   if (len < 0) {
   8202     i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
   8203     i::String::Flatten(istr);
   8204     len = str->Utf8Length();
   8205   }
   8206   return len;
   8207 }
   8208 
   8209 
   8210 THREADED_TEST(StringWrite) {
   8211   LocalContext context;
   8212   v8::HandleScope scope(context->GetIsolate());
   8213   v8::Local<String> str = v8_str("abcde");
   8214   // abc<Icelandic eth><Unicode snowman>.
   8215   v8::Local<String> str2 = v8_str("abc\303\260\342\230\203");
   8216   v8::Local<String> str3 =
   8217       v8::String::NewFromUtf8(context->GetIsolate(), "abc\0def",
   8218                               v8::NewStringType::kNormal, 7)
   8219           .ToLocalChecked();
   8220   // "ab" + lead surrogate + "cd" + trail surrogate + "ef"
   8221   uint16_t orphans[8] = { 0x61, 0x62, 0xd800, 0x63, 0x64, 0xdc00, 0x65, 0x66 };
   8222   v8::Local<String> orphans_str =
   8223       v8::String::NewFromTwoByte(context->GetIsolate(), orphans,
   8224                                  v8::NewStringType::kNormal, 8)
   8225           .ToLocalChecked();
   8226   // single lead surrogate
   8227   uint16_t lead[1] = { 0xd800 };
   8228   v8::Local<String> lead_str =
   8229       v8::String::NewFromTwoByte(context->GetIsolate(), lead,
   8230                                  v8::NewStringType::kNormal, 1)
   8231           .ToLocalChecked();
   8232   // single trail surrogate
   8233   uint16_t trail[1] = { 0xdc00 };
   8234   v8::Local<String> trail_str =
   8235       v8::String::NewFromTwoByte(context->GetIsolate(), trail,
   8236                                  v8::NewStringType::kNormal, 1)
   8237           .ToLocalChecked();
   8238   // surrogate pair
   8239   uint16_t pair[2] = { 0xd800,  0xdc00 };
   8240   v8::Local<String> pair_str =
   8241       v8::String::NewFromTwoByte(context->GetIsolate(), pair,
   8242                                  v8::NewStringType::kNormal, 2)
   8243           .ToLocalChecked();
   8244   const int kStride = 4;  // Must match stride in for loops in JS below.
   8245   CompileRun(
   8246       "var left = '';"
   8247       "for (var i = 0; i < 0xd800; i += 4) {"
   8248       "  left = left + String.fromCharCode(i);"
   8249       "}");
   8250   CompileRun(
   8251       "var right = '';"
   8252       "for (var i = 0; i < 0xd800; i += 4) {"
   8253       "  right = String.fromCharCode(i) + right;"
   8254       "}");
   8255   v8::Local<v8::Object> global = context->Global();
   8256   Local<String> left_tree = global->Get(context.local(), v8_str("left"))
   8257                                 .ToLocalChecked()
   8258                                 .As<String>();
   8259   Local<String> right_tree = global->Get(context.local(), v8_str("right"))
   8260                                  .ToLocalChecked()
   8261                                  .As<String>();
   8262 
   8263   CHECK_EQ(5, str2->Length());
   8264   CHECK_EQ(0xd800 / kStride, left_tree->Length());
   8265   CHECK_EQ(0xd800 / kStride, right_tree->Length());
   8266 
   8267   char buf[100];
   8268   char utf8buf[0xd800 * 3];
   8269   uint16_t wbuf[100];
   8270   int len;
   8271   int charlen;
   8272 
   8273   memset(utf8buf, 0x1, 1000);
   8274   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
   8275   CHECK_EQ(9, len);
   8276   CHECK_EQ(5, charlen);
   8277   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
   8278 
   8279   memset(utf8buf, 0x1, 1000);
   8280   len = str2->WriteUtf8(utf8buf, 8, &charlen);
   8281   CHECK_EQ(8, len);
   8282   CHECK_EQ(5, charlen);
   8283   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
   8284 
   8285   memset(utf8buf, 0x1, 1000);
   8286   len = str2->WriteUtf8(utf8buf, 7, &charlen);
   8287   CHECK_EQ(5, len);
   8288   CHECK_EQ(4, charlen);
   8289   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
   8290 
   8291   memset(utf8buf, 0x1, 1000);
   8292   len = str2->WriteUtf8(utf8buf, 6, &charlen);
   8293   CHECK_EQ(5, len);
   8294   CHECK_EQ(4, charlen);
   8295   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
   8296 
   8297   memset(utf8buf, 0x1, 1000);
   8298   len = str2->WriteUtf8(utf8buf, 5, &charlen);
   8299   CHECK_EQ(5, len);
   8300   CHECK_EQ(4, charlen);
   8301   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
   8302 
   8303   memset(utf8buf, 0x1, 1000);
   8304   len = str2->WriteUtf8(utf8buf, 4, &charlen);
   8305   CHECK_EQ(3, len);
   8306   CHECK_EQ(3, charlen);
   8307   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
   8308 
   8309   memset(utf8buf, 0x1, 1000);
   8310   len = str2->WriteUtf8(utf8buf, 3, &charlen);
   8311   CHECK_EQ(3, len);
   8312   CHECK_EQ(3, charlen);
   8313   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
   8314 
   8315   memset(utf8buf, 0x1, 1000);
   8316   len = str2->WriteUtf8(utf8buf, 2, &charlen);
   8317   CHECK_EQ(2, len);
   8318   CHECK_EQ(2, charlen);
   8319   CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
   8320 
   8321   // allow orphan surrogates by default
   8322   memset(utf8buf, 0x1, 1000);
   8323   len = orphans_str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
   8324   CHECK_EQ(13, len);
   8325   CHECK_EQ(8, charlen);
   8326   CHECK_EQ(0, strcmp(utf8buf, "ab\355\240\200cd\355\260\200ef"));
   8327 
   8328   // replace orphan surrogates with unicode replacement character
   8329   memset(utf8buf, 0x1, 1000);
   8330   len = orphans_str->WriteUtf8(utf8buf,
   8331                                sizeof(utf8buf),
   8332                                &charlen,
   8333                                String::REPLACE_INVALID_UTF8);
   8334   CHECK_EQ(13, len);
   8335   CHECK_EQ(8, charlen);
   8336   CHECK_EQ(0, strcmp(utf8buf, "ab\357\277\275cd\357\277\275ef"));
   8337 
   8338   // replace single lead surrogate with unicode replacement character
   8339   memset(utf8buf, 0x1, 1000);
   8340   len = lead_str->WriteUtf8(utf8buf,
   8341                             sizeof(utf8buf),
   8342                             &charlen,
   8343                             String::REPLACE_INVALID_UTF8);
   8344   CHECK_EQ(4, len);
   8345   CHECK_EQ(1, charlen);
   8346   CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
   8347 
   8348   // replace single trail surrogate with unicode replacement character
   8349   memset(utf8buf, 0x1, 1000);
   8350   len = trail_str->WriteUtf8(utf8buf,
   8351                              sizeof(utf8buf),
   8352                              &charlen,
   8353                              String::REPLACE_INVALID_UTF8);
   8354   CHECK_EQ(4, len);
   8355   CHECK_EQ(1, charlen);
   8356   CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
   8357 
   8358   // do not replace / write anything if surrogate pair does not fit the buffer
   8359   // space
   8360   memset(utf8buf, 0x1, 1000);
   8361   len = pair_str->WriteUtf8(utf8buf,
   8362                              3,
   8363                              &charlen,
   8364                              String::REPLACE_INVALID_UTF8);
   8365   CHECK_EQ(0, len);
   8366   CHECK_EQ(0, charlen);
   8367 
   8368   memset(utf8buf, 0x1, sizeof(utf8buf));
   8369   len = GetUtf8Length(left_tree);
   8370   int utf8_expected =
   8371       (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
   8372   CHECK_EQ(utf8_expected, len);
   8373   len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
   8374   CHECK_EQ(utf8_expected, len);
   8375   CHECK_EQ(0xd800 / kStride, charlen);
   8376   CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
   8377   CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
   8378   CHECK_EQ(0xc0 - kStride,
   8379            static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
   8380   CHECK_EQ(1, utf8buf[utf8_expected]);
   8381 
   8382   memset(utf8buf, 0x1, sizeof(utf8buf));
   8383   len = GetUtf8Length(right_tree);
   8384   CHECK_EQ(utf8_expected, len);
   8385   len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
   8386   CHECK_EQ(utf8_expected, len);
   8387   CHECK_EQ(0xd800 / kStride, charlen);
   8388   CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
   8389   CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
   8390   CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
   8391   CHECK_EQ(1, utf8buf[utf8_expected]);
   8392 
   8393   memset(buf, 0x1, sizeof(buf));
   8394   memset(wbuf, 0x1, sizeof(wbuf));
   8395   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
   8396   CHECK_EQ(5, len);
   8397   len = str->Write(wbuf);
   8398   CHECK_EQ(5, len);
   8399   CHECK_EQ(0, strcmp("abcde", buf));
   8400   uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
   8401   CHECK_EQ(0, StrCmp16(answer1, wbuf));
   8402 
   8403   memset(buf, 0x1, sizeof(buf));
   8404   memset(wbuf, 0x1, sizeof(wbuf));
   8405   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 4);
   8406   CHECK_EQ(4, len);
   8407   len = str->Write(wbuf, 0, 4);
   8408   CHECK_EQ(4, len);
   8409   CHECK_EQ(0, strncmp("abcd\1", buf, 5));
   8410   uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
   8411   CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
   8412 
   8413   memset(buf, 0x1, sizeof(buf));
   8414   memset(wbuf, 0x1, sizeof(wbuf));
   8415   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 5);
   8416   CHECK_EQ(5, len);
   8417   len = str->Write(wbuf, 0, 5);
   8418   CHECK_EQ(5, len);
   8419   CHECK_EQ(0, strncmp("abcde\1", buf, 6));
   8420   uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
   8421   CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
   8422 
   8423   memset(buf, 0x1, sizeof(buf));
   8424   memset(wbuf, 0x1, sizeof(wbuf));
   8425   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 6);
   8426   CHECK_EQ(5, len);
   8427   len = str->Write(wbuf, 0, 6);
   8428   CHECK_EQ(5, len);
   8429   CHECK_EQ(0, strcmp("abcde", buf));
   8430   uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
   8431   CHECK_EQ(0, StrCmp16(answer4, wbuf));
   8432 
   8433   memset(buf, 0x1, sizeof(buf));
   8434   memset(wbuf, 0x1, sizeof(wbuf));
   8435   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, -1);
   8436   CHECK_EQ(1, len);
   8437   len = str->Write(wbuf, 4, -1);
   8438   CHECK_EQ(1, len);
   8439   CHECK_EQ(0, strcmp("e", buf));
   8440   uint16_t answer5[] = {'e', '\0'};
   8441   CHECK_EQ(0, StrCmp16(answer5, wbuf));
   8442 
   8443   memset(buf, 0x1, sizeof(buf));
   8444   memset(wbuf, 0x1, sizeof(wbuf));
   8445   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 6);
   8446   CHECK_EQ(1, len);
   8447   len = str->Write(wbuf, 4, 6);
   8448   CHECK_EQ(1, len);
   8449   CHECK_EQ(0, strcmp("e", buf));
   8450   CHECK_EQ(0, StrCmp16(answer5, wbuf));
   8451 
   8452   memset(buf, 0x1, sizeof(buf));
   8453   memset(wbuf, 0x1, sizeof(wbuf));
   8454   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 1);
   8455   CHECK_EQ(1, len);
   8456   len = str->Write(wbuf, 4, 1);
   8457   CHECK_EQ(1, len);
   8458   CHECK_EQ(0, strncmp("e\1", buf, 2));
   8459   uint16_t answer6[] = {'e', 0x101};
   8460   CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
   8461 
   8462   memset(buf, 0x1, sizeof(buf));
   8463   memset(wbuf, 0x1, sizeof(wbuf));
   8464   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 3, 1);
   8465   CHECK_EQ(1, len);
   8466   len = str->Write(wbuf, 3, 1);
   8467   CHECK_EQ(1, len);
   8468   CHECK_EQ(0, strncmp("d\1", buf, 2));
   8469   uint16_t answer7[] = {'d', 0x101};
   8470   CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
   8471 
   8472   memset(wbuf, 0x1, sizeof(wbuf));
   8473   wbuf[5] = 'X';
   8474   len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
   8475   CHECK_EQ(5, len);
   8476   CHECK_EQ('X', wbuf[5]);
   8477   uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
   8478   uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
   8479   CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
   8480   CHECK_NE(0, StrCmp16(answer8b, wbuf));
   8481   wbuf[5] = '\0';
   8482   CHECK_EQ(0, StrCmp16(answer8b, wbuf));
   8483 
   8484   memset(buf, 0x1, sizeof(buf));
   8485   buf[5] = 'X';
   8486   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
   8487                           0,
   8488                           6,
   8489                           String::NO_NULL_TERMINATION);
   8490   CHECK_EQ(5, len);
   8491   CHECK_EQ('X', buf[5]);
   8492   CHECK_EQ(0, strncmp("abcde", buf, 5));
   8493   CHECK_NE(0, strcmp("abcde", buf));
   8494   buf[5] = '\0';
   8495   CHECK_EQ(0, strcmp("abcde", buf));
   8496 
   8497   memset(utf8buf, 0x1, sizeof(utf8buf));
   8498   utf8buf[8] = 'X';
   8499   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
   8500                         String::NO_NULL_TERMINATION);
   8501   CHECK_EQ(8, len);
   8502   CHECK_EQ('X', utf8buf[8]);
   8503   CHECK_EQ(5, charlen);
   8504   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
   8505   CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
   8506   utf8buf[8] = '\0';
   8507   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
   8508 
   8509   memset(utf8buf, 0x1, sizeof(utf8buf));
   8510   utf8buf[5] = 'X';
   8511   len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
   8512                         String::NO_NULL_TERMINATION);
   8513   CHECK_EQ(5, len);
   8514   CHECK_EQ('X', utf8buf[5]);  // Test that the sixth character is untouched.
   8515   CHECK_EQ(5, charlen);
   8516   utf8buf[5] = '\0';
   8517   CHECK_EQ(0, strcmp(utf8buf, "abcde"));
   8518 
   8519   memset(buf, 0x1, sizeof(buf));
   8520   len = str3->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
   8521   CHECK_EQ(7, len);
   8522   CHECK_EQ(0, strcmp("abc", buf));
   8523   CHECK_EQ(0, buf[3]);
   8524   CHECK_EQ(0, strcmp("def", buf + 4));
   8525 
   8526   CHECK_EQ(0, str->WriteOneByte(NULL, 0, 0, String::NO_NULL_TERMINATION));
   8527   CHECK_EQ(0, str->WriteUtf8(NULL, 0, 0, String::NO_NULL_TERMINATION));
   8528   CHECK_EQ(0, str->Write(NULL, 0, 0, String::NO_NULL_TERMINATION));
   8529 }
   8530 
   8531 
   8532 static void Utf16Helper(
   8533     LocalContext& context,  // NOLINT
   8534     const char* name,
   8535     const char* lengths_name,
   8536     int len) {
   8537   Local<v8::Array> a = Local<v8::Array>::Cast(
   8538       context->Global()->Get(context.local(), v8_str(name)).ToLocalChecked());
   8539   Local<v8::Array> alens =
   8540       Local<v8::Array>::Cast(context->Global()
   8541                                  ->Get(context.local(), v8_str(lengths_name))
   8542                                  .ToLocalChecked());
   8543   for (int i = 0; i < len; i++) {
   8544     Local<v8::String> string =
   8545         Local<v8::String>::Cast(a->Get(context.local(), i).ToLocalChecked());
   8546     Local<v8::Number> expected_len = Local<v8::Number>::Cast(
   8547         alens->Get(context.local(), i).ToLocalChecked());
   8548     int length = GetUtf8Length(string);
   8549     CHECK_EQ(static_cast<int>(expected_len->Value()), length);
   8550   }
   8551 }
   8552 
   8553 
   8554 THREADED_TEST(Utf16) {
   8555   LocalContext context;
   8556   v8::HandleScope scope(context->GetIsolate());
   8557   CompileRun(
   8558       "var pad = '01234567890123456789';"
   8559       "var p = [];"
   8560       "var plens = [20, 3, 3];"
   8561       "p.push('01234567890123456789');"
   8562       "var lead = 0xd800;"
   8563       "var trail = 0xdc00;"
   8564       "p.push(String.fromCharCode(0xd800));"
   8565       "p.push(String.fromCharCode(0xdc00));"
   8566       "var a = [];"
   8567       "var b = [];"
   8568       "var c = [];"
   8569       "var alens = [];"
   8570       "for (var i = 0; i < 3; i++) {"
   8571       "  p[1] = String.fromCharCode(lead++);"
   8572       "  for (var j = 0; j < 3; j++) {"
   8573       "    p[2] = String.fromCharCode(trail++);"
   8574       "    a.push(p[i] + p[j]);"
   8575       "    b.push(p[i] + p[j]);"
   8576       "    c.push(p[i] + p[j]);"
   8577       "    alens.push(plens[i] + plens[j]);"
   8578       "  }"
   8579       "}"
   8580       "alens[5] -= 2;"  // Here the surrogate pairs match up.
   8581       "var a2 = [];"
   8582       "var b2 = [];"
   8583       "var c2 = [];"
   8584       "var a2lens = [];"
   8585       "for (var m = 0; m < 9; m++) {"
   8586       "  for (var n = 0; n < 9; n++) {"
   8587       "    a2.push(a[m] + a[n]);"
   8588       "    b2.push(b[m] + b[n]);"
   8589       "    var newc = 'x' + c[m] + c[n] + 'y';"
   8590       "    c2.push(newc.substring(1, newc.length - 1));"
   8591       "    var utf = alens[m] + alens[n];"  // And here.
   8592            // The 'n's that start with 0xdc.. are 6-8
   8593            // The 'm's that end with 0xd8.. are 1, 4 and 7
   8594       "    if ((m % 3) == 1 && n >= 6) utf -= 2;"
   8595       "    a2lens.push(utf);"
   8596       "  }"
   8597       "}");
   8598   Utf16Helper(context, "a", "alens", 9);
   8599   Utf16Helper(context, "a2", "a2lens", 81);
   8600 }
   8601 
   8602 
   8603 static bool SameSymbol(Local<String> s1, Local<String> s2) {
   8604   i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
   8605   i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
   8606   return *is1 == *is2;
   8607 }
   8608 
   8609 
   8610 THREADED_TEST(Utf16Symbol) {
   8611   LocalContext context;
   8612   v8::HandleScope scope(context->GetIsolate());
   8613 
   8614   Local<String> symbol1 =
   8615       v8::String::NewFromUtf8(context->GetIsolate(), "abc",
   8616                               v8::NewStringType::kInternalized)
   8617           .ToLocalChecked();
   8618   Local<String> symbol2 =
   8619       v8::String::NewFromUtf8(context->GetIsolate(), "abc",
   8620                               v8::NewStringType::kInternalized)
   8621           .ToLocalChecked();
   8622   CHECK(SameSymbol(symbol1, symbol2));
   8623 
   8624   CompileRun(
   8625       "var sym0 = 'benedictus';"
   8626       "var sym0b = 'S\303\270ren';"
   8627       "var sym1 = '\355\240\201\355\260\207';"
   8628       "var sym2 = '\360\220\220\210';"
   8629       "var sym3 = 'x\355\240\201\355\260\207';"
   8630       "var sym4 = 'x\360\220\220\210';"
   8631       "if (sym1.length != 2) throw sym1;"
   8632       "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
   8633       "if (sym2.length != 2) throw sym2;"
   8634       "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
   8635       "if (sym3.length != 3) throw sym3;"
   8636       "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
   8637       "if (sym4.length != 3) throw sym4;"
   8638       "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
   8639   Local<String> sym0 =
   8640       v8::String::NewFromUtf8(context->GetIsolate(), "benedictus",
   8641                               v8::NewStringType::kInternalized)
   8642           .ToLocalChecked();
   8643   Local<String> sym0b =
   8644       v8::String::NewFromUtf8(context->GetIsolate(), "S\303\270ren",
   8645                               v8::NewStringType::kInternalized)
   8646           .ToLocalChecked();
   8647   Local<String> sym1 =
   8648       v8::String::NewFromUtf8(context->GetIsolate(), "\355\240\201\355\260\207",
   8649                               v8::NewStringType::kInternalized)
   8650           .ToLocalChecked();
   8651   Local<String> sym2 =
   8652       v8::String::NewFromUtf8(context->GetIsolate(), "\360\220\220\210",
   8653                               v8::NewStringType::kInternalized)
   8654           .ToLocalChecked();
   8655   Local<String> sym3 = v8::String::NewFromUtf8(context->GetIsolate(),
   8656                                                "x\355\240\201\355\260\207",
   8657                                                v8::NewStringType::kInternalized)
   8658                            .ToLocalChecked();
   8659   Local<String> sym4 =
   8660       v8::String::NewFromUtf8(context->GetIsolate(), "x\360\220\220\210",
   8661                               v8::NewStringType::kInternalized)
   8662           .ToLocalChecked();
   8663   v8::Local<v8::Object> global = context->Global();
   8664   Local<Value> s0 =
   8665       global->Get(context.local(), v8_str("sym0")).ToLocalChecked();
   8666   Local<Value> s0b =
   8667       global->Get(context.local(), v8_str("sym0b")).ToLocalChecked();
   8668   Local<Value> s1 =
   8669       global->Get(context.local(), v8_str("sym1")).ToLocalChecked();
   8670   Local<Value> s2 =
   8671       global->Get(context.local(), v8_str("sym2")).ToLocalChecked();
   8672   Local<Value> s3 =
   8673       global->Get(context.local(), v8_str("sym3")).ToLocalChecked();
   8674   Local<Value> s4 =
   8675       global->Get(context.local(), v8_str("sym4")).ToLocalChecked();
   8676   CHECK(SameSymbol(sym0, Local<String>::Cast(s0)));
   8677   CHECK(SameSymbol(sym0b, Local<String>::Cast(s0b)));
   8678   CHECK(SameSymbol(sym1, Local<String>::Cast(s1)));
   8679   CHECK(SameSymbol(sym2, Local<String>::Cast(s2)));
   8680   CHECK(SameSymbol(sym3, Local<String>::Cast(s3)));
   8681   CHECK(SameSymbol(sym4, Local<String>::Cast(s4)));
   8682 }
   8683 
   8684 
   8685 THREADED_TEST(Utf16MissingTrailing) {
   8686   LocalContext context;
   8687   v8::HandleScope scope(context->GetIsolate());
   8688 
   8689   // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
   8690   int size = 1024 * 64;
   8691   uint8_t* buffer = new uint8_t[size];
   8692   for (int i = 0; i < size; i += 4) {
   8693     buffer[i] = 0xf0;
   8694     buffer[i + 1] = 0x9d;
   8695     buffer[i + 2] = 0x80;
   8696     buffer[i + 3] = 0x9e;
   8697   }
   8698 
   8699   // Now invoke the decoder without last 3 bytes
   8700   v8::Local<v8::String> str =
   8701       v8::String::NewFromUtf8(
   8702           context->GetIsolate(), reinterpret_cast<char*>(buffer),
   8703           v8::NewStringType::kNormal, size - 3).ToLocalChecked();
   8704   USE(str);
   8705   delete[] buffer;
   8706 }
   8707 
   8708 
   8709 THREADED_TEST(Utf16Trailing3Byte) {
   8710   LocalContext context;
   8711   v8::HandleScope scope(context->GetIsolate());
   8712 
   8713   // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
   8714   int size = 1024 * 63;
   8715   uint8_t* buffer = new uint8_t[size];
   8716   for (int i = 0; i < size; i += 3) {
   8717     buffer[i] = 0xe2;
   8718     buffer[i + 1] = 0x80;
   8719     buffer[i + 2] = 0xa6;
   8720   }
   8721 
   8722   // Now invoke the decoder without last 3 bytes
   8723   v8::Local<v8::String> str =
   8724       v8::String::NewFromUtf8(
   8725           context->GetIsolate(), reinterpret_cast<char*>(buffer),
   8726           v8::NewStringType::kNormal, size).ToLocalChecked();
   8727 
   8728   v8::String::Value value(str);
   8729   CHECK_EQ(value.length(), size / 3);
   8730   CHECK_EQ((*value)[value.length() - 1], 0x2026);
   8731 
   8732   delete[] buffer;
   8733 }
   8734 
   8735 
   8736 THREADED_TEST(ToArrayIndex) {
   8737   LocalContext context;
   8738   v8::Isolate* isolate = context->GetIsolate();
   8739   v8::HandleScope scope(isolate);
   8740 
   8741   v8::Local<String> str = v8_str("42");
   8742   v8::MaybeLocal<v8::Uint32> index = str->ToArrayIndex(context.local());
   8743   CHECK(!index.IsEmpty());
   8744   CHECK_EQ(42.0,
   8745            index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
   8746   str = v8_str("42asdf");
   8747   index = str->ToArrayIndex(context.local());
   8748   CHECK(index.IsEmpty());
   8749   str = v8_str("-42");
   8750   index = str->ToArrayIndex(context.local());
   8751   CHECK(index.IsEmpty());
   8752   str = v8_str("4294967294");
   8753   index = str->ToArrayIndex(context.local());
   8754   CHECK(!index.IsEmpty());
   8755   CHECK_EQ(4294967294.0,
   8756            index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
   8757   v8::Local<v8::Number> num = v8::Number::New(isolate, 1);
   8758   index = num->ToArrayIndex(context.local());
   8759   CHECK(!index.IsEmpty());
   8760   CHECK_EQ(1.0,
   8761            index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
   8762   num = v8::Number::New(isolate, -1);
   8763   index = num->ToArrayIndex(context.local());
   8764   CHECK(index.IsEmpty());
   8765   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   8766   index = obj->ToArrayIndex(context.local());
   8767   CHECK(index.IsEmpty());
   8768 }
   8769 
   8770 
   8771 THREADED_TEST(ErrorConstruction) {
   8772   LocalContext context;
   8773   v8::HandleScope scope(context->GetIsolate());
   8774 
   8775   v8::Local<String> foo = v8_str("foo");
   8776   v8::Local<String> message = v8_str("message");
   8777   v8::Local<Value> range_error = v8::Exception::RangeError(foo);
   8778   CHECK(range_error->IsObject());
   8779   CHECK(range_error.As<v8::Object>()
   8780             ->Get(context.local(), message)
   8781             .ToLocalChecked()
   8782             ->Equals(context.local(), foo)
   8783             .FromJust());
   8784   v8::Local<Value> reference_error = v8::Exception::ReferenceError(foo);
   8785   CHECK(reference_error->IsObject());
   8786   CHECK(reference_error.As<v8::Object>()
   8787             ->Get(context.local(), message)
   8788             .ToLocalChecked()
   8789             ->Equals(context.local(), foo)
   8790             .FromJust());
   8791   v8::Local<Value> syntax_error = v8::Exception::SyntaxError(foo);
   8792   CHECK(syntax_error->IsObject());
   8793   CHECK(syntax_error.As<v8::Object>()
   8794             ->Get(context.local(), message)
   8795             .ToLocalChecked()
   8796             ->Equals(context.local(), foo)
   8797             .FromJust());
   8798   v8::Local<Value> type_error = v8::Exception::TypeError(foo);
   8799   CHECK(type_error->IsObject());
   8800   CHECK(type_error.As<v8::Object>()
   8801             ->Get(context.local(), message)
   8802             .ToLocalChecked()
   8803             ->Equals(context.local(), foo)
   8804             .FromJust());
   8805   v8::Local<Value> error = v8::Exception::Error(foo);
   8806   CHECK(error->IsObject());
   8807   CHECK(error.As<v8::Object>()
   8808             ->Get(context.local(), message)
   8809             .ToLocalChecked()
   8810             ->Equals(context.local(), foo)
   8811             .FromJust());
   8812 }
   8813 
   8814 
   8815 static void ThrowV8Exception(const v8::FunctionCallbackInfo<v8::Value>& info) {
   8816   ApiTestFuzzer::Fuzz();
   8817   v8::Local<String> foo = v8_str("foo");
   8818   v8::Local<String> message = v8_str("message");
   8819   v8::Local<Value> error = v8::Exception::Error(foo);
   8820   CHECK(error->IsObject());
   8821   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
   8822   CHECK(error.As<v8::Object>()
   8823             ->Get(context, message)
   8824             .ToLocalChecked()
   8825             ->Equals(context, foo)
   8826             .FromJust());
   8827   info.GetIsolate()->ThrowException(error);
   8828   info.GetReturnValue().SetUndefined();
   8829 }
   8830 
   8831 
   8832 THREADED_TEST(ExceptionCreateMessage) {
   8833   LocalContext context;
   8834   v8::HandleScope scope(context->GetIsolate());
   8835   v8::Local<String> foo_str = v8_str("foo");
   8836   v8::Local<String> message_str = v8_str("message");
   8837 
   8838   context->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(true);
   8839 
   8840   Local<v8::FunctionTemplate> fun =
   8841       v8::FunctionTemplate::New(context->GetIsolate(), ThrowV8Exception);
   8842   v8::Local<v8::Object> global = context->Global();
   8843   CHECK(global->Set(context.local(), v8_str("throwV8Exception"),
   8844                     fun->GetFunction(context.local()).ToLocalChecked())
   8845             .FromJust());
   8846 
   8847   TryCatch try_catch(context->GetIsolate());
   8848   CompileRun(
   8849       "function f1() {\n"
   8850       "  throwV8Exception();\n"
   8851       "};\n"
   8852       "f1();");
   8853   CHECK(try_catch.HasCaught());
   8854 
   8855   v8::Local<v8::Value> error = try_catch.Exception();
   8856   CHECK(error->IsObject());
   8857   CHECK(error.As<v8::Object>()
   8858             ->Get(context.local(), message_str)
   8859             .ToLocalChecked()
   8860             ->Equals(context.local(), foo_str)
   8861             .FromJust());
   8862 
   8863   v8::Local<v8::Message> message =
   8864       v8::Exception::CreateMessage(context->GetIsolate(), error);
   8865   CHECK(!message.IsEmpty());
   8866   CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
   8867   CHECK_EQ(2, message->GetStartColumn(context.local()).FromJust());
   8868 
   8869   v8::Local<v8::StackTrace> stackTrace = message->GetStackTrace();
   8870   CHECK(!stackTrace.IsEmpty());
   8871   CHECK_EQ(2, stackTrace->GetFrameCount());
   8872 
   8873   stackTrace = v8::Exception::GetStackTrace(error);
   8874   CHECK(!stackTrace.IsEmpty());
   8875   CHECK_EQ(2, stackTrace->GetFrameCount());
   8876 
   8877   context->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(false);
   8878 
   8879   // Now check message location when SetCaptureStackTraceForUncaughtExceptions
   8880   // is false.
   8881   try_catch.Reset();
   8882 
   8883   CompileRun(
   8884       "function f2() {\n"
   8885       "  return throwV8Exception();\n"
   8886       "};\n"
   8887       "f2();");
   8888   CHECK(try_catch.HasCaught());
   8889 
   8890   error = try_catch.Exception();
   8891   CHECK(error->IsObject());
   8892   CHECK(error.As<v8::Object>()
   8893             ->Get(context.local(), message_str)
   8894             .ToLocalChecked()
   8895             ->Equals(context.local(), foo_str)
   8896             .FromJust());
   8897 
   8898   message = v8::Exception::CreateMessage(context->GetIsolate(), error);
   8899   CHECK(!message.IsEmpty());
   8900   CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
   8901   CHECK_EQ(9, message->GetStartColumn(context.local()).FromJust());
   8902 
   8903   // Should be empty stack trace.
   8904   stackTrace = message->GetStackTrace();
   8905   CHECK(stackTrace.IsEmpty());
   8906   CHECK(v8::Exception::GetStackTrace(error).IsEmpty());
   8907 }
   8908 
   8909 
   8910 THREADED_TEST(ExceptionCreateMessageLength) {
   8911   LocalContext context;
   8912   v8::HandleScope scope(context->GetIsolate());
   8913 
   8914   // Test that the message is not truncated.
   8915   TryCatch try_catch(context->GetIsolate());
   8916   CompileRun(
   8917       "var message = 'm';"
   8918       "while (message.length < 1000) message += message;"
   8919       "throw message;");
   8920   CHECK(try_catch.HasCaught());
   8921 
   8922   CHECK_LT(1000, try_catch.Message()->Get()->Length());
   8923 }
   8924 
   8925 
   8926 static void YGetter(Local<String> name,
   8927                     const v8::PropertyCallbackInfo<v8::Value>& info) {
   8928   ApiTestFuzzer::Fuzz();
   8929   info.GetReturnValue().Set(v8_num(10));
   8930 }
   8931 
   8932 
   8933 static void YSetter(Local<String> name,
   8934                     Local<Value> value,
   8935                     const v8::PropertyCallbackInfo<void>& info) {
   8936   Local<Object> this_obj = Local<Object>::Cast(info.This());
   8937   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
   8938   if (this_obj->Has(context, name).FromJust())
   8939     this_obj->Delete(context, name).FromJust();
   8940   CHECK(this_obj->Set(context, name, value).FromJust());
   8941 }
   8942 
   8943 
   8944 THREADED_TEST(DeleteAccessor) {
   8945   v8::Isolate* isolate = CcTest::isolate();
   8946   v8::HandleScope scope(isolate);
   8947   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
   8948   obj->SetAccessor(v8_str("y"), YGetter, YSetter);
   8949   LocalContext context;
   8950   v8::Local<v8::Object> holder =
   8951       obj->NewInstance(context.local()).ToLocalChecked();
   8952   CHECK(context->Global()
   8953             ->Set(context.local(), v8_str("holder"), holder)
   8954             .FromJust());
   8955   v8::Local<Value> result =
   8956       CompileRun("holder.y = 11; holder.y = 12; holder.y");
   8957   CHECK_EQ(12u, result->Uint32Value(context.local()).FromJust());
   8958 }
   8959 
   8960 
   8961 static int trouble_nesting = 0;
   8962 static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   8963   ApiTestFuzzer::Fuzz();
   8964   trouble_nesting++;
   8965 
   8966   // Call a JS function that throws an uncaught exception.
   8967   Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   8968   Local<v8::Object> arg_this = context->Global();
   8969   Local<Value> trouble_callee =
   8970       (trouble_nesting == 3)
   8971           ? arg_this->Get(context, v8_str("trouble_callee")).ToLocalChecked()
   8972           : arg_this->Get(context, v8_str("trouble_caller")).ToLocalChecked();
   8973   CHECK(trouble_callee->IsFunction());
   8974   args.GetReturnValue().Set(Function::Cast(*trouble_callee)
   8975                                 ->Call(context, arg_this, 0, NULL)
   8976                                 .FromMaybe(v8::Local<v8::Value>()));
   8977 }
   8978 
   8979 
   8980 static int report_count = 0;
   8981 static void ApiUncaughtExceptionTestListener(v8::Local<v8::Message>,
   8982                                              v8::Local<Value>) {
   8983   report_count++;
   8984 }
   8985 
   8986 
   8987 // Counts uncaught exceptions, but other tests running in parallel
   8988 // also have uncaught exceptions.
   8989 TEST(ApiUncaughtException) {
   8990   report_count = 0;
   8991   LocalContext env;
   8992   v8::Isolate* isolate = env->GetIsolate();
   8993   v8::HandleScope scope(isolate);
   8994   isolate->AddMessageListener(ApiUncaughtExceptionTestListener);
   8995 
   8996   Local<v8::FunctionTemplate> fun =
   8997       v8::FunctionTemplate::New(isolate, TroubleCallback);
   8998   v8::Local<v8::Object> global = env->Global();
   8999   CHECK(global->Set(env.local(), v8_str("trouble"),
   9000                     fun->GetFunction(env.local()).ToLocalChecked())
   9001             .FromJust());
   9002 
   9003   CompileRun(
   9004       "function trouble_callee() {"
   9005       "  var x = null;"
   9006       "  return x.foo;"
   9007       "};"
   9008       "function trouble_caller() {"
   9009       "  trouble();"
   9010       "};");
   9011   Local<Value> trouble =
   9012       global->Get(env.local(), v8_str("trouble")).ToLocalChecked();
   9013   CHECK(trouble->IsFunction());
   9014   Local<Value> trouble_callee =
   9015       global->Get(env.local(), v8_str("trouble_callee")).ToLocalChecked();
   9016   CHECK(trouble_callee->IsFunction());
   9017   Local<Value> trouble_caller =
   9018       global->Get(env.local(), v8_str("trouble_caller")).ToLocalChecked();
   9019   CHECK(trouble_caller->IsFunction());
   9020   Function::Cast(*trouble_caller)
   9021       ->Call(env.local(), global, 0, NULL)
   9022       .FromMaybe(v8::Local<v8::Value>());
   9023   CHECK_EQ(1, report_count);
   9024   isolate->RemoveMessageListeners(ApiUncaughtExceptionTestListener);
   9025 }
   9026 
   9027 
   9028 static const char* script_resource_name = "ExceptionInNativeScript.js";
   9029 static void ExceptionInNativeScriptTestListener(v8::Local<v8::Message> message,
   9030                                                 v8::Local<Value>) {
   9031   v8::Local<v8::Value> name_val = message->GetScriptOrigin().ResourceName();
   9032   CHECK(!name_val.IsEmpty() && name_val->IsString());
   9033   v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
   9034   CHECK_EQ(0, strcmp(script_resource_name, *name));
   9035   v8::Local<v8::Context> context =
   9036       v8::Isolate::GetCurrent()->GetCurrentContext();
   9037   CHECK_EQ(3, message->GetLineNumber(context).FromJust());
   9038   v8::String::Utf8Value source_line(
   9039       message->GetSourceLine(context).ToLocalChecked());
   9040   CHECK_EQ(0, strcmp("  new o.foo();", *source_line));
   9041 }
   9042 
   9043 
   9044 TEST(ExceptionInNativeScript) {
   9045   LocalContext env;
   9046   v8::Isolate* isolate = env->GetIsolate();
   9047   v8::HandleScope scope(isolate);
   9048   isolate->AddMessageListener(ExceptionInNativeScriptTestListener);
   9049 
   9050   Local<v8::FunctionTemplate> fun =
   9051       v8::FunctionTemplate::New(isolate, TroubleCallback);
   9052   v8::Local<v8::Object> global = env->Global();
   9053   CHECK(global->Set(env.local(), v8_str("trouble"),
   9054                     fun->GetFunction(env.local()).ToLocalChecked())
   9055             .FromJust());
   9056 
   9057   CompileRunWithOrigin(
   9058       "function trouble() {\n"
   9059       "  var o = {};\n"
   9060       "  new o.foo();\n"
   9061       "};",
   9062       script_resource_name);
   9063   Local<Value> trouble =
   9064       global->Get(env.local(), v8_str("trouble")).ToLocalChecked();
   9065   CHECK(trouble->IsFunction());
   9066   CHECK(Function::Cast(*trouble)->Call(env.local(), global, 0, NULL).IsEmpty());
   9067   isolate->RemoveMessageListeners(ExceptionInNativeScriptTestListener);
   9068 }
   9069 
   9070 
   9071 TEST(CompilationErrorUsingTryCatchHandler) {
   9072   LocalContext env;
   9073   v8::HandleScope scope(env->GetIsolate());
   9074   v8::TryCatch try_catch(env->GetIsolate());
   9075   v8_compile("This doesn't &*&@#$&*^ compile.");
   9076   CHECK(*try_catch.Exception());
   9077   CHECK(try_catch.HasCaught());
   9078 }
   9079 
   9080 
   9081 TEST(TryCatchFinallyUsingTryCatchHandler) {
   9082   LocalContext env;
   9083   v8::HandleScope scope(env->GetIsolate());
   9084   v8::TryCatch try_catch(env->GetIsolate());
   9085   CompileRun("try { throw ''; } catch (e) {}");
   9086   CHECK(!try_catch.HasCaught());
   9087   CompileRun("try { throw ''; } finally {}");
   9088   CHECK(try_catch.HasCaught());
   9089   try_catch.Reset();
   9090   CompileRun(
   9091       "(function() {"
   9092       "try { throw ''; } finally { return; }"
   9093       "})()");
   9094   CHECK(!try_catch.HasCaught());
   9095   CompileRun(
   9096       "(function()"
   9097       "  { try { throw ''; } finally { throw 0; }"
   9098       "})()");
   9099   CHECK(try_catch.HasCaught());
   9100 }
   9101 
   9102 
   9103 void CEvaluate(const v8::FunctionCallbackInfo<v8::Value>& args) {
   9104   v8::HandleScope scope(args.GetIsolate());
   9105   CompileRun(args[0]
   9106                  ->ToString(args.GetIsolate()->GetCurrentContext())
   9107                  .ToLocalChecked());
   9108 }
   9109 
   9110 
   9111 TEST(TryCatchFinallyStoresMessageUsingTryCatchHandler) {
   9112   v8::Isolate* isolate = CcTest::isolate();
   9113   v8::HandleScope scope(isolate);
   9114   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   9115   templ->Set(v8_str("CEvaluate"),
   9116              v8::FunctionTemplate::New(isolate, CEvaluate));
   9117   LocalContext context(0, templ);
   9118   v8::TryCatch try_catch(isolate);
   9119   CompileRun("try {"
   9120              "  CEvaluate('throw 1;');"
   9121              "} finally {"
   9122              "}");
   9123   CHECK(try_catch.HasCaught());
   9124   CHECK(!try_catch.Message().IsEmpty());
   9125   String::Utf8Value exception_value(try_catch.Exception());
   9126   CHECK_EQ(0, strcmp(*exception_value, "1"));
   9127   try_catch.Reset();
   9128   CompileRun("try {"
   9129              "  CEvaluate('throw 1;');"
   9130              "} finally {"
   9131              "  throw 2;"
   9132              "}");
   9133   CHECK(try_catch.HasCaught());
   9134   CHECK(!try_catch.Message().IsEmpty());
   9135   String::Utf8Value finally_exception_value(try_catch.Exception());
   9136   CHECK_EQ(0, strcmp(*finally_exception_value, "2"));
   9137 }
   9138 
   9139 
   9140 // For use within the TestSecurityHandler() test.
   9141 static bool g_security_callback_result = false;
   9142 static bool SecurityTestCallback(Local<v8::Context> accessing_context,
   9143                                  Local<v8::Object> accessed_object,
   9144                                  Local<v8::Value> data) {
   9145   printf("a\n");
   9146   CHECK(!data.IsEmpty() && data->IsInt32());
   9147   CHECK_EQ(42, data->Int32Value(accessing_context).FromJust());
   9148   return g_security_callback_result;
   9149 }
   9150 
   9151 
   9152 // SecurityHandler can't be run twice
   9153 TEST(SecurityHandler) {
   9154   v8::Isolate* isolate = CcTest::isolate();
   9155   v8::HandleScope scope0(isolate);
   9156   v8::Local<v8::ObjectTemplate> global_template =
   9157       v8::ObjectTemplate::New(isolate);
   9158   global_template->SetAccessCheckCallback(SecurityTestCallback, v8_num(42));
   9159   // Create an environment
   9160   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
   9161   context0->Enter();
   9162 
   9163   v8::Local<v8::Object> global0 = context0->Global();
   9164   v8::Local<Script> script0 = v8_compile("foo = 111");
   9165   script0->Run(context0).ToLocalChecked();
   9166   CHECK(global0->Set(context0, v8_str("0"), v8_num(999)).FromJust());
   9167   v8::Local<Value> foo0 =
   9168       global0->Get(context0, v8_str("foo")).ToLocalChecked();
   9169   CHECK_EQ(111, foo0->Int32Value(context0).FromJust());
   9170   v8::Local<Value> z0 = global0->Get(context0, v8_str("0")).ToLocalChecked();
   9171   CHECK_EQ(999, z0->Int32Value(context0).FromJust());
   9172 
   9173   // Create another environment, should fail security checks.
   9174   v8::HandleScope scope1(isolate);
   9175 
   9176   v8::Local<Context> context1 = Context::New(isolate, NULL, global_template);
   9177   context1->Enter();
   9178 
   9179   v8::Local<v8::Object> global1 = context1->Global();
   9180   global1->Set(context1, v8_str("othercontext"), global0).FromJust();
   9181   // This set will fail the security check.
   9182   v8::Local<Script> script1 =
   9183       v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
   9184   CHECK(script1->Run(context1).IsEmpty());
   9185   g_security_callback_result = true;
   9186   // This read will pass the security check.
   9187   v8::Local<Value> foo1 =
   9188       global0->Get(context1, v8_str("foo")).ToLocalChecked();
   9189   CHECK_EQ(111, foo1->Int32Value(context0).FromJust());
   9190   // This read will pass the security check.
   9191   v8::Local<Value> z1 = global0->Get(context1, v8_str("0")).ToLocalChecked();
   9192   CHECK_EQ(999, z1->Int32Value(context1).FromJust());
   9193 
   9194   // Create another environment, should pass security checks.
   9195   {
   9196     v8::HandleScope scope2(isolate);
   9197     LocalContext context2;
   9198     v8::Local<v8::Object> global2 = context2->Global();
   9199     CHECK(global2->Set(context2.local(), v8_str("othercontext"), global0)
   9200               .FromJust());
   9201     v8::Local<Script> script2 =
   9202         v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
   9203     script2->Run(context2.local()).ToLocalChecked();
   9204     v8::Local<Value> foo2 =
   9205         global0->Get(context2.local(), v8_str("foo")).ToLocalChecked();
   9206     CHECK_EQ(333, foo2->Int32Value(context2.local()).FromJust());
   9207     v8::Local<Value> z2 =
   9208         global0->Get(context2.local(), v8_str("0")).ToLocalChecked();
   9209     CHECK_EQ(888, z2->Int32Value(context2.local()).FromJust());
   9210   }
   9211 
   9212   context1->Exit();
   9213   context0->Exit();
   9214 }
   9215 
   9216 
   9217 THREADED_TEST(SecurityChecks) {
   9218   LocalContext env1;
   9219   v8::HandleScope handle_scope(env1->GetIsolate());
   9220   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
   9221 
   9222   Local<Value> foo = v8_str("foo");
   9223   Local<Value> bar = v8_str("bar");
   9224 
   9225   // Set to the same domain.
   9226   env1->SetSecurityToken(foo);
   9227 
   9228   // Create a function in env1.
   9229   CompileRun("spy=function(){return spy;}");
   9230   Local<Value> spy =
   9231       env1->Global()->Get(env1.local(), v8_str("spy")).ToLocalChecked();
   9232   CHECK(spy->IsFunction());
   9233 
   9234   // Create another function accessing global objects.
   9235   CompileRun("spy2=function(){return new this.Array();}");
   9236   Local<Value> spy2 =
   9237       env1->Global()->Get(env1.local(), v8_str("spy2")).ToLocalChecked();
   9238   CHECK(spy2->IsFunction());
   9239 
   9240   // Switch to env2 in the same domain and invoke spy on env2.
   9241   {
   9242     env2->SetSecurityToken(foo);
   9243     // Enter env2
   9244     Context::Scope scope_env2(env2);
   9245     Local<Value> result = Function::Cast(*spy)
   9246                               ->Call(env2, env2->Global(), 0, NULL)
   9247                               .ToLocalChecked();
   9248     CHECK(result->IsFunction());
   9249   }
   9250 
   9251   {
   9252     env2->SetSecurityToken(bar);
   9253     Context::Scope scope_env2(env2);
   9254 
   9255     // Call cross_domain_call, it should throw an exception
   9256     v8::TryCatch try_catch(env1->GetIsolate());
   9257     CHECK(Function::Cast(*spy2)->Call(env2, env2->Global(), 0, NULL).IsEmpty());
   9258     CHECK(try_catch.HasCaught());
   9259   }
   9260 }
   9261 
   9262 
   9263 // Regression test case for issue 1183439.
   9264 THREADED_TEST(SecurityChecksForPrototypeChain) {
   9265   LocalContext current;
   9266   v8::HandleScope scope(current->GetIsolate());
   9267   v8::Local<Context> other = Context::New(current->GetIsolate());
   9268 
   9269   // Change context to be able to get to the Object function in the
   9270   // other context without hitting the security checks.
   9271   v8::Local<Value> other_object;
   9272   { Context::Scope scope(other);
   9273     other_object =
   9274         other->Global()->Get(other, v8_str("Object")).ToLocalChecked();
   9275     CHECK(other->Global()->Set(other, v8_num(42), v8_num(87)).FromJust());
   9276   }
   9277 
   9278   CHECK(current->Global()
   9279             ->Set(current.local(), v8_str("other"), other->Global())
   9280             .FromJust());
   9281   CHECK(v8_compile("other")
   9282             ->Run(current.local())
   9283             .ToLocalChecked()
   9284             ->Equals(current.local(), other->Global())
   9285             .FromJust());
   9286 
   9287   // Make sure the security check fails here and we get an undefined
   9288   // result instead of getting the Object function. Repeat in a loop
   9289   // to make sure to exercise the IC code.
   9290   v8::Local<Script> access_other0 = v8_compile("other.Object");
   9291   v8::Local<Script> access_other1 = v8_compile("other[42]");
   9292   for (int i = 0; i < 5; i++) {
   9293     CHECK(access_other0->Run(current.local()).IsEmpty());
   9294     CHECK(access_other1->Run(current.local()).IsEmpty());
   9295   }
   9296 
   9297   // Create an object that has 'other' in its prototype chain and make
   9298   // sure we cannot access the Object function indirectly through
   9299   // that. Repeat in a loop to make sure to exercise the IC code.
   9300   v8_compile(
   9301       "function F() { };"
   9302       "F.prototype = other;"
   9303       "var f = new F();")
   9304       ->Run(current.local())
   9305       .ToLocalChecked();
   9306   v8::Local<Script> access_f0 = v8_compile("f.Object");
   9307   v8::Local<Script> access_f1 = v8_compile("f[42]");
   9308   for (int j = 0; j < 5; j++) {
   9309     CHECK(access_f0->Run(current.local()).IsEmpty());
   9310     CHECK(access_f1->Run(current.local()).IsEmpty());
   9311   }
   9312 
   9313   // Now it gets hairy: Set the prototype for the other global object
   9314   // to be the current global object. The prototype chain for 'f' now
   9315   // goes through 'other' but ends up in the current global object.
   9316   { Context::Scope scope(other);
   9317     CHECK(other->Global()
   9318               ->Set(other, v8_str("__proto__"), current->Global())
   9319               .FromJust());
   9320   }
   9321   // Set a named and an index property on the current global
   9322   // object. To force the lookup to go through the other global object,
   9323   // the properties must not exist in the other global object.
   9324   CHECK(current->Global()
   9325             ->Set(current.local(), v8_str("foo"), v8_num(100))
   9326             .FromJust());
   9327   CHECK(current->Global()
   9328             ->Set(current.local(), v8_num(99), v8_num(101))
   9329             .FromJust());
   9330   // Try to read the properties from f and make sure that the access
   9331   // gets stopped by the security checks on the other global object.
   9332   Local<Script> access_f2 = v8_compile("f.foo");
   9333   Local<Script> access_f3 = v8_compile("f[99]");
   9334   for (int k = 0; k < 5; k++) {
   9335     CHECK(access_f2->Run(current.local()).IsEmpty());
   9336     CHECK(access_f3->Run(current.local()).IsEmpty());
   9337   }
   9338 }
   9339 
   9340 
   9341 static bool security_check_with_gc_called;
   9342 
   9343 static bool SecurityTestCallbackWithGC(Local<v8::Context> accessing_context,
   9344                                        Local<v8::Object> accessed_object,
   9345                                        Local<v8::Value> data) {
   9346   CcTest::heap()->CollectAllGarbage();
   9347   security_check_with_gc_called = true;
   9348   return true;
   9349 }
   9350 
   9351 
   9352 TEST(SecurityTestGCAllowed) {
   9353   v8::Isolate* isolate = CcTest::isolate();
   9354   v8::HandleScope handle_scope(isolate);
   9355   v8::Local<v8::ObjectTemplate> object_template =
   9356       v8::ObjectTemplate::New(isolate);
   9357   object_template->SetAccessCheckCallback(SecurityTestCallbackWithGC);
   9358 
   9359   v8::Local<Context> context = Context::New(isolate);
   9360   v8::Context::Scope context_scope(context);
   9361 
   9362   CHECK(context->Global()
   9363             ->Set(context, v8_str("obj"),
   9364                   object_template->NewInstance(context).ToLocalChecked())
   9365             .FromJust());
   9366 
   9367   security_check_with_gc_called = false;
   9368   CompileRun("obj[0] = new String(1002);");
   9369   CHECK(security_check_with_gc_called);
   9370 
   9371   security_check_with_gc_called = false;
   9372   CHECK(CompileRun("obj[0]")
   9373             ->ToString(context)
   9374             .ToLocalChecked()
   9375             ->Equals(context, v8_str("1002"))
   9376             .FromJust());
   9377   CHECK(security_check_with_gc_called);
   9378 }
   9379 
   9380 
   9381 THREADED_TEST(CrossDomainDelete) {
   9382   LocalContext env1;
   9383   v8::HandleScope handle_scope(env1->GetIsolate());
   9384   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
   9385 
   9386   Local<Value> foo = v8_str("foo");
   9387   Local<Value> bar = v8_str("bar");
   9388 
   9389   // Set to the same domain.
   9390   env1->SetSecurityToken(foo);
   9391   env2->SetSecurityToken(foo);
   9392 
   9393   CHECK(
   9394       env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
   9395   CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
   9396 
   9397   // Change env2 to a different domain and delete env1.prop.
   9398   env2->SetSecurityToken(bar);
   9399   {
   9400     Context::Scope scope_env2(env2);
   9401     Local<Value> result =
   9402         CompileRun("delete env1.prop");
   9403     CHECK(result.IsEmpty());
   9404   }
   9405 
   9406   // Check that env1.prop still exists.
   9407   Local<Value> v =
   9408       env1->Global()->Get(env1.local(), v8_str("prop")).ToLocalChecked();
   9409   CHECK(v->IsNumber());
   9410   CHECK_EQ(3, v->Int32Value(env1.local()).FromJust());
   9411 }
   9412 
   9413 
   9414 THREADED_TEST(CrossDomainPropertyIsEnumerable) {
   9415   LocalContext env1;
   9416   v8::HandleScope handle_scope(env1->GetIsolate());
   9417   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
   9418 
   9419   Local<Value> foo = v8_str("foo");
   9420   Local<Value> bar = v8_str("bar");
   9421 
   9422   // Set to the same domain.
   9423   env1->SetSecurityToken(foo);
   9424   env2->SetSecurityToken(foo);
   9425 
   9426   CHECK(
   9427       env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
   9428   CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
   9429 
   9430   // env1.prop is enumerable in env2.
   9431   Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
   9432   {
   9433     Context::Scope scope_env2(env2);
   9434     Local<Value> result = CompileRun(test);
   9435     CHECK(result->IsTrue());
   9436   }
   9437 
   9438   // Change env2 to a different domain and test again.
   9439   env2->SetSecurityToken(bar);
   9440   {
   9441     Context::Scope scope_env2(env2);
   9442     Local<Value> result = CompileRun(test);
   9443     CHECK(result.IsEmpty());
   9444   }
   9445 }
   9446 
   9447 
   9448 THREADED_TEST(CrossDomainFor) {
   9449   LocalContext env1;
   9450   v8::HandleScope handle_scope(env1->GetIsolate());
   9451   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
   9452 
   9453   Local<Value> foo = v8_str("foo");
   9454   Local<Value> bar = v8_str("bar");
   9455 
   9456   // Set to the same domain.
   9457   env1->SetSecurityToken(foo);
   9458   env2->SetSecurityToken(foo);
   9459 
   9460   CHECK(
   9461       env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
   9462   CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
   9463 
   9464   // Change env2 to a different domain and set env1's global object
   9465   // as the __proto__ of an object in env2 and enumerate properties
   9466   // in for-in. It shouldn't enumerate properties on env1's global
   9467   // object. It shouldn't throw either, just silently ignore them.
   9468   env2->SetSecurityToken(bar);
   9469   {
   9470     Context::Scope scope_env2(env2);
   9471     Local<Value> result = CompileRun(
   9472         "(function() {"
   9473         "  try {"
   9474         "    for (var p in env1) {"
   9475         "      if (p == 'prop') return false;"
   9476         "    }"
   9477         "    return true;"
   9478         "  } catch (e) {"
   9479         "    return false;"
   9480         "  }"
   9481         "})()");
   9482     CHECK(result->IsTrue());
   9483   }
   9484 }
   9485 
   9486 
   9487 THREADED_TEST(CrossDomainForInOnPrototype) {
   9488   LocalContext env1;
   9489   v8::HandleScope handle_scope(env1->GetIsolate());
   9490   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
   9491 
   9492   Local<Value> foo = v8_str("foo");
   9493   Local<Value> bar = v8_str("bar");
   9494 
   9495   // Set to the same domain.
   9496   env1->SetSecurityToken(foo);
   9497   env2->SetSecurityToken(foo);
   9498 
   9499   CHECK(
   9500       env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
   9501   CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
   9502 
   9503   // Change env2 to a different domain and set env1's global object
   9504   // as the __proto__ of an object in env2 and enumerate properties
   9505   // in for-in. It shouldn't enumerate properties on env1's global
   9506   // object.
   9507   env2->SetSecurityToken(bar);
   9508   {
   9509     Context::Scope scope_env2(env2);
   9510     Local<Value> result = CompileRun(
   9511         "(function() {"
   9512         "  var obj = { '__proto__': env1 };"
   9513         "  try {"
   9514         "    for (var p in obj) {"
   9515         "      if (p == 'prop') return false;"
   9516         "    }"
   9517         "    return true;"
   9518         "  } catch (e) {"
   9519         "    return false;"
   9520         "  }"
   9521         "})()");
   9522     CHECK(result->IsTrue());
   9523   }
   9524 }
   9525 
   9526 
   9527 TEST(ContextDetachGlobal) {
   9528   LocalContext env1;
   9529   v8::HandleScope handle_scope(env1->GetIsolate());
   9530   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
   9531 
   9532 
   9533   Local<Value> foo = v8_str("foo");
   9534 
   9535   // Set to the same domain.
   9536   env1->SetSecurityToken(foo);
   9537   env2->SetSecurityToken(foo);
   9538 
   9539   // Enter env2
   9540   env2->Enter();
   9541 
   9542   // Create a function in env2 and add a reference to it in env1.
   9543   Local<v8::Object> global2 = env2->Global();
   9544   CHECK(global2->Set(env2, v8_str("prop"),
   9545                      v8::Integer::New(env2->GetIsolate(), 1))
   9546             .FromJust());
   9547   CompileRun("function getProp() {return prop;}");
   9548 
   9549   CHECK(env1->Global()
   9550             ->Set(env1.local(), v8_str("getProp"),
   9551                   global2->Get(env2, v8_str("getProp")).ToLocalChecked())
   9552             .FromJust());
   9553 
   9554   // Detach env2's global, and reuse the global object of env2
   9555   env2->Exit();
   9556   env2->DetachGlobal();
   9557 
   9558   v8::Local<Context> env3 = Context::New(
   9559       env1->GetIsolate(), 0, v8::Local<v8::ObjectTemplate>(), global2);
   9560   env3->SetSecurityToken(v8_str("bar"));
   9561 
   9562   env3->Enter();
   9563   Local<v8::Object> global3 = env3->Global();
   9564   CHECK(global2->Equals(env3, global3).FromJust());
   9565   CHECK(global3->Get(env3, v8_str("prop")).ToLocalChecked()->IsUndefined());
   9566   CHECK(global3->Get(env3, v8_str("getProp")).ToLocalChecked()->IsUndefined());
   9567   CHECK(global3->Set(env3, v8_str("prop"),
   9568                      v8::Integer::New(env3->GetIsolate(), -1))
   9569             .FromJust());
   9570   CHECK(global3->Set(env3, v8_str("prop2"),
   9571                      v8::Integer::New(env3->GetIsolate(), 2))
   9572             .FromJust());
   9573   env3->Exit();
   9574 
   9575   // Call getProp in env1, and it should return the value 1
   9576   {
   9577     Local<v8::Object> global1 = env1->Global();
   9578     Local<Value> get_prop =
   9579         global1->Get(env1.local(), v8_str("getProp")).ToLocalChecked();
   9580     CHECK(get_prop->IsFunction());
   9581     v8::TryCatch try_catch(env1->GetIsolate());
   9582     Local<Value> r = Function::Cast(*get_prop)
   9583                          ->Call(env1.local(), global1, 0, NULL)
   9584                          .ToLocalChecked();
   9585     CHECK(!try_catch.HasCaught());
   9586     CHECK_EQ(1, r->Int32Value(env1.local()).FromJust());
   9587   }
   9588 
   9589   // Check that env3 is not accessible from env1
   9590   {
   9591     v8::MaybeLocal<Value> r = global3->Get(env1.local(), v8_str("prop2"));
   9592     CHECK(r.IsEmpty());
   9593   }
   9594 }
   9595 
   9596 
   9597 TEST(DetachGlobal) {
   9598   LocalContext env1;
   9599   v8::HandleScope scope(env1->GetIsolate());
   9600 
   9601   // Create second environment.
   9602   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
   9603 
   9604   Local<Value> foo = v8_str("foo");
   9605 
   9606   // Set same security token for env1 and env2.
   9607   env1->SetSecurityToken(foo);
   9608   env2->SetSecurityToken(foo);
   9609 
   9610   // Create a property on the global object in env2.
   9611   {
   9612     v8::Context::Scope scope(env2);
   9613     CHECK(env2->Global()
   9614               ->Set(env2, v8_str("p"), v8::Integer::New(env2->GetIsolate(), 42))
   9615               .FromJust());
   9616   }
   9617 
   9618   // Create a reference to env2 global from env1 global.
   9619   CHECK(env1->Global()
   9620             ->Set(env1.local(), v8_str("other"), env2->Global())
   9621             .FromJust());
   9622 
   9623   // Check that we have access to other.p in env2 from env1.
   9624   Local<Value> result = CompileRun("other.p");
   9625   CHECK(result->IsInt32());
   9626   CHECK_EQ(42, result->Int32Value(env1.local()).FromJust());
   9627 
   9628   // Hold on to global from env2 and detach global from env2.
   9629   Local<v8::Object> global2 = env2->Global();
   9630   env2->DetachGlobal();
   9631 
   9632   // Check that the global has been detached. No other.p property can
   9633   // be found.
   9634   result = CompileRun("other.p");
   9635   CHECK(result.IsEmpty());
   9636 
   9637   // Reuse global2 for env3.
   9638   v8::Local<Context> env3 = Context::New(
   9639       env1->GetIsolate(), 0, v8::Local<v8::ObjectTemplate>(), global2);
   9640   CHECK(global2->Equals(env1.local(), env3->Global()).FromJust());
   9641 
   9642   // Start by using the same security token for env3 as for env1 and env2.
   9643   env3->SetSecurityToken(foo);
   9644 
   9645   // Create a property on the global object in env3.
   9646   {
   9647     v8::Context::Scope scope(env3);
   9648     CHECK(env3->Global()
   9649               ->Set(env3, v8_str("p"), v8::Integer::New(env3->GetIsolate(), 24))
   9650               .FromJust());
   9651   }
   9652 
   9653   // Check that other.p is now the property in env3 and that we have access.
   9654   result = CompileRun("other.p");
   9655   CHECK(result->IsInt32());
   9656   CHECK_EQ(24, result->Int32Value(env3).FromJust());
   9657 
   9658   // Change security token for env3 to something different from env1 and env2.
   9659   env3->SetSecurityToken(v8_str("bar"));
   9660 
   9661   // Check that we do not have access to other.p in env1. |other| is now
   9662   // the global object for env3 which has a different security token,
   9663   // so access should be blocked.
   9664   result = CompileRun("other.p");
   9665   CHECK(result.IsEmpty());
   9666 }
   9667 
   9668 
   9669 void GetThisX(const v8::FunctionCallbackInfo<v8::Value>& info) {
   9670   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
   9671   info.GetReturnValue().Set(
   9672       context->Global()->Get(context, v8_str("x")).ToLocalChecked());
   9673 }
   9674 
   9675 
   9676 TEST(DetachedAccesses) {
   9677   LocalContext env1;
   9678   v8::HandleScope scope(env1->GetIsolate());
   9679 
   9680   // Create second environment.
   9681   Local<ObjectTemplate> inner_global_template =
   9682       FunctionTemplate::New(env1->GetIsolate())->InstanceTemplate();
   9683   inner_global_template ->SetAccessorProperty(
   9684       v8_str("this_x"), FunctionTemplate::New(env1->GetIsolate(), GetThisX));
   9685   v8::Local<Context> env2 =
   9686       Context::New(env1->GetIsolate(), NULL, inner_global_template);
   9687 
   9688   Local<Value> foo = v8_str("foo");
   9689 
   9690   // Set same security token for env1 and env2.
   9691   env1->SetSecurityToken(foo);
   9692   env2->SetSecurityToken(foo);
   9693 
   9694   CHECK(env1->Global()
   9695             ->Set(env1.local(), v8_str("x"), v8_str("env1_x"))
   9696             .FromJust());
   9697 
   9698   {
   9699     v8::Context::Scope scope(env2);
   9700     CHECK(env2->Global()->Set(env2, v8_str("x"), v8_str("env2_x")).FromJust());
   9701     CompileRun(
   9702         "function bound_x() { return x; }"
   9703         "function get_x()   { return this.x; }"
   9704         "function get_x_w() { return (function() {return this.x;})(); }");
   9705     CHECK(env1->Global()
   9706               ->Set(env1.local(), v8_str("bound_x"), CompileRun("bound_x"))
   9707               .FromJust());
   9708     CHECK(env1->Global()
   9709               ->Set(env1.local(), v8_str("get_x"), CompileRun("get_x"))
   9710               .FromJust());
   9711     CHECK(env1->Global()
   9712               ->Set(env1.local(), v8_str("get_x_w"), CompileRun("get_x_w"))
   9713               .FromJust());
   9714     env1->Global()
   9715         ->Set(env1.local(), v8_str("this_x"),
   9716               CompileRun("Object.getOwnPropertyDescriptor(this, 'this_x').get"))
   9717         .FromJust();
   9718   }
   9719 
   9720   Local<Object> env2_global = env2->Global();
   9721   env2->DetachGlobal();
   9722 
   9723   Local<Value> result;
   9724   result = CompileRun("bound_x()");
   9725   CHECK(v8_str("env2_x")->Equals(env1.local(), result).FromJust());
   9726   result = CompileRun("get_x()");
   9727   CHECK(result.IsEmpty());
   9728   result = CompileRun("get_x_w()");
   9729   CHECK(result.IsEmpty());
   9730   result = CompileRun("this_x()");
   9731   CHECK(v8_str("env2_x")->Equals(env1.local(), result).FromJust());
   9732 
   9733   // Reattach env2's proxy
   9734   env2 = Context::New(env1->GetIsolate(), 0, v8::Local<v8::ObjectTemplate>(),
   9735                       env2_global);
   9736   env2->SetSecurityToken(foo);
   9737   {
   9738     v8::Context::Scope scope(env2);
   9739     CHECK(env2->Global()->Set(env2, v8_str("x"), v8_str("env3_x")).FromJust());
   9740     CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
   9741     result = CompileRun(
   9742         "results = [];"
   9743         "for (var i = 0; i < 4; i++ ) {"
   9744         "  results.push(env1.bound_x());"
   9745         "  results.push(env1.get_x());"
   9746         "  results.push(env1.get_x_w());"
   9747         "  results.push(env1.this_x());"
   9748         "}"
   9749         "results");
   9750     Local<v8::Array> results = Local<v8::Array>::Cast(result);
   9751     CHECK_EQ(16u, results->Length());
   9752     for (int i = 0; i < 16; i += 4) {
   9753       CHECK(v8_str("env2_x")
   9754                 ->Equals(env2, results->Get(env2, i + 0).ToLocalChecked())
   9755                 .FromJust());
   9756       CHECK(v8_str("env1_x")
   9757                 ->Equals(env2, results->Get(env2, i + 1).ToLocalChecked())
   9758                 .FromJust());
   9759       CHECK(v8_str("env3_x")
   9760                 ->Equals(env2, results->Get(env2, i + 2).ToLocalChecked())
   9761                 .FromJust());
   9762       CHECK(v8_str("env2_x")
   9763                 ->Equals(env2, results->Get(env2, i + 3).ToLocalChecked())
   9764                 .FromJust());
   9765     }
   9766   }
   9767 
   9768   result = CompileRun(
   9769       "results = [];"
   9770       "for (var i = 0; i < 4; i++ ) {"
   9771       "  results.push(bound_x());"
   9772       "  results.push(get_x());"
   9773       "  results.push(get_x_w());"
   9774       "  results.push(this_x());"
   9775       "}"
   9776       "results");
   9777   Local<v8::Array> results = Local<v8::Array>::Cast(result);
   9778   CHECK_EQ(16u, results->Length());
   9779   for (int i = 0; i < 16; i += 4) {
   9780     CHECK(v8_str("env2_x")
   9781               ->Equals(env1.local(),
   9782                        results->Get(env1.local(), i + 0).ToLocalChecked())
   9783               .FromJust());
   9784     CHECK(v8_str("env3_x")
   9785               ->Equals(env1.local(),
   9786                        results->Get(env1.local(), i + 1).ToLocalChecked())
   9787               .FromJust());
   9788     CHECK(v8_str("env3_x")
   9789               ->Equals(env1.local(),
   9790                        results->Get(env1.local(), i + 2).ToLocalChecked())
   9791               .FromJust());
   9792     CHECK(v8_str("env2_x")
   9793               ->Equals(env1.local(),
   9794                        results->Get(env1.local(), i + 3).ToLocalChecked())
   9795               .FromJust());
   9796   }
   9797 
   9798   result = CompileRun(
   9799       "results = [];"
   9800       "for (var i = 0; i < 4; i++ ) {"
   9801       "  results.push(this.bound_x());"
   9802       "  results.push(this.get_x());"
   9803       "  results.push(this.get_x_w());"
   9804       "  results.push(this.this_x());"
   9805       "}"
   9806       "results");
   9807   results = Local<v8::Array>::Cast(result);
   9808   CHECK_EQ(16u, results->Length());
   9809   for (int i = 0; i < 16; i += 4) {
   9810     CHECK(v8_str("env2_x")
   9811               ->Equals(env1.local(),
   9812                        results->Get(env1.local(), i + 0).ToLocalChecked())
   9813               .FromJust());
   9814     CHECK(v8_str("env1_x")
   9815               ->Equals(env1.local(),
   9816                        results->Get(env1.local(), i + 1).ToLocalChecked())
   9817               .FromJust());
   9818     CHECK(v8_str("env3_x")
   9819               ->Equals(env1.local(),
   9820                        results->Get(env1.local(), i + 2).ToLocalChecked())
   9821               .FromJust());
   9822     CHECK(v8_str("env2_x")
   9823               ->Equals(env1.local(),
   9824                        results->Get(env1.local(), i + 3).ToLocalChecked())
   9825               .FromJust());
   9826   }
   9827 }
   9828 
   9829 
   9830 static bool allowed_access = false;
   9831 static bool AccessBlocker(Local<v8::Context> accessing_context,
   9832                           Local<v8::Object> accessed_object,
   9833                           Local<v8::Value> data) {
   9834   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   9835   return context->Global()->Equals(context, accessed_object).FromJust() ||
   9836          allowed_access;
   9837 }
   9838 
   9839 
   9840 static int g_echo_value = -1;
   9841 
   9842 
   9843 static void EchoGetter(
   9844     Local<String> name,
   9845     const v8::PropertyCallbackInfo<v8::Value>& info) {
   9846   info.GetReturnValue().Set(v8_num(g_echo_value));
   9847 }
   9848 
   9849 
   9850 static void EchoSetter(Local<String> name, Local<Value> value,
   9851                        const v8::PropertyCallbackInfo<void>& args) {
   9852   if (value->IsNumber())
   9853     g_echo_value =
   9854         value->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
   9855 }
   9856 
   9857 
   9858 static void UnreachableGetter(
   9859     Local<String> name,
   9860     const v8::PropertyCallbackInfo<v8::Value>& info) {
   9861   CHECK(false);  // This function should not be called..
   9862 }
   9863 
   9864 
   9865 static void UnreachableSetter(Local<String>,
   9866                               Local<Value>,
   9867                               const v8::PropertyCallbackInfo<void>&) {
   9868   CHECK(false);  // This function should nto be called.
   9869 }
   9870 
   9871 
   9872 static void UnreachableFunction(
   9873     const v8::FunctionCallbackInfo<v8::Value>& info) {
   9874   CHECK(false);  // This function should not be called..
   9875 }
   9876 
   9877 
   9878 TEST(AccessControl) {
   9879   v8::Isolate* isolate = CcTest::isolate();
   9880   v8::HandleScope handle_scope(isolate);
   9881   v8::Local<v8::ObjectTemplate> global_template =
   9882       v8::ObjectTemplate::New(isolate);
   9883 
   9884   global_template->SetAccessCheckCallback(AccessBlocker);
   9885 
   9886   // Add an accessor accessible by cross-domain JS code.
   9887   global_template->SetAccessor(
   9888       v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
   9889       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   9890 
   9891 
   9892   // Add an accessor that is not accessible by cross-domain JS code.
   9893   global_template->SetAccessor(v8_str("blocked_prop"), UnreachableGetter,
   9894                                UnreachableSetter, v8::Local<Value>(),
   9895                                v8::DEFAULT);
   9896 
   9897   global_template->SetAccessorProperty(
   9898       v8_str("blocked_js_prop"),
   9899       v8::FunctionTemplate::New(isolate, UnreachableFunction),
   9900       v8::FunctionTemplate::New(isolate, UnreachableFunction),
   9901       v8::None,
   9902       v8::DEFAULT);
   9903 
   9904   // Create an environment
   9905   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
   9906   context0->Enter();
   9907 
   9908   v8::Local<v8::Object> global0 = context0->Global();
   9909 
   9910   // Define a property with JS getter and setter.
   9911   CompileRun(
   9912       "function getter() { return 'getter'; };\n"
   9913       "function setter() { return 'setter'; }\n"
   9914       "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
   9915 
   9916   Local<Value> getter =
   9917       global0->Get(context0, v8_str("getter")).ToLocalChecked();
   9918   Local<Value> setter =
   9919       global0->Get(context0, v8_str("setter")).ToLocalChecked();
   9920 
   9921   // And define normal element.
   9922   CHECK(global0->Set(context0, 239, v8_str("239")).FromJust());
   9923 
   9924   // Define an element with JS getter and setter.
   9925   CompileRun(
   9926       "function el_getter() { return 'el_getter'; };\n"
   9927       "function el_setter() { return 'el_setter'; };\n"
   9928       "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
   9929 
   9930   Local<Value> el_getter =
   9931       global0->Get(context0, v8_str("el_getter")).ToLocalChecked();
   9932   Local<Value> el_setter =
   9933       global0->Get(context0, v8_str("el_setter")).ToLocalChecked();
   9934 
   9935   v8::HandleScope scope1(isolate);
   9936 
   9937   v8::Local<Context> context1 = Context::New(isolate);
   9938   context1->Enter();
   9939 
   9940   v8::Local<v8::Object> global1 = context1->Global();
   9941   CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
   9942 
   9943   // Access blocked property.
   9944   CompileRun("other.blocked_prop = 1");
   9945 
   9946   CHECK(CompileRun("other.blocked_prop").IsEmpty());
   9947   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
   9948             .IsEmpty());
   9949   CHECK(
   9950       CompileRun("propertyIsEnumerable.call(other, 'blocked_prop')").IsEmpty());
   9951 
   9952   // Access blocked element.
   9953   CHECK(CompileRun("other[239] = 1").IsEmpty());
   9954 
   9955   CHECK(CompileRun("other[239]").IsEmpty());
   9956   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239')").IsEmpty());
   9957   CHECK(CompileRun("propertyIsEnumerable.call(other, '239')").IsEmpty());
   9958 
   9959   allowed_access = true;
   9960   // Now we can enumerate the property.
   9961   ExpectTrue("propertyIsEnumerable.call(other, '239')");
   9962   allowed_access = false;
   9963 
   9964   // Access a property with JS accessor.
   9965   CHECK(CompileRun("other.js_accessor_p = 2").IsEmpty());
   9966 
   9967   CHECK(CompileRun("other.js_accessor_p").IsEmpty());
   9968   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'js_accessor_p')")
   9969             .IsEmpty());
   9970 
   9971   allowed_access = true;
   9972 
   9973   ExpectString("other.js_accessor_p", "getter");
   9974   ExpectObject(
   9975       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
   9976   ExpectObject(
   9977       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
   9978   ExpectUndefined(
   9979       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
   9980 
   9981   allowed_access = false;
   9982 
   9983   // Access an element with JS accessor.
   9984   CHECK(CompileRun("other[42] = 2").IsEmpty());
   9985 
   9986   CHECK(CompileRun("other[42]").IsEmpty());
   9987   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '42')").IsEmpty());
   9988 
   9989   allowed_access = true;
   9990 
   9991   ExpectString("other[42]", "el_getter");
   9992   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
   9993   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
   9994   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
   9995 
   9996   allowed_access = false;
   9997 
   9998   v8::Local<Value> value;
   9999 
   10000   // Access accessible property
   10001   value = CompileRun("other.accessible_prop = 3");
   10002   CHECK(value->IsNumber());
   10003   CHECK_EQ(3, value->Int32Value(context1).FromJust());
   10004   CHECK_EQ(3, g_echo_value);
   10005 
   10006   value = CompileRun("other.accessible_prop");
   10007   CHECK(value->IsNumber());
   10008   CHECK_EQ(3, value->Int32Value(context1).FromJust());
   10009 
   10010   value = CompileRun(
   10011       "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
   10012   CHECK(value->IsNumber());
   10013   CHECK_EQ(3, value->Int32Value(context1).FromJust());
   10014 
   10015   value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
   10016   CHECK(value->IsTrue());
   10017 
   10018   // Enumeration doesn't enumerate accessors from inaccessible objects in
   10019   // the prototype chain even if the accessors are in themselves accessible.
   10020   // Enumeration doesn't throw, it silently ignores what it can't access.
   10021   value = CompileRun(
   10022       "(function() {"
   10023       "  var obj = { '__proto__': other };"
   10024       "  try {"
   10025       "    for (var p in obj) {"
   10026       "      if (p == 'accessible_prop' ||"
   10027       "          p == 'blocked_js_prop' ||"
   10028       "          p == 'blocked_js_prop') {"
   10029       "        return false;"
   10030       "      }"
   10031       "    }"
   10032       "    return true;"
   10033       "  } catch (e) {"
   10034       "    return false;"
   10035       "  }"
   10036       "})()");
   10037   CHECK(value->IsTrue());
   10038 
   10039   // Test that preventExtensions fails on a non-accessible object even if that
   10040   // object is already non-extensible.
   10041   CHECK(global1->Set(context1, v8_str("checked_object"),
   10042                      global_template->NewInstance(context1).ToLocalChecked())
   10043             .FromJust());
   10044   allowed_access = true;
   10045   CompileRun("Object.preventExtensions(checked_object)");
   10046   ExpectFalse("Object.isExtensible(checked_object)");
   10047   allowed_access = false;
   10048   CHECK(CompileRun("Object.preventExtensions(checked_object)").IsEmpty());
   10049 
   10050   context1->Exit();
   10051   context0->Exit();
   10052 }
   10053 
   10054 
   10055 TEST(AccessControlES5) {
   10056   v8::Isolate* isolate = CcTest::isolate();
   10057   v8::HandleScope handle_scope(isolate);
   10058   v8::Local<v8::ObjectTemplate> global_template =
   10059       v8::ObjectTemplate::New(isolate);
   10060 
   10061   global_template->SetAccessCheckCallback(AccessBlocker);
   10062 
   10063   // Add accessible accessor.
   10064   global_template->SetAccessor(
   10065       v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
   10066       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   10067 
   10068 
   10069   // Add an accessor that is not accessible by cross-domain JS code.
   10070   global_template->SetAccessor(v8_str("blocked_prop"), UnreachableGetter,
   10071                                UnreachableSetter, v8::Local<Value>(),
   10072                                v8::DEFAULT);
   10073 
   10074   // Create an environment
   10075   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
   10076   context0->Enter();
   10077 
   10078   v8::Local<v8::Object> global0 = context0->Global();
   10079 
   10080   v8::Local<Context> context1 = Context::New(isolate);
   10081   context1->Enter();
   10082   v8::Local<v8::Object> global1 = context1->Global();
   10083   CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
   10084 
   10085   // Regression test for issue 1154.
   10086   CHECK(CompileRun("Object.keys(other).length == 1")
   10087             ->BooleanValue(context1)
   10088             .FromJust());
   10089   CHECK(CompileRun("Object.keys(other)[0] == 'accessible_prop'")
   10090             ->BooleanValue(context1)
   10091             .FromJust());
   10092   CHECK(CompileRun("other.blocked_prop").IsEmpty());
   10093 
   10094   // Regression test for issue 1027.
   10095   CompileRun("Object.defineProperty(\n"
   10096              "  other, 'blocked_prop', {configurable: false})");
   10097   CHECK(CompileRun("other.blocked_prop").IsEmpty());
   10098   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
   10099             .IsEmpty());
   10100 
   10101   // Regression test for issue 1171.
   10102   ExpectTrue("Object.isExtensible(other)");
   10103   CompileRun("Object.preventExtensions(other)");
   10104   ExpectTrue("Object.isExtensible(other)");
   10105 
   10106   // Object.seal and Object.freeze.
   10107   CompileRun("Object.freeze(other)");
   10108   ExpectTrue("Object.isExtensible(other)");
   10109 
   10110   CompileRun("Object.seal(other)");
   10111   ExpectTrue("Object.isExtensible(other)");
   10112 
   10113   // Regression test for issue 1250.
   10114   // Make sure that we can set the accessible accessors value using normal
   10115   // assignment.
   10116   CompileRun("other.accessible_prop = 42");
   10117   CHECK_EQ(42, g_echo_value);
   10118 
   10119   // [[DefineOwnProperty]] always throws for access-checked objects.
   10120   CHECK(
   10121       CompileRun("Object.defineProperty(other, 'accessible_prop', {value: 43})")
   10122           .IsEmpty());
   10123   CHECK(CompileRun("other.accessible_prop == 42")->IsTrue());
   10124   CHECK_EQ(42, g_echo_value);  // Make sure we didn't call the setter.
   10125 }
   10126 
   10127 static bool AccessAlwaysBlocked(Local<v8::Context> accessing_context,
   10128                                 Local<v8::Object> global,
   10129                                 Local<v8::Value> data) {
   10130   i::PrintF("Access blocked.\n");
   10131   return false;
   10132 }
   10133 
   10134 
   10135 THREADED_TEST(AccessControlGetOwnPropertyNames) {
   10136   v8::Isolate* isolate = CcTest::isolate();
   10137   v8::HandleScope handle_scope(isolate);
   10138   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   10139 
   10140   obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
   10141   obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   10142 
   10143   // Add an accessor accessible by cross-domain JS code.
   10144   obj_template->SetAccessor(
   10145       v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
   10146       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   10147 
   10148   // Create an environment
   10149   v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
   10150   context0->Enter();
   10151 
   10152   v8::Local<v8::Object> global0 = context0->Global();
   10153 
   10154   v8::HandleScope scope1(CcTest::isolate());
   10155 
   10156   v8::Local<Context> context1 = Context::New(isolate);
   10157   context1->Enter();
   10158 
   10159   v8::Local<v8::Object> global1 = context1->Global();
   10160   CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
   10161   CHECK(global1->Set(context1, v8_str("object"),
   10162                      obj_template->NewInstance(context1).ToLocalChecked())
   10163             .FromJust());
   10164 
   10165   v8::Local<Value> value;
   10166 
   10167   // Attempt to get the property names of the other global object and
   10168   // of an object that requires access checks.  Accessing the other
   10169   // global object should be blocked by access checks on the global
   10170   // proxy object.  Accessing the object that requires access checks
   10171   // is blocked by the access checks on the object itself.
   10172   value = CompileRun(
   10173       "var names = Object.getOwnPropertyNames(other);"
   10174       "names.length == 1 && names[0] == 'accessible_prop';");
   10175   CHECK(value->BooleanValue(context1).FromJust());
   10176 
   10177   value = CompileRun(
   10178       "var names = Object.getOwnPropertyNames(object);"
   10179       "names.length == 1 && names[0] == 'accessible_prop';");
   10180   CHECK(value->BooleanValue(context1).FromJust());
   10181 
   10182   context1->Exit();
   10183   context0->Exit();
   10184 }
   10185 
   10186 
   10187 TEST(Regress470113) {
   10188   v8::Isolate* isolate = CcTest::isolate();
   10189   v8::HandleScope handle_scope(isolate);
   10190   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   10191   obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   10192   LocalContext env;
   10193   CHECK(env->Global()
   10194             ->Set(env.local(), v8_str("prohibited"),
   10195                   obj_template->NewInstance(env.local()).ToLocalChecked())
   10196             .FromJust());
   10197 
   10198   {
   10199     v8::TryCatch try_catch(isolate);
   10200     CompileRun(
   10201         "'use strict';\n"
   10202         "class C extends Object {\n"
   10203         "   m() { super.powned = 'Powned!'; }\n"
   10204         "}\n"
   10205         "let c = new C();\n"
   10206         "c.m.call(prohibited)");
   10207 
   10208     CHECK(try_catch.HasCaught());
   10209   }
   10210 }
   10211 
   10212 
   10213 static void ConstTenGetter(Local<String> name,
   10214                            const v8::PropertyCallbackInfo<v8::Value>& info) {
   10215   info.GetReturnValue().Set(v8_num(10));
   10216 }
   10217 
   10218 
   10219 THREADED_TEST(CrossDomainAccessors) {
   10220   v8::Isolate* isolate = CcTest::isolate();
   10221   v8::HandleScope handle_scope(isolate);
   10222 
   10223   v8::Local<v8::FunctionTemplate> func_template =
   10224       v8::FunctionTemplate::New(isolate);
   10225 
   10226   v8::Local<v8::ObjectTemplate> global_template =
   10227       func_template->InstanceTemplate();
   10228 
   10229   v8::Local<v8::ObjectTemplate> proto_template =
   10230       func_template->PrototypeTemplate();
   10231 
   10232   // Add an accessor to proto that's accessible by cross-domain JS code.
   10233   proto_template->SetAccessor(v8_str("accessible"), ConstTenGetter, 0,
   10234                               v8::Local<Value>(), v8::ALL_CAN_READ);
   10235 
   10236   // Add an accessor that is not accessible by cross-domain JS code.
   10237   global_template->SetAccessor(v8_str("unreachable"), UnreachableGetter, 0,
   10238                                v8::Local<Value>(), v8::DEFAULT);
   10239 
   10240   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
   10241   context0->Enter();
   10242 
   10243   Local<v8::Object> global = context0->Global();
   10244   // Add a normal property that shadows 'accessible'
   10245   CHECK(global->Set(context0, v8_str("accessible"), v8_num(11)).FromJust());
   10246 
   10247   // Enter a new context.
   10248   v8::HandleScope scope1(CcTest::isolate());
   10249   v8::Local<Context> context1 = Context::New(isolate);
   10250   context1->Enter();
   10251 
   10252   v8::Local<v8::Object> global1 = context1->Global();
   10253   CHECK(global1->Set(context1, v8_str("other"), global).FromJust());
   10254 
   10255   // Should return 10, instead of 11
   10256   v8::Local<Value> value =
   10257       v8_compile("other.accessible")->Run(context1).ToLocalChecked();
   10258   CHECK(value->IsNumber());
   10259   CHECK_EQ(10, value->Int32Value(context1).FromJust());
   10260 
   10261   v8::MaybeLocal<v8::Value> maybe_value =
   10262       v8_compile("other.unreachable")->Run(context1);
   10263   CHECK(maybe_value.IsEmpty());
   10264 
   10265   context1->Exit();
   10266   context0->Exit();
   10267 }
   10268 
   10269 
   10270 static int access_count = 0;
   10271 
   10272 static bool AccessCounter(Local<v8::Context> accessing_context,
   10273                           Local<v8::Object> accessed_object,
   10274                           Local<v8::Value> data) {
   10275   access_count++;
   10276   return true;
   10277 }
   10278 
   10279 
   10280 // This one is too easily disturbed by other tests.
   10281 TEST(AccessControlIC) {
   10282   access_count = 0;
   10283 
   10284   v8::Isolate* isolate = CcTest::isolate();
   10285   v8::HandleScope handle_scope(isolate);
   10286 
   10287   // Create an environment.
   10288   v8::Local<Context> context0 = Context::New(isolate);
   10289   context0->Enter();
   10290 
   10291   // Create an object that requires access-check functions to be
   10292   // called for cross-domain access.
   10293   v8::Local<v8::ObjectTemplate> object_template =
   10294       v8::ObjectTemplate::New(isolate);
   10295   object_template->SetAccessCheckCallback(AccessCounter);
   10296   Local<v8::Object> object =
   10297       object_template->NewInstance(context0).ToLocalChecked();
   10298 
   10299   v8::HandleScope scope1(isolate);
   10300 
   10301   // Create another environment.
   10302   v8::Local<Context> context1 = Context::New(isolate);
   10303   context1->Enter();
   10304 
   10305   // Make easy access to the object from the other environment.
   10306   v8::Local<v8::Object> global1 = context1->Global();
   10307   CHECK(global1->Set(context1, v8_str("obj"), object).FromJust());
   10308 
   10309   v8::Local<Value> value;
   10310 
   10311   // Check that the named access-control function is called every time.
   10312   CompileRun("function testProp(obj) {"
   10313              "  for (var i = 0; i < 10; i++) obj.prop = 1;"
   10314              "  for (var j = 0; j < 10; j++) obj.prop;"
   10315              "  return obj.prop"
   10316              "}");
   10317   value = CompileRun("testProp(obj)");
   10318   CHECK(value->IsNumber());
   10319   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10320   CHECK_EQ(21, access_count);
   10321 
   10322   // Check that the named access-control function is called every time.
   10323   CompileRun("var p = 'prop';"
   10324              "function testKeyed(obj) {"
   10325              "  for (var i = 0; i < 10; i++) obj[p] = 1;"
   10326              "  for (var j = 0; j < 10; j++) obj[p];"
   10327              "  return obj[p];"
   10328              "}");
   10329   // Use obj which requires access checks.  No inline caching is used
   10330   // in that case.
   10331   value = CompileRun("testKeyed(obj)");
   10332   CHECK(value->IsNumber());
   10333   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10334   CHECK_EQ(42, access_count);
   10335   // Force the inline caches into generic state and try again.
   10336   CompileRun("testKeyed({ a: 0 })");
   10337   CompileRun("testKeyed({ b: 0 })");
   10338   value = CompileRun("testKeyed(obj)");
   10339   CHECK(value->IsNumber());
   10340   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10341   CHECK_EQ(63, access_count);
   10342 
   10343   // Check that the indexed access-control function is called every time.
   10344   access_count = 0;
   10345 
   10346   CompileRun("function testIndexed(obj) {"
   10347              "  for (var i = 0; i < 10; i++) obj[0] = 1;"
   10348              "  for (var j = 0; j < 10; j++) obj[0];"
   10349              "  return obj[0]"
   10350              "}");
   10351   value = CompileRun("testIndexed(obj)");
   10352   CHECK(value->IsNumber());
   10353   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10354   CHECK_EQ(21, access_count);
   10355   // Force the inline caches into generic state.
   10356   CompileRun("testIndexed(new Array(1))");
   10357   // Test that the indexed access check is called.
   10358   value = CompileRun("testIndexed(obj)");
   10359   CHECK(value->IsNumber());
   10360   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10361   CHECK_EQ(42, access_count);
   10362 
   10363   access_count = 0;
   10364   // Check that the named access check is called when invoking
   10365   // functions on an object that requires access checks.
   10366   CompileRun("obj.f = function() {}");
   10367   CompileRun("function testCallNormal(obj) {"
   10368              "  for (var i = 0; i < 10; i++) obj.f();"
   10369              "}");
   10370   CompileRun("testCallNormal(obj)");
   10371   printf("%i\n", access_count);
   10372   CHECK_EQ(11, access_count);
   10373 
   10374   // Force obj into slow case.
   10375   value = CompileRun("delete obj.prop");
   10376   CHECK(value->BooleanValue(context1).FromJust());
   10377   // Force inline caches into dictionary probing mode.
   10378   CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
   10379   // Test that the named access check is called.
   10380   value = CompileRun("testProp(obj);");
   10381   CHECK(value->IsNumber());
   10382   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10383   CHECK_EQ(33, access_count);
   10384 
   10385   // Force the call inline cache into dictionary probing mode.
   10386   CompileRun("o.f = function() {}; testCallNormal(o)");
   10387   // Test that the named access check is still called for each
   10388   // invocation of the function.
   10389   value = CompileRun("testCallNormal(obj)");
   10390   CHECK_EQ(43, access_count);
   10391 
   10392   context1->Exit();
   10393   context0->Exit();
   10394 }
   10395 
   10396 
   10397 THREADED_TEST(Version) { v8::V8::GetVersion(); }
   10398 
   10399 
   10400 static void InstanceFunctionCallback(
   10401     const v8::FunctionCallbackInfo<v8::Value>& args) {
   10402   ApiTestFuzzer::Fuzz();
   10403   args.GetReturnValue().Set(v8_num(12));
   10404 }
   10405 
   10406 
   10407 THREADED_TEST(InstanceProperties) {
   10408   LocalContext context;
   10409   v8::Isolate* isolate = context->GetIsolate();
   10410   v8::HandleScope handle_scope(isolate);
   10411 
   10412   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10413   Local<ObjectTemplate> instance = t->InstanceTemplate();
   10414 
   10415   instance->Set(v8_str("x"), v8_num(42));
   10416   instance->Set(v8_str("f"),
   10417                 v8::FunctionTemplate::New(isolate, InstanceFunctionCallback));
   10418 
   10419   Local<Value> o = t->GetFunction(context.local())
   10420                        .ToLocalChecked()
   10421                        ->NewInstance(context.local())
   10422                        .ToLocalChecked();
   10423 
   10424   CHECK(context->Global()->Set(context.local(), v8_str("i"), o).FromJust());
   10425   Local<Value> value = CompileRun("i.x");
   10426   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   10427 
   10428   value = CompileRun("i.f()");
   10429   CHECK_EQ(12, value->Int32Value(context.local()).FromJust());
   10430 }
   10431 
   10432 
   10433 static void GlobalObjectInstancePropertiesGet(
   10434     Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>&) {
   10435   ApiTestFuzzer::Fuzz();
   10436 }
   10437 
   10438 
   10439 THREADED_TEST(GlobalObjectInstanceProperties) {
   10440   v8::Isolate* isolate = CcTest::isolate();
   10441   v8::HandleScope handle_scope(isolate);
   10442 
   10443   Local<Value> global_object;
   10444 
   10445   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10446   t->InstanceTemplate()->SetHandler(
   10447       v8::NamedPropertyHandlerConfiguration(GlobalObjectInstancePropertiesGet));
   10448   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   10449   instance_template->Set(v8_str("x"), v8_num(42));
   10450   instance_template->Set(v8_str("f"),
   10451                          v8::FunctionTemplate::New(isolate,
   10452                                                    InstanceFunctionCallback));
   10453 
   10454   // The script to check how Crankshaft compiles missing global function
   10455   // invocations.  function g is not defined and should throw on call.
   10456   const char* script =
   10457       "function wrapper(call) {"
   10458       "  var x = 0, y = 1;"
   10459       "  for (var i = 0; i < 1000; i++) {"
   10460       "    x += i * 100;"
   10461       "    y += i * 100;"
   10462       "  }"
   10463       "  if (call) g();"
   10464       "}"
   10465       "for (var i = 0; i < 17; i++) wrapper(false);"
   10466       "var thrown = 0;"
   10467       "try { wrapper(true); } catch (e) { thrown = 1; };"
   10468       "thrown";
   10469 
   10470   {
   10471     LocalContext env(NULL, instance_template);
   10472     // Hold on to the global object so it can be used again in another
   10473     // environment initialization.
   10474     global_object = env->Global();
   10475 
   10476     Local<Value> value = CompileRun("x");
   10477     CHECK_EQ(42, value->Int32Value(env.local()).FromJust());
   10478     value = CompileRun("f()");
   10479     CHECK_EQ(12, value->Int32Value(env.local()).FromJust());
   10480     value = CompileRun(script);
   10481     CHECK_EQ(1, value->Int32Value(env.local()).FromJust());
   10482   }
   10483 
   10484   {
   10485     // Create new environment reusing the global object.
   10486     LocalContext env(NULL, instance_template, global_object);
   10487     Local<Value> value = CompileRun("x");
   10488     CHECK_EQ(42, value->Int32Value(env.local()).FromJust());
   10489     value = CompileRun("f()");
   10490     CHECK_EQ(12, value->Int32Value(env.local()).FromJust());
   10491     value = CompileRun(script);
   10492     CHECK_EQ(1, value->Int32Value(env.local()).FromJust());
   10493   }
   10494 }
   10495 
   10496 THREADED_TEST(ObjectGetOwnPropertyNames) {
   10497   LocalContext context;
   10498   v8::Isolate* isolate = context->GetIsolate();
   10499   v8::HandleScope handle_scope(isolate);
   10500 
   10501   v8::Local<v8::Object> value =
   10502       v8::Local<v8::Object>::Cast(v8::StringObject::New(v8_str("test")));
   10503   v8::Local<v8::Array> properties;
   10504 
   10505   CHECK(value
   10506             ->GetOwnPropertyNames(context.local(),
   10507                                   static_cast<v8::PropertyFilter>(
   10508                                       v8::PropertyFilter::ALL_PROPERTIES |
   10509                                       v8::PropertyFilter::SKIP_SYMBOLS))
   10510             .ToLocal(&properties));
   10511   CHECK_EQ(5, properties->Length());
   10512   v8::Local<v8::Value> property;
   10513   CHECK(properties->Get(context.local(), 4).ToLocal(&property) &&
   10514         property->IsString());
   10515   CHECK(property.As<v8::String>()
   10516             ->Equals(context.local(), v8_str("length"))
   10517             .FromMaybe(false));
   10518   for (int i = 0; i < 4; ++i) {
   10519     v8::Local<v8::Value> property;
   10520     CHECK(properties->Get(context.local(), i).ToLocal(&property) &&
   10521           property->IsInt32());
   10522     CHECK_EQ(property.As<v8::Int32>()->Value(), i);
   10523   }
   10524 
   10525   CHECK(value->GetOwnPropertyNames(context.local(), v8::ONLY_ENUMERABLE)
   10526             .ToLocal(&properties));
   10527   CHECK_EQ(4, properties->Length());
   10528   for (int i = 0; i < 4; ++i) {
   10529     v8::Local<v8::Value> property;
   10530     CHECK(properties->Get(context.local(), i).ToLocal(&property) &&
   10531           property->IsInt32());
   10532     CHECK_EQ(property.As<v8::Int32>()->Value(), i);
   10533   }
   10534 
   10535   value = value->GetPrototype().As<v8::Object>();
   10536   CHECK(value
   10537             ->GetOwnPropertyNames(context.local(),
   10538                                   static_cast<v8::PropertyFilter>(
   10539                                       v8::PropertyFilter::ALL_PROPERTIES |
   10540                                       v8::PropertyFilter::SKIP_SYMBOLS))
   10541             .ToLocal(&properties));
   10542   bool concat_found = false;
   10543   bool starts_with_found = false;
   10544   for (uint32_t i = 0; i < properties->Length(); ++i) {
   10545     v8::Local<v8::Value> property;
   10546     CHECK(properties->Get(context.local(), i).ToLocal(&property));
   10547     if (!property->IsString()) continue;
   10548     if (!concat_found)
   10549       concat_found = property.As<v8::String>()
   10550                          ->Equals(context.local(), v8_str("concat"))
   10551                          .FromMaybe(false);
   10552     if (!starts_with_found)
   10553       starts_with_found = property.As<v8::String>()
   10554                               ->Equals(context.local(), v8_str("startsWith"))
   10555                               .FromMaybe(false);
   10556   }
   10557   CHECK(concat_found && starts_with_found);
   10558 }
   10559 
   10560 THREADED_TEST(CallKnownGlobalReceiver) {
   10561   v8::Isolate* isolate = CcTest::isolate();
   10562   v8::HandleScope handle_scope(isolate);
   10563 
   10564   Local<Value> global_object;
   10565 
   10566   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10567   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   10568 
   10569   // The script to check that we leave global object not
   10570   // global object proxy on stack when we deoptimize from inside
   10571   // arguments evaluation.
   10572   // To provoke error we need to both force deoptimization
   10573   // from arguments evaluation and to force CallIC to take
   10574   // CallIC_Miss code path that can't cope with global proxy.
   10575   const char* script =
   10576       "function bar(x, y) { try { } finally { } }"
   10577       "function baz(x) { try { } finally { } }"
   10578       "function bom(x) { try { } finally { } }"
   10579       "function foo(x) { bar([x], bom(2)); }"
   10580       "for (var i = 0; i < 10000; i++) foo(1);"
   10581       "foo";
   10582 
   10583   Local<Value> foo;
   10584   {
   10585     LocalContext env(NULL, instance_template);
   10586     // Hold on to the global object so it can be used again in another
   10587     // environment initialization.
   10588     global_object = env->Global();
   10589     foo = CompileRun(script);
   10590   }
   10591 
   10592   {
   10593     // Create new environment reusing the global object.
   10594     LocalContext env(NULL, instance_template, global_object);
   10595     CHECK(env->Global()->Set(env.local(), v8_str("foo"), foo).FromJust());
   10596     CompileRun("foo()");
   10597   }
   10598 }
   10599 
   10600 
   10601 static void ShadowFunctionCallback(
   10602     const v8::FunctionCallbackInfo<v8::Value>& args) {
   10603   ApiTestFuzzer::Fuzz();
   10604   args.GetReturnValue().Set(v8_num(42));
   10605 }
   10606 
   10607 
   10608 static int shadow_y;
   10609 static int shadow_y_setter_call_count;
   10610 static int shadow_y_getter_call_count;
   10611 
   10612 
   10613 static void ShadowYSetter(Local<String>,
   10614                           Local<Value>,
   10615                           const v8::PropertyCallbackInfo<void>&) {
   10616   shadow_y_setter_call_count++;
   10617   shadow_y = 42;
   10618 }
   10619 
   10620 
   10621 static void ShadowYGetter(Local<String> name,
   10622                           const v8::PropertyCallbackInfo<v8::Value>& info) {
   10623   ApiTestFuzzer::Fuzz();
   10624   shadow_y_getter_call_count++;
   10625   info.GetReturnValue().Set(v8_num(shadow_y));
   10626 }
   10627 
   10628 
   10629 static void ShadowIndexedGet(uint32_t index,
   10630                              const v8::PropertyCallbackInfo<v8::Value>&) {
   10631 }
   10632 
   10633 
   10634 static void ShadowNamedGet(Local<Name> key,
   10635                            const v8::PropertyCallbackInfo<v8::Value>&) {}
   10636 
   10637 
   10638 THREADED_TEST(ShadowObject) {
   10639   shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
   10640   v8::Isolate* isolate = CcTest::isolate();
   10641   v8::HandleScope handle_scope(isolate);
   10642 
   10643   Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
   10644   LocalContext context(NULL, global_template);
   10645 
   10646   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10647   t->InstanceTemplate()->SetHandler(
   10648       v8::NamedPropertyHandlerConfiguration(ShadowNamedGet));
   10649   t->InstanceTemplate()->SetHandler(
   10650       v8::IndexedPropertyHandlerConfiguration(ShadowIndexedGet));
   10651   Local<ObjectTemplate> proto = t->PrototypeTemplate();
   10652   Local<ObjectTemplate> instance = t->InstanceTemplate();
   10653 
   10654   proto->Set(v8_str("f"),
   10655              v8::FunctionTemplate::New(isolate,
   10656                                        ShadowFunctionCallback,
   10657                                        Local<Value>()));
   10658   proto->Set(v8_str("x"), v8_num(12));
   10659 
   10660   instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
   10661 
   10662   Local<Value> o = t->GetFunction(context.local())
   10663                        .ToLocalChecked()
   10664                        ->NewInstance(context.local())
   10665                        .ToLocalChecked();
   10666   CHECK(context->Global()
   10667             ->Set(context.local(), v8_str("__proto__"), o)
   10668             .FromJust());
   10669 
   10670   Local<Value> value =
   10671       CompileRun("this.propertyIsEnumerable(0)");
   10672   CHECK(value->IsBoolean());
   10673   CHECK(!value->BooleanValue(context.local()).FromJust());
   10674 
   10675   value = CompileRun("x");
   10676   CHECK_EQ(12, value->Int32Value(context.local()).FromJust());
   10677 
   10678   value = CompileRun("f()");
   10679   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   10680 
   10681   CompileRun("y = 43");
   10682   CHECK_EQ(1, shadow_y_setter_call_count);
   10683   value = CompileRun("y");
   10684   CHECK_EQ(1, shadow_y_getter_call_count);
   10685   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   10686 }
   10687 
   10688 
   10689 THREADED_TEST(HiddenPrototype) {
   10690   LocalContext context;
   10691   v8::Isolate* isolate = context->GetIsolate();
   10692   v8::HandleScope handle_scope(isolate);
   10693 
   10694   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
   10695   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   10696   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   10697   t1->SetHiddenPrototype(true);
   10698   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
   10699   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   10700   t2->SetHiddenPrototype(true);
   10701   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
   10702   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
   10703   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
   10704 
   10705   Local<v8::Object> o0 = t0->GetFunction(context.local())
   10706                              .ToLocalChecked()
   10707                              ->NewInstance(context.local())
   10708                              .ToLocalChecked();
   10709   Local<v8::Object> o1 = t1->GetFunction(context.local())
   10710                              .ToLocalChecked()
   10711                              ->NewInstance(context.local())
   10712                              .ToLocalChecked();
   10713   Local<v8::Object> o2 = t2->GetFunction(context.local())
   10714                              .ToLocalChecked()
   10715                              ->NewInstance(context.local())
   10716                              .ToLocalChecked();
   10717   Local<v8::Object> o3 = t3->GetFunction(context.local())
   10718                              .ToLocalChecked()
   10719                              ->NewInstance(context.local())
   10720                              .ToLocalChecked();
   10721 
   10722   // Setting the prototype on an object skips hidden prototypes.
   10723   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   10724                   .ToLocalChecked()
   10725                   ->Int32Value(context.local())
   10726                   .FromJust());
   10727   CHECK(o0->Set(context.local(), v8_str("__proto__"), o1).FromJust());
   10728   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   10729                   .ToLocalChecked()
   10730                   ->Int32Value(context.local())
   10731                   .FromJust());
   10732   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   10733                   .ToLocalChecked()
   10734                   ->Int32Value(context.local())
   10735                   .FromJust());
   10736   CHECK(o0->Set(context.local(), v8_str("__proto__"), o2).FromJust());
   10737   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   10738                   .ToLocalChecked()
   10739                   ->Int32Value(context.local())
   10740                   .FromJust());
   10741   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   10742                   .ToLocalChecked()
   10743                   ->Int32Value(context.local())
   10744                   .FromJust());
   10745   CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
   10746                   .ToLocalChecked()
   10747                   ->Int32Value(context.local())
   10748                   .FromJust());
   10749   CHECK(o0->Set(context.local(), v8_str("__proto__"), o3).FromJust());
   10750   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   10751                   .ToLocalChecked()
   10752                   ->Int32Value(context.local())
   10753                   .FromJust());
   10754   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   10755                   .ToLocalChecked()
   10756                   ->Int32Value(context.local())
   10757                   .FromJust());
   10758   CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
   10759                   .ToLocalChecked()
   10760                   ->Int32Value(context.local())
   10761                   .FromJust());
   10762   CHECK_EQ(3, o0->Get(context.local(), v8_str("u"))
   10763                   .ToLocalChecked()
   10764                   ->Int32Value(context.local())
   10765                   .FromJust());
   10766 
   10767   // Getting the prototype of o0 should get the first visible one
   10768   // which is o3.  Therefore, z should not be defined on the prototype
   10769   // object.
   10770   Local<Value> proto =
   10771       o0->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   10772   CHECK(proto->IsObject());
   10773   CHECK(proto.As<v8::Object>()
   10774             ->Get(context.local(), v8_str("z"))
   10775             .ToLocalChecked()
   10776             ->IsUndefined());
   10777 }
   10778 
   10779 
   10780 THREADED_TEST(HiddenPrototypeSet) {
   10781   LocalContext context;
   10782   v8::Isolate* isolate = context->GetIsolate();
   10783   v8::HandleScope handle_scope(isolate);
   10784 
   10785   Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New(isolate);
   10786   Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New(isolate);
   10787   ht->SetHiddenPrototype(true);
   10788   Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New(isolate);
   10789   ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   10790 
   10791   Local<v8::Object> o = ot->GetFunction(context.local())
   10792                             .ToLocalChecked()
   10793                             ->NewInstance(context.local())
   10794                             .ToLocalChecked();
   10795   Local<v8::Object> h = ht->GetFunction(context.local())
   10796                             .ToLocalChecked()
   10797                             ->NewInstance(context.local())
   10798                             .ToLocalChecked();
   10799   Local<v8::Object> p = pt->GetFunction(context.local())
   10800                             .ToLocalChecked()
   10801                             ->NewInstance(context.local())
   10802                             .ToLocalChecked();
   10803   CHECK(o->Set(context.local(), v8_str("__proto__"), h).FromJust());
   10804   CHECK(h->Set(context.local(), v8_str("__proto__"), p).FromJust());
   10805 
   10806   // Setting a property that exists on the hidden prototype goes there.
   10807   CHECK(o->Set(context.local(), v8_str("x"), v8_num(7)).FromJust());
   10808   CHECK_EQ(7, o->Get(context.local(), v8_str("x"))
   10809                   .ToLocalChecked()
   10810                   ->Int32Value(context.local())
   10811                   .FromJust());
   10812   CHECK_EQ(7, h->Get(context.local(), v8_str("x"))
   10813                   .ToLocalChecked()
   10814                   ->Int32Value(context.local())
   10815                   .FromJust());
   10816   CHECK(p->Get(context.local(), v8_str("x")).ToLocalChecked()->IsUndefined());
   10817 
   10818   // Setting a new property should not be forwarded to the hidden prototype.
   10819   CHECK(o->Set(context.local(), v8_str("y"), v8_num(6)).FromJust());
   10820   CHECK_EQ(6, o->Get(context.local(), v8_str("y"))
   10821                   .ToLocalChecked()
   10822                   ->Int32Value(context.local())
   10823                   .FromJust());
   10824   CHECK(h->Get(context.local(), v8_str("y")).ToLocalChecked()->IsUndefined());
   10825   CHECK(p->Get(context.local(), v8_str("y")).ToLocalChecked()->IsUndefined());
   10826 
   10827   // Setting a property that only exists on a prototype of the hidden prototype
   10828   // is treated normally again.
   10829   CHECK(p->Set(context.local(), v8_str("z"), v8_num(8)).FromJust());
   10830   CHECK_EQ(8, o->Get(context.local(), v8_str("z"))
   10831                   .ToLocalChecked()
   10832                   ->Int32Value(context.local())
   10833                   .FromJust());
   10834   CHECK_EQ(8, h->Get(context.local(), v8_str("z"))
   10835                   .ToLocalChecked()
   10836                   ->Int32Value(context.local())
   10837                   .FromJust());
   10838   CHECK_EQ(8, p->Get(context.local(), v8_str("z"))
   10839                   .ToLocalChecked()
   10840                   ->Int32Value(context.local())
   10841                   .FromJust());
   10842   CHECK(o->Set(context.local(), v8_str("z"), v8_num(9)).FromJust());
   10843   CHECK_EQ(9, o->Get(context.local(), v8_str("z"))
   10844                   .ToLocalChecked()
   10845                   ->Int32Value(context.local())
   10846                   .FromJust());
   10847   CHECK_EQ(8, h->Get(context.local(), v8_str("z"))
   10848                   .ToLocalChecked()
   10849                   ->Int32Value(context.local())
   10850                   .FromJust());
   10851   CHECK_EQ(8, p->Get(context.local(), v8_str("z"))
   10852                   .ToLocalChecked()
   10853                   ->Int32Value(context.local())
   10854                   .FromJust());
   10855 }
   10856 
   10857 
   10858 // Regression test for issue 2457.
   10859 THREADED_TEST(HiddenPrototypeIdentityHash) {
   10860   LocalContext context;
   10861   v8::HandleScope handle_scope(context->GetIsolate());
   10862 
   10863   Local<FunctionTemplate> t = FunctionTemplate::New(context->GetIsolate());
   10864   t->SetHiddenPrototype(true);
   10865   t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
   10866   Local<Object> p = t->GetFunction(context.local())
   10867                         .ToLocalChecked()
   10868                         ->NewInstance(context.local())
   10869                         .ToLocalChecked();
   10870   Local<Object> o = Object::New(context->GetIsolate());
   10871   CHECK(o->SetPrototype(context.local(), p).FromJust());
   10872 
   10873   int hash = o->GetIdentityHash();
   10874   USE(hash);
   10875   CHECK(o->Set(context.local(), v8_str("foo"), v8_num(42)).FromJust());
   10876   CHECK_EQ(hash, o->GetIdentityHash());
   10877 }
   10878 
   10879 
   10880 THREADED_TEST(SetPrototype) {
   10881   LocalContext context;
   10882   v8::Isolate* isolate = context->GetIsolate();
   10883   v8::HandleScope handle_scope(isolate);
   10884 
   10885   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
   10886   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   10887   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   10888   t1->SetHiddenPrototype(true);
   10889   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
   10890   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   10891   t2->SetHiddenPrototype(true);
   10892   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
   10893   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
   10894   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
   10895 
   10896   Local<v8::Object> o0 = t0->GetFunction(context.local())
   10897                              .ToLocalChecked()
   10898                              ->NewInstance(context.local())
   10899                              .ToLocalChecked();
   10900   Local<v8::Object> o1 = t1->GetFunction(context.local())
   10901                              .ToLocalChecked()
   10902                              ->NewInstance(context.local())
   10903                              .ToLocalChecked();
   10904   Local<v8::Object> o2 = t2->GetFunction(context.local())
   10905                              .ToLocalChecked()
   10906                              ->NewInstance(context.local())
   10907                              .ToLocalChecked();
   10908   Local<v8::Object> o3 = t3->GetFunction(context.local())
   10909                              .ToLocalChecked()
   10910                              ->NewInstance(context.local())
   10911                              .ToLocalChecked();
   10912 
   10913   // Setting the prototype on an object does not skip hidden prototypes.
   10914   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   10915                   .ToLocalChecked()
   10916                   ->Int32Value(context.local())
   10917                   .FromJust());
   10918   CHECK(o0->SetPrototype(context.local(), o1).FromJust());
   10919   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   10920                   .ToLocalChecked()
   10921                   ->Int32Value(context.local())
   10922                   .FromJust());
   10923   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   10924                   .ToLocalChecked()
   10925                   ->Int32Value(context.local())
   10926                   .FromJust());
   10927   CHECK(o1->SetPrototype(context.local(), o2).FromJust());
   10928   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   10929                   .ToLocalChecked()
   10930                   ->Int32Value(context.local())
   10931                   .FromJust());
   10932   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   10933                   .ToLocalChecked()
   10934                   ->Int32Value(context.local())
   10935                   .FromJust());
   10936   CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
   10937                   .ToLocalChecked()
   10938                   ->Int32Value(context.local())
   10939                   .FromJust());
   10940   CHECK(o2->SetPrototype(context.local(), o3).FromJust());
   10941   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   10942                   .ToLocalChecked()
   10943                   ->Int32Value(context.local())
   10944                   .FromJust());
   10945   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   10946                   .ToLocalChecked()
   10947                   ->Int32Value(context.local())
   10948                   .FromJust());
   10949   CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
   10950                   .ToLocalChecked()
   10951                   ->Int32Value(context.local())
   10952                   .FromJust());
   10953   CHECK_EQ(3, o0->Get(context.local(), v8_str("u"))
   10954                   .ToLocalChecked()
   10955                   ->Int32Value(context.local())
   10956                   .FromJust());
   10957 
   10958   // Getting the prototype of o0 should get the first visible one
   10959   // which is o3.  Therefore, z should not be defined on the prototype
   10960   // object.
   10961   Local<Value> proto =
   10962       o0->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   10963   CHECK(proto->IsObject());
   10964   CHECK(proto.As<v8::Object>()->Equals(context.local(), o3).FromJust());
   10965 
   10966   // However, Object::GetPrototype ignores hidden prototype.
   10967   Local<Value> proto0 = o0->GetPrototype();
   10968   CHECK(proto0->IsObject());
   10969   CHECK(proto0.As<v8::Object>()->Equals(context.local(), o1).FromJust());
   10970 
   10971   Local<Value> proto1 = o1->GetPrototype();
   10972   CHECK(proto1->IsObject());
   10973   CHECK(proto1.As<v8::Object>()->Equals(context.local(), o2).FromJust());
   10974 
   10975   Local<Value> proto2 = o2->GetPrototype();
   10976   CHECK(proto2->IsObject());
   10977   CHECK(proto2.As<v8::Object>()->Equals(context.local(), o3).FromJust());
   10978 }
   10979 
   10980 
   10981 // Getting property names of an object with a prototype chain that
   10982 // triggers dictionary elements in GetOwnPropertyNames() shouldn't
   10983 // crash the runtime.
   10984 THREADED_TEST(Regress91517) {
   10985   i::FLAG_allow_natives_syntax = true;
   10986   LocalContext context;
   10987   v8::Isolate* isolate = context->GetIsolate();
   10988   v8::HandleScope handle_scope(isolate);
   10989 
   10990   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   10991   t1->SetHiddenPrototype(true);
   10992   t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
   10993   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   10994   t2->SetHiddenPrototype(true);
   10995   t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
   10996   t2->InstanceTemplate()->Set(v8_str("objects"),
   10997                               v8::ObjectTemplate::New(isolate));
   10998   t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
   10999   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
   11000   t3->SetHiddenPrototype(true);
   11001   t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
   11002   Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(isolate);
   11003   t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
   11004 
   11005   // Force dictionary-based properties.
   11006   i::ScopedVector<char> name_buf(1024);
   11007   for (int i = 1; i <= 1000; i++) {
   11008     i::SNPrintF(name_buf, "sdf%d", i);
   11009     t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
   11010   }
   11011 
   11012   Local<v8::Object> o1 = t1->GetFunction(context.local())
   11013                              .ToLocalChecked()
   11014                              ->NewInstance(context.local())
   11015                              .ToLocalChecked();
   11016   Local<v8::Object> o2 = t2->GetFunction(context.local())
   11017                              .ToLocalChecked()
   11018                              ->NewInstance(context.local())
   11019                              .ToLocalChecked();
   11020   Local<v8::Object> o3 = t3->GetFunction(context.local())
   11021                              .ToLocalChecked()
   11022                              ->NewInstance(context.local())
   11023                              .ToLocalChecked();
   11024   Local<v8::Object> o4 = t4->GetFunction(context.local())
   11025                              .ToLocalChecked()
   11026                              ->NewInstance(context.local())
   11027                              .ToLocalChecked();
   11028 
   11029   // Create prototype chain of hidden prototypes.
   11030   CHECK(o4->SetPrototype(context.local(), o3).FromJust());
   11031   CHECK(o3->SetPrototype(context.local(), o2).FromJust());
   11032   CHECK(o2->SetPrototype(context.local(), o1).FromJust());
   11033 
   11034   // Call the runtime version of GetOwnPropertyNames() on the natively
   11035   // created object through JavaScript.
   11036   CHECK(context->Global()->Set(context.local(), v8_str("obj"), o4).FromJust());
   11037   // PROPERTY_FILTER_NONE = 0
   11038   CompileRun("var names = %GetOwnPropertyKeys(obj, 0);");
   11039 
   11040   ExpectInt32("names.length", 1006);
   11041   ExpectTrue("names.indexOf(\"baz\") >= 0");
   11042   ExpectTrue("names.indexOf(\"boo\") >= 0");
   11043   ExpectTrue("names.indexOf(\"foo\") >= 0");
   11044   ExpectTrue("names.indexOf(\"fuz1\") >= 0");
   11045   ExpectTrue("names.indexOf(\"objects\") >= 0");
   11046   ExpectTrue("names.indexOf(\"fuz2\") >= 0");
   11047   ExpectFalse("names[1005] == undefined");
   11048 }
   11049 
   11050 
   11051 // Getting property names of an object with a hidden and inherited
   11052 // prototype should not duplicate the accessor properties inherited.
   11053 THREADED_TEST(Regress269562) {
   11054   i::FLAG_allow_natives_syntax = true;
   11055   LocalContext context;
   11056   v8::HandleScope handle_scope(context->GetIsolate());
   11057 
   11058   Local<v8::FunctionTemplate> t1 =
   11059       v8::FunctionTemplate::New(context->GetIsolate());
   11060   t1->SetHiddenPrototype(true);
   11061 
   11062   Local<v8::ObjectTemplate> i1 = t1->InstanceTemplate();
   11063   i1->SetAccessor(v8_str("foo"),
   11064                   SimpleAccessorGetter, SimpleAccessorSetter);
   11065   i1->SetAccessor(v8_str("bar"),
   11066                   SimpleAccessorGetter, SimpleAccessorSetter);
   11067   i1->SetAccessor(v8_str("baz"),
   11068                   SimpleAccessorGetter, SimpleAccessorSetter);
   11069   i1->Set(v8_str("n1"), v8_num(1));
   11070   i1->Set(v8_str("n2"), v8_num(2));
   11071 
   11072   Local<v8::Object> o1 = t1->GetFunction(context.local())
   11073                              .ToLocalChecked()
   11074                              ->NewInstance(context.local())
   11075                              .ToLocalChecked();
   11076   Local<v8::FunctionTemplate> t2 =
   11077       v8::FunctionTemplate::New(context->GetIsolate());
   11078   t2->SetHiddenPrototype(true);
   11079 
   11080   // Inherit from t1 and mark prototype as hidden.
   11081   t2->Inherit(t1);
   11082   t2->InstanceTemplate()->Set(v8_str("mine"), v8_num(4));
   11083 
   11084   Local<v8::Object> o2 = t2->GetFunction(context.local())
   11085                              .ToLocalChecked()
   11086                              ->NewInstance(context.local())
   11087                              .ToLocalChecked();
   11088   CHECK(o2->SetPrototype(context.local(), o1).FromJust());
   11089 
   11090   v8::Local<v8::Symbol> sym =
   11091       v8::Symbol::New(context->GetIsolate(), v8_str("s1"));
   11092   CHECK(o1->Set(context.local(), sym, v8_num(3)).FromJust());
   11093   o1->SetPrivate(context.local(),
   11094                  v8::Private::New(context->GetIsolate(), v8_str("h1")),
   11095                  v8::Integer::New(context->GetIsolate(), 2013))
   11096       .FromJust();
   11097 
   11098   // Call the runtime version of GetOwnPropertyNames() on
   11099   // the natively created object through JavaScript.
   11100   CHECK(context->Global()->Set(context.local(), v8_str("obj"), o2).FromJust());
   11101   CHECK(context->Global()->Set(context.local(), v8_str("sym"), sym).FromJust());
   11102   // PROPERTY_FILTER_NONE = 0
   11103   CompileRun("var names = %GetOwnPropertyKeys(obj, 0);");
   11104 
   11105   ExpectInt32("names.length", 7);
   11106   ExpectTrue("names.indexOf(\"foo\") >= 0");
   11107   ExpectTrue("names.indexOf(\"bar\") >= 0");
   11108   ExpectTrue("names.indexOf(\"baz\") >= 0");
   11109   ExpectTrue("names.indexOf(\"n1\") >= 0");
   11110   ExpectTrue("names.indexOf(\"n2\") >= 0");
   11111   ExpectTrue("names.indexOf(sym) >= 0");
   11112   ExpectTrue("names.indexOf(\"mine\") >= 0");
   11113 }
   11114 
   11115 
   11116 THREADED_TEST(FunctionReadOnlyPrototype) {
   11117   LocalContext context;
   11118   v8::Isolate* isolate = context->GetIsolate();
   11119   v8::HandleScope handle_scope(isolate);
   11120 
   11121   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   11122   t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
   11123   t1->ReadOnlyPrototype();
   11124   CHECK(context->Global()
   11125             ->Set(context.local(), v8_str("func1"),
   11126                   t1->GetFunction(context.local()).ToLocalChecked())
   11127             .FromJust());
   11128   // Configured value of ReadOnly flag.
   11129   CHECK(
   11130       CompileRun(
   11131           "(function() {"
   11132           "  descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
   11133           "  return (descriptor['writable'] == false);"
   11134           "})()")
   11135           ->BooleanValue(context.local())
   11136           .FromJust());
   11137   CHECK_EQ(
   11138       42,
   11139       CompileRun("func1.prototype.x")->Int32Value(context.local()).FromJust());
   11140   CHECK_EQ(42, CompileRun("func1.prototype = {}; func1.prototype.x")
   11141                    ->Int32Value(context.local())
   11142                    .FromJust());
   11143 
   11144   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   11145   t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
   11146   CHECK(context->Global()
   11147             ->Set(context.local(), v8_str("func2"),
   11148                   t2->GetFunction(context.local()).ToLocalChecked())
   11149             .FromJust());
   11150   // Default value of ReadOnly flag.
   11151   CHECK(
   11152       CompileRun(
   11153           "(function() {"
   11154           "  descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
   11155           "  return (descriptor['writable'] == true);"
   11156           "})()")
   11157           ->BooleanValue(context.local())
   11158           .FromJust());
   11159   CHECK_EQ(
   11160       42,
   11161       CompileRun("func2.prototype.x")->Int32Value(context.local()).FromJust());
   11162 }
   11163 
   11164 
   11165 THREADED_TEST(SetPrototypeThrows) {
   11166   LocalContext context;
   11167   v8::Isolate* isolate = context->GetIsolate();
   11168   v8::HandleScope handle_scope(isolate);
   11169 
   11170   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11171 
   11172   Local<v8::Object> o0 = t->GetFunction(context.local())
   11173                              .ToLocalChecked()
   11174                              ->NewInstance(context.local())
   11175                              .ToLocalChecked();
   11176   Local<v8::Object> o1 = t->GetFunction(context.local())
   11177                              .ToLocalChecked()
   11178                              ->NewInstance(context.local())
   11179                              .ToLocalChecked();
   11180 
   11181   CHECK(o0->SetPrototype(context.local(), o1).FromJust());
   11182   // If setting the prototype leads to the cycle, SetPrototype should
   11183   // return false and keep VM in sane state.
   11184   v8::TryCatch try_catch(isolate);
   11185   CHECK(o1->SetPrototype(context.local(), o0).IsNothing());
   11186   CHECK(!try_catch.HasCaught());
   11187   CHECK(!CcTest::i_isolate()->has_pending_exception());
   11188 
   11189   CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")
   11190                    ->Int32Value(context.local())
   11191                    .FromJust());
   11192 }
   11193 
   11194 
   11195 THREADED_TEST(FunctionRemovePrototype) {
   11196   LocalContext context;
   11197   v8::Isolate* isolate = context->GetIsolate();
   11198   v8::HandleScope handle_scope(isolate);
   11199 
   11200   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   11201   t1->RemovePrototype();
   11202   Local<v8::Function> fun = t1->GetFunction(context.local()).ToLocalChecked();
   11203   CHECK(!fun->IsConstructor());
   11204   CHECK(context->Global()->Set(context.local(), v8_str("fun"), fun).FromJust());
   11205   CHECK(!CompileRun("'prototype' in fun")
   11206              ->BooleanValue(context.local())
   11207              .FromJust());
   11208 
   11209   v8::TryCatch try_catch(isolate);
   11210   CompileRun("new fun()");
   11211   CHECK(try_catch.HasCaught());
   11212 
   11213   try_catch.Reset();
   11214   CHECK(fun->NewInstance(context.local()).IsEmpty());
   11215   CHECK(try_catch.HasCaught());
   11216 }
   11217 
   11218 
   11219 THREADED_TEST(GetterSetterExceptions) {
   11220   LocalContext context;
   11221   v8::Isolate* isolate = context->GetIsolate();
   11222   v8::HandleScope handle_scope(isolate);
   11223   CompileRun(
   11224       "function Foo() { };"
   11225       "function Throw() { throw 5; };"
   11226       "var x = { };"
   11227       "x.__defineSetter__('set', Throw);"
   11228       "x.__defineGetter__('get', Throw);");
   11229   Local<v8::Object> x = Local<v8::Object>::Cast(
   11230       context->Global()->Get(context.local(), v8_str("x")).ToLocalChecked());
   11231   v8::TryCatch try_catch(isolate);
   11232   CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
   11233             .IsNothing());
   11234   CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
   11235   CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
   11236             .IsNothing());
   11237   CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
   11238   CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
   11239             .IsNothing());
   11240   CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
   11241   CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
   11242             .IsNothing());
   11243   CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
   11244 }
   11245 
   11246 
   11247 THREADED_TEST(Constructor) {
   11248   LocalContext context;
   11249   v8::Isolate* isolate = context->GetIsolate();
   11250   v8::HandleScope handle_scope(isolate);
   11251   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   11252   templ->SetClassName(v8_str("Fun"));
   11253   Local<Function> cons = templ->GetFunction(context.local()).ToLocalChecked();
   11254   CHECK(
   11255       context->Global()->Set(context.local(), v8_str("Fun"), cons).FromJust());
   11256   Local<v8::Object> inst = cons->NewInstance(context.local()).ToLocalChecked();
   11257   i::Handle<i::JSReceiver> obj(v8::Utils::OpenHandle(*inst));
   11258   CHECK(obj->IsJSObject());
   11259   Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
   11260   CHECK(value->BooleanValue(context.local()).FromJust());
   11261 }
   11262 
   11263 
   11264 static void ConstructorCallback(
   11265     const v8::FunctionCallbackInfo<v8::Value>& args) {
   11266   ApiTestFuzzer::Fuzz();
   11267   Local<Object> This;
   11268 
   11269   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   11270   if (args.IsConstructCall()) {
   11271     Local<Object> Holder = args.Holder();
   11272     This = Object::New(args.GetIsolate());
   11273     Local<Value> proto = Holder->GetPrototype();
   11274     if (proto->IsObject()) {
   11275       This->SetPrototype(context, proto).FromJust();
   11276     }
   11277   } else {
   11278     This = args.This();
   11279   }
   11280 
   11281   This->Set(context, v8_str("a"), args[0]).FromJust();
   11282   args.GetReturnValue().Set(This);
   11283 }
   11284 
   11285 
   11286 static void FakeConstructorCallback(
   11287     const v8::FunctionCallbackInfo<v8::Value>& args) {
   11288   ApiTestFuzzer::Fuzz();
   11289   args.GetReturnValue().Set(args[0]);
   11290 }
   11291 
   11292 
   11293 THREADED_TEST(ConstructorForObject) {
   11294   LocalContext context;
   11295   v8::Isolate* isolate = context->GetIsolate();
   11296   v8::HandleScope handle_scope(isolate);
   11297 
   11298   {
   11299     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   11300     instance_template->SetCallAsFunctionHandler(ConstructorCallback);
   11301     Local<Object> instance =
   11302         instance_template->NewInstance(context.local()).ToLocalChecked();
   11303     CHECK(context->Global()
   11304               ->Set(context.local(), v8_str("obj"), instance)
   11305               .FromJust());
   11306     v8::TryCatch try_catch(isolate);
   11307     Local<Value> value;
   11308     CHECK(!try_catch.HasCaught());
   11309 
   11310     // Call the Object's constructor with a 32-bit signed integer.
   11311     value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
   11312     CHECK(!try_catch.HasCaught());
   11313     CHECK(value->IsInt32());
   11314     CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
   11315 
   11316     Local<Value> args1[] = {v8_num(28)};
   11317     Local<Value> value_obj1 =
   11318         instance->CallAsConstructor(context.local(), 1, args1).ToLocalChecked();
   11319     CHECK(value_obj1->IsObject());
   11320     Local<Object> object1 = Local<Object>::Cast(value_obj1);
   11321     value = object1->Get(context.local(), v8_str("a")).ToLocalChecked();
   11322     CHECK(value->IsInt32());
   11323     CHECK(!try_catch.HasCaught());
   11324     CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
   11325 
   11326     // Call the Object's constructor with a String.
   11327     value =
   11328         CompileRun("(function() { var o = new obj('tipli'); return o.a; })()");
   11329     CHECK(!try_catch.HasCaught());
   11330     CHECK(value->IsString());
   11331     String::Utf8Value string_value1(
   11332         value->ToString(context.local()).ToLocalChecked());
   11333     CHECK_EQ(0, strcmp("tipli", *string_value1));
   11334 
   11335     Local<Value> args2[] = {v8_str("tipli")};
   11336     Local<Value> value_obj2 =
   11337         instance->CallAsConstructor(context.local(), 1, args2).ToLocalChecked();
   11338     CHECK(value_obj2->IsObject());
   11339     Local<Object> object2 = Local<Object>::Cast(value_obj2);
   11340     value = object2->Get(context.local(), v8_str("a")).ToLocalChecked();
   11341     CHECK(!try_catch.HasCaught());
   11342     CHECK(value->IsString());
   11343     String::Utf8Value string_value2(
   11344         value->ToString(context.local()).ToLocalChecked());
   11345     CHECK_EQ(0, strcmp("tipli", *string_value2));
   11346 
   11347     // Call the Object's constructor with a Boolean.
   11348     value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
   11349     CHECK(!try_catch.HasCaught());
   11350     CHECK(value->IsBoolean());
   11351     CHECK_EQ(true, value->BooleanValue(context.local()).FromJust());
   11352 
   11353     Local<Value> args3[] = {v8::True(isolate)};
   11354     Local<Value> value_obj3 =
   11355         instance->CallAsConstructor(context.local(), 1, args3).ToLocalChecked();
   11356     CHECK(value_obj3->IsObject());
   11357     Local<Object> object3 = Local<Object>::Cast(value_obj3);
   11358     value = object3->Get(context.local(), v8_str("a")).ToLocalChecked();
   11359     CHECK(!try_catch.HasCaught());
   11360     CHECK(value->IsBoolean());
   11361     CHECK_EQ(true, value->BooleanValue(context.local()).FromJust());
   11362 
   11363     // Call the Object's constructor with undefined.
   11364     Local<Value> args4[] = {v8::Undefined(isolate)};
   11365     Local<Value> value_obj4 =
   11366         instance->CallAsConstructor(context.local(), 1, args4).ToLocalChecked();
   11367     CHECK(value_obj4->IsObject());
   11368     Local<Object> object4 = Local<Object>::Cast(value_obj4);
   11369     value = object4->Get(context.local(), v8_str("a")).ToLocalChecked();
   11370     CHECK(!try_catch.HasCaught());
   11371     CHECK(value->IsUndefined());
   11372 
   11373     // Call the Object's constructor with null.
   11374     Local<Value> args5[] = {v8::Null(isolate)};
   11375     Local<Value> value_obj5 =
   11376         instance->CallAsConstructor(context.local(), 1, args5).ToLocalChecked();
   11377     CHECK(value_obj5->IsObject());
   11378     Local<Object> object5 = Local<Object>::Cast(value_obj5);
   11379     value = object5->Get(context.local(), v8_str("a")).ToLocalChecked();
   11380     CHECK(!try_catch.HasCaught());
   11381     CHECK(value->IsNull());
   11382   }
   11383 
   11384   // Check exception handling when there is no constructor set for the Object.
   11385   {
   11386     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   11387     Local<Object> instance =
   11388         instance_template->NewInstance(context.local()).ToLocalChecked();
   11389     CHECK(context->Global()
   11390               ->Set(context.local(), v8_str("obj2"), instance)
   11391               .FromJust());
   11392     v8::TryCatch try_catch(isolate);
   11393     Local<Value> value;
   11394     CHECK(!try_catch.HasCaught());
   11395 
   11396     value = CompileRun("new obj2(28)");
   11397     CHECK(try_catch.HasCaught());
   11398     String::Utf8Value exception_value1(try_catch.Exception());
   11399     CHECK_EQ(0,
   11400              strcmp("TypeError: obj2 is not a constructor", *exception_value1));
   11401     try_catch.Reset();
   11402 
   11403     Local<Value> args[] = {v8_num(29)};
   11404     CHECK(instance->CallAsConstructor(context.local(), 1, args).IsEmpty());
   11405     CHECK(try_catch.HasCaught());
   11406     String::Utf8Value exception_value2(try_catch.Exception());
   11407     CHECK_EQ(
   11408         0, strcmp("TypeError: object is not a constructor", *exception_value2));
   11409     try_catch.Reset();
   11410   }
   11411 
   11412   // Check the case when constructor throws exception.
   11413   {
   11414     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   11415     instance_template->SetCallAsFunctionHandler(ThrowValue);
   11416     Local<Object> instance =
   11417         instance_template->NewInstance(context.local()).ToLocalChecked();
   11418     CHECK(context->Global()
   11419               ->Set(context.local(), v8_str("obj3"), instance)
   11420               .FromJust());
   11421     v8::TryCatch try_catch(isolate);
   11422     Local<Value> value;
   11423     CHECK(!try_catch.HasCaught());
   11424 
   11425     value = CompileRun("new obj3(22)");
   11426     CHECK(try_catch.HasCaught());
   11427     String::Utf8Value exception_value1(try_catch.Exception());
   11428     CHECK_EQ(0, strcmp("22", *exception_value1));
   11429     try_catch.Reset();
   11430 
   11431     Local<Value> args[] = {v8_num(23)};
   11432     CHECK(instance->CallAsConstructor(context.local(), 1, args).IsEmpty());
   11433     CHECK(try_catch.HasCaught());
   11434     String::Utf8Value exception_value2(try_catch.Exception());
   11435     CHECK_EQ(0, strcmp("23", *exception_value2));
   11436     try_catch.Reset();
   11437   }
   11438 
   11439   // Check whether constructor returns with an object or non-object.
   11440   {
   11441     Local<FunctionTemplate> function_template =
   11442         FunctionTemplate::New(isolate, FakeConstructorCallback);
   11443     Local<Function> function =
   11444         function_template->GetFunction(context.local()).ToLocalChecked();
   11445     Local<Object> instance1 = function;
   11446     CHECK(context->Global()
   11447               ->Set(context.local(), v8_str("obj4"), instance1)
   11448               .FromJust());
   11449     v8::TryCatch try_catch(isolate);
   11450     Local<Value> value;
   11451     CHECK(!try_catch.HasCaught());
   11452 
   11453     CHECK(instance1->IsObject());
   11454     CHECK(instance1->IsFunction());
   11455 
   11456     value = CompileRun("new obj4(28)");
   11457     CHECK(!try_catch.HasCaught());
   11458     CHECK(value->IsObject());
   11459 
   11460     Local<Value> args1[] = {v8_num(28)};
   11461     value = instance1->CallAsConstructor(context.local(), 1, args1)
   11462                 .ToLocalChecked();
   11463     CHECK(!try_catch.HasCaught());
   11464     CHECK(value->IsObject());
   11465 
   11466     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   11467     instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
   11468     Local<Object> instance2 =
   11469         instance_template->NewInstance(context.local()).ToLocalChecked();
   11470     CHECK(context->Global()
   11471               ->Set(context.local(), v8_str("obj5"), instance2)
   11472               .FromJust());
   11473     CHECK(!try_catch.HasCaught());
   11474 
   11475     CHECK(instance2->IsObject());
   11476     CHECK(instance2->IsFunction());
   11477 
   11478     value = CompileRun("new obj5(28)");
   11479     CHECK(!try_catch.HasCaught());
   11480     CHECK(!value->IsObject());
   11481 
   11482     Local<Value> args2[] = {v8_num(28)};
   11483     value = instance2->CallAsConstructor(context.local(), 1, args2)
   11484                 .ToLocalChecked();
   11485     CHECK(!try_catch.HasCaught());
   11486     CHECK(!value->IsObject());
   11487   }
   11488 }
   11489 
   11490 
   11491 THREADED_TEST(FunctionDescriptorException) {
   11492   LocalContext context;
   11493   v8::Isolate* isolate = context->GetIsolate();
   11494   v8::HandleScope handle_scope(isolate);
   11495   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   11496   templ->SetClassName(v8_str("Fun"));
   11497   Local<Function> cons = templ->GetFunction(context.local()).ToLocalChecked();
   11498   CHECK(
   11499       context->Global()->Set(context.local(), v8_str("Fun"), cons).FromJust());
   11500   Local<Value> value = CompileRun(
   11501       "function test() {"
   11502       "  try {"
   11503       "    (new Fun()).blah()"
   11504       "  } catch (e) {"
   11505       "    var str = String(e);"
   11506       // "    if (str.indexOf('TypeError') == -1) return 1;"
   11507       // "    if (str.indexOf('[object Fun]') != -1) return 2;"
   11508       // "    if (str.indexOf('#<Fun>') == -1) return 3;"
   11509       "    return 0;"
   11510       "  }"
   11511       "  return 4;"
   11512       "}"
   11513       "test();");
   11514   CHECK_EQ(0, value->Int32Value(context.local()).FromJust());
   11515 }
   11516 
   11517 
   11518 THREADED_TEST(EvalAliasedDynamic) {
   11519   LocalContext current;
   11520   v8::HandleScope scope(current->GetIsolate());
   11521 
   11522   // Tests where aliased eval can only be resolved dynamically.
   11523   Local<Script> script = v8_compile(
   11524       "function f(x) { "
   11525       "  var foo = 2;"
   11526       "  with (x) { return eval('foo'); }"
   11527       "}"
   11528       "foo = 0;"
   11529       "result1 = f(new Object());"
   11530       "result2 = f(this);"
   11531       "var x = new Object();"
   11532       "x.eval = function(x) { return 1; };"
   11533       "result3 = f(x);");
   11534   script->Run(current.local()).ToLocalChecked();
   11535   CHECK_EQ(2, current->Global()
   11536                   ->Get(current.local(), v8_str("result1"))
   11537                   .ToLocalChecked()
   11538                   ->Int32Value(current.local())
   11539                   .FromJust());
   11540   CHECK_EQ(0, current->Global()
   11541                   ->Get(current.local(), v8_str("result2"))
   11542                   .ToLocalChecked()
   11543                   ->Int32Value(current.local())
   11544                   .FromJust());
   11545   CHECK_EQ(1, current->Global()
   11546                   ->Get(current.local(), v8_str("result3"))
   11547                   .ToLocalChecked()
   11548                   ->Int32Value(current.local())
   11549                   .FromJust());
   11550 
   11551   v8::TryCatch try_catch(current->GetIsolate());
   11552   script = v8_compile(
   11553       "function f(x) { "
   11554       "  var bar = 2;"
   11555       "  with (x) { return eval('bar'); }"
   11556       "}"
   11557       "result4 = f(this)");
   11558   script->Run(current.local()).ToLocalChecked();
   11559   CHECK(!try_catch.HasCaught());
   11560   CHECK_EQ(2, current->Global()
   11561                   ->Get(current.local(), v8_str("result4"))
   11562                   .ToLocalChecked()
   11563                   ->Int32Value(current.local())
   11564                   .FromJust());
   11565 
   11566   try_catch.Reset();
   11567 }
   11568 
   11569 
   11570 THREADED_TEST(CrossEval) {
   11571   v8::HandleScope scope(CcTest::isolate());
   11572   LocalContext other;
   11573   LocalContext current;
   11574 
   11575   Local<String> token = v8_str("<security token>");
   11576   other->SetSecurityToken(token);
   11577   current->SetSecurityToken(token);
   11578 
   11579   // Set up reference from current to other.
   11580   CHECK(current->Global()
   11581             ->Set(current.local(), v8_str("other"), other->Global())
   11582             .FromJust());
   11583 
   11584   // Check that new variables are introduced in other context.
   11585   Local<Script> script = v8_compile("other.eval('var foo = 1234')");
   11586   script->Run(current.local()).ToLocalChecked();
   11587   Local<Value> foo =
   11588       other->Global()->Get(current.local(), v8_str("foo")).ToLocalChecked();
   11589   CHECK_EQ(1234, foo->Int32Value(other.local()).FromJust());
   11590   CHECK(!current->Global()->Has(current.local(), v8_str("foo")).FromJust());
   11591 
   11592   // Check that writing to non-existing properties introduces them in
   11593   // the other context.
   11594   script = v8_compile("other.eval('na = 1234')");
   11595   script->Run(current.local()).ToLocalChecked();
   11596   CHECK_EQ(1234, other->Global()
   11597                      ->Get(current.local(), v8_str("na"))
   11598                      .ToLocalChecked()
   11599                      ->Int32Value(other.local())
   11600                      .FromJust());
   11601   CHECK(!current->Global()->Has(current.local(), v8_str("na")).FromJust());
   11602 
   11603   // Check that global variables in current context are not visible in other
   11604   // context.
   11605   v8::TryCatch try_catch(CcTest::isolate());
   11606   script = v8_compile("var bar = 42; other.eval('bar');");
   11607   CHECK(script->Run(current.local()).IsEmpty());
   11608   CHECK(try_catch.HasCaught());
   11609   try_catch.Reset();
   11610 
   11611   // Check that local variables in current context are not visible in other
   11612   // context.
   11613   script = v8_compile(
   11614       "(function() { "
   11615       "  var baz = 87;"
   11616       "  return other.eval('baz');"
   11617       "})();");
   11618   CHECK(script->Run(current.local()).IsEmpty());
   11619   CHECK(try_catch.HasCaught());
   11620   try_catch.Reset();
   11621 
   11622   // Check that global variables in the other environment are visible
   11623   // when evaluting code.
   11624   CHECK(other->Global()
   11625             ->Set(other.local(), v8_str("bis"), v8_num(1234))
   11626             .FromJust());
   11627   script = v8_compile("other.eval('bis')");
   11628   CHECK_EQ(1234, script->Run(current.local())
   11629                      .ToLocalChecked()
   11630                      ->Int32Value(current.local())
   11631                      .FromJust());
   11632   CHECK(!try_catch.HasCaught());
   11633 
   11634   // Check that the 'this' pointer points to the global object evaluating
   11635   // code.
   11636   CHECK(other->Global()
   11637             ->Set(current.local(), v8_str("t"), other->Global())
   11638             .FromJust());
   11639   script = v8_compile("other.eval('this == t')");
   11640   Local<Value> result = script->Run(current.local()).ToLocalChecked();
   11641   CHECK(result->IsTrue());
   11642   CHECK(!try_catch.HasCaught());
   11643 
   11644   // Check that variables introduced in with-statement are not visible in
   11645   // other context.
   11646   script = v8_compile("with({x:2}){other.eval('x')}");
   11647   CHECK(script->Run(current.local()).IsEmpty());
   11648   CHECK(try_catch.HasCaught());
   11649   try_catch.Reset();
   11650 
   11651   // Check that you cannot use 'eval.call' with another object than the
   11652   // current global object.
   11653   script = v8_compile("other.y = 1; eval.call(other, 'y')");
   11654   CHECK(script->Run(current.local()).IsEmpty());
   11655   CHECK(try_catch.HasCaught());
   11656 }
   11657 
   11658 
   11659 // Test that calling eval in a context which has been detached from
   11660 // its global proxy works.
   11661 THREADED_TEST(EvalInDetachedGlobal) {
   11662   v8::Isolate* isolate = CcTest::isolate();
   11663   v8::HandleScope scope(isolate);
   11664 
   11665   v8::Local<Context> context0 = Context::New(isolate);
   11666   v8::Local<Context> context1 = Context::New(isolate);
   11667 
   11668   // Set up function in context0 that uses eval from context0.
   11669   context0->Enter();
   11670   v8::Local<v8::Value> fun = CompileRun(
   11671       "var x = 42;"
   11672       "(function() {"
   11673       "  var e = eval;"
   11674       "  return function(s) { return e(s); }"
   11675       "})()");
   11676   context0->Exit();
   11677 
   11678   // Put the function into context1 and call it before and after
   11679   // detaching the global.  Before detaching, the call succeeds and
   11680   // after detaching and exception is thrown.
   11681   context1->Enter();
   11682   CHECK(context1->Global()->Set(context1, v8_str("fun"), fun).FromJust());
   11683   v8::Local<v8::Value> x_value = CompileRun("fun('x')");
   11684   CHECK_EQ(42, x_value->Int32Value(context1).FromJust());
   11685   context0->DetachGlobal();
   11686   v8::TryCatch catcher(isolate);
   11687   x_value = CompileRun("fun('x')");
   11688   CHECK_EQ(42, x_value->Int32Value(context1).FromJust());
   11689   context1->Exit();
   11690 }
   11691 
   11692 
   11693 THREADED_TEST(CrossLazyLoad) {
   11694   v8::HandleScope scope(CcTest::isolate());
   11695   LocalContext other;
   11696   LocalContext current;
   11697 
   11698   Local<String> token = v8_str("<security token>");
   11699   other->SetSecurityToken(token);
   11700   current->SetSecurityToken(token);
   11701 
   11702   // Set up reference from current to other.
   11703   CHECK(current->Global()
   11704             ->Set(current.local(), v8_str("other"), other->Global())
   11705             .FromJust());
   11706 
   11707   // Trigger lazy loading in other context.
   11708   Local<Script> script = v8_compile("other.eval('new Date(42)')");
   11709   Local<Value> value = script->Run(current.local()).ToLocalChecked();
   11710   CHECK_EQ(42.0, value->NumberValue(current.local()).FromJust());
   11711 }
   11712 
   11713 
   11714 static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
   11715   ApiTestFuzzer::Fuzz();
   11716   if (args.IsConstructCall()) {
   11717     if (args[0]->IsInt32()) {
   11718       args.GetReturnValue().Set(
   11719           v8_num(-args[0]
   11720                       ->Int32Value(args.GetIsolate()->GetCurrentContext())
   11721                       .FromJust()));
   11722       return;
   11723     }
   11724   }
   11725 
   11726   args.GetReturnValue().Set(args[0]);
   11727 }
   11728 
   11729 
   11730 static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
   11731   args.GetReturnValue().Set(args.This());
   11732 }
   11733 
   11734 
   11735 // Test that a call handler can be set for objects which will allow
   11736 // non-function objects created through the API to be called as
   11737 // functions.
   11738 THREADED_TEST(CallAsFunction) {
   11739   LocalContext context;
   11740   v8::Isolate* isolate = context->GetIsolate();
   11741   v8::HandleScope scope(isolate);
   11742 
   11743   {
   11744     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11745     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   11746     instance_template->SetCallAsFunctionHandler(call_as_function);
   11747     Local<v8::Object> instance = t->GetFunction(context.local())
   11748                                      .ToLocalChecked()
   11749                                      ->NewInstance(context.local())
   11750                                      .ToLocalChecked();
   11751     CHECK(context->Global()
   11752               ->Set(context.local(), v8_str("obj"), instance)
   11753               .FromJust());
   11754     v8::TryCatch try_catch(isolate);
   11755     Local<Value> value;
   11756     CHECK(!try_catch.HasCaught());
   11757 
   11758     value = CompileRun("obj(42)");
   11759     CHECK(!try_catch.HasCaught());
   11760     CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   11761 
   11762     value = CompileRun("(function(o){return o(49)})(obj)");
   11763     CHECK(!try_catch.HasCaught());
   11764     CHECK_EQ(49, value->Int32Value(context.local()).FromJust());
   11765 
   11766     // test special case of call as function
   11767     value = CompileRun("[obj]['0'](45)");
   11768     CHECK(!try_catch.HasCaught());
   11769     CHECK_EQ(45, value->Int32Value(context.local()).FromJust());
   11770 
   11771     value = CompileRun(
   11772         "obj.call = Function.prototype.call;"
   11773         "obj.call(null, 87)");
   11774     CHECK(!try_catch.HasCaught());
   11775     CHECK_EQ(87, value->Int32Value(context.local()).FromJust());
   11776 
   11777     // Regression tests for bug #1116356: Calling call through call/apply
   11778     // must work for non-function receivers.
   11779     const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
   11780     value = CompileRun(apply_99);
   11781     CHECK(!try_catch.HasCaught());
   11782     CHECK_EQ(99, value->Int32Value(context.local()).FromJust());
   11783 
   11784     const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
   11785     value = CompileRun(call_17);
   11786     CHECK(!try_catch.HasCaught());
   11787     CHECK_EQ(17, value->Int32Value(context.local()).FromJust());
   11788 
   11789     // Check that the call-as-function handler can be called through
   11790     // new.
   11791     value = CompileRun("new obj(43)");
   11792     CHECK(!try_catch.HasCaught());
   11793     CHECK_EQ(-43, value->Int32Value(context.local()).FromJust());
   11794 
   11795     // Check that the call-as-function handler can be called through
   11796     // the API.
   11797     v8::Local<Value> args[] = {v8_num(28)};
   11798     value = instance->CallAsFunction(context.local(), instance, 1, args)
   11799                 .ToLocalChecked();
   11800     CHECK(!try_catch.HasCaught());
   11801     CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
   11802   }
   11803 
   11804   {
   11805     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11806     Local<ObjectTemplate> instance_template(t->InstanceTemplate());
   11807     USE(instance_template);
   11808     Local<v8::Object> instance = t->GetFunction(context.local())
   11809                                      .ToLocalChecked()
   11810                                      ->NewInstance(context.local())
   11811                                      .ToLocalChecked();
   11812     CHECK(context->Global()
   11813               ->Set(context.local(), v8_str("obj2"), instance)
   11814               .FromJust());
   11815     v8::TryCatch try_catch(isolate);
   11816     Local<Value> value;
   11817     CHECK(!try_catch.HasCaught());
   11818 
   11819     // Call an object without call-as-function handler through the JS
   11820     value = CompileRun("obj2(28)");
   11821     CHECK(value.IsEmpty());
   11822     CHECK(try_catch.HasCaught());
   11823     String::Utf8Value exception_value1(try_catch.Exception());
   11824     // TODO(verwaest): Better message
   11825     CHECK_EQ(0, strcmp("TypeError: obj2 is not a function", *exception_value1));
   11826     try_catch.Reset();
   11827 
   11828     // Call an object without call-as-function handler through the API
   11829     value = CompileRun("obj2(28)");
   11830     v8::Local<Value> args[] = {v8_num(28)};
   11831     CHECK(
   11832         instance->CallAsFunction(context.local(), instance, 1, args).IsEmpty());
   11833     CHECK(try_catch.HasCaught());
   11834     String::Utf8Value exception_value2(try_catch.Exception());
   11835     CHECK_EQ(0,
   11836              strcmp("TypeError: object is not a function", *exception_value2));
   11837     try_catch.Reset();
   11838   }
   11839 
   11840   {
   11841     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11842     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   11843     instance_template->SetCallAsFunctionHandler(ThrowValue);
   11844     Local<v8::Object> instance = t->GetFunction(context.local())
   11845                                      .ToLocalChecked()
   11846                                      ->NewInstance(context.local())
   11847                                      .ToLocalChecked();
   11848     CHECK(context->Global()
   11849               ->Set(context.local(), v8_str("obj3"), instance)
   11850               .FromJust());
   11851     v8::TryCatch try_catch(isolate);
   11852     Local<Value> value;
   11853     CHECK(!try_catch.HasCaught());
   11854 
   11855     // Catch the exception which is thrown by call-as-function handler
   11856     value = CompileRun("obj3(22)");
   11857     CHECK(try_catch.HasCaught());
   11858     String::Utf8Value exception_value1(try_catch.Exception());
   11859     CHECK_EQ(0, strcmp("22", *exception_value1));
   11860     try_catch.Reset();
   11861 
   11862     v8::Local<Value> args[] = {v8_num(23)};
   11863     CHECK(
   11864         instance->CallAsFunction(context.local(), instance, 1, args).IsEmpty());
   11865     CHECK(try_catch.HasCaught());
   11866     String::Utf8Value exception_value2(try_catch.Exception());
   11867     CHECK_EQ(0, strcmp("23", *exception_value2));
   11868     try_catch.Reset();
   11869   }
   11870 
   11871   {
   11872     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11873     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   11874     instance_template->SetCallAsFunctionHandler(ReturnThis);
   11875     Local<v8::Object> instance = t->GetFunction(context.local())
   11876                                      .ToLocalChecked()
   11877                                      ->NewInstance(context.local())
   11878                                      .ToLocalChecked();
   11879 
   11880     Local<v8::Value> a1 =
   11881         instance->CallAsFunction(context.local(), v8::Undefined(isolate), 0,
   11882                                  NULL)
   11883             .ToLocalChecked();
   11884     CHECK(a1->StrictEquals(instance));
   11885     Local<v8::Value> a2 =
   11886         instance->CallAsFunction(context.local(), v8::Null(isolate), 0, NULL)
   11887             .ToLocalChecked();
   11888     CHECK(a2->StrictEquals(instance));
   11889     Local<v8::Value> a3 =
   11890         instance->CallAsFunction(context.local(), v8_num(42), 0, NULL)
   11891             .ToLocalChecked();
   11892     CHECK(a3->StrictEquals(instance));
   11893     Local<v8::Value> a4 =
   11894         instance->CallAsFunction(context.local(), v8_str("hello"), 0, NULL)
   11895             .ToLocalChecked();
   11896     CHECK(a4->StrictEquals(instance));
   11897     Local<v8::Value> a5 =
   11898         instance->CallAsFunction(context.local(), v8::True(isolate), 0, NULL)
   11899             .ToLocalChecked();
   11900     CHECK(a5->StrictEquals(instance));
   11901   }
   11902 
   11903   {
   11904     CompileRun(
   11905         "function ReturnThisSloppy() {"
   11906         "  return this;"
   11907         "}"
   11908         "function ReturnThisStrict() {"
   11909         "  'use strict';"
   11910         "  return this;"
   11911         "}");
   11912     Local<Function> ReturnThisSloppy = Local<Function>::Cast(
   11913         context->Global()
   11914             ->Get(context.local(), v8_str("ReturnThisSloppy"))
   11915             .ToLocalChecked());
   11916     Local<Function> ReturnThisStrict = Local<Function>::Cast(
   11917         context->Global()
   11918             ->Get(context.local(), v8_str("ReturnThisStrict"))
   11919             .ToLocalChecked());
   11920 
   11921     Local<v8::Value> a1 =
   11922         ReturnThisSloppy->CallAsFunction(context.local(),
   11923                                          v8::Undefined(isolate), 0, NULL)
   11924             .ToLocalChecked();
   11925     CHECK(a1->StrictEquals(context->Global()));
   11926     Local<v8::Value> a2 =
   11927         ReturnThisSloppy->CallAsFunction(context.local(), v8::Null(isolate), 0,
   11928                                          NULL)
   11929             .ToLocalChecked();
   11930     CHECK(a2->StrictEquals(context->Global()));
   11931     Local<v8::Value> a3 =
   11932         ReturnThisSloppy->CallAsFunction(context.local(), v8_num(42), 0, NULL)
   11933             .ToLocalChecked();
   11934     CHECK(a3->IsNumberObject());
   11935     CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
   11936     Local<v8::Value> a4 =
   11937         ReturnThisSloppy->CallAsFunction(context.local(), v8_str("hello"), 0,
   11938                                          NULL)
   11939             .ToLocalChecked();
   11940     CHECK(a4->IsStringObject());
   11941     CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
   11942     Local<v8::Value> a5 =
   11943         ReturnThisSloppy->CallAsFunction(context.local(), v8::True(isolate), 0,
   11944                                          NULL)
   11945             .ToLocalChecked();
   11946     CHECK(a5->IsBooleanObject());
   11947     CHECK(a5.As<v8::BooleanObject>()->ValueOf());
   11948 
   11949     Local<v8::Value> a6 =
   11950         ReturnThisStrict->CallAsFunction(context.local(),
   11951                                          v8::Undefined(isolate), 0, NULL)
   11952             .ToLocalChecked();
   11953     CHECK(a6->IsUndefined());
   11954     Local<v8::Value> a7 =
   11955         ReturnThisStrict->CallAsFunction(context.local(), v8::Null(isolate), 0,
   11956                                          NULL)
   11957             .ToLocalChecked();
   11958     CHECK(a7->IsNull());
   11959     Local<v8::Value> a8 =
   11960         ReturnThisStrict->CallAsFunction(context.local(), v8_num(42), 0, NULL)
   11961             .ToLocalChecked();
   11962     CHECK(a8->StrictEquals(v8_num(42)));
   11963     Local<v8::Value> a9 =
   11964         ReturnThisStrict->CallAsFunction(context.local(), v8_str("hello"), 0,
   11965                                          NULL)
   11966             .ToLocalChecked();
   11967     CHECK(a9->StrictEquals(v8_str("hello")));
   11968     Local<v8::Value> a10 =
   11969         ReturnThisStrict->CallAsFunction(context.local(), v8::True(isolate), 0,
   11970                                          NULL)
   11971             .ToLocalChecked();
   11972     CHECK(a10->StrictEquals(v8::True(isolate)));
   11973   }
   11974 }
   11975 
   11976 
   11977 // Check whether a non-function object is callable.
   11978 THREADED_TEST(CallableObject) {
   11979   LocalContext context;
   11980   v8::Isolate* isolate = context->GetIsolate();
   11981   v8::HandleScope scope(isolate);
   11982 
   11983   {
   11984     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   11985     instance_template->SetCallAsFunctionHandler(call_as_function);
   11986     Local<Object> instance =
   11987         instance_template->NewInstance(context.local()).ToLocalChecked();
   11988     v8::TryCatch try_catch(isolate);
   11989 
   11990     CHECK(instance->IsCallable());
   11991     CHECK(!try_catch.HasCaught());
   11992   }
   11993 
   11994   {
   11995     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   11996     Local<Object> instance =
   11997         instance_template->NewInstance(context.local()).ToLocalChecked();
   11998     v8::TryCatch try_catch(isolate);
   11999 
   12000     CHECK(!instance->IsCallable());
   12001     CHECK(!try_catch.HasCaught());
   12002   }
   12003 
   12004   {
   12005     Local<FunctionTemplate> function_template =
   12006         FunctionTemplate::New(isolate, call_as_function);
   12007     Local<Function> function =
   12008         function_template->GetFunction(context.local()).ToLocalChecked();
   12009     Local<Object> instance = function;
   12010     v8::TryCatch try_catch(isolate);
   12011 
   12012     CHECK(instance->IsCallable());
   12013     CHECK(!try_catch.HasCaught());
   12014   }
   12015 
   12016   {
   12017     Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
   12018     Local<Function> function =
   12019         function_template->GetFunction(context.local()).ToLocalChecked();
   12020     Local<Object> instance = function;
   12021     v8::TryCatch try_catch(isolate);
   12022 
   12023     CHECK(instance->IsCallable());
   12024     CHECK(!try_catch.HasCaught());
   12025   }
   12026 }
   12027 
   12028 
   12029 THREADED_TEST(Regress567998) {
   12030   LocalContext env;
   12031   v8::HandleScope scope(env->GetIsolate());
   12032 
   12033   Local<v8::FunctionTemplate> desc =
   12034       v8::FunctionTemplate::New(env->GetIsolate());
   12035   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   12036   desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis);  // callable
   12037 
   12038   Local<v8::Object> obj = desc->GetFunction(env.local())
   12039                               .ToLocalChecked()
   12040                               ->NewInstance(env.local())
   12041                               .ToLocalChecked();
   12042   CHECK(
   12043       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
   12044 
   12045   ExpectString("undetectable.toString()", "[object Object]");
   12046   ExpectString("typeof undetectable", "undefined");
   12047   ExpectString("typeof(undetectable)", "undefined");
   12048   ExpectBoolean("typeof undetectable == 'undefined'", true);
   12049   ExpectBoolean("typeof undetectable == 'object'", false);
   12050   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
   12051   ExpectBoolean("!undetectable", true);
   12052 
   12053   ExpectObject("true&&undetectable", obj);
   12054   ExpectBoolean("false&&undetectable", false);
   12055   ExpectBoolean("true||undetectable", true);
   12056   ExpectObject("false||undetectable", obj);
   12057 
   12058   ExpectObject("undetectable&&true", obj);
   12059   ExpectObject("undetectable&&false", obj);
   12060   ExpectBoolean("undetectable||true", true);
   12061   ExpectBoolean("undetectable||false", false);
   12062 
   12063   ExpectBoolean("undetectable==null", true);
   12064   ExpectBoolean("null==undetectable", true);
   12065   ExpectBoolean("undetectable==undefined", true);
   12066   ExpectBoolean("undefined==undetectable", true);
   12067   ExpectBoolean("undetectable==undetectable", true);
   12068 
   12069   ExpectBoolean("undetectable===null", false);
   12070   ExpectBoolean("null===undetectable", false);
   12071   ExpectBoolean("undetectable===undefined", false);
   12072   ExpectBoolean("undefined===undetectable", false);
   12073   ExpectBoolean("undetectable===undetectable", true);
   12074 }
   12075 
   12076 
   12077 static int Recurse(v8::Isolate* isolate, int depth, int iterations) {
   12078   v8::HandleScope scope(isolate);
   12079   if (depth == 0) return v8::HandleScope::NumberOfHandles(isolate);
   12080   for (int i = 0; i < iterations; i++) {
   12081     Local<v8::Number> n(v8::Integer::New(isolate, 42));
   12082   }
   12083   return Recurse(isolate, depth - 1, iterations);
   12084 }
   12085 
   12086 
   12087 THREADED_TEST(HandleIteration) {
   12088   static const int kIterations = 500;
   12089   static const int kNesting = 200;
   12090   LocalContext context;
   12091   v8::Isolate* isolate = context->GetIsolate();
   12092   v8::HandleScope scope0(isolate);
   12093   CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
   12094   {
   12095     v8::HandleScope scope1(isolate);
   12096     CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
   12097     for (int i = 0; i < kIterations; i++) {
   12098       Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
   12099       CHECK_EQ(i + 1, v8::HandleScope::NumberOfHandles(isolate));
   12100     }
   12101 
   12102     CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
   12103     {
   12104       v8::HandleScope scope2(CcTest::isolate());
   12105       for (int j = 0; j < kIterations; j++) {
   12106         Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
   12107         CHECK_EQ(j + 1 + kIterations,
   12108                  v8::HandleScope::NumberOfHandles(isolate));
   12109       }
   12110     }
   12111     CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
   12112   }
   12113   CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
   12114   CHECK_EQ(kNesting * kIterations, Recurse(isolate, kNesting, kIterations));
   12115 }
   12116 
   12117 
   12118 static void InterceptorCallICFastApi(
   12119     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   12120   ApiTestFuzzer::Fuzz();
   12121   CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
   12122   int* call_count =
   12123       reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
   12124   ++(*call_count);
   12125   if ((*call_count) % 20 == 0) {
   12126     CcTest::heap()->CollectAllGarbage();
   12127   }
   12128 }
   12129 
   12130 static void FastApiCallback_TrivialSignature(
   12131     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12132   ApiTestFuzzer::Fuzz();
   12133   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
   12134   v8::Isolate* isolate = CcTest::isolate();
   12135   CHECK_EQ(isolate, args.GetIsolate());
   12136   CHECK(args.This()
   12137             ->Equals(isolate->GetCurrentContext(), args.Holder())
   12138             .FromJust());
   12139   CHECK(args.Data()
   12140             ->Equals(isolate->GetCurrentContext(), v8_str("method_data"))
   12141             .FromJust());
   12142   args.GetReturnValue().Set(
   12143       args[0]->Int32Value(isolate->GetCurrentContext()).FromJust() + 1);
   12144 }
   12145 
   12146 static void FastApiCallback_SimpleSignature(
   12147     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12148   ApiTestFuzzer::Fuzz();
   12149   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
   12150   v8::Isolate* isolate = CcTest::isolate();
   12151   CHECK_EQ(isolate, args.GetIsolate());
   12152   CHECK(args.This()
   12153             ->GetPrototype()
   12154             ->Equals(isolate->GetCurrentContext(), args.Holder())
   12155             .FromJust());
   12156   CHECK(args.Data()
   12157             ->Equals(isolate->GetCurrentContext(), v8_str("method_data"))
   12158             .FromJust());
   12159   // Note, we're using HasRealNamedProperty instead of Has to avoid
   12160   // invoking the interceptor again.
   12161   CHECK(args.Holder()
   12162             ->HasRealNamedProperty(isolate->GetCurrentContext(), v8_str("foo"))
   12163             .FromJust());
   12164   args.GetReturnValue().Set(
   12165       args[0]->Int32Value(isolate->GetCurrentContext()).FromJust() + 1);
   12166 }
   12167 
   12168 
   12169 // Helper to maximize the odds of object moving.
   12170 static void GenerateSomeGarbage() {
   12171   CompileRun(
   12172       "var garbage;"
   12173       "for (var i = 0; i < 1000; i++) {"
   12174       "  garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
   12175       "}"
   12176       "garbage = undefined;");
   12177 }
   12178 
   12179 
   12180 void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   12181   static int count = 0;
   12182   if (count++ % 3 == 0) {
   12183     CcTest::heap()->CollectAllGarbage();
   12184         // This should move the stub
   12185     GenerateSomeGarbage();  // This should ensure the old stub memory is flushed
   12186   }
   12187 }
   12188 
   12189 
   12190 THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
   12191   LocalContext context;
   12192   v8::Isolate* isolate = context->GetIsolate();
   12193   v8::HandleScope scope(isolate);
   12194   v8::Local<v8::ObjectTemplate> nativeobject_templ =
   12195       v8::ObjectTemplate::New(isolate);
   12196   nativeobject_templ->Set(isolate, "callback",
   12197                           v8::FunctionTemplate::New(isolate,
   12198                                                     DirectApiCallback));
   12199   v8::Local<v8::Object> nativeobject_obj =
   12200       nativeobject_templ->NewInstance(context.local()).ToLocalChecked();
   12201   CHECK(context->Global()
   12202             ->Set(context.local(), v8_str("nativeobject"), nativeobject_obj)
   12203             .FromJust());
   12204   // call the api function multiple times to ensure direct call stub creation.
   12205   CompileRun(
   12206         "function f() {"
   12207         "  for (var i = 1; i <= 30; i++) {"
   12208         "    nativeobject.callback();"
   12209         "  }"
   12210         "}"
   12211         "f();");
   12212 }
   12213 
   12214 
   12215 void ThrowingDirectApiCallback(
   12216     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12217   args.GetIsolate()->ThrowException(v8_str("g"));
   12218 }
   12219 
   12220 
   12221 THREADED_TEST(CallICFastApi_DirectCall_Throw) {
   12222   LocalContext context;
   12223   v8::Isolate* isolate = context->GetIsolate();
   12224   v8::HandleScope scope(isolate);
   12225   v8::Local<v8::ObjectTemplate> nativeobject_templ =
   12226       v8::ObjectTemplate::New(isolate);
   12227   nativeobject_templ->Set(isolate, "callback",
   12228                           v8::FunctionTemplate::New(isolate,
   12229                                                     ThrowingDirectApiCallback));
   12230   v8::Local<v8::Object> nativeobject_obj =
   12231       nativeobject_templ->NewInstance(context.local()).ToLocalChecked();
   12232   CHECK(context->Global()
   12233             ->Set(context.local(), v8_str("nativeobject"), nativeobject_obj)
   12234             .FromJust());
   12235   // call the api function multiple times to ensure direct call stub creation.
   12236   v8::Local<Value> result = CompileRun(
   12237       "var result = '';"
   12238       "function f() {"
   12239       "  for (var i = 1; i <= 5; i++) {"
   12240       "    try { nativeobject.callback(); } catch (e) { result += e; }"
   12241       "  }"
   12242       "}"
   12243       "f(); result;");
   12244   CHECK(v8_str("ggggg")->Equals(context.local(), result).FromJust());
   12245 }
   12246 
   12247 
   12248 static int p_getter_count_3;
   12249 
   12250 
   12251 static Local<Value> DoDirectGetter() {
   12252   if (++p_getter_count_3 % 3 == 0) {
   12253     CcTest::heap()->CollectAllGarbage();
   12254     GenerateSomeGarbage();
   12255   }
   12256   return v8_str("Direct Getter Result");
   12257 }
   12258 
   12259 
   12260 static void DirectGetterCallback(
   12261     Local<String> name,
   12262     const v8::PropertyCallbackInfo<v8::Value>& info) {
   12263   CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
   12264   info.GetReturnValue().Set(DoDirectGetter());
   12265 }
   12266 
   12267 
   12268 template<typename Accessor>
   12269 static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
   12270   LocalContext context;
   12271   v8::Isolate* isolate = context->GetIsolate();
   12272   v8::HandleScope scope(isolate);
   12273   v8::Local<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
   12274   obj->SetAccessor(v8_str("p1"), accessor);
   12275   CHECK(context->Global()
   12276             ->Set(context.local(), v8_str("o1"),
   12277                   obj->NewInstance(context.local()).ToLocalChecked())
   12278             .FromJust());
   12279   p_getter_count_3 = 0;
   12280   v8::Local<v8::Value> result = CompileRun(
   12281       "function f() {"
   12282       "  for (var i = 0; i < 30; i++) o1.p1;"
   12283       "  return o1.p1"
   12284       "}"
   12285       "f();");
   12286   CHECK(v8_str("Direct Getter Result")
   12287             ->Equals(context.local(), result)
   12288             .FromJust());
   12289   CHECK_EQ(31, p_getter_count_3);
   12290 }
   12291 
   12292 
   12293 THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
   12294   LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
   12295 }
   12296 
   12297 
   12298 void ThrowingDirectGetterCallback(
   12299     Local<String> name,
   12300     const v8::PropertyCallbackInfo<v8::Value>& info) {
   12301   info.GetIsolate()->ThrowException(v8_str("g"));
   12302 }
   12303 
   12304 
   12305 THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
   12306   LocalContext context;
   12307   v8::Isolate* isolate = context->GetIsolate();
   12308   v8::HandleScope scope(isolate);
   12309   v8::Local<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
   12310   obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
   12311   CHECK(context->Global()
   12312             ->Set(context.local(), v8_str("o1"),
   12313                   obj->NewInstance(context.local()).ToLocalChecked())
   12314             .FromJust());
   12315   v8::Local<Value> result = CompileRun(
   12316       "var result = '';"
   12317       "for (var i = 0; i < 5; i++) {"
   12318       "    try { o1.p1; } catch (e) { result += e; }"
   12319       "}"
   12320       "result;");
   12321   CHECK(v8_str("ggggg")->Equals(context.local(), result).FromJust());
   12322 }
   12323 
   12324 
   12325 THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
   12326   int interceptor_call_count = 0;
   12327   v8::Isolate* isolate = CcTest::isolate();
   12328   v8::HandleScope scope(isolate);
   12329   v8::Local<v8::FunctionTemplate> fun_templ =
   12330       v8::FunctionTemplate::New(isolate);
   12331   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12332       isolate, FastApiCallback_TrivialSignature, v8_str("method_data"),
   12333       v8::Local<v8::Signature>());
   12334   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12335   proto_templ->Set(v8_str("method"), method_templ);
   12336   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12337   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12338       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
   12339       v8::External::New(isolate, &interceptor_call_count)));
   12340   LocalContext context;
   12341   v8::Local<v8::Function> fun =
   12342       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12343   GenerateSomeGarbage();
   12344   CHECK(context->Global()
   12345             ->Set(context.local(), v8_str("o"),
   12346                   fun->NewInstance(context.local()).ToLocalChecked())
   12347             .FromJust());
   12348   CompileRun(
   12349       "var result = 0;"
   12350       "for (var i = 0; i < 100; i++) {"
   12351       "  result = o.method(41);"
   12352       "}");
   12353   CHECK_EQ(42, context->Global()
   12354                    ->Get(context.local(), v8_str("result"))
   12355                    .ToLocalChecked()
   12356                    ->Int32Value(context.local())
   12357                    .FromJust());
   12358   CHECK_EQ(100, interceptor_call_count);
   12359 }
   12360 
   12361 
   12362 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
   12363   int interceptor_call_count = 0;
   12364   v8::Isolate* isolate = CcTest::isolate();
   12365   v8::HandleScope scope(isolate);
   12366   v8::Local<v8::FunctionTemplate> fun_templ =
   12367       v8::FunctionTemplate::New(isolate);
   12368   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12369       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12370       v8::Signature::New(isolate, fun_templ));
   12371   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12372   proto_templ->Set(v8_str("method"), method_templ);
   12373   fun_templ->SetHiddenPrototype(true);
   12374   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12375   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12376       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
   12377       v8::External::New(isolate, &interceptor_call_count)));
   12378   LocalContext context;
   12379   v8::Local<v8::Function> fun =
   12380       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12381   GenerateSomeGarbage();
   12382   CHECK(context->Global()
   12383             ->Set(context.local(), v8_str("o"),
   12384                   fun->NewInstance(context.local()).ToLocalChecked())
   12385             .FromJust());
   12386   CompileRun(
   12387       "o.foo = 17;"
   12388       "var receiver = {};"
   12389       "receiver.__proto__ = o;"
   12390       "var result = 0;"
   12391       "for (var i = 0; i < 100; i++) {"
   12392       "  result = receiver.method(41);"
   12393       "}");
   12394   CHECK_EQ(42, context->Global()
   12395                    ->Get(context.local(), v8_str("result"))
   12396                    .ToLocalChecked()
   12397                    ->Int32Value(context.local())
   12398                    .FromJust());
   12399   CHECK_EQ(100, interceptor_call_count);
   12400 }
   12401 
   12402 
   12403 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
   12404   int interceptor_call_count = 0;
   12405   v8::Isolate* isolate = CcTest::isolate();
   12406   v8::HandleScope scope(isolate);
   12407   v8::Local<v8::FunctionTemplate> fun_templ =
   12408       v8::FunctionTemplate::New(isolate);
   12409   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12410       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12411       v8::Signature::New(isolate, fun_templ));
   12412   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12413   proto_templ->Set(v8_str("method"), method_templ);
   12414   fun_templ->SetHiddenPrototype(true);
   12415   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12416   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12417       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
   12418       v8::External::New(isolate, &interceptor_call_count)));
   12419   LocalContext context;
   12420   v8::Local<v8::Function> fun =
   12421       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12422   GenerateSomeGarbage();
   12423   CHECK(context->Global()
   12424             ->Set(context.local(), v8_str("o"),
   12425                   fun->NewInstance(context.local()).ToLocalChecked())
   12426             .FromJust());
   12427   CompileRun(
   12428       "o.foo = 17;"
   12429       "var receiver = {};"
   12430       "receiver.__proto__ = o;"
   12431       "var result = 0;"
   12432       "var saved_result = 0;"
   12433       "for (var i = 0; i < 100; i++) {"
   12434       "  result = receiver.method(41);"
   12435       "  if (i == 50) {"
   12436       "    saved_result = result;"
   12437       "    receiver = {method: function(x) { return x - 1 }};"
   12438       "  }"
   12439       "}");
   12440   CHECK_EQ(40, context->Global()
   12441                    ->Get(context.local(), v8_str("result"))
   12442                    .ToLocalChecked()
   12443                    ->Int32Value(context.local())
   12444                    .FromJust());
   12445   CHECK_EQ(42, context->Global()
   12446                    ->Get(context.local(), v8_str("saved_result"))
   12447                    .ToLocalChecked()
   12448                    ->Int32Value(context.local())
   12449                    .FromJust());
   12450   CHECK_GE(interceptor_call_count, 50);
   12451 }
   12452 
   12453 
   12454 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
   12455   int interceptor_call_count = 0;
   12456   v8::Isolate* isolate = CcTest::isolate();
   12457   v8::HandleScope scope(isolate);
   12458   v8::Local<v8::FunctionTemplate> fun_templ =
   12459       v8::FunctionTemplate::New(isolate);
   12460   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12461       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12462       v8::Signature::New(isolate, fun_templ));
   12463   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12464   proto_templ->Set(v8_str("method"), method_templ);
   12465   fun_templ->SetHiddenPrototype(true);
   12466   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12467   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12468       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
   12469       v8::External::New(isolate, &interceptor_call_count)));
   12470   LocalContext context;
   12471   v8::Local<v8::Function> fun =
   12472       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12473   GenerateSomeGarbage();
   12474   CHECK(context->Global()
   12475             ->Set(context.local(), v8_str("o"),
   12476                   fun->NewInstance(context.local()).ToLocalChecked())
   12477             .FromJust());
   12478   CompileRun(
   12479       "o.foo = 17;"
   12480       "var receiver = {};"
   12481       "receiver.__proto__ = o;"
   12482       "var result = 0;"
   12483       "var saved_result = 0;"
   12484       "for (var i = 0; i < 100; i++) {"
   12485       "  result = receiver.method(41);"
   12486       "  if (i == 50) {"
   12487       "    saved_result = result;"
   12488       "    o.method = function(x) { return x - 1 };"
   12489       "  }"
   12490       "}");
   12491   CHECK_EQ(40, context->Global()
   12492                    ->Get(context.local(), v8_str("result"))
   12493                    .ToLocalChecked()
   12494                    ->Int32Value(context.local())
   12495                    .FromJust());
   12496   CHECK_EQ(42, context->Global()
   12497                    ->Get(context.local(), v8_str("saved_result"))
   12498                    .ToLocalChecked()
   12499                    ->Int32Value(context.local())
   12500                    .FromJust());
   12501   CHECK_GE(interceptor_call_count, 50);
   12502 }
   12503 
   12504 
   12505 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
   12506   int interceptor_call_count = 0;
   12507   v8::Isolate* isolate = CcTest::isolate();
   12508   v8::HandleScope scope(isolate);
   12509   v8::Local<v8::FunctionTemplate> fun_templ =
   12510       v8::FunctionTemplate::New(isolate);
   12511   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12512       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12513       v8::Signature::New(isolate, fun_templ));
   12514   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12515   proto_templ->Set(v8_str("method"), method_templ);
   12516   fun_templ->SetHiddenPrototype(true);
   12517   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12518   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12519       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
   12520       v8::External::New(isolate, &interceptor_call_count)));
   12521   LocalContext context;
   12522   v8::Local<v8::Function> fun =
   12523       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12524   GenerateSomeGarbage();
   12525   CHECK(context->Global()
   12526             ->Set(context.local(), v8_str("o"),
   12527                   fun->NewInstance(context.local()).ToLocalChecked())
   12528             .FromJust());
   12529   v8::TryCatch try_catch(isolate);
   12530   CompileRun(
   12531       "o.foo = 17;"
   12532       "var receiver = {};"
   12533       "receiver.__proto__ = o;"
   12534       "var result = 0;"
   12535       "var saved_result = 0;"
   12536       "for (var i = 0; i < 100; i++) {"
   12537       "  result = receiver.method(41);"
   12538       "  if (i == 50) {"
   12539       "    saved_result = result;"
   12540       "    receiver = 333;"
   12541       "  }"
   12542       "}");
   12543   CHECK(try_catch.HasCaught());
   12544   // TODO(verwaest): Adjust message.
   12545   CHECK(
   12546       v8_str("TypeError: receiver.method is not a function")
   12547           ->Equals(
   12548               context.local(),
   12549               try_catch.Exception()->ToString(context.local()).ToLocalChecked())
   12550           .FromJust());
   12551   CHECK_EQ(42, context->Global()
   12552                    ->Get(context.local(), v8_str("saved_result"))
   12553                    .ToLocalChecked()
   12554                    ->Int32Value(context.local())
   12555                    .FromJust());
   12556   CHECK_GE(interceptor_call_count, 50);
   12557 }
   12558 
   12559 
   12560 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
   12561   int interceptor_call_count = 0;
   12562   v8::Isolate* isolate = CcTest::isolate();
   12563   v8::HandleScope scope(isolate);
   12564   v8::Local<v8::FunctionTemplate> fun_templ =
   12565       v8::FunctionTemplate::New(isolate);
   12566   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12567       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12568       v8::Signature::New(isolate, fun_templ));
   12569   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12570   proto_templ->Set(v8_str("method"), method_templ);
   12571   fun_templ->SetHiddenPrototype(true);
   12572   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12573   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12574       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
   12575       v8::External::New(isolate, &interceptor_call_count)));
   12576   LocalContext context;
   12577   v8::Local<v8::Function> fun =
   12578       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12579   GenerateSomeGarbage();
   12580   CHECK(context->Global()
   12581             ->Set(context.local(), v8_str("o"),
   12582                   fun->NewInstance(context.local()).ToLocalChecked())
   12583             .FromJust());
   12584   v8::TryCatch try_catch(isolate);
   12585   CompileRun(
   12586       "o.foo = 17;"
   12587       "var receiver = {};"
   12588       "receiver.__proto__ = o;"
   12589       "var result = 0;"
   12590       "var saved_result = 0;"
   12591       "for (var i = 0; i < 100; i++) {"
   12592       "  result = receiver.method(41);"
   12593       "  if (i == 50) {"
   12594       "    saved_result = result;"
   12595       "    receiver = {method: receiver.method};"
   12596       "  }"
   12597       "}");
   12598   CHECK(try_catch.HasCaught());
   12599   CHECK(
   12600       v8_str("TypeError: Illegal invocation")
   12601           ->Equals(
   12602               context.local(),
   12603               try_catch.Exception()->ToString(context.local()).ToLocalChecked())
   12604           .FromJust());
   12605   CHECK_EQ(42, context->Global()
   12606                    ->Get(context.local(), v8_str("saved_result"))
   12607                    .ToLocalChecked()
   12608                    ->Int32Value(context.local())
   12609                    .FromJust());
   12610   CHECK_GE(interceptor_call_count, 50);
   12611 }
   12612 
   12613 
   12614 THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
   12615   v8::Isolate* isolate = CcTest::isolate();
   12616   v8::HandleScope scope(isolate);
   12617   v8::Local<v8::FunctionTemplate> fun_templ =
   12618       v8::FunctionTemplate::New(isolate);
   12619   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12620       isolate, FastApiCallback_TrivialSignature, v8_str("method_data"),
   12621       v8::Local<v8::Signature>());
   12622   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12623   proto_templ->Set(v8_str("method"), method_templ);
   12624   v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12625   USE(templ);
   12626   LocalContext context;
   12627   v8::Local<v8::Function> fun =
   12628       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12629   GenerateSomeGarbage();
   12630   CHECK(context->Global()
   12631             ->Set(context.local(), v8_str("o"),
   12632                   fun->NewInstance(context.local()).ToLocalChecked())
   12633             .FromJust());
   12634   CompileRun(
   12635       "var result = 0;"
   12636       "for (var i = 0; i < 100; i++) {"
   12637       "  result = o.method(41);"
   12638       "}");
   12639 
   12640   CHECK_EQ(42, context->Global()
   12641                    ->Get(context.local(), v8_str("result"))
   12642                    .ToLocalChecked()
   12643                    ->Int32Value(context.local())
   12644                    .FromJust());
   12645 }
   12646 
   12647 
   12648 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
   12649   v8::Isolate* isolate = CcTest::isolate();
   12650   v8::HandleScope scope(isolate);
   12651   v8::Local<v8::FunctionTemplate> fun_templ =
   12652       v8::FunctionTemplate::New(isolate);
   12653   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12654       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12655       v8::Signature::New(isolate, fun_templ));
   12656   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12657   proto_templ->Set(v8_str("method"), method_templ);
   12658   fun_templ->SetHiddenPrototype(true);
   12659   v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12660   CHECK(!templ.IsEmpty());
   12661   LocalContext context;
   12662   v8::Local<v8::Function> fun =
   12663       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12664   GenerateSomeGarbage();
   12665   CHECK(context->Global()
   12666             ->Set(context.local(), v8_str("o"),
   12667                   fun->NewInstance(context.local()).ToLocalChecked())
   12668             .FromJust());
   12669   CompileRun(
   12670       "o.foo = 17;"
   12671       "var receiver = {};"
   12672       "receiver.__proto__ = o;"
   12673       "var result = 0;"
   12674       "for (var i = 0; i < 100; i++) {"
   12675       "  result = receiver.method(41);"
   12676       "}");
   12677 
   12678   CHECK_EQ(42, context->Global()
   12679                    ->Get(context.local(), v8_str("result"))
   12680                    .ToLocalChecked()
   12681                    ->Int32Value(context.local())
   12682                    .FromJust());
   12683 }
   12684 
   12685 
   12686 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
   12687   v8::Isolate* isolate = CcTest::isolate();
   12688   v8::HandleScope scope(isolate);
   12689   v8::Local<v8::FunctionTemplate> fun_templ =
   12690       v8::FunctionTemplate::New(isolate);
   12691   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12692       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12693       v8::Signature::New(isolate, fun_templ));
   12694   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12695   proto_templ->Set(v8_str("method"), method_templ);
   12696   fun_templ->SetHiddenPrototype(true);
   12697   v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12698   CHECK(!templ.IsEmpty());
   12699   LocalContext context;
   12700   v8::Local<v8::Function> fun =
   12701       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12702   GenerateSomeGarbage();
   12703   CHECK(context->Global()
   12704             ->Set(context.local(), v8_str("o"),
   12705                   fun->NewInstance(context.local()).ToLocalChecked())
   12706             .FromJust());
   12707   CompileRun(
   12708       "o.foo = 17;"
   12709       "var receiver = {};"
   12710       "receiver.__proto__ = o;"
   12711       "var result = 0;"
   12712       "var saved_result = 0;"
   12713       "for (var i = 0; i < 100; i++) {"
   12714       "  result = receiver.method(41);"
   12715       "  if (i == 50) {"
   12716       "    saved_result = result;"
   12717       "    receiver = {method: function(x) { return x - 1 }};"
   12718       "  }"
   12719       "}");
   12720   CHECK_EQ(40, context->Global()
   12721                    ->Get(context.local(), v8_str("result"))
   12722                    .ToLocalChecked()
   12723                    ->Int32Value(context.local())
   12724                    .FromJust());
   12725   CHECK_EQ(42, context->Global()
   12726                    ->Get(context.local(), v8_str("saved_result"))
   12727                    .ToLocalChecked()
   12728                    ->Int32Value(context.local())
   12729                    .FromJust());
   12730 }
   12731 
   12732 
   12733 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
   12734   v8::Isolate* isolate = CcTest::isolate();
   12735   v8::HandleScope scope(isolate);
   12736   v8::Local<v8::FunctionTemplate> fun_templ =
   12737       v8::FunctionTemplate::New(isolate);
   12738   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12739       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12740       v8::Signature::New(isolate, fun_templ));
   12741   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12742   proto_templ->Set(v8_str("method"), method_templ);
   12743   fun_templ->SetHiddenPrototype(true);
   12744   v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12745   CHECK(!templ.IsEmpty());
   12746   LocalContext context;
   12747   v8::Local<v8::Function> fun =
   12748       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12749   GenerateSomeGarbage();
   12750   CHECK(context->Global()
   12751             ->Set(context.local(), v8_str("o"),
   12752                   fun->NewInstance(context.local()).ToLocalChecked())
   12753             .FromJust());
   12754   v8::TryCatch try_catch(isolate);
   12755   CompileRun(
   12756       "o.foo = 17;"
   12757       "var receiver = {};"
   12758       "receiver.__proto__ = o;"
   12759       "var result = 0;"
   12760       "var saved_result = 0;"
   12761       "for (var i = 0; i < 100; i++) {"
   12762       "  result = receiver.method(41);"
   12763       "  if (i == 50) {"
   12764       "    saved_result = result;"
   12765       "    receiver = 333;"
   12766       "  }"
   12767       "}");
   12768   CHECK(try_catch.HasCaught());
   12769   // TODO(verwaest): Adjust message.
   12770   CHECK(
   12771       v8_str("TypeError: receiver.method is not a function")
   12772           ->Equals(
   12773               context.local(),
   12774               try_catch.Exception()->ToString(context.local()).ToLocalChecked())
   12775           .FromJust());
   12776   CHECK_EQ(42, context->Global()
   12777                    ->Get(context.local(), v8_str("saved_result"))
   12778                    .ToLocalChecked()
   12779                    ->Int32Value(context.local())
   12780                    .FromJust());
   12781 }
   12782 
   12783 
   12784 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
   12785   v8::Isolate* isolate = CcTest::isolate();
   12786   v8::HandleScope scope(isolate);
   12787   v8::Local<v8::FunctionTemplate> fun_templ =
   12788       v8::FunctionTemplate::New(isolate);
   12789   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12790       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12791       v8::Signature::New(isolate, fun_templ));
   12792   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12793   proto_templ->Set(v8_str("method"), method_templ);
   12794   fun_templ->SetHiddenPrototype(true);
   12795   v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12796   CHECK(!templ.IsEmpty());
   12797   LocalContext context;
   12798   v8::Local<v8::Function> fun =
   12799       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12800   GenerateSomeGarbage();
   12801   CHECK(context->Global()
   12802             ->Set(context.local(), v8_str("o"),
   12803                   fun->NewInstance(context.local()).ToLocalChecked())
   12804             .FromJust());
   12805   v8::TryCatch try_catch(isolate);
   12806   CompileRun(
   12807       "o.foo = 17;"
   12808       "var receiver = {};"
   12809       "receiver.__proto__ = o;"
   12810       "var result = 0;"
   12811       "var saved_result = 0;"
   12812       "for (var i = 0; i < 100; i++) {"
   12813       "  result = receiver.method(41);"
   12814       "  if (i == 50) {"
   12815       "    saved_result = result;"
   12816       "    receiver = Object.create(receiver);"
   12817       "  }"
   12818       "}");
   12819   CHECK(try_catch.HasCaught());
   12820   CHECK(
   12821       v8_str("TypeError: Illegal invocation")
   12822           ->Equals(
   12823               context.local(),
   12824               try_catch.Exception()->ToString(context.local()).ToLocalChecked())
   12825           .FromJust());
   12826   CHECK_EQ(42, context->Global()
   12827                    ->Get(context.local(), v8_str("saved_result"))
   12828                    .ToLocalChecked()
   12829                    ->Int32Value(context.local())
   12830                    .FromJust());
   12831 }
   12832 
   12833 
   12834 static void ThrowingGetter(Local<String> name,
   12835                            const v8::PropertyCallbackInfo<v8::Value>& info) {
   12836   ApiTestFuzzer::Fuzz();
   12837   info.GetIsolate()->ThrowException(Local<Value>());
   12838   info.GetReturnValue().SetUndefined();
   12839 }
   12840 
   12841 
   12842 THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
   12843   LocalContext context;
   12844   HandleScope scope(context->GetIsolate());
   12845 
   12846   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   12847   Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
   12848   instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
   12849 
   12850   Local<Object> instance = templ->GetFunction(context.local())
   12851                                .ToLocalChecked()
   12852                                ->NewInstance(context.local())
   12853                                .ToLocalChecked();
   12854 
   12855   Local<Object> another = Object::New(context->GetIsolate());
   12856   CHECK(another->SetPrototype(context.local(), instance).FromJust());
   12857 
   12858   Local<Object> with_js_getter = CompileRun(
   12859       "o = {};\n"
   12860       "o.__defineGetter__('f', function() { throw undefined; });\n"
   12861       "o\n").As<Object>();
   12862   CHECK(!with_js_getter.IsEmpty());
   12863 
   12864   TryCatch try_catch(context->GetIsolate());
   12865 
   12866   v8::MaybeLocal<Value> result =
   12867       instance->GetRealNamedProperty(context.local(), v8_str("f"));
   12868   CHECK(try_catch.HasCaught());
   12869   try_catch.Reset();
   12870   CHECK(result.IsEmpty());
   12871 
   12872   Maybe<PropertyAttribute> attr =
   12873       instance->GetRealNamedPropertyAttributes(context.local(), v8_str("f"));
   12874   CHECK(!try_catch.HasCaught());
   12875   CHECK(Just(None) == attr);
   12876 
   12877   result = another->GetRealNamedProperty(context.local(), v8_str("f"));
   12878   CHECK(try_catch.HasCaught());
   12879   try_catch.Reset();
   12880   CHECK(result.IsEmpty());
   12881 
   12882   attr = another->GetRealNamedPropertyAttributes(context.local(), v8_str("f"));
   12883   CHECK(!try_catch.HasCaught());
   12884   CHECK(Just(None) == attr);
   12885 
   12886   result = another->GetRealNamedPropertyInPrototypeChain(context.local(),
   12887                                                          v8_str("f"));
   12888   CHECK(try_catch.HasCaught());
   12889   try_catch.Reset();
   12890   CHECK(result.IsEmpty());
   12891 
   12892   attr = another->GetRealNamedPropertyAttributesInPrototypeChain(
   12893       context.local(), v8_str("f"));
   12894   CHECK(!try_catch.HasCaught());
   12895   CHECK(Just(None) == attr);
   12896 
   12897   result = another->Get(context.local(), v8_str("f"));
   12898   CHECK(try_catch.HasCaught());
   12899   try_catch.Reset();
   12900   CHECK(result.IsEmpty());
   12901 
   12902   result = with_js_getter->GetRealNamedProperty(context.local(), v8_str("f"));
   12903   CHECK(try_catch.HasCaught());
   12904   try_catch.Reset();
   12905   CHECK(result.IsEmpty());
   12906 
   12907   attr = with_js_getter->GetRealNamedPropertyAttributes(context.local(),
   12908                                                         v8_str("f"));
   12909   CHECK(!try_catch.HasCaught());
   12910   CHECK(Just(None) == attr);
   12911 
   12912   result = with_js_getter->Get(context.local(), v8_str("f"));
   12913   CHECK(try_catch.HasCaught());
   12914   try_catch.Reset();
   12915   CHECK(result.IsEmpty());
   12916 
   12917   Local<Object> target = CompileRun("({})").As<Object>();
   12918   Local<Object> handler = CompileRun("({})").As<Object>();
   12919   Local<v8::Proxy> proxy =
   12920       v8::Proxy::New(context.local(), target, handler).ToLocalChecked();
   12921 
   12922   result = target->GetRealNamedProperty(context.local(), v8_str("f"));
   12923   CHECK(!try_catch.HasCaught());
   12924   CHECK(result.IsEmpty());
   12925 
   12926   result = proxy->GetRealNamedProperty(context.local(), v8_str("f"));
   12927   CHECK(!try_catch.HasCaught());
   12928   CHECK(result.IsEmpty());
   12929 }
   12930 
   12931 
   12932 static void ThrowingCallbackWithTryCatch(
   12933     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12934   TryCatch try_catch(args.GetIsolate());
   12935   // Verboseness is important: it triggers message delivery which can call into
   12936   // external code.
   12937   try_catch.SetVerbose(true);
   12938   CompileRun("throw 'from JS';");
   12939   CHECK(try_catch.HasCaught());
   12940   CHECK(!CcTest::i_isolate()->has_pending_exception());
   12941   CHECK(!CcTest::i_isolate()->has_scheduled_exception());
   12942 }
   12943 
   12944 
   12945 static int call_depth;
   12946 
   12947 
   12948 static void WithTryCatch(Local<Message> message, Local<Value> data) {
   12949   TryCatch try_catch(CcTest::isolate());
   12950 }
   12951 
   12952 
   12953 static void ThrowFromJS(Local<Message> message, Local<Value> data) {
   12954   if (--call_depth) CompileRun("throw 'ThrowInJS';");
   12955 }
   12956 
   12957 
   12958 static void ThrowViaApi(Local<Message> message, Local<Value> data) {
   12959   if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
   12960 }
   12961 
   12962 
   12963 static void WebKitLike(Local<Message> message, Local<Value> data) {
   12964   Local<String> errorMessageString = message->Get();
   12965   CHECK(!errorMessageString.IsEmpty());
   12966   message->GetStackTrace();
   12967   message->GetScriptOrigin().ResourceName();
   12968 }
   12969 
   12970 
   12971 THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
   12972   LocalContext context;
   12973   v8::Isolate* isolate = context->GetIsolate();
   12974   HandleScope scope(isolate);
   12975 
   12976   Local<Function> func =
   12977       FunctionTemplate::New(isolate, ThrowingCallbackWithTryCatch)
   12978           ->GetFunction(context.local())
   12979           .ToLocalChecked();
   12980   CHECK(
   12981       context->Global()->Set(context.local(), v8_str("func"), func).FromJust());
   12982 
   12983   MessageCallback callbacks[] =
   12984       { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
   12985   for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
   12986     MessageCallback callback = callbacks[i];
   12987     if (callback != NULL) {
   12988       isolate->AddMessageListener(callback);
   12989     }
   12990     // Some small number to control number of times message handler should
   12991     // throw an exception.
   12992     call_depth = 5;
   12993     ExpectFalse(
   12994         "var thrown = false;\n"
   12995         "try { func(); } catch(e) { thrown = true; }\n"
   12996         "thrown\n");
   12997     if (callback != NULL) {
   12998       isolate->RemoveMessageListeners(callback);
   12999     }
   13000   }
   13001 }
   13002 
   13003 
   13004 static void ParentGetter(Local<String> name,
   13005                          const v8::PropertyCallbackInfo<v8::Value>& info) {
   13006   ApiTestFuzzer::Fuzz();
   13007   info.GetReturnValue().Set(v8_num(1));
   13008 }
   13009 
   13010 
   13011 static void ChildGetter(Local<String> name,
   13012                         const v8::PropertyCallbackInfo<v8::Value>& info) {
   13013   ApiTestFuzzer::Fuzz();
   13014   info.GetReturnValue().Set(v8_num(42));
   13015 }
   13016 
   13017 
   13018 THREADED_TEST(Overriding) {
   13019   LocalContext context;
   13020   v8::Isolate* isolate = context->GetIsolate();
   13021   v8::HandleScope scope(isolate);
   13022 
   13023   // Parent template.
   13024   Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
   13025   Local<ObjectTemplate> parent_instance_templ =
   13026       parent_templ->InstanceTemplate();
   13027   parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
   13028 
   13029   // Template that inherits from the parent template.
   13030   Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New(isolate);
   13031   Local<ObjectTemplate> child_instance_templ =
   13032       child_templ->InstanceTemplate();
   13033   child_templ->Inherit(parent_templ);
   13034   // Override 'f'.  The child version of 'f' should get called for child
   13035   // instances.
   13036   child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
   13037   // Add 'g' twice.  The 'g' added last should get called for instances.
   13038   child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
   13039   child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
   13040 
   13041   // Add 'h' as an accessor to the proto template with ReadOnly attributes
   13042   // so 'h' can be shadowed on the instance object.
   13043   Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
   13044   child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
   13045                                  v8::Local<Value>(), v8::DEFAULT, v8::ReadOnly);
   13046 
   13047   // Add 'i' as an accessor to the instance template with ReadOnly attributes
   13048   // but the attribute does not have effect because it is duplicated with
   13049   // NULL setter.
   13050   child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
   13051                                     v8::Local<Value>(), v8::DEFAULT,
   13052                                     v8::ReadOnly);
   13053 
   13054 
   13055   // Instantiate the child template.
   13056   Local<v8::Object> instance = child_templ->GetFunction(context.local())
   13057                                    .ToLocalChecked()
   13058                                    ->NewInstance(context.local())
   13059                                    .ToLocalChecked();
   13060 
   13061   // Check that the child function overrides the parent one.
   13062   CHECK(context->Global()
   13063             ->Set(context.local(), v8_str("o"), instance)
   13064             .FromJust());
   13065   Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
   13066   // Check that the 'g' that was added last is hit.
   13067   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   13068   value = v8_compile("o.g")->Run(context.local()).ToLocalChecked();
   13069   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   13070 
   13071   // Check that 'h' cannot be shadowed.
   13072   value = v8_compile("o.h = 3; o.h")->Run(context.local()).ToLocalChecked();
   13073   CHECK_EQ(1, value->Int32Value(context.local()).FromJust());
   13074 
   13075   // Check that 'i' cannot be shadowed or changed.
   13076   value = v8_compile("o.i = 3; o.i")->Run(context.local()).ToLocalChecked();
   13077   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   13078 }
   13079 
   13080 
   13081 static void ShouldThrowOnErrorGetter(
   13082     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   13083   ApiTestFuzzer::Fuzz();
   13084   v8::Isolate* isolate = info.GetIsolate();
   13085   Local<Boolean> should_throw_on_error =
   13086       Boolean::New(isolate, info.ShouldThrowOnError());
   13087   info.GetReturnValue().Set(should_throw_on_error);
   13088 }
   13089 
   13090 
   13091 template <typename T>
   13092 static void ShouldThrowOnErrorSetter(Local<Name> name, Local<v8::Value> value,
   13093                                      const v8::PropertyCallbackInfo<T>& info) {
   13094   ApiTestFuzzer::Fuzz();
   13095   v8::Isolate* isolate = info.GetIsolate();
   13096   auto context = isolate->GetCurrentContext();
   13097   Local<Boolean> should_throw_on_error_value =
   13098       Boolean::New(isolate, info.ShouldThrowOnError());
   13099   CHECK(context->Global()
   13100             ->Set(isolate->GetCurrentContext(), v8_str("should_throw_setter"),
   13101                   should_throw_on_error_value)
   13102             .FromJust());
   13103 }
   13104 
   13105 
   13106 THREADED_TEST(AccessorShouldThrowOnError) {
   13107   LocalContext context;
   13108   v8::Isolate* isolate = context->GetIsolate();
   13109   v8::HandleScope scope(isolate);
   13110   Local<Object> global = context->Global();
   13111 
   13112   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   13113   Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
   13114   instance_templ->SetAccessor(v8_str("f"), ShouldThrowOnErrorGetter,
   13115                               ShouldThrowOnErrorSetter<void>);
   13116 
   13117   Local<v8::Object> instance = templ->GetFunction(context.local())
   13118                                    .ToLocalChecked()
   13119                                    ->NewInstance(context.local())
   13120                                    .ToLocalChecked();
   13121 
   13122   CHECK(global->Set(context.local(), v8_str("o"), instance).FromJust());
   13123 
   13124   // SLOPPY mode
   13125   Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
   13126   CHECK(value->IsFalse());
   13127   v8_compile("o.f = 153")->Run(context.local()).ToLocalChecked();
   13128   value = global->Get(context.local(), v8_str("should_throw_setter"))
   13129               .ToLocalChecked();
   13130   CHECK(value->IsFalse());
   13131 
   13132   // STRICT mode
   13133   value = v8_compile("'use strict';o.f")->Run(context.local()).ToLocalChecked();
   13134   CHECK(value->IsFalse());
   13135   v8_compile("'use strict'; o.f = 153")->Run(context.local()).ToLocalChecked();
   13136   value = global->Get(context.local(), v8_str("should_throw_setter"))
   13137               .ToLocalChecked();
   13138   CHECK(value->IsTrue());
   13139 }
   13140 
   13141 
   13142 static void ShouldThrowOnErrorQuery(
   13143     Local<Name> name, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   13144   ApiTestFuzzer::Fuzz();
   13145   v8::Isolate* isolate = info.GetIsolate();
   13146   info.GetReturnValue().Set(v8::None);
   13147 
   13148   auto context = isolate->GetCurrentContext();
   13149   Local<Boolean> should_throw_on_error_value =
   13150       Boolean::New(isolate, info.ShouldThrowOnError());
   13151   CHECK(context->Global()
   13152             ->Set(isolate->GetCurrentContext(), v8_str("should_throw_query"),
   13153                   should_throw_on_error_value)
   13154             .FromJust());
   13155 }
   13156 
   13157 
   13158 static void ShouldThrowOnErrorDeleter(
   13159     Local<Name> name, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
   13160   ApiTestFuzzer::Fuzz();
   13161   v8::Isolate* isolate = info.GetIsolate();
   13162   info.GetReturnValue().Set(v8::True(isolate));
   13163 
   13164   auto context = isolate->GetCurrentContext();
   13165   Local<Boolean> should_throw_on_error_value =
   13166       Boolean::New(isolate, info.ShouldThrowOnError());
   13167   CHECK(context->Global()
   13168             ->Set(isolate->GetCurrentContext(), v8_str("should_throw_deleter"),
   13169                   should_throw_on_error_value)
   13170             .FromJust());
   13171 }
   13172 
   13173 
   13174 static void ShouldThrowOnErrorPropertyEnumerator(
   13175     const v8::PropertyCallbackInfo<v8::Array>& info) {
   13176   ApiTestFuzzer::Fuzz();
   13177   v8::Isolate* isolate = info.GetIsolate();
   13178   Local<v8::Array> names = v8::Array::New(isolate, 1);
   13179   CHECK(names->Set(isolate->GetCurrentContext(), names, v8_num(1)).FromJust());
   13180   info.GetReturnValue().Set(names);
   13181 
   13182   auto context = isolate->GetCurrentContext();
   13183   Local<Boolean> should_throw_on_error_value =
   13184       Boolean::New(isolate, info.ShouldThrowOnError());
   13185   CHECK(context->Global()
   13186             ->Set(isolate->GetCurrentContext(),
   13187                   v8_str("should_throw_enumerator"),
   13188                   should_throw_on_error_value)
   13189             .FromJust());
   13190 }
   13191 
   13192 
   13193 THREADED_TEST(InterceptorShouldThrowOnError) {
   13194   LocalContext context;
   13195   v8::Isolate* isolate = context->GetIsolate();
   13196   v8::HandleScope scope(isolate);
   13197   Local<Object> global = context->Global();
   13198 
   13199   auto interceptor_templ = v8::ObjectTemplate::New(isolate);
   13200   v8::NamedPropertyHandlerConfiguration handler(
   13201       ShouldThrowOnErrorGetter, ShouldThrowOnErrorSetter<Value>,
   13202       ShouldThrowOnErrorQuery, ShouldThrowOnErrorDeleter,
   13203       ShouldThrowOnErrorPropertyEnumerator);
   13204   interceptor_templ->SetHandler(handler);
   13205 
   13206   Local<v8::Object> instance =
   13207       interceptor_templ->NewInstance(context.local()).ToLocalChecked();
   13208 
   13209   CHECK(global->Set(context.local(), v8_str("o"), instance).FromJust());
   13210 
   13211   // SLOPPY mode
   13212   Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
   13213   CHECK(value->IsFalse());
   13214   v8_compile("o.f = 153")->Run(context.local()).ToLocalChecked();
   13215   value = global->Get(context.local(), v8_str("should_throw_setter"))
   13216               .ToLocalChecked();
   13217   CHECK(value->IsFalse());
   13218 
   13219   v8_compile("delete o.f")->Run(context.local()).ToLocalChecked();
   13220   value = global->Get(context.local(), v8_str("should_throw_deleter"))
   13221               .ToLocalChecked();
   13222   CHECK(value->IsFalse());
   13223 
   13224   v8_compile("Object.getOwnPropertyNames(o)")
   13225       ->Run(context.local())
   13226       .ToLocalChecked();
   13227   value = global->Get(context.local(), v8_str("should_throw_enumerator"))
   13228               .ToLocalChecked();
   13229   CHECK(value->IsFalse());
   13230 
   13231   // STRICT mode
   13232   value = v8_compile("'use strict';o.f")->Run(context.local()).ToLocalChecked();
   13233   CHECK(value->IsFalse());
   13234   v8_compile("'use strict'; o.f = 153")->Run(context.local()).ToLocalChecked();
   13235   value = global->Get(context.local(), v8_str("should_throw_setter"))
   13236               .ToLocalChecked();
   13237   CHECK(value->IsTrue());
   13238 
   13239   v8_compile("'use strict'; delete o.f")->Run(context.local()).ToLocalChecked();
   13240   value = global->Get(context.local(), v8_str("should_throw_deleter"))
   13241               .ToLocalChecked();
   13242   CHECK(value->IsTrue());
   13243 
   13244   v8_compile("'use strict'; Object.getOwnPropertyNames(o)")
   13245       ->Run(context.local())
   13246       .ToLocalChecked();
   13247   value = global->Get(context.local(), v8_str("should_throw_enumerator"))
   13248               .ToLocalChecked();
   13249   CHECK(value->IsFalse());
   13250 }
   13251 
   13252 
   13253 static void IsConstructHandler(
   13254     const v8::FunctionCallbackInfo<v8::Value>& args) {
   13255   ApiTestFuzzer::Fuzz();
   13256   args.GetReturnValue().Set(args.IsConstructCall());
   13257 }
   13258 
   13259 
   13260 THREADED_TEST(IsConstructCall) {
   13261   v8::Isolate* isolate = CcTest::isolate();
   13262   v8::HandleScope scope(isolate);
   13263 
   13264   // Function template with call handler.
   13265   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   13266   templ->SetCallHandler(IsConstructHandler);
   13267 
   13268   LocalContext context;
   13269 
   13270   CHECK(context->Global()
   13271             ->Set(context.local(), v8_str("f"),
   13272                   templ->GetFunction(context.local()).ToLocalChecked())
   13273             .FromJust());
   13274   Local<Value> value = v8_compile("f()")->Run(context.local()).ToLocalChecked();
   13275   CHECK(!value->BooleanValue(context.local()).FromJust());
   13276   value = v8_compile("new f()")->Run(context.local()).ToLocalChecked();
   13277   CHECK(value->BooleanValue(context.local()).FromJust());
   13278 }
   13279 
   13280 static void NewTargetHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13281   ApiTestFuzzer::Fuzz();
   13282   args.GetReturnValue().Set(args.NewTarget());
   13283 }
   13284 
   13285 THREADED_TEST(NewTargetHandler) {
   13286   v8::Isolate* isolate = CcTest::isolate();
   13287   v8::HandleScope scope(isolate);
   13288 
   13289   // Function template with call handler.
   13290   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   13291   templ->SetCallHandler(NewTargetHandler);
   13292 
   13293   LocalContext context;
   13294 
   13295   Local<Function> function =
   13296       templ->GetFunction(context.local()).ToLocalChecked();
   13297   CHECK(context->Global()
   13298             ->Set(context.local(), v8_str("f"), function)
   13299             .FromJust());
   13300   Local<Value> value = CompileRun("f()");
   13301   CHECK(value->IsUndefined());
   13302   value = CompileRun("new f()");
   13303   CHECK(value->IsFunction());
   13304   CHECK(value == function);
   13305   Local<Value> subclass = CompileRun("var g = class extends f { }; g");
   13306   CHECK(subclass->IsFunction());
   13307   value = CompileRun("new g()");
   13308   CHECK(value->IsFunction());
   13309   CHECK(value == subclass);
   13310   value = CompileRun("Reflect.construct(f, [], Array)");
   13311   CHECK(value->IsFunction());
   13312   CHECK(value ==
   13313         context->Global()
   13314             ->Get(context.local(), v8_str("Array"))
   13315             .ToLocalChecked());
   13316 }
   13317 
   13318 THREADED_TEST(ObjectProtoToString) {
   13319   v8::Isolate* isolate = CcTest::isolate();
   13320   v8::HandleScope scope(isolate);
   13321   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   13322   templ->SetClassName(v8_str("MyClass"));
   13323 
   13324   LocalContext context;
   13325 
   13326   Local<String> customized_tostring = v8_str("customized toString");
   13327 
   13328   // Replace Object.prototype.toString
   13329   v8_compile(
   13330       "Object.prototype.toString = function() {"
   13331       "  return 'customized toString';"
   13332       "}")
   13333       ->Run(context.local())
   13334       .ToLocalChecked();
   13335 
   13336   // Normal ToString call should call replaced Object.prototype.toString
   13337   Local<v8::Object> instance = templ->GetFunction(context.local())
   13338                                    .ToLocalChecked()
   13339                                    ->NewInstance(context.local())
   13340                                    .ToLocalChecked();
   13341   Local<String> value = instance->ToString(context.local()).ToLocalChecked();
   13342   CHECK(value->IsString() &&
   13343         value->Equals(context.local(), customized_tostring).FromJust());
   13344 
   13345   // ObjectProtoToString should not call replace toString function.
   13346   value = instance->ObjectProtoToString(context.local()).ToLocalChecked();
   13347   CHECK(value->IsString() &&
   13348         value->Equals(context.local(), v8_str("[object MyClass]")).FromJust());
   13349 
   13350   // Check global
   13351   value =
   13352       context->Global()->ObjectProtoToString(context.local()).ToLocalChecked();
   13353   CHECK(value->IsString() &&
   13354         value->Equals(context.local(), v8_str("[object Object]")).FromJust());
   13355 
   13356   // Check ordinary object
   13357   Local<Value> object =
   13358       v8_compile("new Object()")->Run(context.local()).ToLocalChecked();
   13359   value = object.As<v8::Object>()
   13360               ->ObjectProtoToString(context.local())
   13361               .ToLocalChecked();
   13362   CHECK(value->IsString() &&
   13363         value->Equals(context.local(), v8_str("[object Object]")).FromJust());
   13364 }
   13365 
   13366 
   13367 TEST(ObjectProtoToStringES6) {
   13368   LocalContext context;
   13369   v8::Isolate* isolate = CcTest::isolate();
   13370   v8::HandleScope scope(isolate);
   13371   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   13372   templ->SetClassName(v8_str("MyClass"));
   13373 
   13374   Local<String> customized_tostring = v8_str("customized toString");
   13375 
   13376   // Replace Object.prototype.toString
   13377   CompileRun(
   13378       "Object.prototype.toString = function() {"
   13379       "  return 'customized toString';"
   13380       "}");
   13381 
   13382   // Normal ToString call should call replaced Object.prototype.toString
   13383   Local<v8::Object> instance = templ->GetFunction(context.local())
   13384                                    .ToLocalChecked()
   13385                                    ->NewInstance(context.local())
   13386                                    .ToLocalChecked();
   13387   Local<String> value = instance->ToString(context.local()).ToLocalChecked();
   13388   CHECK(value->IsString() &&
   13389         value->Equals(context.local(), customized_tostring).FromJust());
   13390 
   13391   // ObjectProtoToString should not call replace toString function.
   13392   value = instance->ObjectProtoToString(context.local()).ToLocalChecked();
   13393   CHECK(value->IsString() &&
   13394         value->Equals(context.local(), v8_str("[object MyClass]")).FromJust());
   13395 
   13396   // Check global
   13397   value =
   13398       context->Global()->ObjectProtoToString(context.local()).ToLocalChecked();
   13399   CHECK(value->IsString() &&
   13400         value->Equals(context.local(), v8_str("[object Object]")).FromJust());
   13401 
   13402   // Check ordinary object
   13403   Local<Value> object = CompileRun("new Object()");
   13404   value = object.As<v8::Object>()
   13405               ->ObjectProtoToString(context.local())
   13406               .ToLocalChecked();
   13407   CHECK(value->IsString() &&
   13408         value->Equals(context.local(), v8_str("[object Object]")).FromJust());
   13409 
   13410   // Check that ES6 semantics using @@toStringTag work
   13411   Local<v8::Symbol> toStringTag = v8::Symbol::GetToStringTag(isolate);
   13412 
   13413 #define TEST_TOSTRINGTAG(type, tag, expected)                              \
   13414   do {                                                                     \
   13415     object = CompileRun("new " #type "()");                                \
   13416     CHECK(object.As<v8::Object>()                                          \
   13417               ->Set(context.local(), toStringTag, v8_str(#tag))            \
   13418               .FromJust());                                                \
   13419     value = object.As<v8::Object>()                                        \
   13420                 ->ObjectProtoToString(context.local())                     \
   13421                 .ToLocalChecked();                                         \
   13422     CHECK(value->IsString() &&                                             \
   13423           value->Equals(context.local(), v8_str("[object " #expected "]")) \
   13424               .FromJust());                                                \
   13425   } while (0)
   13426 
   13427   TEST_TOSTRINGTAG(Array, Object, Object);
   13428   TEST_TOSTRINGTAG(Object, Arguments, Arguments);
   13429   TEST_TOSTRINGTAG(Object, Array, Array);
   13430   TEST_TOSTRINGTAG(Object, Boolean, Boolean);
   13431   TEST_TOSTRINGTAG(Object, Date, Date);
   13432   TEST_TOSTRINGTAG(Object, Error, Error);
   13433   TEST_TOSTRINGTAG(Object, Function, Function);
   13434   TEST_TOSTRINGTAG(Object, Number, Number);
   13435   TEST_TOSTRINGTAG(Object, RegExp, RegExp);
   13436   TEST_TOSTRINGTAG(Object, String, String);
   13437   TEST_TOSTRINGTAG(Object, Foo, Foo);
   13438 
   13439 #undef TEST_TOSTRINGTAG
   13440 
   13441   Local<v8::RegExp> valueRegExp =
   13442       v8::RegExp::New(context.local(), v8_str("^$"), v8::RegExp::kNone)
   13443           .ToLocalChecked();
   13444   Local<Value> valueNumber = v8_num(123);
   13445   Local<v8::Symbol> valueSymbol = v8_symbol("TestSymbol");
   13446   Local<v8::Function> valueFunction =
   13447       CompileRun("(function fn() {})").As<v8::Function>();
   13448   Local<v8::Object> valueObject = v8::Object::New(v8::Isolate::GetCurrent());
   13449   Local<v8::Primitive> valueNull = v8::Null(v8::Isolate::GetCurrent());
   13450   Local<v8::Primitive> valueUndef = v8::Undefined(v8::Isolate::GetCurrent());
   13451 
   13452 #define TEST_TOSTRINGTAG(type, tagValue, expected)                         \
   13453   do {                                                                     \
   13454     object = CompileRun("new " #type "()");                                \
   13455     CHECK(object.As<v8::Object>()                                          \
   13456               ->Set(context.local(), toStringTag, tagValue)                \
   13457               .FromJust());                                                \
   13458     value = object.As<v8::Object>()                                        \
   13459                 ->ObjectProtoToString(context.local())                     \
   13460                 .ToLocalChecked();                                         \
   13461     CHECK(value->IsString() &&                                             \
   13462           value->Equals(context.local(), v8_str("[object " #expected "]")) \
   13463               .FromJust());                                                \
   13464   } while (0)
   13465 
   13466 #define TEST_TOSTRINGTAG_TYPES(tagValue)                    \
   13467   TEST_TOSTRINGTAG(Array, tagValue, Array);                 \
   13468   TEST_TOSTRINGTAG(Object, tagValue, Object);               \
   13469   TEST_TOSTRINGTAG(Function, tagValue, Function);           \
   13470   TEST_TOSTRINGTAG(Date, tagValue, Date);                   \
   13471   TEST_TOSTRINGTAG(RegExp, tagValue, RegExp);               \
   13472   TEST_TOSTRINGTAG(Error, tagValue, Error);                 \
   13473 
   13474   // Test non-String-valued @@toStringTag
   13475   TEST_TOSTRINGTAG_TYPES(valueRegExp);
   13476   TEST_TOSTRINGTAG_TYPES(valueNumber);
   13477   TEST_TOSTRINGTAG_TYPES(valueSymbol);
   13478   TEST_TOSTRINGTAG_TYPES(valueFunction);
   13479   TEST_TOSTRINGTAG_TYPES(valueObject);
   13480   TEST_TOSTRINGTAG_TYPES(valueNull);
   13481   TEST_TOSTRINGTAG_TYPES(valueUndef);
   13482 
   13483 #undef TEST_TOSTRINGTAG
   13484 #undef TEST_TOSTRINGTAG_TYPES
   13485 
   13486   // @@toStringTag getter throws
   13487   Local<Value> obj = v8::Object::New(isolate);
   13488   obj.As<v8::Object>()
   13489       ->SetAccessor(context.local(), toStringTag, ThrowingSymbolAccessorGetter)
   13490       .FromJust();
   13491   {
   13492     TryCatch try_catch(isolate);
   13493     CHECK(obj.As<v8::Object>()->ObjectProtoToString(context.local()).IsEmpty());
   13494     CHECK(try_catch.HasCaught());
   13495   }
   13496 
   13497   // @@toStringTag getter does not throw
   13498   obj = v8::Object::New(isolate);
   13499   obj.As<v8::Object>()
   13500       ->SetAccessor(context.local(), toStringTag,
   13501                     SymbolAccessorGetterReturnsDefault, 0, v8_str("Test"))
   13502       .FromJust();
   13503   {
   13504     TryCatch try_catch(isolate);
   13505     value = obj.As<v8::Object>()
   13506                 ->ObjectProtoToString(context.local())
   13507                 .ToLocalChecked();
   13508     CHECK(value->IsString() &&
   13509           value->Equals(context.local(), v8_str("[object Test]")).FromJust());
   13510     CHECK(!try_catch.HasCaught());
   13511   }
   13512 
   13513   // JS @@toStringTag value
   13514   obj = CompileRun("obj = {}; obj[Symbol.toStringTag] = 'Test'; obj");
   13515   {
   13516     TryCatch try_catch(isolate);
   13517     value = obj.As<v8::Object>()
   13518                 ->ObjectProtoToString(context.local())
   13519                 .ToLocalChecked();
   13520     CHECK(value->IsString() &&
   13521           value->Equals(context.local(), v8_str("[object Test]")).FromJust());
   13522     CHECK(!try_catch.HasCaught());
   13523   }
   13524 
   13525   // JS @@toStringTag getter throws
   13526   obj = CompileRun(
   13527       "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
   13528       "  get: function() { throw 'Test'; }"
   13529       "}); obj");
   13530   {
   13531     TryCatch try_catch(isolate);
   13532     CHECK(obj.As<v8::Object>()->ObjectProtoToString(context.local()).IsEmpty());
   13533     CHECK(try_catch.HasCaught());
   13534   }
   13535 
   13536   // JS @@toStringTag getter does not throw
   13537   obj = CompileRun(
   13538       "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
   13539       "  get: function() { return 'Test'; }"
   13540       "}); obj");
   13541   {
   13542     TryCatch try_catch(isolate);
   13543     value = obj.As<v8::Object>()
   13544                 ->ObjectProtoToString(context.local())
   13545                 .ToLocalChecked();
   13546     CHECK(value->IsString() &&
   13547           value->Equals(context.local(), v8_str("[object Test]")).FromJust());
   13548     CHECK(!try_catch.HasCaught());
   13549   }
   13550 }
   13551 
   13552 
   13553 THREADED_TEST(ObjectGetConstructorName) {
   13554   v8::Isolate* isolate = CcTest::isolate();
   13555   LocalContext context;
   13556   v8::HandleScope scope(isolate);
   13557   v8_compile(
   13558       "function Parent() {};"
   13559       "function Child() {};"
   13560       "Child.prototype = new Parent();"
   13561       "Child.prototype.constructor = Child;"
   13562       "var outer = { inner: (0, function() { }) };"
   13563       "var p = new Parent();"
   13564       "var c = new Child();"
   13565       "var x = new outer.inner();"
   13566       "var proto = Child.prototype;")
   13567       ->Run(context.local())
   13568       .ToLocalChecked();
   13569 
   13570   Local<v8::Value> p =
   13571       context->Global()->Get(context.local(), v8_str("p")).ToLocalChecked();
   13572   CHECK(p->IsObject() &&
   13573         p->ToObject(context.local())
   13574             .ToLocalChecked()
   13575             ->GetConstructorName()
   13576             ->Equals(context.local(), v8_str("Parent"))
   13577             .FromJust());
   13578 
   13579   Local<v8::Value> c =
   13580       context->Global()->Get(context.local(), v8_str("c")).ToLocalChecked();
   13581   CHECK(c->IsObject() &&
   13582         c->ToObject(context.local())
   13583             .ToLocalChecked()
   13584             ->GetConstructorName()
   13585             ->Equals(context.local(), v8_str("Child"))
   13586             .FromJust());
   13587 
   13588   Local<v8::Value> x =
   13589       context->Global()->Get(context.local(), v8_str("x")).ToLocalChecked();
   13590   CHECK(x->IsObject() &&
   13591         x->ToObject(context.local())
   13592             .ToLocalChecked()
   13593             ->GetConstructorName()
   13594             ->Equals(context.local(), v8_str("outer.inner"))
   13595             .FromJust());
   13596 
   13597   Local<v8::Value> child_prototype =
   13598       context->Global()->Get(context.local(), v8_str("proto")).ToLocalChecked();
   13599   CHECK(child_prototype->IsObject() &&
   13600         child_prototype->ToObject(context.local())
   13601             .ToLocalChecked()
   13602             ->GetConstructorName()
   13603             ->Equals(context.local(), v8_str("Parent"))
   13604             .FromJust());
   13605 }
   13606 
   13607 
   13608 THREADED_TEST(SubclassGetConstructorName) {
   13609   v8::Isolate* isolate = CcTest::isolate();
   13610   LocalContext context;
   13611   v8::HandleScope scope(isolate);
   13612   v8_compile(
   13613       "\"use strict\";"
   13614       "class Parent {}"
   13615       "class Child extends Parent {}"
   13616       "var p = new Parent();"
   13617       "var c = new Child();")
   13618       ->Run(context.local())
   13619       .ToLocalChecked();
   13620 
   13621   Local<v8::Value> p =
   13622       context->Global()->Get(context.local(), v8_str("p")).ToLocalChecked();
   13623   CHECK(p->IsObject() &&
   13624         p->ToObject(context.local())
   13625             .ToLocalChecked()
   13626             ->GetConstructorName()
   13627             ->Equals(context.local(), v8_str("Parent"))
   13628             .FromJust());
   13629 
   13630   Local<v8::Value> c =
   13631       context->Global()->Get(context.local(), v8_str("c")).ToLocalChecked();
   13632   CHECK(c->IsObject() &&
   13633         c->ToObject(context.local())
   13634             .ToLocalChecked()
   13635             ->GetConstructorName()
   13636             ->Equals(context.local(), v8_str("Child"))
   13637             .FromJust());
   13638 }
   13639 
   13640 
   13641 bool ApiTestFuzzer::fuzzing_ = false;
   13642 v8::base::Semaphore ApiTestFuzzer::all_tests_done_(0);
   13643 int ApiTestFuzzer::active_tests_;
   13644 int ApiTestFuzzer::tests_being_run_;
   13645 int ApiTestFuzzer::current_;
   13646 
   13647 
   13648 // We are in a callback and want to switch to another thread (if we
   13649 // are currently running the thread fuzzing test).
   13650 void ApiTestFuzzer::Fuzz() {
   13651   if (!fuzzing_) return;
   13652   ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
   13653   test->ContextSwitch();
   13654 }
   13655 
   13656 
   13657 // Let the next thread go.  Since it is also waiting on the V8 lock it may
   13658 // not start immediately.
   13659 bool ApiTestFuzzer::NextThread() {
   13660   int test_position = GetNextTestNumber();
   13661   const char* test_name = RegisterThreadedTest::nth(current_)->name();
   13662   if (test_position == current_) {
   13663     if (kLogThreading)
   13664       printf("Stay with %s\n", test_name);
   13665     return false;
   13666   }
   13667   if (kLogThreading) {
   13668     printf("Switch from %s to %s\n",
   13669            test_name,
   13670            RegisterThreadedTest::nth(test_position)->name());
   13671   }
   13672   current_ = test_position;
   13673   RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
   13674   return true;
   13675 }
   13676 
   13677 
   13678 void ApiTestFuzzer::Run() {
   13679   // When it is our turn...
   13680   gate_.Wait();
   13681   {
   13682     // ... get the V8 lock and start running the test.
   13683     v8::Locker locker(CcTest::isolate());
   13684     CallTest();
   13685   }
   13686   // This test finished.
   13687   active_ = false;
   13688   active_tests_--;
   13689   // If it was the last then signal that fact.
   13690   if (active_tests_ == 0) {
   13691     all_tests_done_.Signal();
   13692   } else {
   13693     // Otherwise select a new test and start that.
   13694     NextThread();
   13695   }
   13696 }
   13697 
   13698 
   13699 static unsigned linear_congruential_generator;
   13700 
   13701 
   13702 void ApiTestFuzzer::SetUp(PartOfTest part) {
   13703   linear_congruential_generator = i::FLAG_testing_prng_seed;
   13704   fuzzing_ = true;
   13705   int count = RegisterThreadedTest::count();
   13706   int start =  count * part / (LAST_PART + 1);
   13707   int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
   13708   active_tests_ = tests_being_run_ = end - start + 1;
   13709   for (int i = 0; i < tests_being_run_; i++) {
   13710     RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
   13711   }
   13712   for (int i = 0; i < active_tests_; i++) {
   13713     RegisterThreadedTest::nth(i)->fuzzer_->Start();
   13714   }
   13715 }
   13716 
   13717 
   13718 static void CallTestNumber(int test_number) {
   13719   (RegisterThreadedTest::nth(test_number)->callback())();
   13720 }
   13721 
   13722 
   13723 void ApiTestFuzzer::RunAllTests() {
   13724   // Set off the first test.
   13725   current_ = -1;
   13726   NextThread();
   13727   // Wait till they are all done.
   13728   all_tests_done_.Wait();
   13729 }
   13730 
   13731 
   13732 int ApiTestFuzzer::GetNextTestNumber() {
   13733   int next_test;
   13734   do {
   13735     next_test = (linear_congruential_generator >> 16) % tests_being_run_;
   13736     linear_congruential_generator *= 1664525u;
   13737     linear_congruential_generator += 1013904223u;
   13738   } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
   13739   return next_test;
   13740 }
   13741 
   13742 
   13743 void ApiTestFuzzer::ContextSwitch() {
   13744   // If the new thread is the same as the current thread there is nothing to do.
   13745   if (NextThread()) {
   13746     // Now it can start.
   13747     v8::Unlocker unlocker(CcTest::isolate());
   13748     // Wait till someone starts us again.
   13749     gate_.Wait();
   13750     // And we're off.
   13751   }
   13752 }
   13753 
   13754 
   13755 void ApiTestFuzzer::TearDown() {
   13756   fuzzing_ = false;
   13757   for (int i = 0; i < RegisterThreadedTest::count(); i++) {
   13758     ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
   13759     if (fuzzer != NULL) fuzzer->Join();
   13760   }
   13761 }
   13762 
   13763 
   13764 // Lets not be needlessly self-referential.
   13765 TEST(Threading1) {
   13766   ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
   13767   ApiTestFuzzer::RunAllTests();
   13768   ApiTestFuzzer::TearDown();
   13769 }
   13770 
   13771 
   13772 TEST(Threading2) {
   13773   ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
   13774   ApiTestFuzzer::RunAllTests();
   13775   ApiTestFuzzer::TearDown();
   13776 }
   13777 
   13778 
   13779 TEST(Threading3) {
   13780   ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
   13781   ApiTestFuzzer::RunAllTests();
   13782   ApiTestFuzzer::TearDown();
   13783 }
   13784 
   13785 
   13786 TEST(Threading4) {
   13787   ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
   13788   ApiTestFuzzer::RunAllTests();
   13789   ApiTestFuzzer::TearDown();
   13790 }
   13791 
   13792 
   13793 void ApiTestFuzzer::CallTest() {
   13794   v8::Isolate::Scope scope(CcTest::isolate());
   13795   if (kLogThreading)
   13796     printf("Start test %d\n", test_number_);
   13797   CallTestNumber(test_number_);
   13798   if (kLogThreading)
   13799     printf("End test %d\n", test_number_);
   13800 }
   13801 
   13802 
   13803 static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13804   v8::Isolate* isolate = args.GetIsolate();
   13805   CHECK(v8::Locker::IsLocked(isolate));
   13806   ApiTestFuzzer::Fuzz();
   13807   v8::Unlocker unlocker(isolate);
   13808   const char* code = "throw 7;";
   13809   {
   13810     v8::Locker nested_locker(isolate);
   13811     v8::HandleScope scope(isolate);
   13812     v8::Local<Value> exception;
   13813     {
   13814       v8::TryCatch try_catch(isolate);
   13815       v8::Local<Value> value = CompileRun(code);
   13816       CHECK(value.IsEmpty());
   13817       CHECK(try_catch.HasCaught());
   13818       // Make sure to wrap the exception in a new handle because
   13819       // the handle returned from the TryCatch is destroyed
   13820       // when the TryCatch is destroyed.
   13821       exception = Local<Value>::New(isolate, try_catch.Exception());
   13822     }
   13823     args.GetIsolate()->ThrowException(exception);
   13824   }
   13825 }
   13826 
   13827 
   13828 static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13829   CHECK(v8::Locker::IsLocked(CcTest::isolate()));
   13830   ApiTestFuzzer::Fuzz();
   13831   v8::Unlocker unlocker(CcTest::isolate());
   13832   const char* code = "throw 7;";
   13833   {
   13834     v8::Locker nested_locker(CcTest::isolate());
   13835     v8::HandleScope scope(args.GetIsolate());
   13836     v8::Local<Value> value = CompileRun(code);
   13837     CHECK(value.IsEmpty());
   13838     args.GetReturnValue().Set(v8_str("foo"));
   13839   }
   13840 }
   13841 
   13842 
   13843 // These are locking tests that don't need to be run again
   13844 // as part of the locking aggregation tests.
   13845 TEST(NestedLockers) {
   13846   v8::Isolate* isolate = CcTest::isolate();
   13847   v8::Locker locker(isolate);
   13848   CHECK(v8::Locker::IsLocked(isolate));
   13849   LocalContext env;
   13850   v8::HandleScope scope(env->GetIsolate());
   13851   Local<v8::FunctionTemplate> fun_templ =
   13852       v8::FunctionTemplate::New(isolate, ThrowInJS);
   13853   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   13854   CHECK(env->Global()->Set(env.local(), v8_str("throw_in_js"), fun).FromJust());
   13855   Local<Script> script = v8_compile("(function () {"
   13856                                     "  try {"
   13857                                     "    throw_in_js();"
   13858                                     "    return 42;"
   13859                                     "  } catch (e) {"
   13860                                     "    return e * 13;"
   13861                                     "  }"
   13862                                     "})();");
   13863   CHECK_EQ(91, script->Run(env.local())
   13864                    .ToLocalChecked()
   13865                    ->Int32Value(env.local())
   13866                    .FromJust());
   13867 }
   13868 
   13869 
   13870 // These are locking tests that don't need to be run again
   13871 // as part of the locking aggregation tests.
   13872 TEST(NestedLockersNoTryCatch) {
   13873   v8::Locker locker(CcTest::isolate());
   13874   LocalContext env;
   13875   v8::HandleScope scope(env->GetIsolate());
   13876   Local<v8::FunctionTemplate> fun_templ =
   13877       v8::FunctionTemplate::New(env->GetIsolate(), ThrowInJSNoCatch);
   13878   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   13879   CHECK(env->Global()->Set(env.local(), v8_str("throw_in_js"), fun).FromJust());
   13880   Local<Script> script = v8_compile("(function () {"
   13881                                     "  try {"
   13882                                     "    throw_in_js();"
   13883                                     "    return 42;"
   13884                                     "  } catch (e) {"
   13885                                     "    return e * 13;"
   13886                                     "  }"
   13887                                     "})();");
   13888   CHECK_EQ(91, script->Run(env.local())
   13889                    .ToLocalChecked()
   13890                    ->Int32Value(env.local())
   13891                    .FromJust());
   13892 }
   13893 
   13894 
   13895 THREADED_TEST(RecursiveLocking) {
   13896   v8::Locker locker(CcTest::isolate());
   13897   {
   13898     v8::Locker locker2(CcTest::isolate());
   13899     CHECK(v8::Locker::IsLocked(CcTest::isolate()));
   13900   }
   13901 }
   13902 
   13903 
   13904 static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13905   ApiTestFuzzer::Fuzz();
   13906   v8::Unlocker unlocker(CcTest::isolate());
   13907 }
   13908 
   13909 
   13910 THREADED_TEST(LockUnlockLock) {
   13911   {
   13912     v8::Locker locker(CcTest::isolate());
   13913     v8::HandleScope scope(CcTest::isolate());
   13914     LocalContext env;
   13915     Local<v8::FunctionTemplate> fun_templ =
   13916         v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
   13917     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   13918     CHECK(env->Global()
   13919               ->Set(env.local(), v8_str("unlock_for_a_moment"), fun)
   13920               .FromJust());
   13921     Local<Script> script = v8_compile("(function () {"
   13922                                       "  unlock_for_a_moment();"
   13923                                       "  return 42;"
   13924                                       "})();");
   13925     CHECK_EQ(42, script->Run(env.local())
   13926                      .ToLocalChecked()
   13927                      ->Int32Value(env.local())
   13928                      .FromJust());
   13929   }
   13930   {
   13931     v8::Locker locker(CcTest::isolate());
   13932     v8::HandleScope scope(CcTest::isolate());
   13933     LocalContext env;
   13934     Local<v8::FunctionTemplate> fun_templ =
   13935         v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
   13936     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   13937     CHECK(env->Global()
   13938               ->Set(env.local(), v8_str("unlock_for_a_moment"), fun)
   13939               .FromJust());
   13940     Local<Script> script = v8_compile("(function () {"
   13941                                       "  unlock_for_a_moment();"
   13942                                       "  return 42;"
   13943                                       "})();");
   13944     CHECK_EQ(42, script->Run(env.local())
   13945                      .ToLocalChecked()
   13946                      ->Int32Value(env.local())
   13947                      .FromJust());
   13948   }
   13949 }
   13950 
   13951 
   13952 static int GetGlobalObjectsCount() {
   13953   int count = 0;
   13954   i::HeapIterator it(CcTest::heap());
   13955   for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
   13956     if (object->IsJSGlobalObject()) {
   13957       i::JSGlobalObject* g = i::JSGlobalObject::cast(object);
   13958       // Skip dummy global object.
   13959       if (i::GlobalDictionary::cast(g->properties())->NumberOfElements() != 0) {
   13960         count++;
   13961       }
   13962     }
   13963   return count;
   13964 }
   13965 
   13966 
   13967 static void CheckSurvivingGlobalObjectsCount(int expected) {
   13968   // We need to collect all garbage twice to be sure that everything
   13969   // has been collected.  This is because inline caches are cleared in
   13970   // the first garbage collection but some of the maps have already
   13971   // been marked at that point.  Therefore some of the maps are not
   13972   // collected until the second garbage collection.
   13973   CcTest::heap()->CollectAllGarbage();
   13974   CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
   13975   int count = GetGlobalObjectsCount();
   13976 #ifdef DEBUG
   13977   if (count != expected) CcTest::heap()->TracePathToGlobal();
   13978 #endif
   13979   CHECK_EQ(expected, count);
   13980 }
   13981 
   13982 
   13983 TEST(DontLeakGlobalObjects) {
   13984   // Regression test for issues 1139850 and 1174891.
   13985 
   13986   i::FLAG_expose_gc = true;
   13987   v8::V8::Initialize();
   13988 
   13989   for (int i = 0; i < 5; i++) {
   13990     { v8::HandleScope scope(CcTest::isolate());
   13991       LocalContext context;
   13992     }
   13993     CcTest::isolate()->ContextDisposedNotification();
   13994     CheckSurvivingGlobalObjectsCount(0);
   13995 
   13996     { v8::HandleScope scope(CcTest::isolate());
   13997       LocalContext context;
   13998       v8_compile("Date")->Run(context.local()).ToLocalChecked();
   13999     }
   14000     CcTest::isolate()->ContextDisposedNotification();
   14001     CheckSurvivingGlobalObjectsCount(0);
   14002 
   14003     { v8::HandleScope scope(CcTest::isolate());
   14004       LocalContext context;
   14005       v8_compile("/aaa/")->Run(context.local()).ToLocalChecked();
   14006     }
   14007     CcTest::isolate()->ContextDisposedNotification();
   14008     CheckSurvivingGlobalObjectsCount(0);
   14009 
   14010     { v8::HandleScope scope(CcTest::isolate());
   14011       const char* extension_list[] = { "v8/gc" };
   14012       v8::ExtensionConfiguration extensions(1, extension_list);
   14013       LocalContext context(&extensions);
   14014       v8_compile("gc();")->Run(context.local()).ToLocalChecked();
   14015     }
   14016     CcTest::isolate()->ContextDisposedNotification();
   14017     CheckSurvivingGlobalObjectsCount(0);
   14018   }
   14019 }
   14020 
   14021 
   14022 TEST(CopyablePersistent) {
   14023   LocalContext context;
   14024   v8::Isolate* isolate = context->GetIsolate();
   14025   i::GlobalHandles* globals =
   14026       reinterpret_cast<i::Isolate*>(isolate)->global_handles();
   14027   int initial_handles = globals->global_handles_count();
   14028   typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
   14029       CopyableObject;
   14030   {
   14031     CopyableObject handle1;
   14032     {
   14033       v8::HandleScope scope(isolate);
   14034       handle1.Reset(isolate, v8::Object::New(isolate));
   14035     }
   14036     CHECK_EQ(initial_handles + 1, globals->global_handles_count());
   14037     CopyableObject  handle2;
   14038     handle2 = handle1;
   14039     CHECK(handle1 == handle2);
   14040     CHECK_EQ(initial_handles + 2, globals->global_handles_count());
   14041     CopyableObject handle3(handle2);
   14042     CHECK(handle1 == handle3);
   14043     CHECK_EQ(initial_handles + 3, globals->global_handles_count());
   14044   }
   14045   // Verify autodispose
   14046   CHECK_EQ(initial_handles, globals->global_handles_count());
   14047 }
   14048 
   14049 
   14050 static void WeakApiCallback(
   14051     const v8::WeakCallbackInfo<Persistent<v8::Object>>& data) {
   14052   data.GetParameter()->Reset();
   14053   delete data.GetParameter();
   14054 }
   14055 
   14056 
   14057 TEST(WeakCallbackApi) {
   14058   LocalContext context;
   14059   v8::Isolate* isolate = context->GetIsolate();
   14060   i::GlobalHandles* globals =
   14061       reinterpret_cast<i::Isolate*>(isolate)->global_handles();
   14062   int initial_handles = globals->global_handles_count();
   14063   {
   14064     v8::HandleScope scope(isolate);
   14065     v8::Local<v8::Object> obj = v8::Object::New(isolate);
   14066     CHECK(
   14067         obj->Set(context.local(), v8_str("key"), v8::Integer::New(isolate, 231))
   14068             .FromJust());
   14069     v8::Persistent<v8::Object>* handle =
   14070         new v8::Persistent<v8::Object>(isolate, obj);
   14071     handle->SetWeak<v8::Persistent<v8::Object>>(
   14072         handle, WeakApiCallback, v8::WeakCallbackType::kParameter);
   14073   }
   14074   reinterpret_cast<i::Isolate*>(isolate)->heap()->CollectAllGarbage(
   14075       i::Heap::kAbortIncrementalMarkingMask);
   14076   // Verify disposed.
   14077   CHECK_EQ(initial_handles, globals->global_handles_count());
   14078 }
   14079 
   14080 
   14081 v8::Persistent<v8::Object> some_object;
   14082 v8::Persistent<v8::Object> bad_handle;
   14083 
   14084 
   14085 void NewPersistentHandleCallback2(
   14086     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   14087   v8::HandleScope scope(data.GetIsolate());
   14088   bad_handle.Reset(data.GetIsolate(), some_object);
   14089 }
   14090 
   14091 
   14092 void NewPersistentHandleCallback1(
   14093     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   14094   data.GetParameter()->Reset();
   14095   data.SetSecondPassCallback(NewPersistentHandleCallback2);
   14096 }
   14097 
   14098 
   14099 THREADED_TEST(NewPersistentHandleFromWeakCallback) {
   14100   LocalContext context;
   14101   v8::Isolate* isolate = context->GetIsolate();
   14102 
   14103   v8::Persistent<v8::Object> handle1, handle2;
   14104   {
   14105     v8::HandleScope scope(isolate);
   14106     some_object.Reset(isolate, v8::Object::New(isolate));
   14107     handle1.Reset(isolate, v8::Object::New(isolate));
   14108     handle2.Reset(isolate, v8::Object::New(isolate));
   14109   }
   14110   // Note: order is implementation dependent alas: currently
   14111   // global handle nodes are processed by PostGarbageCollectionProcessing
   14112   // in reverse allocation order, so if second allocated handle is deleted,
   14113   // weak callback of the first handle would be able to 'reallocate' it.
   14114   handle1.SetWeak(&handle1, NewPersistentHandleCallback1,
   14115                   v8::WeakCallbackType::kParameter);
   14116   handle2.Reset();
   14117   CcTest::heap()->CollectAllGarbage();
   14118 }
   14119 
   14120 
   14121 v8::Persistent<v8::Object> to_be_disposed;
   14122 
   14123 
   14124 void DisposeAndForceGcCallback2(
   14125     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   14126   to_be_disposed.Reset();
   14127   CcTest::heap()->CollectAllGarbage();
   14128 }
   14129 
   14130 
   14131 void DisposeAndForceGcCallback1(
   14132     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   14133   data.GetParameter()->Reset();
   14134   data.SetSecondPassCallback(DisposeAndForceGcCallback2);
   14135 }
   14136 
   14137 
   14138 THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
   14139   LocalContext context;
   14140   v8::Isolate* isolate = context->GetIsolate();
   14141 
   14142   v8::Persistent<v8::Object> handle1, handle2;
   14143   {
   14144     v8::HandleScope scope(isolate);
   14145     handle1.Reset(isolate, v8::Object::New(isolate));
   14146     handle2.Reset(isolate, v8::Object::New(isolate));
   14147   }
   14148   handle1.SetWeak(&handle1, DisposeAndForceGcCallback1,
   14149                   v8::WeakCallbackType::kParameter);
   14150   to_be_disposed.Reset(isolate, handle2);
   14151   CcTest::heap()->CollectAllGarbage();
   14152 }
   14153 
   14154 void DisposingCallback(
   14155     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   14156   data.GetParameter()->Reset();
   14157 }
   14158 
   14159 void HandleCreatingCallback2(
   14160     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   14161   v8::HandleScope scope(data.GetIsolate());
   14162   v8::Global<v8::Object>(data.GetIsolate(), v8::Object::New(data.GetIsolate()));
   14163 }
   14164 
   14165 
   14166 void HandleCreatingCallback1(
   14167     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   14168   data.GetParameter()->Reset();
   14169   data.SetSecondPassCallback(HandleCreatingCallback2);
   14170 }
   14171 
   14172 
   14173 THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
   14174   v8::Locker locker(CcTest::isolate());
   14175   LocalContext context;
   14176   v8::Isolate* isolate = context->GetIsolate();
   14177 
   14178   v8::Persistent<v8::Object> handle1, handle2, handle3;
   14179   {
   14180     v8::HandleScope scope(isolate);
   14181     handle3.Reset(isolate, v8::Object::New(isolate));
   14182     handle2.Reset(isolate, v8::Object::New(isolate));
   14183     handle1.Reset(isolate, v8::Object::New(isolate));
   14184   }
   14185   handle2.SetWeak(&handle2, DisposingCallback,
   14186                   v8::WeakCallbackType::kParameter);
   14187   handle3.SetWeak(&handle3, HandleCreatingCallback1,
   14188                   v8::WeakCallbackType::kParameter);
   14189   CcTest::heap()->CollectAllGarbage();
   14190   EmptyMessageQueues(isolate);
   14191 }
   14192 
   14193 
   14194 THREADED_TEST(CheckForCrossContextObjectLiterals) {
   14195   v8::V8::Initialize();
   14196 
   14197   const int nof = 2;
   14198   const char* sources[nof] = {
   14199     "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
   14200     "Object()"
   14201   };
   14202 
   14203   for (int i = 0; i < nof; i++) {
   14204     const char* source = sources[i];
   14205     { v8::HandleScope scope(CcTest::isolate());
   14206       LocalContext context;
   14207       CompileRun(source);
   14208     }
   14209     { v8::HandleScope scope(CcTest::isolate());
   14210       LocalContext context;
   14211       CompileRun(source);
   14212     }
   14213   }
   14214 }
   14215 
   14216 
   14217 static v8::Local<Value> NestedScope(v8::Local<Context> env) {
   14218   v8::EscapableHandleScope inner(env->GetIsolate());
   14219   env->Enter();
   14220   v8::Local<Value> three = v8_num(3);
   14221   v8::Local<Value> value = inner.Escape(three);
   14222   env->Exit();
   14223   return value;
   14224 }
   14225 
   14226 
   14227 THREADED_TEST(NestedHandleScopeAndContexts) {
   14228   v8::Isolate* isolate = CcTest::isolate();
   14229   v8::HandleScope outer(isolate);
   14230   v8::Local<Context> env = Context::New(isolate);
   14231   env->Enter();
   14232   v8::Local<Value> value = NestedScope(env);
   14233   v8::Local<String> str(value->ToString(env).ToLocalChecked());
   14234   CHECK(!str.IsEmpty());
   14235   env->Exit();
   14236 }
   14237 
   14238 
   14239 static bool MatchPointers(void* key1, void* key2) {
   14240   return key1 == key2;
   14241 }
   14242 
   14243 
   14244 struct SymbolInfo {
   14245   size_t id;
   14246   size_t size;
   14247   std::string name;
   14248 };
   14249 
   14250 
   14251 class SetFunctionEntryHookTest {
   14252  public:
   14253   SetFunctionEntryHookTest() {
   14254     CHECK(instance_ == NULL);
   14255     instance_ = this;
   14256   }
   14257   ~SetFunctionEntryHookTest() {
   14258     CHECK(instance_ == this);
   14259     instance_ = NULL;
   14260   }
   14261   void Reset() {
   14262     symbols_.clear();
   14263     symbol_locations_.clear();
   14264     invocations_.clear();
   14265   }
   14266   void RunTest();
   14267   void OnJitEvent(const v8::JitCodeEvent* event);
   14268   static void JitEvent(const v8::JitCodeEvent* event) {
   14269     CHECK(instance_ != NULL);
   14270     instance_->OnJitEvent(event);
   14271   }
   14272 
   14273   void OnEntryHook(uintptr_t function,
   14274                    uintptr_t return_addr_location);
   14275   static void EntryHook(uintptr_t function,
   14276                         uintptr_t return_addr_location) {
   14277     CHECK(instance_ != NULL);
   14278     instance_->OnEntryHook(function, return_addr_location);
   14279   }
   14280 
   14281   static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   14282     CHECK(instance_ != NULL);
   14283     args.GetReturnValue().Set(v8_num(42));
   14284   }
   14285   void RunLoopInNewEnv(v8::Isolate* isolate);
   14286 
   14287   // Records addr as location of symbol.
   14288   void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
   14289 
   14290   // Finds the symbol containing addr
   14291   SymbolInfo* FindSymbolForAddr(i::Address addr);
   14292   // Returns the number of invocations where the caller name contains
   14293   // \p caller_name and the function name contains \p function_name.
   14294   int CountInvocations(const char* caller_name,
   14295                        const char* function_name);
   14296 
   14297   i::Handle<i::JSFunction> foo_func_;
   14298   i::Handle<i::JSFunction> bar_func_;
   14299 
   14300   typedef std::map<size_t, SymbolInfo> SymbolMap;
   14301   typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
   14302   typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
   14303   SymbolMap symbols_;
   14304   SymbolLocationMap symbol_locations_;
   14305   InvocationMap invocations_;
   14306 
   14307   static SetFunctionEntryHookTest* instance_;
   14308 };
   14309 SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
   14310 
   14311 
   14312 // Returns true if addr is in the range [start, start+len).
   14313 static bool Overlaps(i::Address start, size_t len, i::Address addr) {
   14314   if (start <= addr && start + len > addr)
   14315     return true;
   14316 
   14317   return false;
   14318 }
   14319 
   14320 void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
   14321                                               SymbolInfo* symbol) {
   14322   // Insert the symbol at the new location.
   14323   SymbolLocationMap::iterator it =
   14324       symbol_locations_.insert(std::make_pair(addr, symbol)).first;
   14325   // Now erase symbols to the left and right that overlap this one.
   14326   while (it != symbol_locations_.begin()) {
   14327     SymbolLocationMap::iterator left = it;
   14328     --left;
   14329     if (!Overlaps(left->first, left->second->size, addr))
   14330       break;
   14331     symbol_locations_.erase(left);
   14332   }
   14333 
   14334   // Now erase symbols to the left and right that overlap this one.
   14335   while (true) {
   14336     SymbolLocationMap::iterator right = it;
   14337     ++right;
   14338     if (right == symbol_locations_.end())
   14339         break;
   14340     if (!Overlaps(addr, symbol->size, right->first))
   14341       break;
   14342     symbol_locations_.erase(right);
   14343   }
   14344 }
   14345 
   14346 
   14347 void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
   14348   switch (event->type) {
   14349     case v8::JitCodeEvent::CODE_ADDED: {
   14350         CHECK(event->code_start != NULL);
   14351         CHECK_NE(0, static_cast<int>(event->code_len));
   14352         CHECK(event->name.str != NULL);
   14353         size_t symbol_id = symbols_.size();
   14354 
   14355         // Record the new symbol.
   14356         SymbolInfo& info = symbols_[symbol_id];
   14357         info.id = symbol_id;
   14358         info.size = event->code_len;
   14359         info.name.assign(event->name.str, event->name.str + event->name.len);
   14360 
   14361         // And record it's location.
   14362         InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
   14363       }
   14364       break;
   14365 
   14366     case v8::JitCodeEvent::CODE_MOVED: {
   14367         // We would like to never see code move that we haven't seen before,
   14368         // but the code creation event does not happen until the line endings
   14369         // have been calculated (this is so that we can report the line in the
   14370         // script at which the function source is found, see
   14371         // Compiler::RecordFunctionCompilation) and the line endings
   14372         // calculations can cause a GC, which can move the newly created code
   14373         // before its existence can be logged.
   14374         SymbolLocationMap::iterator it(
   14375             symbol_locations_.find(
   14376                 reinterpret_cast<i::Address>(event->code_start)));
   14377         if (it != symbol_locations_.end()) {
   14378           // Found a symbol at this location, move it.
   14379           SymbolInfo* info = it->second;
   14380           symbol_locations_.erase(it);
   14381           InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
   14382                          info);
   14383         }
   14384       }
   14385     default:
   14386       break;
   14387   }
   14388 }
   14389 
   14390 void SetFunctionEntryHookTest::OnEntryHook(
   14391     uintptr_t function, uintptr_t return_addr_location) {
   14392   // Get the function's code object.
   14393   i::Code* function_code = i::Code::GetCodeFromTargetAddress(
   14394       reinterpret_cast<i::Address>(function));
   14395   CHECK(function_code != NULL);
   14396 
   14397   // Then try and look up the caller's code object.
   14398   i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
   14399 
   14400   // Count the invocation.
   14401   SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
   14402   SymbolInfo* function_symbol =
   14403       FindSymbolForAddr(reinterpret_cast<i::Address>(function));
   14404   ++invocations_[std::make_pair(caller_symbol, function_symbol)];
   14405 
   14406   if (!bar_func_.is_null() && function_code == bar_func_->code()) {
   14407     // Check that we have a symbol for the "bar" function at the right location.
   14408     SymbolLocationMap::iterator it(
   14409         symbol_locations_.find(function_code->instruction_start()));
   14410     CHECK(it != symbol_locations_.end());
   14411   }
   14412 
   14413   if (!foo_func_.is_null() && function_code == foo_func_->code()) {
   14414     // Check that we have a symbol for "foo" at the right location.
   14415     SymbolLocationMap::iterator it(
   14416         symbol_locations_.find(function_code->instruction_start()));
   14417     CHECK(it != symbol_locations_.end());
   14418   }
   14419 }
   14420 
   14421 
   14422 SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
   14423   SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
   14424   // Do we have a direct hit on a symbol?
   14425   if (it != symbol_locations_.end()) {
   14426     if (it->first == addr)
   14427       return it->second;
   14428   }
   14429 
   14430   // If not a direct hit, it'll have to be the previous symbol.
   14431   if (it == symbol_locations_.begin())
   14432     return NULL;
   14433 
   14434   --it;
   14435   size_t offs = addr - it->first;
   14436   if (offs < it->second->size)
   14437     return it->second;
   14438 
   14439   return NULL;
   14440 }
   14441 
   14442 
   14443 int SetFunctionEntryHookTest::CountInvocations(
   14444     const char* caller_name, const char* function_name) {
   14445   InvocationMap::iterator it(invocations_.begin());
   14446   int invocations = 0;
   14447   for (; it != invocations_.end(); ++it) {
   14448     SymbolInfo* caller = it->first.first;
   14449     SymbolInfo* function = it->first.second;
   14450 
   14451     // Filter out non-matching functions.
   14452     if (function_name != NULL) {
   14453       if (function->name.find(function_name) == std::string::npos)
   14454         continue;
   14455     }
   14456 
   14457     // Filter out non-matching callers.
   14458     if (caller_name != NULL) {
   14459       if (caller == NULL)
   14460         continue;
   14461       if (caller->name.find(caller_name) == std::string::npos)
   14462         continue;
   14463     }
   14464 
   14465     // It matches add the invocation count to the tally.
   14466     invocations += it->second;
   14467   }
   14468 
   14469   return invocations;
   14470 }
   14471 
   14472 void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
   14473   v8::HandleScope outer(isolate);
   14474   v8::Local<Context> env = Context::New(isolate);
   14475   env->Enter();
   14476 
   14477   Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
   14478   t->Set(v8_str("asdf"), v8::FunctionTemplate::New(isolate, RuntimeCallback));
   14479   CHECK(env->Global()
   14480             ->Set(env, v8_str("obj"), t->NewInstance(env).ToLocalChecked())
   14481             .FromJust());
   14482 
   14483   const char* script =
   14484       "function bar() {\n"
   14485       "  var sum = 0;\n"
   14486       "  for (i = 0; i < 100; ++i)\n"
   14487       "    sum = foo(i);\n"
   14488       "  return sum;\n"
   14489       "}\n"
   14490       "function foo(i) { return i * i; }\n"
   14491       "// Invoke on the runtime function.\n"
   14492       "obj.asdf()";
   14493   CompileRun(script);
   14494   bar_func_ = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(
   14495       *env->Global()->Get(env, v8_str("bar")).ToLocalChecked()));
   14496   CHECK(!bar_func_.is_null());
   14497 
   14498   foo_func_ = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(
   14499       *env->Global()->Get(env, v8_str("foo")).ToLocalChecked()));
   14500   CHECK(!foo_func_.is_null());
   14501 
   14502   v8::Local<v8::Value> value = CompileRun("bar();");
   14503   CHECK(value->IsNumber());
   14504   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
   14505 
   14506   // Test the optimized codegen path.
   14507   value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
   14508                      "bar();");
   14509   CHECK(value->IsNumber());
   14510   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
   14511 
   14512   env->Exit();
   14513 }
   14514 
   14515 
   14516 void SetFunctionEntryHookTest::RunTest() {
   14517   // Work in a new isolate throughout.
   14518   v8::Isolate::CreateParams create_params;
   14519   create_params.entry_hook = EntryHook;
   14520   create_params.code_event_handler = JitEvent;
   14521   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   14522   v8::Isolate* isolate = v8::Isolate::New(create_params);
   14523 
   14524   {
   14525     v8::Isolate::Scope scope(isolate);
   14526 
   14527     RunLoopInNewEnv(isolate);
   14528 
   14529     // Check the expected invocation counts.
   14530     if (!i::FLAG_ignition) {
   14531       CHECK_EQ(2, CountInvocations(NULL, "bar"));
   14532       CHECK_EQ(200, CountInvocations("bar", "foo"));
   14533       CHECK_EQ(200, CountInvocations(NULL, "foo"));
   14534     } else {
   14535       // For ignition we don't see the actual functions being called, instead
   14536       // we see the IterpreterEntryTrampoline at least 102 times
   14537       // (100 unoptimized calls to foo, and 2 calls to bar).
   14538       CHECK_LE(102, CountInvocations(NULL, "InterpreterEntryTrampoline"));
   14539       // We should also see the calls to the optimized function foo.
   14540       CHECK_EQ(100, CountInvocations(NULL, "foo"));
   14541     }
   14542 
   14543     // Verify that we have an entry hook on some specific stubs.
   14544     CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
   14545     CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
   14546     CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
   14547   }
   14548   isolate->Dispose();
   14549 
   14550   Reset();
   14551 
   14552   // Make sure a second isolate is unaffected by the previous entry hook.
   14553   create_params = v8::Isolate::CreateParams();
   14554   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   14555   isolate = v8::Isolate::New(create_params);
   14556   {
   14557     v8::Isolate::Scope scope(isolate);
   14558 
   14559     // Reset the entry count to zero and set the entry hook.
   14560     RunLoopInNewEnv(isolate);
   14561 
   14562     // We should record no invocations in this isolate.
   14563     CHECK_EQ(0, static_cast<int>(invocations_.size()));
   14564   }
   14565 
   14566   isolate->Dispose();
   14567 }
   14568 
   14569 
   14570 TEST(SetFunctionEntryHook) {
   14571   // FunctionEntryHook does not work well with experimental natives.
   14572   // Experimental natives are compiled during snapshot deserialization.
   14573   // This test breaks because InstallGetter (function from snapshot that
   14574   // only gets called from experimental natives) is compiled with entry hooks.
   14575   i::FLAG_allow_natives_syntax = true;
   14576   i::FLAG_turbo_inlining = false;
   14577   i::FLAG_use_inlining = false;
   14578 
   14579   SetFunctionEntryHookTest test;
   14580   test.RunTest();
   14581 }
   14582 
   14583 static v8::base::HashMap* code_map = NULL;
   14584 static v8::base::HashMap* jitcode_line_info = NULL;
   14585 static int saw_bar = 0;
   14586 static int move_events = 0;
   14587 
   14588 
   14589 static bool FunctionNameIs(const char* expected,
   14590                            const v8::JitCodeEvent* event) {
   14591   // Log lines for functions are of the general form:
   14592   // "LazyCompile:<type><function_name>" or Function:<type><function_name>,
   14593   // where the type is one of "*", "~" or "".
   14594   static const char* kPreamble;
   14595   if (!i::FLAG_lazy || (i::FLAG_ignition && i::FLAG_ignition_eager)) {
   14596     kPreamble = "Function:";
   14597   } else {
   14598     kPreamble = "LazyCompile:";
   14599   }
   14600   static size_t kPreambleLen = strlen(kPreamble);
   14601 
   14602   if (event->name.len < kPreambleLen ||
   14603       strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
   14604     return false;
   14605   }
   14606 
   14607   const char* tail = event->name.str + kPreambleLen;
   14608   size_t tail_len = event->name.len - kPreambleLen;
   14609   size_t expected_len = strlen(expected);
   14610   if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
   14611     --tail_len;
   14612     ++tail;
   14613   }
   14614 
   14615   // Check for tails like 'bar :1'.
   14616   if (tail_len > expected_len + 2 &&
   14617       tail[expected_len] == ' ' &&
   14618       tail[expected_len + 1] == ':' &&
   14619       tail[expected_len + 2] &&
   14620       !strncmp(tail, expected, expected_len)) {
   14621     return true;
   14622   }
   14623 
   14624   if (tail_len != expected_len)
   14625     return false;
   14626 
   14627   return strncmp(tail, expected, expected_len) == 0;
   14628 }
   14629 
   14630 
   14631 static void event_handler(const v8::JitCodeEvent* event) {
   14632   CHECK(event != NULL);
   14633   CHECK(code_map != NULL);
   14634   CHECK(jitcode_line_info != NULL);
   14635 
   14636   class DummyJitCodeLineInfo {
   14637   };
   14638 
   14639   switch (event->type) {
   14640     case v8::JitCodeEvent::CODE_ADDED: {
   14641         CHECK(event->code_start != NULL);
   14642         CHECK_NE(0, static_cast<int>(event->code_len));
   14643         CHECK(event->name.str != NULL);
   14644         v8::base::HashMap::Entry* entry = code_map->LookupOrInsert(
   14645             event->code_start, i::ComputePointerHash(event->code_start));
   14646         entry->value = reinterpret_cast<void*>(event->code_len);
   14647 
   14648         if (FunctionNameIs("bar", event)) {
   14649           ++saw_bar;
   14650         }
   14651       }
   14652       break;
   14653 
   14654     case v8::JitCodeEvent::CODE_MOVED: {
   14655         uint32_t hash = i::ComputePointerHash(event->code_start);
   14656         // We would like to never see code move that we haven't seen before,
   14657         // but the code creation event does not happen until the line endings
   14658         // have been calculated (this is so that we can report the line in the
   14659         // script at which the function source is found, see
   14660         // Compiler::RecordFunctionCompilation) and the line endings
   14661         // calculations can cause a GC, which can move the newly created code
   14662         // before its existence can be logged.
   14663         v8::base::HashMap::Entry* entry =
   14664             code_map->Lookup(event->code_start, hash);
   14665         if (entry != NULL) {
   14666           ++move_events;
   14667 
   14668           CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
   14669           code_map->Remove(event->code_start, hash);
   14670 
   14671           entry = code_map->LookupOrInsert(
   14672               event->new_code_start,
   14673               i::ComputePointerHash(event->new_code_start));
   14674           entry->value = reinterpret_cast<void*>(event->code_len);
   14675         }
   14676       }
   14677       break;
   14678 
   14679     case v8::JitCodeEvent::CODE_REMOVED:
   14680       // Object/code removal events are currently not dispatched from the GC.
   14681       CHECK(false);
   14682       break;
   14683 
   14684     // For CODE_START_LINE_INFO_RECORDING event, we will create one
   14685     // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
   14686     // record it in jitcode_line_info.
   14687     case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
   14688         DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
   14689         v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
   14690         temp_event->user_data = line_info;
   14691         v8::base::HashMap::Entry* entry = jitcode_line_info->LookupOrInsert(
   14692             line_info, i::ComputePointerHash(line_info));
   14693         entry->value = reinterpret_cast<void*>(line_info);
   14694       }
   14695       break;
   14696     // For these two events, we will check whether the event->user_data
   14697     // data structure is created before during CODE_START_LINE_INFO_RECORDING
   14698     // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
   14699     case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
   14700         CHECK(event->user_data != NULL);
   14701         uint32_t hash = i::ComputePointerHash(event->user_data);
   14702         v8::base::HashMap::Entry* entry =
   14703             jitcode_line_info->Lookup(event->user_data, hash);
   14704         CHECK(entry != NULL);
   14705         delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
   14706       }
   14707       break;
   14708 
   14709     case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
   14710         CHECK(event->user_data != NULL);
   14711         uint32_t hash = i::ComputePointerHash(event->user_data);
   14712         v8::base::HashMap::Entry* entry =
   14713             jitcode_line_info->Lookup(event->user_data, hash);
   14714         CHECK(entry != NULL);
   14715       }
   14716       break;
   14717 
   14718     default:
   14719       // Impossible event.
   14720       CHECK(false);
   14721       break;
   14722   }
   14723 }
   14724 
   14725 
   14726 UNINITIALIZED_TEST(SetJitCodeEventHandler) {
   14727   i::FLAG_stress_compaction = true;
   14728   i::FLAG_incremental_marking = false;
   14729   if (i::FLAG_never_compact) return;
   14730   const char* script =
   14731       "function bar() {"
   14732       "  var sum = 0;"
   14733       "  for (i = 0; i < 10; ++i)"
   14734       "    sum = foo(i);"
   14735       "  return sum;"
   14736       "}"
   14737       "function foo(i) { return i; };"
   14738       "bar();";
   14739 
   14740   // Run this test in a new isolate to make sure we don't
   14741   // have remnants of state from other code.
   14742   v8::Isolate::CreateParams create_params;
   14743   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   14744   v8::Isolate* isolate = v8::Isolate::New(create_params);
   14745   isolate->Enter();
   14746   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   14747   i::Heap* heap = i_isolate->heap();
   14748 
   14749   // Start with a clean slate.
   14750   heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler_Prepare");
   14751 
   14752   {
   14753     v8::HandleScope scope(isolate);
   14754     v8::base::HashMap code(MatchPointers);
   14755     code_map = &code;
   14756 
   14757     v8::base::HashMap lineinfo(MatchPointers);
   14758     jitcode_line_info = &lineinfo;
   14759 
   14760     saw_bar = 0;
   14761     move_events = 0;
   14762 
   14763     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
   14764 
   14765     // Generate new code objects sparsely distributed across several
   14766     // different fragmented code-space pages.
   14767     const int kIterations = 10;
   14768     for (int i = 0; i < kIterations; ++i) {
   14769       LocalContext env(isolate);
   14770       i::AlwaysAllocateScope always_allocate(i_isolate);
   14771       i::heap::SimulateFullSpace(i::FLAG_ignition ? heap->old_space()
   14772                                                   : heap->code_space());
   14773       CompileRun(script);
   14774 
   14775       // Keep a strong reference to the code object in the handle scope.
   14776       i::Handle<i::Code> bar_code(
   14777           i::Handle<i::JSFunction>::cast(
   14778               v8::Utils::OpenHandle(*env->Global()
   14779                                          ->Get(env.local(), v8_str("bar"))
   14780                                          .ToLocalChecked()))
   14781               ->code());
   14782       i::Handle<i::Code> foo_code(
   14783           i::Handle<i::JSFunction>::cast(
   14784               v8::Utils::OpenHandle(*env->Global()
   14785                                          ->Get(env.local(), v8_str("foo"))
   14786                                          .ToLocalChecked()))
   14787               ->code());
   14788 
   14789       // Clear the compilation cache to get more wastage.
   14790       reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
   14791     }
   14792 
   14793     // Force code movement.
   14794     heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler_Move");
   14795 
   14796     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
   14797 
   14798     CHECK_LE(kIterations, saw_bar);
   14799     CHECK_LT(0, move_events);
   14800 
   14801     code_map = NULL;
   14802     jitcode_line_info = NULL;
   14803   }
   14804 
   14805   isolate->Exit();
   14806   isolate->Dispose();
   14807 
   14808   // Do this in a new isolate.
   14809   isolate = v8::Isolate::New(create_params);
   14810   isolate->Enter();
   14811 
   14812   // Verify that we get callbacks for existing code objects when we
   14813   // request enumeration of existing code.
   14814   {
   14815     v8::HandleScope scope(isolate);
   14816     LocalContext env(isolate);
   14817     CompileRun(script);
   14818 
   14819     // Now get code through initial iteration.
   14820     v8::base::HashMap code(MatchPointers);
   14821     code_map = &code;
   14822 
   14823     v8::base::HashMap lineinfo(MatchPointers);
   14824     jitcode_line_info = &lineinfo;
   14825 
   14826     isolate->SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting,
   14827                                     event_handler);
   14828     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
   14829 
   14830     jitcode_line_info = NULL;
   14831     // We expect that we got some events. Note that if we could get code removal
   14832     // notifications, we could compare two collections, one created by listening
   14833     // from the time of creation of an isolate, and the other by subscribing
   14834     // with EnumExisting.
   14835     CHECK_LT(0u, code.occupancy());
   14836 
   14837     code_map = NULL;
   14838   }
   14839 
   14840   isolate->Exit();
   14841   isolate->Dispose();
   14842 }
   14843 
   14844 
   14845 THREADED_TEST(ExternalAllocatedMemory) {
   14846   v8::Isolate* isolate = CcTest::isolate();
   14847   v8::HandleScope outer(isolate);
   14848   v8::Local<Context> env(Context::New(isolate));
   14849   CHECK(!env.IsEmpty());
   14850   const int64_t kSize = 1024*1024;
   14851   int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
   14852   CHECK_EQ(baseline + kSize,
   14853            isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
   14854   CHECK_EQ(baseline,
   14855            isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
   14856   const int64_t kTriggerGCSize = i::kExternalAllocationLimit + 1;
   14857   CHECK_EQ(baseline + kTriggerGCSize,
   14858            isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize));
   14859   CHECK_EQ(baseline,
   14860            isolate->AdjustAmountOfExternalAllocatedMemory(-kTriggerGCSize));
   14861 }
   14862 
   14863 
   14864 TEST(Regress51719) {
   14865   i::FLAG_incremental_marking = false;
   14866   CcTest::InitializeVM();
   14867 
   14868   const int64_t kTriggerGCSize = i::kExternalAllocationLimit + 1;
   14869   v8::Isolate* isolate = CcTest::isolate();
   14870   isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize);
   14871 }
   14872 
   14873 
   14874 // Regression test for issue 54, object templates with internal fields
   14875 // but no accessors or interceptors did not get their internal field
   14876 // count set on instances.
   14877 THREADED_TEST(Regress54) {
   14878   LocalContext context;
   14879   v8::Isolate* isolate = context->GetIsolate();
   14880   v8::HandleScope outer(isolate);
   14881   static v8::Persistent<v8::ObjectTemplate> templ;
   14882   if (templ.IsEmpty()) {
   14883     v8::EscapableHandleScope inner(isolate);
   14884     v8::Local<v8::ObjectTemplate> local = v8::ObjectTemplate::New(isolate);
   14885     local->SetInternalFieldCount(1);
   14886     templ.Reset(isolate, inner.Escape(local));
   14887   }
   14888   v8::Local<v8::Object> result =
   14889       v8::Local<v8::ObjectTemplate>::New(isolate, templ)
   14890           ->NewInstance(context.local())
   14891           .ToLocalChecked();
   14892   CHECK_EQ(1, result->InternalFieldCount());
   14893 }
   14894 
   14895 
   14896 // If part of the threaded tests, this test makes ThreadingTest fail
   14897 // on mac.
   14898 TEST(CatchStackOverflow) {
   14899   LocalContext context;
   14900   v8::HandleScope scope(context->GetIsolate());
   14901   v8::TryCatch try_catch(context->GetIsolate());
   14902   v8::Local<v8::Value> result = CompileRun(
   14903       "function f() {"
   14904       "  return f();"
   14905       "}"
   14906       ""
   14907       "f();");
   14908   CHECK(result.IsEmpty());
   14909 }
   14910 
   14911 
   14912 static void CheckTryCatchSourceInfo(v8::Local<v8::Script> script,
   14913                                     const char* resource_name,
   14914                                     int line_offset) {
   14915   v8::HandleScope scope(CcTest::isolate());
   14916   v8::TryCatch try_catch(CcTest::isolate());
   14917   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   14918   CHECK(script->Run(context).IsEmpty());
   14919   CHECK(try_catch.HasCaught());
   14920   v8::Local<v8::Message> message = try_catch.Message();
   14921   CHECK(!message.IsEmpty());
   14922   CHECK_EQ(10 + line_offset, message->GetLineNumber(context).FromJust());
   14923   CHECK_EQ(91, message->GetStartPosition());
   14924   CHECK_EQ(92, message->GetEndPosition());
   14925   CHECK_EQ(2, message->GetStartColumn(context).FromJust());
   14926   CHECK_EQ(3, message->GetEndColumn(context).FromJust());
   14927   v8::String::Utf8Value line(message->GetSourceLine(context).ToLocalChecked());
   14928   CHECK_EQ(0, strcmp("  throw 'nirk';", *line));
   14929   v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
   14930   CHECK_EQ(0, strcmp(resource_name, *name));
   14931 }
   14932 
   14933 
   14934 THREADED_TEST(TryCatchSourceInfo) {
   14935   LocalContext context;
   14936   v8::HandleScope scope(context->GetIsolate());
   14937   v8::Local<v8::String> source = v8_str(
   14938       "function Foo() {\n"
   14939       "  return Bar();\n"
   14940       "}\n"
   14941       "\n"
   14942       "function Bar() {\n"
   14943       "  return Baz();\n"
   14944       "}\n"
   14945       "\n"
   14946       "function Baz() {\n"
   14947       "  throw 'nirk';\n"
   14948       "}\n"
   14949       "\n"
   14950       "Foo();\n");
   14951 
   14952   const char* resource_name;
   14953   v8::Local<v8::Script> script;
   14954   resource_name = "test.js";
   14955   script = CompileWithOrigin(source, resource_name);
   14956   CheckTryCatchSourceInfo(script, resource_name, 0);
   14957 
   14958   resource_name = "test1.js";
   14959   v8::ScriptOrigin origin1(v8_str(resource_name));
   14960   script =
   14961       v8::Script::Compile(context.local(), source, &origin1).ToLocalChecked();
   14962   CheckTryCatchSourceInfo(script, resource_name, 0);
   14963 
   14964   resource_name = "test2.js";
   14965   v8::ScriptOrigin origin2(v8_str(resource_name),
   14966                            v8::Integer::New(context->GetIsolate(), 7));
   14967   script =
   14968       v8::Script::Compile(context.local(), source, &origin2).ToLocalChecked();
   14969   CheckTryCatchSourceInfo(script, resource_name, 7);
   14970 }
   14971 
   14972 
   14973 THREADED_TEST(TryCatchSourceInfoForEOSError) {
   14974   LocalContext context;
   14975   v8::HandleScope scope(context->GetIsolate());
   14976   v8::TryCatch try_catch(context->GetIsolate());
   14977   CHECK(v8::Script::Compile(context.local(), v8_str("!\n")).IsEmpty());
   14978   CHECK(try_catch.HasCaught());
   14979   v8::Local<v8::Message> message = try_catch.Message();
   14980   CHECK_EQ(1, message->GetLineNumber(context.local()).FromJust());
   14981   CHECK_EQ(0, message->GetStartColumn(context.local()).FromJust());
   14982 }
   14983 
   14984 
   14985 THREADED_TEST(CompilationCache) {
   14986   LocalContext context;
   14987   v8::HandleScope scope(context->GetIsolate());
   14988   v8::Local<v8::String> source0 = v8_str("1234");
   14989   v8::Local<v8::String> source1 = v8_str("1234");
   14990   v8::Local<v8::Script> script0 = CompileWithOrigin(source0, "test.js");
   14991   v8::Local<v8::Script> script1 = CompileWithOrigin(source1, "test.js");
   14992   v8::Local<v8::Script> script2 = v8::Script::Compile(context.local(), source0)
   14993                                       .ToLocalChecked();  // different origin
   14994   CHECK_EQ(1234, script0->Run(context.local())
   14995                      .ToLocalChecked()
   14996                      ->Int32Value(context.local())
   14997                      .FromJust());
   14998   CHECK_EQ(1234, script1->Run(context.local())
   14999                      .ToLocalChecked()
   15000                      ->Int32Value(context.local())
   15001                      .FromJust());
   15002   CHECK_EQ(1234, script2->Run(context.local())
   15003                      .ToLocalChecked()
   15004                      ->Int32Value(context.local())
   15005                      .FromJust());
   15006 }
   15007 
   15008 
   15009 static void FunctionNameCallback(
   15010     const v8::FunctionCallbackInfo<v8::Value>& args) {
   15011   ApiTestFuzzer::Fuzz();
   15012   args.GetReturnValue().Set(v8_num(42));
   15013 }
   15014 
   15015 
   15016 THREADED_TEST(CallbackFunctionName) {
   15017   LocalContext context;
   15018   v8::Isolate* isolate = context->GetIsolate();
   15019   v8::HandleScope scope(isolate);
   15020   Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
   15021   t->Set(v8_str("asdf"),
   15022          v8::FunctionTemplate::New(isolate, FunctionNameCallback));
   15023   CHECK(context->Global()
   15024             ->Set(context.local(), v8_str("obj"),
   15025                   t->NewInstance(context.local()).ToLocalChecked())
   15026             .FromJust());
   15027   v8::Local<v8::Value> value = CompileRun("obj.asdf.name");
   15028   CHECK(value->IsString());
   15029   v8::String::Utf8Value name(value);
   15030   CHECK_EQ(0, strcmp("asdf", *name));
   15031 }
   15032 
   15033 
   15034 THREADED_TEST(DateAccess) {
   15035   LocalContext context;
   15036   v8::HandleScope scope(context->GetIsolate());
   15037   v8::Local<v8::Value> date =
   15038       v8::Date::New(context.local(), 1224744689038.0).ToLocalChecked();
   15039   CHECK(date->IsDate());
   15040   CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
   15041 }
   15042 
   15043 void CheckIsSymbolAt(v8::Isolate* isolate, v8::Local<v8::Array> properties,
   15044                      unsigned index, const char* name) {
   15045   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   15046   v8::Local<v8::Value> value =
   15047       properties->Get(context, v8::Integer::New(isolate, index))
   15048           .ToLocalChecked();
   15049   CHECK(value->IsSymbol());
   15050   v8::String::Utf8Value symbol_name(Local<Symbol>::Cast(value)->Name());
   15051   CHECK_EQ(0, strcmp(name, *symbol_name));
   15052 }
   15053 
   15054 void CheckStringArray(v8::Isolate* isolate, v8::Local<v8::Array> properties,
   15055                       unsigned length, const char* names[]) {
   15056   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   15057   CHECK_EQ(length, properties->Length());
   15058   for (unsigned i = 0; i < length; i++) {
   15059     v8::Local<v8::Value> value =
   15060         properties->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked();
   15061     if (names[i] == nullptr) {
   15062       DCHECK(value->IsSymbol());
   15063     } else {
   15064       v8::String::Utf8Value elm(value);
   15065       CHECK_EQ(0, strcmp(names[i], *elm));
   15066     }
   15067   }
   15068 }
   15069 
   15070 void CheckProperties(v8::Isolate* isolate, v8::Local<v8::Value> val,
   15071                      unsigned length, const char* names[]) {
   15072   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   15073   v8::Local<v8::Object> obj = val.As<v8::Object>();
   15074   v8::Local<v8::Array> props = obj->GetPropertyNames(context).ToLocalChecked();
   15075   CheckStringArray(isolate, props, length, names);
   15076 }
   15077 
   15078 
   15079 void CheckOwnProperties(v8::Isolate* isolate, v8::Local<v8::Value> val,
   15080                         unsigned elmc, const char* elmv[]) {
   15081   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   15082   v8::Local<v8::Object> obj = val.As<v8::Object>();
   15083   v8::Local<v8::Array> props =
   15084       obj->GetOwnPropertyNames(context).ToLocalChecked();
   15085   CHECK_EQ(elmc, props->Length());
   15086   for (unsigned i = 0; i < elmc; i++) {
   15087     v8::String::Utf8Value elm(
   15088         props->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked());
   15089     CHECK_EQ(0, strcmp(elmv[i], *elm));
   15090   }
   15091 }
   15092 
   15093 
   15094 THREADED_TEST(PropertyEnumeration) {
   15095   LocalContext context;
   15096   v8::Isolate* isolate = context->GetIsolate();
   15097   v8::HandleScope scope(isolate);
   15098   v8::Local<v8::Value> obj = CompileRun(
   15099       "var result = [];"
   15100       "result[0] = {};"
   15101       "result[1] = {a: 1, b: 2};"
   15102       "result[2] = [1, 2, 3];"
   15103       "var proto = {x: 1, y: 2, z: 3};"
   15104       "var x = { __proto__: proto, w: 0, z: 1 };"
   15105       "result[3] = x;"
   15106       "result;");
   15107   v8::Local<v8::Array> elms = obj.As<v8::Array>();
   15108   CHECK_EQ(4u, elms->Length());
   15109   int elmc0 = 0;
   15110   const char** elmv0 = NULL;
   15111   CheckProperties(
   15112       isolate,
   15113       elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
   15114       elmc0, elmv0);
   15115   CheckOwnProperties(
   15116       isolate,
   15117       elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
   15118       elmc0, elmv0);
   15119   int elmc1 = 2;
   15120   const char* elmv1[] = {"a", "b"};
   15121   CheckProperties(
   15122       isolate,
   15123       elms->Get(context.local(), v8::Integer::New(isolate, 1)).ToLocalChecked(),
   15124       elmc1, elmv1);
   15125   CheckOwnProperties(
   15126       isolate,
   15127       elms->Get(context.local(), v8::Integer::New(isolate, 1)).ToLocalChecked(),
   15128       elmc1, elmv1);
   15129   int elmc2 = 3;
   15130   const char* elmv2[] = {"0", "1", "2"};
   15131   CheckProperties(
   15132       isolate,
   15133       elms->Get(context.local(), v8::Integer::New(isolate, 2)).ToLocalChecked(),
   15134       elmc2, elmv2);
   15135   CheckOwnProperties(
   15136       isolate,
   15137       elms->Get(context.local(), v8::Integer::New(isolate, 2)).ToLocalChecked(),
   15138       elmc2, elmv2);
   15139   int elmc3 = 4;
   15140   const char* elmv3[] = {"w", "z", "x", "y"};
   15141   CheckProperties(
   15142       isolate,
   15143       elms->Get(context.local(), v8::Integer::New(isolate, 3)).ToLocalChecked(),
   15144       elmc3, elmv3);
   15145   int elmc4 = 2;
   15146   const char* elmv4[] = {"w", "z"};
   15147   CheckOwnProperties(
   15148       isolate,
   15149       elms->Get(context.local(), v8::Integer::New(isolate, 3)).ToLocalChecked(),
   15150       elmc4, elmv4);
   15151 }
   15152 
   15153 
   15154 THREADED_TEST(PropertyEnumeration2) {
   15155   LocalContext context;
   15156   v8::Isolate* isolate = context->GetIsolate();
   15157   v8::HandleScope scope(isolate);
   15158   v8::Local<v8::Value> obj = CompileRun(
   15159       "var result = [];"
   15160       "result[0] = {};"
   15161       "result[1] = {a: 1, b: 2};"
   15162       "result[2] = [1, 2, 3];"
   15163       "var proto = {x: 1, y: 2, z: 3};"
   15164       "var x = { __proto__: proto, w: 0, z: 1 };"
   15165       "result[3] = x;"
   15166       "result;");
   15167   v8::Local<v8::Array> elms = obj.As<v8::Array>();
   15168   CHECK_EQ(4u, elms->Length());
   15169   int elmc0 = 0;
   15170   const char** elmv0 = NULL;
   15171   CheckProperties(
   15172       isolate,
   15173       elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
   15174       elmc0, elmv0);
   15175 
   15176   v8::Local<v8::Value> val =
   15177       elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked();
   15178   v8::Local<v8::Array> props =
   15179       val.As<v8::Object>()->GetPropertyNames(context.local()).ToLocalChecked();
   15180   CHECK_EQ(0u, props->Length());
   15181   for (uint32_t i = 0; i < props->Length(); i++) {
   15182     printf("p[%u]\n", i);
   15183   }
   15184 }
   15185 
   15186 THREADED_TEST(PropertyNames) {
   15187   LocalContext context;
   15188   v8::Isolate* isolate = context->GetIsolate();
   15189   v8::HandleScope scope(isolate);
   15190   v8::Local<v8::Value> result = CompileRun(
   15191       "var result = {0: 0, 1: 1, a: 2, b: 3};"
   15192       "result[Symbol('symbol')] = true;"
   15193       "result.__proto__ = {2: 4, 3: 5, c: 6, d: 7};"
   15194       "result;");
   15195   v8::Local<v8::Object> object = result.As<v8::Object>();
   15196   v8::PropertyFilter default_filter =
   15197       static_cast<v8::PropertyFilter>(v8::ONLY_ENUMERABLE | v8::SKIP_SYMBOLS);
   15198   v8::PropertyFilter include_symbols_filter = v8::ONLY_ENUMERABLE;
   15199 
   15200   v8::Local<v8::Array> properties =
   15201       object->GetPropertyNames(context.local()).ToLocalChecked();
   15202   const char* expected_properties1[] = {"0", "1", "a", "b", "2", "3", "c", "d"};
   15203   CheckStringArray(isolate, properties, 8, expected_properties1);
   15204 
   15205   properties =
   15206       object
   15207           ->GetPropertyNames(context.local(),
   15208                              v8::KeyCollectionMode::kIncludePrototypes,
   15209                              default_filter, v8::IndexFilter::kIncludeIndices)
   15210           .ToLocalChecked();
   15211   CheckStringArray(isolate, properties, 8, expected_properties1);
   15212 
   15213   properties = object
   15214                    ->GetPropertyNames(context.local(),
   15215                                       v8::KeyCollectionMode::kIncludePrototypes,
   15216                                       include_symbols_filter,
   15217                                       v8::IndexFilter::kIncludeIndices)
   15218                    .ToLocalChecked();
   15219   const char* expected_properties1_1[] = {"0", "1", "a", "b", nullptr,
   15220                                           "2", "3", "c", "d"};
   15221   CheckStringArray(isolate, properties, 9, expected_properties1_1);
   15222   CheckIsSymbolAt(isolate, properties, 4, "symbol");
   15223 
   15224   properties =
   15225       object
   15226           ->GetPropertyNames(context.local(),
   15227                              v8::KeyCollectionMode::kIncludePrototypes,
   15228                              default_filter, v8::IndexFilter::kSkipIndices)
   15229           .ToLocalChecked();
   15230   const char* expected_properties2[] = {"a", "b", "c", "d"};
   15231   CheckStringArray(isolate, properties, 4, expected_properties2);
   15232 
   15233   properties = object
   15234                    ->GetPropertyNames(context.local(),
   15235                                       v8::KeyCollectionMode::kIncludePrototypes,
   15236                                       include_symbols_filter,
   15237                                       v8::IndexFilter::kSkipIndices)
   15238                    .ToLocalChecked();
   15239   const char* expected_properties2_1[] = {"a", "b", nullptr, "c", "d"};
   15240   CheckStringArray(isolate, properties, 5, expected_properties2_1);
   15241   CheckIsSymbolAt(isolate, properties, 2, "symbol");
   15242 
   15243   properties =
   15244       object
   15245           ->GetPropertyNames(context.local(), v8::KeyCollectionMode::kOwnOnly,
   15246                              default_filter, v8::IndexFilter::kIncludeIndices)
   15247           .ToLocalChecked();
   15248   const char* expected_properties3[] = {"0", "1", "a", "b"};
   15249   CheckStringArray(isolate, properties, 4, expected_properties3);
   15250 
   15251   properties = object
   15252                    ->GetPropertyNames(
   15253                        context.local(), v8::KeyCollectionMode::kOwnOnly,
   15254                        include_symbols_filter, v8::IndexFilter::kIncludeIndices)
   15255                    .ToLocalChecked();
   15256   const char* expected_properties3_1[] = {"0", "1", "a", "b", nullptr};
   15257   CheckStringArray(isolate, properties, 5, expected_properties3_1);
   15258   CheckIsSymbolAt(isolate, properties, 4, "symbol");
   15259 
   15260   properties =
   15261       object
   15262           ->GetPropertyNames(context.local(), v8::KeyCollectionMode::kOwnOnly,
   15263                              default_filter, v8::IndexFilter::kSkipIndices)
   15264           .ToLocalChecked();
   15265   const char* expected_properties4[] = {"a", "b"};
   15266   CheckStringArray(isolate, properties, 2, expected_properties4);
   15267 
   15268   properties = object
   15269                    ->GetPropertyNames(
   15270                        context.local(), v8::KeyCollectionMode::kOwnOnly,
   15271                        include_symbols_filter, v8::IndexFilter::kSkipIndices)
   15272                    .ToLocalChecked();
   15273   const char* expected_properties4_1[] = {"a", "b", nullptr};
   15274   CheckStringArray(isolate, properties, 3, expected_properties4_1);
   15275   CheckIsSymbolAt(isolate, properties, 2, "symbol");
   15276 }
   15277 
   15278 THREADED_TEST(AccessChecksReenabledCorrectly) {
   15279   LocalContext context;
   15280   v8::Isolate* isolate = context->GetIsolate();
   15281   v8::HandleScope scope(isolate);
   15282   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   15283   templ->SetAccessCheckCallback(AccessAlwaysBlocked);
   15284   templ->Set(v8_str("a"), v8_str("a"));
   15285   // Add more than 8 (see kMaxFastProperties) properties
   15286   // so that the constructor will force copying map.
   15287   // Cannot sprintf, gcc complains unsafety.
   15288   char buf[4];
   15289   for (char i = '0'; i <= '9' ; i++) {
   15290     buf[0] = i;
   15291     for (char j = '0'; j <= '9'; j++) {
   15292       buf[1] = j;
   15293       for (char k = '0'; k <= '9'; k++) {
   15294         buf[2] = k;
   15295         buf[3] = 0;
   15296         templ->Set(v8_str(buf), v8::Number::New(isolate, k));
   15297       }
   15298     }
   15299   }
   15300 
   15301   Local<v8::Object> instance_1 =
   15302       templ->NewInstance(context.local()).ToLocalChecked();
   15303   CHECK(context->Global()
   15304             ->Set(context.local(), v8_str("obj_1"), instance_1)
   15305             .FromJust());
   15306 
   15307   Local<Value> value_1 = CompileRun("obj_1.a");
   15308   CHECK(value_1.IsEmpty());
   15309 
   15310   Local<v8::Object> instance_2 =
   15311       templ->NewInstance(context.local()).ToLocalChecked();
   15312   CHECK(context->Global()
   15313             ->Set(context.local(), v8_str("obj_2"), instance_2)
   15314             .FromJust());
   15315 
   15316   Local<Value> value_2 = CompileRun("obj_2.a");
   15317   CHECK(value_2.IsEmpty());
   15318 }
   15319 
   15320 
   15321 // Tests that ScriptData can be serialized and deserialized.
   15322 TEST(PreCompileSerialization) {
   15323   // Producing cached parser data while parsing eagerly is not supported.
   15324   if (!i::FLAG_lazy || (i::FLAG_ignition && i::FLAG_ignition_eager)) return;
   15325 
   15326   v8::V8::Initialize();
   15327   LocalContext env;
   15328   v8::Isolate* isolate = env->GetIsolate();
   15329   HandleScope handle_scope(isolate);
   15330 
   15331   i::FLAG_min_preparse_length = 0;
   15332   const char* script = "function foo(a) { return a+1; }";
   15333   v8::ScriptCompiler::Source source(v8_str(script));
   15334   v8::ScriptCompiler::Compile(env.local(), &source,
   15335                               v8::ScriptCompiler::kProduceParserCache)
   15336       .ToLocalChecked();
   15337   // Serialize.
   15338   const v8::ScriptCompiler::CachedData* cd = source.GetCachedData();
   15339   i::byte* serialized_data = i::NewArray<i::byte>(cd->length);
   15340   i::MemCopy(serialized_data, cd->data, cd->length);
   15341 
   15342   // Deserialize.
   15343   i::ScriptData* deserialized = new i::ScriptData(serialized_data, cd->length);
   15344 
   15345   // Verify that the original is the same as the deserialized.
   15346   CHECK_EQ(cd->length, deserialized->length());
   15347   CHECK_EQ(0, memcmp(cd->data, deserialized->data(), cd->length));
   15348 
   15349   delete deserialized;
   15350   i::DeleteArray(serialized_data);
   15351 }
   15352 
   15353 
   15354 // This tests that we do not allow dictionary load/call inline caches
   15355 // to use functions that have not yet been compiled.  The potential
   15356 // problem of loading a function that has not yet been compiled can
   15357 // arise because we share code between contexts via the compilation
   15358 // cache.
   15359 THREADED_TEST(DictionaryICLoadedFunction) {
   15360   v8::HandleScope scope(CcTest::isolate());
   15361   // Test LoadIC.
   15362   for (int i = 0; i < 2; i++) {
   15363     LocalContext context;
   15364     CHECK(context->Global()
   15365               ->Set(context.local(), v8_str("tmp"), v8::True(CcTest::isolate()))
   15366               .FromJust());
   15367     context->Global()->Delete(context.local(), v8_str("tmp")).FromJust();
   15368     CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
   15369   }
   15370   // Test CallIC.
   15371   for (int i = 0; i < 2; i++) {
   15372     LocalContext context;
   15373     CHECK(context->Global()
   15374               ->Set(context.local(), v8_str("tmp"), v8::True(CcTest::isolate()))
   15375               .FromJust());
   15376     context->Global()->Delete(context.local(), v8_str("tmp")).FromJust();
   15377     CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
   15378   }
   15379 }
   15380 
   15381 
   15382 // Test that cross-context new calls use the context of the callee to
   15383 // create the new JavaScript object.
   15384 THREADED_TEST(CrossContextNew) {
   15385   v8::Isolate* isolate = CcTest::isolate();
   15386   v8::HandleScope scope(isolate);
   15387   v8::Local<Context> context0 = Context::New(isolate);
   15388   v8::Local<Context> context1 = Context::New(isolate);
   15389 
   15390   // Allow cross-domain access.
   15391   Local<String> token = v8_str("<security token>");
   15392   context0->SetSecurityToken(token);
   15393   context1->SetSecurityToken(token);
   15394 
   15395   // Set an 'x' property on the Object prototype and define a
   15396   // constructor function in context0.
   15397   context0->Enter();
   15398   CompileRun("Object.prototype.x = 42; function C() {};");
   15399   context0->Exit();
   15400 
   15401   // Call the constructor function from context0 and check that the
   15402   // result has the 'x' property.
   15403   context1->Enter();
   15404   CHECK(context1->Global()
   15405             ->Set(context1, v8_str("other"), context0->Global())
   15406             .FromJust());
   15407   Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
   15408   CHECK(value->IsInt32());
   15409   CHECK_EQ(42, value->Int32Value(context1).FromJust());
   15410   context1->Exit();
   15411 }
   15412 
   15413 
   15414 // Verify that we can clone an object
   15415 TEST(ObjectClone) {
   15416   LocalContext env;
   15417   v8::Isolate* isolate = env->GetIsolate();
   15418   v8::HandleScope scope(isolate);
   15419 
   15420   const char* sample =
   15421     "var rv = {};"      \
   15422     "rv.alpha = 'hello';" \
   15423     "rv.beta = 123;"     \
   15424     "rv;";
   15425 
   15426   // Create an object, verify basics.
   15427   Local<Value> val = CompileRun(sample);
   15428   CHECK(val->IsObject());
   15429   Local<v8::Object> obj = val.As<v8::Object>();
   15430   obj->Set(env.local(), v8_str("gamma"), v8_str("cloneme")).FromJust();
   15431 
   15432   CHECK(v8_str("hello")
   15433             ->Equals(env.local(),
   15434                      obj->Get(env.local(), v8_str("alpha")).ToLocalChecked())
   15435             .FromJust());
   15436   CHECK(v8::Integer::New(isolate, 123)
   15437             ->Equals(env.local(),
   15438                      obj->Get(env.local(), v8_str("beta")).ToLocalChecked())
   15439             .FromJust());
   15440   CHECK(v8_str("cloneme")
   15441             ->Equals(env.local(),
   15442                      obj->Get(env.local(), v8_str("gamma")).ToLocalChecked())
   15443             .FromJust());
   15444 
   15445   // Clone it.
   15446   Local<v8::Object> clone = obj->Clone();
   15447   CHECK(v8_str("hello")
   15448             ->Equals(env.local(),
   15449                      clone->Get(env.local(), v8_str("alpha")).ToLocalChecked())
   15450             .FromJust());
   15451   CHECK(v8::Integer::New(isolate, 123)
   15452             ->Equals(env.local(),
   15453                      clone->Get(env.local(), v8_str("beta")).ToLocalChecked())
   15454             .FromJust());
   15455   CHECK(v8_str("cloneme")
   15456             ->Equals(env.local(),
   15457                      clone->Get(env.local(), v8_str("gamma")).ToLocalChecked())
   15458             .FromJust());
   15459 
   15460   // Set a property on the clone, verify each object.
   15461   CHECK(clone->Set(env.local(), v8_str("beta"), v8::Integer::New(isolate, 456))
   15462             .FromJust());
   15463   CHECK(v8::Integer::New(isolate, 123)
   15464             ->Equals(env.local(),
   15465                      obj->Get(env.local(), v8_str("beta")).ToLocalChecked())
   15466             .FromJust());
   15467   CHECK(v8::Integer::New(isolate, 456)
   15468             ->Equals(env.local(),
   15469                      clone->Get(env.local(), v8_str("beta")).ToLocalChecked())
   15470             .FromJust());
   15471 }
   15472 
   15473 
   15474 class OneByteVectorResource : public v8::String::ExternalOneByteStringResource {
   15475  public:
   15476   explicit OneByteVectorResource(i::Vector<const char> vector)
   15477       : data_(vector) {}
   15478   virtual ~OneByteVectorResource() {}
   15479   virtual size_t length() const { return data_.length(); }
   15480   virtual const char* data() const { return data_.start(); }
   15481  private:
   15482   i::Vector<const char> data_;
   15483 };
   15484 
   15485 
   15486 class UC16VectorResource : public v8::String::ExternalStringResource {
   15487  public:
   15488   explicit UC16VectorResource(i::Vector<const i::uc16> vector)
   15489       : data_(vector) {}
   15490   virtual ~UC16VectorResource() {}
   15491   virtual size_t length() const { return data_.length(); }
   15492   virtual const i::uc16* data() const { return data_.start(); }
   15493  private:
   15494   i::Vector<const i::uc16> data_;
   15495 };
   15496 
   15497 
   15498 static void MorphAString(i::String* string,
   15499                          OneByteVectorResource* one_byte_resource,
   15500                          UC16VectorResource* uc16_resource) {
   15501   CHECK(i::StringShape(string).IsExternal());
   15502   if (string->IsOneByteRepresentation()) {
   15503     // Check old map is not internalized or long.
   15504     CHECK(string->map() == CcTest::heap()->external_one_byte_string_map());
   15505     // Morph external string to be TwoByte string.
   15506     string->set_map(CcTest::heap()->external_string_map());
   15507     i::ExternalTwoByteString* morphed =
   15508          i::ExternalTwoByteString::cast(string);
   15509     morphed->set_resource(uc16_resource);
   15510   } else {
   15511     // Check old map is not internalized or long.
   15512     CHECK(string->map() == CcTest::heap()->external_string_map());
   15513     // Morph external string to be one-byte string.
   15514     string->set_map(CcTest::heap()->external_one_byte_string_map());
   15515     i::ExternalOneByteString* morphed = i::ExternalOneByteString::cast(string);
   15516     morphed->set_resource(one_byte_resource);
   15517   }
   15518 }
   15519 
   15520 
   15521 // Test that we can still flatten a string if the components it is built up
   15522 // from have been turned into 16 bit strings in the mean time.
   15523 THREADED_TEST(MorphCompositeStringTest) {
   15524   char utf_buffer[129];
   15525   const char* c_string = "Now is the time for all good men"
   15526                          " to come to the aid of the party";
   15527   uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
   15528   {
   15529     LocalContext env;
   15530     i::Factory* factory = CcTest::i_isolate()->factory();
   15531     v8::HandleScope scope(env->GetIsolate());
   15532     OneByteVectorResource one_byte_resource(
   15533         i::Vector<const char>(c_string, i::StrLength(c_string)));
   15534     UC16VectorResource uc16_resource(
   15535         i::Vector<const uint16_t>(two_byte_string,
   15536                                   i::StrLength(c_string)));
   15537 
   15538     Local<String> lhs(
   15539         v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
   15540                                         &one_byte_resource).ToHandleChecked()));
   15541     Local<String> rhs(
   15542         v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
   15543                                         &one_byte_resource).ToHandleChecked()));
   15544 
   15545     CHECK(env->Global()->Set(env.local(), v8_str("lhs"), lhs).FromJust());
   15546     CHECK(env->Global()->Set(env.local(), v8_str("rhs"), rhs).FromJust());
   15547 
   15548     CompileRun(
   15549         "var cons = lhs + rhs;"
   15550         "var slice = lhs.substring(1, lhs.length - 1);"
   15551         "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
   15552 
   15553     CHECK(lhs->IsOneByte());
   15554     CHECK(rhs->IsOneByte());
   15555 
   15556     MorphAString(*v8::Utils::OpenHandle(*lhs), &one_byte_resource,
   15557                  &uc16_resource);
   15558     MorphAString(*v8::Utils::OpenHandle(*rhs), &one_byte_resource,
   15559                  &uc16_resource);
   15560 
   15561     // This should UTF-8 without flattening, since everything is ASCII.
   15562     Local<String> cons =
   15563         v8_compile("cons")->Run(env.local()).ToLocalChecked().As<String>();
   15564     CHECK_EQ(128, cons->Utf8Length());
   15565     int nchars = -1;
   15566     CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
   15567     CHECK_EQ(128, nchars);
   15568     CHECK_EQ(0, strcmp(
   15569         utf_buffer,
   15570         "Now is the time for all good men to come to the aid of the party"
   15571         "Now is the time for all good men to come to the aid of the party"));
   15572 
   15573     // Now do some stuff to make sure the strings are flattened, etc.
   15574     CompileRun(
   15575         "/[^a-z]/.test(cons);"
   15576         "/[^a-z]/.test(slice);"
   15577         "/[^a-z]/.test(slice_on_cons);");
   15578     const char* expected_cons =
   15579         "Now is the time for all good men to come to the aid of the party"
   15580         "Now is the time for all good men to come to the aid of the party";
   15581     const char* expected_slice =
   15582         "ow is the time for all good men to come to the aid of the part";
   15583     const char* expected_slice_on_cons =
   15584         "ow is the time for all good men to come to the aid of the party"
   15585         "Now is the time for all good men to come to the aid of the part";
   15586     CHECK(v8_str(expected_cons)
   15587               ->Equals(env.local(), env->Global()
   15588                                         ->Get(env.local(), v8_str("cons"))
   15589                                         .ToLocalChecked())
   15590               .FromJust());
   15591     CHECK(v8_str(expected_slice)
   15592               ->Equals(env.local(), env->Global()
   15593                                         ->Get(env.local(), v8_str("slice"))
   15594                                         .ToLocalChecked())
   15595               .FromJust());
   15596     CHECK(v8_str(expected_slice_on_cons)
   15597               ->Equals(env.local(),
   15598                        env->Global()
   15599                            ->Get(env.local(), v8_str("slice_on_cons"))
   15600                            .ToLocalChecked())
   15601               .FromJust());
   15602   }
   15603   i::DeleteArray(two_byte_string);
   15604 }
   15605 
   15606 
   15607 TEST(CompileExternalTwoByteSource) {
   15608   LocalContext context;
   15609   v8::HandleScope scope(context->GetIsolate());
   15610 
   15611   // This is a very short list of sources, which currently is to check for a
   15612   // regression caused by r2703.
   15613   const char* one_byte_sources[] = {
   15614       "0.5",
   15615       "-0.5",   // This mainly testes PushBack in the Scanner.
   15616       "--0.5",  // This mainly testes PushBack in the Scanner.
   15617       NULL};
   15618 
   15619   // Compile the sources as external two byte strings.
   15620   for (int i = 0; one_byte_sources[i] != NULL; i++) {
   15621     uint16_t* two_byte_string = AsciiToTwoByteString(one_byte_sources[i]);
   15622     TestResource* uc16_resource = new TestResource(two_byte_string);
   15623     v8::Local<v8::String> source =
   15624         v8::String::NewExternalTwoByte(context->GetIsolate(), uc16_resource)
   15625             .ToLocalChecked();
   15626     v8::Script::Compile(context.local(), source).FromMaybe(Local<Script>());
   15627   }
   15628 }
   15629 
   15630 
   15631 #ifndef V8_INTERPRETED_REGEXP
   15632 
   15633 struct RegExpInterruptionData {
   15634   v8::base::Atomic32 loop_count;
   15635   UC16VectorResource* string_resource;
   15636   v8::Persistent<v8::String> string;
   15637 } regexp_interruption_data;
   15638 
   15639 
   15640 class RegExpInterruptionThread : public v8::base::Thread {
   15641  public:
   15642   explicit RegExpInterruptionThread(v8::Isolate* isolate)
   15643       : Thread(Options("TimeoutThread")), isolate_(isolate) {}
   15644 
   15645   virtual void Run() {
   15646     for (v8::base::NoBarrier_Store(&regexp_interruption_data.loop_count, 0);
   15647          v8::base::NoBarrier_Load(&regexp_interruption_data.loop_count) < 7;
   15648          v8::base::NoBarrier_AtomicIncrement(
   15649              &regexp_interruption_data.loop_count, 1)) {
   15650       // Wait a bit before requesting GC.
   15651       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
   15652       reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
   15653     }
   15654     // Wait a bit before terminating.
   15655     v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
   15656     isolate_->TerminateExecution();
   15657   }
   15658 
   15659  private:
   15660   v8::Isolate* isolate_;
   15661 };
   15662 
   15663 
   15664 void RunBeforeGC(v8::Isolate* isolate, v8::GCType type,
   15665                  v8::GCCallbackFlags flags) {
   15666   if (v8::base::NoBarrier_Load(&regexp_interruption_data.loop_count) != 2) {
   15667     return;
   15668   }
   15669   v8::HandleScope scope(isolate);
   15670   v8::Local<v8::String> string = v8::Local<v8::String>::New(
   15671       CcTest::isolate(), regexp_interruption_data.string);
   15672   string->MakeExternal(regexp_interruption_data.string_resource);
   15673 }
   15674 
   15675 
   15676 // Test that RegExp execution can be interrupted.  Specifically, we test
   15677 // * interrupting with GC
   15678 // * turn the subject string from one-byte internal to two-byte external string
   15679 // * force termination
   15680 TEST(RegExpInterruption) {
   15681   LocalContext env;
   15682   v8::HandleScope scope(env->GetIsolate());
   15683 
   15684   RegExpInterruptionThread timeout_thread(env->GetIsolate());
   15685 
   15686   env->GetIsolate()->AddGCPrologueCallback(RunBeforeGC);
   15687   static const char* one_byte_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
   15688   i::uc16* uc16_content = AsciiToTwoByteString(one_byte_content);
   15689   v8::Local<v8::String> string = v8_str(one_byte_content);
   15690 
   15691   env->Global()->Set(env.local(), v8_str("a"), string).FromJust();
   15692   regexp_interruption_data.string.Reset(env->GetIsolate(), string);
   15693   regexp_interruption_data.string_resource = new UC16VectorResource(
   15694       i::Vector<const i::uc16>(uc16_content, i::StrLength(one_byte_content)));
   15695 
   15696   v8::TryCatch try_catch(env->GetIsolate());
   15697   timeout_thread.Start();
   15698 
   15699   CompileRun("/((a*)*)*b/.exec(a)");
   15700   CHECK(try_catch.HasTerminated());
   15701 
   15702   timeout_thread.Join();
   15703 
   15704   regexp_interruption_data.string.Reset();
   15705   i::DeleteArray(uc16_content);
   15706 }
   15707 
   15708 #endif  // V8_INTERPRETED_REGEXP
   15709 
   15710 
   15711 // Test that we cannot set a property on the global object if there
   15712 // is a read-only property in the prototype chain.
   15713 TEST(ReadOnlyPropertyInGlobalProto) {
   15714   v8::Isolate* isolate = CcTest::isolate();
   15715   v8::HandleScope scope(isolate);
   15716   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   15717   LocalContext context(0, templ);
   15718   v8::Local<v8::Object> global = context->Global();
   15719   v8::Local<v8::Object> global_proto = v8::Local<v8::Object>::Cast(
   15720       global->Get(context.local(), v8_str("__proto__")).ToLocalChecked());
   15721   global_proto->DefineOwnProperty(context.local(), v8_str("x"),
   15722                                   v8::Integer::New(isolate, 0), v8::ReadOnly)
   15723       .FromJust();
   15724   global_proto->DefineOwnProperty(context.local(), v8_str("y"),
   15725                                   v8::Integer::New(isolate, 0), v8::ReadOnly)
   15726       .FromJust();
   15727   // Check without 'eval' or 'with'.
   15728   v8::Local<v8::Value> res =
   15729       CompileRun("function f() { x = 42; return x; }; f()");
   15730   CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
   15731   // Check with 'eval'.
   15732   res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
   15733   CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
   15734   // Check with 'with'.
   15735   res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
   15736   CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
   15737 }
   15738 
   15739 
   15740 TEST(CreateDataProperty) {
   15741   LocalContext env;
   15742   v8::Isolate* isolate = env->GetIsolate();
   15743   v8::HandleScope handle_scope(isolate);
   15744 
   15745   CompileRun(
   15746       "var a = {};"
   15747       "var b = [];"
   15748       "Object.defineProperty(a, 'foo', {value: 23});"
   15749       "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
   15750 
   15751   v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
   15752       env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
   15753   v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
   15754       env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
   15755   {
   15756     // Can't change a non-configurable properties.
   15757     v8::TryCatch try_catch(isolate);
   15758     CHECK(!obj->CreateDataProperty(env.local(), v8_str("foo"),
   15759                                    v8::Integer::New(isolate, 42)).FromJust());
   15760     CHECK(!try_catch.HasCaught());
   15761     CHECK(obj->CreateDataProperty(env.local(), v8_str("bar"),
   15762                                   v8::Integer::New(isolate, 42)).FromJust());
   15763     CHECK(!try_catch.HasCaught());
   15764     v8::Local<v8::Value> val =
   15765         obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
   15766     CHECK(val->IsNumber());
   15767     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15768   }
   15769 
   15770   {
   15771     // Set a regular property.
   15772     v8::TryCatch try_catch(isolate);
   15773     CHECK(obj->CreateDataProperty(env.local(), v8_str("blub"),
   15774                                   v8::Integer::New(isolate, 42)).FromJust());
   15775     CHECK(!try_catch.HasCaught());
   15776     v8::Local<v8::Value> val =
   15777         obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
   15778     CHECK(val->IsNumber());
   15779     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15780   }
   15781 
   15782   {
   15783     // Set an indexed property.
   15784     v8::TryCatch try_catch(isolate);
   15785     CHECK(obj->CreateDataProperty(env.local(), v8_str("1"),
   15786                                   v8::Integer::New(isolate, 42)).FromJust());
   15787     CHECK(!try_catch.HasCaught());
   15788     v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
   15789     CHECK(val->IsNumber());
   15790     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15791   }
   15792 
   15793   {
   15794     // Special cases for arrays.
   15795     v8::TryCatch try_catch(isolate);
   15796     CHECK(!arr->CreateDataProperty(env.local(), v8_str("length"),
   15797                                    v8::Integer::New(isolate, 1)).FromJust());
   15798     CHECK(!try_catch.HasCaught());
   15799   }
   15800   {
   15801     // Special cases for arrays: index exceeds the array's length
   15802     v8::TryCatch try_catch(isolate);
   15803     CHECK(arr->CreateDataProperty(env.local(), 1, v8::Integer::New(isolate, 23))
   15804               .FromJust());
   15805     CHECK(!try_catch.HasCaught());
   15806     CHECK_EQ(2U, arr->Length());
   15807     v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
   15808     CHECK(val->IsNumber());
   15809     CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
   15810 
   15811     // Set an existing entry.
   15812     CHECK(arr->CreateDataProperty(env.local(), 0, v8::Integer::New(isolate, 42))
   15813               .FromJust());
   15814     CHECK(!try_catch.HasCaught());
   15815     val = arr->Get(env.local(), 0).ToLocalChecked();
   15816     CHECK(val->IsNumber());
   15817     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15818   }
   15819 
   15820   CompileRun("Object.freeze(a);");
   15821   {
   15822     // Can't change non-extensible objects.
   15823     v8::TryCatch try_catch(isolate);
   15824     CHECK(!obj->CreateDataProperty(env.local(), v8_str("baz"),
   15825                                    v8::Integer::New(isolate, 42)).FromJust());
   15826     CHECK(!try_catch.HasCaught());
   15827   }
   15828 
   15829   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   15830   templ->SetAccessCheckCallback(AccessAlwaysBlocked);
   15831   v8::Local<v8::Object> access_checked =
   15832       templ->NewInstance(env.local()).ToLocalChecked();
   15833   {
   15834     v8::TryCatch try_catch(isolate);
   15835     CHECK(access_checked->CreateDataProperty(env.local(), v8_str("foo"),
   15836                                              v8::Integer::New(isolate, 42))
   15837               .IsNothing());
   15838     CHECK(try_catch.HasCaught());
   15839   }
   15840 }
   15841 
   15842 
   15843 TEST(DefineOwnProperty) {
   15844   LocalContext env;
   15845   v8::Isolate* isolate = env->GetIsolate();
   15846   v8::HandleScope handle_scope(isolate);
   15847 
   15848   CompileRun(
   15849       "var a = {};"
   15850       "var b = [];"
   15851       "Object.defineProperty(a, 'foo', {value: 23});"
   15852       "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
   15853 
   15854   v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
   15855       env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
   15856   v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
   15857       env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
   15858   {
   15859     // Can't change a non-configurable properties.
   15860     v8::TryCatch try_catch(isolate);
   15861     CHECK(!obj->DefineOwnProperty(env.local(), v8_str("foo"),
   15862                                   v8::Integer::New(isolate, 42)).FromJust());
   15863     CHECK(!try_catch.HasCaught());
   15864     CHECK(obj->DefineOwnProperty(env.local(), v8_str("bar"),
   15865                                  v8::Integer::New(isolate, 42)).FromJust());
   15866     CHECK(!try_catch.HasCaught());
   15867     v8::Local<v8::Value> val =
   15868         obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
   15869     CHECK(val->IsNumber());
   15870     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15871   }
   15872 
   15873   {
   15874     // Set a regular property.
   15875     v8::TryCatch try_catch(isolate);
   15876     CHECK(obj->DefineOwnProperty(env.local(), v8_str("blub"),
   15877                                  v8::Integer::New(isolate, 42)).FromJust());
   15878     CHECK(!try_catch.HasCaught());
   15879     v8::Local<v8::Value> val =
   15880         obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
   15881     CHECK(val->IsNumber());
   15882     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15883   }
   15884 
   15885   {
   15886     // Set an indexed property.
   15887     v8::TryCatch try_catch(isolate);
   15888     CHECK(obj->DefineOwnProperty(env.local(), v8_str("1"),
   15889                                  v8::Integer::New(isolate, 42)).FromJust());
   15890     CHECK(!try_catch.HasCaught());
   15891     v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
   15892     CHECK(val->IsNumber());
   15893     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15894   }
   15895 
   15896   {
   15897     // Special cases for arrays.
   15898     v8::TryCatch try_catch(isolate);
   15899     CHECK(!arr->DefineOwnProperty(env.local(), v8_str("length"),
   15900                                   v8::Integer::New(isolate, 1)).FromJust());
   15901     CHECK(!try_catch.HasCaught());
   15902   }
   15903   {
   15904     // Special cases for arrays: index exceeds the array's length
   15905     v8::TryCatch try_catch(isolate);
   15906     CHECK(arr->DefineOwnProperty(env.local(), v8_str("1"),
   15907                                  v8::Integer::New(isolate, 23)).FromJust());
   15908     CHECK(!try_catch.HasCaught());
   15909     CHECK_EQ(2U, arr->Length());
   15910     v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
   15911     CHECK(val->IsNumber());
   15912     CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
   15913 
   15914     // Set an existing entry.
   15915     CHECK(arr->DefineOwnProperty(env.local(), v8_str("0"),
   15916                                  v8::Integer::New(isolate, 42)).FromJust());
   15917     CHECK(!try_catch.HasCaught());
   15918     val = arr->Get(env.local(), 0).ToLocalChecked();
   15919     CHECK(val->IsNumber());
   15920     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15921   }
   15922 
   15923   {
   15924     // Set a non-writable property.
   15925     v8::TryCatch try_catch(isolate);
   15926     CHECK(obj->DefineOwnProperty(env.local(), v8_str("lala"),
   15927                                  v8::Integer::New(isolate, 42),
   15928                                  v8::ReadOnly).FromJust());
   15929     CHECK(!try_catch.HasCaught());
   15930     v8::Local<v8::Value> val =
   15931         obj->Get(env.local(), v8_str("lala")).ToLocalChecked();
   15932     CHECK(val->IsNumber());
   15933     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15934     CHECK_EQ(v8::ReadOnly, obj->GetPropertyAttributes(
   15935                                     env.local(), v8_str("lala")).FromJust());
   15936     CHECK(!try_catch.HasCaught());
   15937   }
   15938 
   15939   CompileRun("Object.freeze(a);");
   15940   {
   15941     // Can't change non-extensible objects.
   15942     v8::TryCatch try_catch(isolate);
   15943     CHECK(!obj->DefineOwnProperty(env.local(), v8_str("baz"),
   15944                                   v8::Integer::New(isolate, 42)).FromJust());
   15945     CHECK(!try_catch.HasCaught());
   15946   }
   15947 
   15948   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   15949   templ->SetAccessCheckCallback(AccessAlwaysBlocked);
   15950   v8::Local<v8::Object> access_checked =
   15951       templ->NewInstance(env.local()).ToLocalChecked();
   15952   {
   15953     v8::TryCatch try_catch(isolate);
   15954     CHECK(access_checked->DefineOwnProperty(env.local(), v8_str("foo"),
   15955                                             v8::Integer::New(isolate, 42))
   15956               .IsNothing());
   15957     CHECK(try_catch.HasCaught());
   15958   }
   15959 }
   15960 
   15961 
   15962 THREADED_TEST(GetCurrentContextWhenNotInContext) {
   15963   i::Isolate* isolate = CcTest::i_isolate();
   15964   CHECK(isolate != NULL);
   15965   CHECK(isolate->context() == NULL);
   15966   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
   15967   v8::HandleScope scope(v8_isolate);
   15968   // The following should not crash, but return an empty handle.
   15969   v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
   15970   CHECK(current.IsEmpty());
   15971 }
   15972 
   15973 
   15974 // Check that a variable declaration with no explicit initialization
   15975 // value does shadow an existing property in the prototype chain.
   15976 THREADED_TEST(InitGlobalVarInProtoChain) {
   15977   LocalContext context;
   15978   v8::HandleScope scope(context->GetIsolate());
   15979   // Introduce a variable in the prototype chain.
   15980   CompileRun("__proto__.x = 42");
   15981   v8::Local<v8::Value> result = CompileRun("var x = 43; x");
   15982   CHECK(!result->IsUndefined());
   15983   CHECK_EQ(43, result->Int32Value(context.local()).FromJust());
   15984 }
   15985 
   15986 
   15987 // Regression test for issue 398.
   15988 // If a function is added to an object, creating a constant function
   15989 // field, and the result is cloned, replacing the constant function on the
   15990 // original should not affect the clone.
   15991 // See http://code.google.com/p/v8/issues/detail?id=398
   15992 THREADED_TEST(ReplaceConstantFunction) {
   15993   LocalContext context;
   15994   v8::Isolate* isolate = context->GetIsolate();
   15995   v8::HandleScope scope(isolate);
   15996   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   15997   v8::Local<v8::FunctionTemplate> func_templ =
   15998       v8::FunctionTemplate::New(isolate);
   15999   v8::Local<v8::String> foo_string = v8_str("foo");
   16000   obj->Set(context.local(), foo_string,
   16001            func_templ->GetFunction(context.local()).ToLocalChecked())
   16002       .FromJust();
   16003   v8::Local<v8::Object> obj_clone = obj->Clone();
   16004   obj_clone->Set(context.local(), foo_string, v8_str("Hello")).FromJust();
   16005   CHECK(!obj->Get(context.local(), foo_string).ToLocalChecked()->IsUndefined());
   16006 }
   16007 
   16008 
   16009 static void CheckElementValue(i::Isolate* isolate,
   16010                               int expected,
   16011                               i::Handle<i::Object> obj,
   16012                               int offset) {
   16013   i::Object* element =
   16014       *i::Object::GetElement(isolate, obj, offset).ToHandleChecked();
   16015   CHECK_EQ(expected, i::Smi::cast(element)->value());
   16016 }
   16017 
   16018 
   16019 template <class ExternalArrayClass, class ElementType>
   16020 static void ObjectWithExternalArrayTestHelper(Local<Context> context,
   16021                                               v8::Local<Object> obj,
   16022                                               int element_count,
   16023                                               i::ExternalArrayType array_type,
   16024                                               int64_t low, int64_t high) {
   16025   i::Handle<i::JSReceiver> jsobj = v8::Utils::OpenHandle(*obj);
   16026   i::Isolate* isolate = jsobj->GetIsolate();
   16027   obj->Set(context, v8_str("field"),
   16028            v8::Int32::New(reinterpret_cast<v8::Isolate*>(isolate), 1503))
   16029       .FromJust();
   16030   CHECK(context->Global()->Set(context, v8_str("ext_array"), obj).FromJust());
   16031   v8::Local<v8::Value> result = CompileRun("ext_array.field");
   16032   CHECK_EQ(1503, result->Int32Value(context).FromJust());
   16033   result = CompileRun("ext_array[1]");
   16034   CHECK_EQ(1, result->Int32Value(context).FromJust());
   16035 
   16036   // Check assigned smis
   16037   result = CompileRun("for (var i = 0; i < 8; i++) {"
   16038                       "  ext_array[i] = i;"
   16039                       "}"
   16040                       "var sum = 0;"
   16041                       "for (var i = 0; i < 8; i++) {"
   16042                       "  sum += ext_array[i];"
   16043                       "}"
   16044                       "sum;");
   16045 
   16046   CHECK_EQ(28, result->Int32Value(context).FromJust());
   16047   // Check pass through of assigned smis
   16048   result = CompileRun("var sum = 0;"
   16049                       "for (var i = 0; i < 8; i++) {"
   16050                       "  sum += ext_array[i] = ext_array[i] = -i;"
   16051                       "}"
   16052                       "sum;");
   16053   CHECK_EQ(-28, result->Int32Value(context).FromJust());
   16054 
   16055 
   16056   // Check assigned smis in reverse order
   16057   result = CompileRun("for (var i = 8; --i >= 0; ) {"
   16058                       "  ext_array[i] = i;"
   16059                       "}"
   16060                       "var sum = 0;"
   16061                       "for (var i = 0; i < 8; i++) {"
   16062                       "  sum += ext_array[i];"
   16063                       "}"
   16064                       "sum;");
   16065   CHECK_EQ(28, result->Int32Value(context).FromJust());
   16066 
   16067   // Check pass through of assigned HeapNumbers
   16068   result = CompileRun("var sum = 0;"
   16069                       "for (var i = 0; i < 16; i+=2) {"
   16070                       "  sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
   16071                       "}"
   16072                       "sum;");
   16073   CHECK_EQ(-28, result->Int32Value(context).FromJust());
   16074 
   16075   // Check assigned HeapNumbers
   16076   result = CompileRun("for (var i = 0; i < 16; i+=2) {"
   16077                       "  ext_array[i] = (i * 0.5);"
   16078                       "}"
   16079                       "var sum = 0;"
   16080                       "for (var i = 0; i < 16; i+=2) {"
   16081                       "  sum += ext_array[i];"
   16082                       "}"
   16083                       "sum;");
   16084   CHECK_EQ(28, result->Int32Value(context).FromJust());
   16085 
   16086   // Check assigned HeapNumbers in reverse order
   16087   result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
   16088                       "  ext_array[i] = (i * 0.5);"
   16089                       "}"
   16090                       "var sum = 0;"
   16091                       "for (var i = 0; i < 16; i+=2) {"
   16092                       "  sum += ext_array[i];"
   16093                       "}"
   16094                       "sum;");
   16095   CHECK_EQ(28, result->Int32Value(context).FromJust());
   16096 
   16097   i::ScopedVector<char> test_buf(1024);
   16098 
   16099   // Check legal boundary conditions.
   16100   // The repeated loads and stores ensure the ICs are exercised.
   16101   const char* boundary_program =
   16102       "var res = 0;"
   16103       "for (var i = 0; i < 16; i++) {"
   16104       "  ext_array[i] = %lld;"
   16105       "  if (i > 8) {"
   16106       "    res = ext_array[i];"
   16107       "  }"
   16108       "}"
   16109       "res;";
   16110   i::SNPrintF(test_buf,
   16111               boundary_program,
   16112               low);
   16113   result = CompileRun(test_buf.start());
   16114   CHECK_EQ(low, result->IntegerValue(context).FromJust());
   16115 
   16116   i::SNPrintF(test_buf,
   16117               boundary_program,
   16118               high);
   16119   result = CompileRun(test_buf.start());
   16120   CHECK_EQ(high, result->IntegerValue(context).FromJust());
   16121 
   16122   // Check misprediction of type in IC.
   16123   result = CompileRun("var tmp_array = ext_array;"
   16124                       "var sum = 0;"
   16125                       "for (var i = 0; i < 8; i++) {"
   16126                       "  tmp_array[i] = i;"
   16127                       "  sum += tmp_array[i];"
   16128                       "  if (i == 4) {"
   16129                       "    tmp_array = {};"
   16130                       "  }"
   16131                       "}"
   16132                       "sum;");
   16133   // Force GC to trigger verification.
   16134   CcTest::heap()->CollectAllGarbage();
   16135   CHECK_EQ(28, result->Int32Value(context).FromJust());
   16136 
   16137   // Make sure out-of-range loads do not throw.
   16138   i::SNPrintF(test_buf,
   16139               "var caught_exception = false;"
   16140               "try {"
   16141               "  ext_array[%d];"
   16142               "} catch (e) {"
   16143               "  caught_exception = true;"
   16144               "}"
   16145               "caught_exception;",
   16146               element_count);
   16147   result = CompileRun(test_buf.start());
   16148   CHECK_EQ(false, result->BooleanValue(context).FromJust());
   16149 
   16150   // Make sure out-of-range stores do not throw.
   16151   i::SNPrintF(test_buf,
   16152               "var caught_exception = false;"
   16153               "try {"
   16154               "  ext_array[%d] = 1;"
   16155               "} catch (e) {"
   16156               "  caught_exception = true;"
   16157               "}"
   16158               "caught_exception;",
   16159               element_count);
   16160   result = CompileRun(test_buf.start());
   16161   CHECK_EQ(false, result->BooleanValue(context).FromJust());
   16162 
   16163   // Check other boundary conditions, values and operations.
   16164   result = CompileRun("for (var i = 0; i < 8; i++) {"
   16165                       "  ext_array[7] = undefined;"
   16166                       "}"
   16167                       "ext_array[7];");
   16168   CHECK_EQ(0, result->Int32Value(context).FromJust());
   16169   if (array_type == i::kExternalFloat64Array ||
   16170       array_type == i::kExternalFloat32Array) {
   16171     CHECK(std::isnan(
   16172         i::Object::GetElement(isolate, jsobj, 7).ToHandleChecked()->Number()));
   16173   } else {
   16174     CheckElementValue(isolate, 0, jsobj, 7);
   16175   }
   16176 
   16177   result = CompileRun("for (var i = 0; i < 8; i++) {"
   16178                       "  ext_array[6] = '2.3';"
   16179                       "}"
   16180                       "ext_array[6];");
   16181   CHECK_EQ(2, result->Int32Value(context).FromJust());
   16182   CHECK_EQ(2,
   16183            static_cast<int>(
   16184                i::Object::GetElement(
   16185                    isolate, jsobj, 6).ToHandleChecked()->Number()));
   16186 
   16187   if (array_type != i::kExternalFloat32Array &&
   16188       array_type != i::kExternalFloat64Array) {
   16189     // Though the specification doesn't state it, be explicit about
   16190     // converting NaNs and +/-Infinity to zero.
   16191     result = CompileRun("for (var i = 0; i < 8; i++) {"
   16192                         "  ext_array[i] = 5;"
   16193                         "}"
   16194                         "for (var i = 0; i < 8; i++) {"
   16195                         "  ext_array[i] = NaN;"
   16196                         "}"
   16197                         "ext_array[5];");
   16198     CHECK_EQ(0, result->Int32Value(context).FromJust());
   16199     CheckElementValue(isolate, 0, jsobj, 5);
   16200 
   16201     result = CompileRun("for (var i = 0; i < 8; i++) {"
   16202                         "  ext_array[i] = 5;"
   16203                         "}"
   16204                         "for (var i = 0; i < 8; i++) {"
   16205                         "  ext_array[i] = Infinity;"
   16206                         "}"
   16207                         "ext_array[5];");
   16208     int expected_value =
   16209         (array_type == i::kExternalUint8ClampedArray) ? 255 : 0;
   16210     CHECK_EQ(expected_value, result->Int32Value(context).FromJust());
   16211     CheckElementValue(isolate, expected_value, jsobj, 5);
   16212 
   16213     result = CompileRun("for (var i = 0; i < 8; i++) {"
   16214                         "  ext_array[i] = 5;"
   16215                         "}"
   16216                         "for (var i = 0; i < 8; i++) {"
   16217                         "  ext_array[i] = -Infinity;"
   16218                         "}"
   16219                         "ext_array[5];");
   16220     CHECK_EQ(0, result->Int32Value(context).FromJust());
   16221     CheckElementValue(isolate, 0, jsobj, 5);
   16222 
   16223     // Check truncation behavior of integral arrays.
   16224     const char* unsigned_data =
   16225         "var source_data = [0.6, 10.6];"
   16226         "var expected_results = [0, 10];";
   16227     const char* signed_data =
   16228         "var source_data = [0.6, 10.6, -0.6, -10.6];"
   16229         "var expected_results = [0, 10, 0, -10];";
   16230     const char* pixel_data =
   16231         "var source_data = [0.6, 10.6];"
   16232         "var expected_results = [1, 11];";
   16233     bool is_unsigned = (array_type == i::kExternalUint8Array ||
   16234                         array_type == i::kExternalUint16Array ||
   16235                         array_type == i::kExternalUint32Array);
   16236     bool is_pixel_data = array_type == i::kExternalUint8ClampedArray;
   16237 
   16238     i::SNPrintF(test_buf,
   16239                 "%s"
   16240                 "var all_passed = true;"
   16241                 "for (var i = 0; i < source_data.length; i++) {"
   16242                 "  for (var j = 0; j < 8; j++) {"
   16243                 "    ext_array[j] = source_data[i];"
   16244                 "  }"
   16245                 "  all_passed = all_passed &&"
   16246                 "               (ext_array[5] == expected_results[i]);"
   16247                 "}"
   16248                 "all_passed;",
   16249                 (is_unsigned ?
   16250                      unsigned_data :
   16251                      (is_pixel_data ? pixel_data : signed_data)));
   16252     result = CompileRun(test_buf.start());
   16253     CHECK_EQ(true, result->BooleanValue(context).FromJust());
   16254   }
   16255 
   16256   i::Handle<ExternalArrayClass> array(ExternalArrayClass::cast(
   16257       i::Handle<i::JSObject>::cast(jsobj)->elements()));
   16258   for (int i = 0; i < element_count; i++) {
   16259     array->set(i, static_cast<ElementType>(i));
   16260   }
   16261 
   16262   // Test complex assignments
   16263   result = CompileRun("function ee_op_test_complex_func(sum) {"
   16264                       " for (var i = 0; i < 40; ++i) {"
   16265                       "   sum += (ext_array[i] += 1);"
   16266                       "   sum += (ext_array[i] -= 1);"
   16267                       " } "
   16268                       " return sum;"
   16269                       "}"
   16270                       "sum=0;"
   16271                       "for (var i=0;i<10000;++i) {"
   16272                       "  sum=ee_op_test_complex_func(sum);"
   16273                       "}"
   16274                       "sum;");
   16275   CHECK_EQ(16000000, result->Int32Value(context).FromJust());
   16276 
   16277   // Test count operations
   16278   result = CompileRun("function ee_op_test_count_func(sum) {"
   16279                       " for (var i = 0; i < 40; ++i) {"
   16280                       "   sum += (++ext_array[i]);"
   16281                       "   sum += (--ext_array[i]);"
   16282                       " } "
   16283                       " return sum;"
   16284                       "}"
   16285                       "sum=0;"
   16286                       "for (var i=0;i<10000;++i) {"
   16287                       "  sum=ee_op_test_count_func(sum);"
   16288                       "}"
   16289                       "sum;");
   16290   CHECK_EQ(16000000, result->Int32Value(context).FromJust());
   16291 
   16292   result = CompileRun("ext_array[3] = 33;"
   16293                       "delete ext_array[3];"
   16294                       "ext_array[3];");
   16295   CHECK_EQ(33, result->Int32Value(context).FromJust());
   16296 
   16297   result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
   16298                       "ext_array[2] = 12; ext_array[3] = 13;"
   16299                       "ext_array.__defineGetter__('2',"
   16300                       "function() { return 120; });"
   16301                       "ext_array[2];");
   16302   CHECK_EQ(12, result->Int32Value(context).FromJust());
   16303 
   16304   result = CompileRun("var js_array = new Array(40);"
   16305                       "js_array[0] = 77;"
   16306                       "js_array;");
   16307   CHECK_EQ(77, v8::Object::Cast(*result)
   16308                    ->Get(context, v8_str("0"))
   16309                    .ToLocalChecked()
   16310                    ->Int32Value(context)
   16311                    .FromJust());
   16312 
   16313   result = CompileRun("ext_array[1] = 23;"
   16314                       "ext_array.__proto__ = [];"
   16315                       "js_array.__proto__ = ext_array;"
   16316                       "js_array.concat(ext_array);");
   16317   CHECK_EQ(77, v8::Object::Cast(*result)
   16318                    ->Get(context, v8_str("0"))
   16319                    .ToLocalChecked()
   16320                    ->Int32Value(context)
   16321                    .FromJust());
   16322   CHECK_EQ(23, v8::Object::Cast(*result)
   16323                    ->Get(context, v8_str("1"))
   16324                    .ToLocalChecked()
   16325                    ->Int32Value(context)
   16326                    .FromJust());
   16327 
   16328   result = CompileRun("ext_array[1] = 23;");
   16329   CHECK_EQ(23, result->Int32Value(context).FromJust());
   16330 }
   16331 
   16332 
   16333 template <class FixedTypedArrayClass, i::ElementsKind elements_kind,
   16334           class ElementType>
   16335 static void FixedTypedArrayTestHelper(i::ExternalArrayType array_type,
   16336                                       ElementType low, ElementType high) {
   16337   i::FLAG_allow_natives_syntax = true;
   16338   LocalContext context;
   16339   i::Isolate* isolate = CcTest::i_isolate();
   16340   i::Factory* factory = isolate->factory();
   16341   v8::HandleScope scope(context->GetIsolate());
   16342   const int kElementCount = 260;
   16343   i::Handle<i::JSTypedArray> jsobj =
   16344       factory->NewJSTypedArray(elements_kind, kElementCount);
   16345   i::Handle<FixedTypedArrayClass> fixed_array(
   16346       FixedTypedArrayClass::cast(jsobj->elements()));
   16347   CHECK_EQ(FixedTypedArrayClass::kInstanceType,
   16348            fixed_array->map()->instance_type());
   16349   CHECK_EQ(kElementCount, fixed_array->length());
   16350   CcTest::heap()->CollectAllGarbage();
   16351   for (int i = 0; i < kElementCount; i++) {
   16352     fixed_array->set(i, static_cast<ElementType>(i));
   16353   }
   16354   // Force GC to trigger verification.
   16355   CcTest::heap()->CollectAllGarbage();
   16356   for (int i = 0; i < kElementCount; i++) {
   16357     CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
   16358              static_cast<int64_t>(fixed_array->get_scalar(i)));
   16359   }
   16360   v8::Local<v8::Object> obj = v8::Utils::ToLocal(jsobj);
   16361 
   16362   ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
   16363       context.local(), obj, kElementCount, array_type,
   16364       static_cast<int64_t>(low),
   16365       static_cast<int64_t>(high));
   16366 }
   16367 
   16368 
   16369 THREADED_TEST(FixedUint8Array) {
   16370   FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
   16371       i::kExternalUint8Array, 0x0, 0xFF);
   16372 }
   16373 
   16374 
   16375 THREADED_TEST(FixedUint8ClampedArray) {
   16376   FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
   16377                             i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
   16378       i::kExternalUint8ClampedArray, 0x0, 0xFF);
   16379 }
   16380 
   16381 
   16382 THREADED_TEST(FixedInt8Array) {
   16383   FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
   16384       i::kExternalInt8Array, -0x80, 0x7F);
   16385 }
   16386 
   16387 
   16388 THREADED_TEST(FixedUint16Array) {
   16389   FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
   16390       i::kExternalUint16Array, 0x0, 0xFFFF);
   16391 }
   16392 
   16393 
   16394 THREADED_TEST(FixedInt16Array) {
   16395   FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
   16396       i::kExternalInt16Array, -0x8000, 0x7FFF);
   16397 }
   16398 
   16399 
   16400 THREADED_TEST(FixedUint32Array) {
   16401   FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
   16402       i::kExternalUint32Array, 0x0, UINT_MAX);
   16403 }
   16404 
   16405 
   16406 THREADED_TEST(FixedInt32Array) {
   16407   FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
   16408       i::kExternalInt32Array, INT_MIN, INT_MAX);
   16409 }
   16410 
   16411 
   16412 THREADED_TEST(FixedFloat32Array) {
   16413   FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
   16414       i::kExternalFloat32Array, -500, 500);
   16415 }
   16416 
   16417 
   16418 THREADED_TEST(FixedFloat64Array) {
   16419   FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
   16420       i::kExternalFloat64Array, -500, 500);
   16421 }
   16422 
   16423 
   16424 template <typename ElementType, typename TypedArray, class ExternalArrayClass,
   16425           class ArrayBufferType>
   16426 void TypedArrayTestHelper(i::ExternalArrayType array_type, int64_t low,
   16427                           int64_t high) {
   16428   const int kElementCount = 50;
   16429 
   16430   i::ScopedVector<ElementType> backing_store(kElementCount+2);
   16431 
   16432   LocalContext env;
   16433   v8::Isolate* isolate = env->GetIsolate();
   16434   v8::HandleScope handle_scope(isolate);
   16435 
   16436   Local<ArrayBufferType> ab =
   16437       ArrayBufferType::New(isolate, backing_store.start(),
   16438                            (kElementCount + 2) * sizeof(ElementType));
   16439   Local<TypedArray> ta =
   16440       TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
   16441   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
   16442   CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
   16443   CHECK_EQ(2 * sizeof(ElementType), ta->ByteOffset());
   16444   CHECK_EQ(kElementCount * sizeof(ElementType), ta->ByteLength());
   16445   CHECK(ab->Equals(env.local(), ta->Buffer()).FromJust());
   16446 
   16447   ElementType* data = backing_store.start() + 2;
   16448   for (int i = 0; i < kElementCount; i++) {
   16449     data[i] = static_cast<ElementType>(i);
   16450   }
   16451 
   16452   ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
   16453       env.local(), ta, kElementCount, array_type, low, high);
   16454 }
   16455 
   16456 
   16457 THREADED_TEST(Uint8Array) {
   16458   TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
   16459                        v8::ArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
   16460 }
   16461 
   16462 
   16463 THREADED_TEST(Int8Array) {
   16464   TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
   16465                        v8::ArrayBuffer>(i::kExternalInt8Array, -0x80, 0x7F);
   16466 }
   16467 
   16468 
   16469 THREADED_TEST(Uint16Array) {
   16470   TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
   16471                        v8::ArrayBuffer>(i::kExternalUint16Array, 0, 0xFFFF);
   16472 }
   16473 
   16474 
   16475 THREADED_TEST(Int16Array) {
   16476   TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
   16477                        v8::ArrayBuffer>(i::kExternalInt16Array, -0x8000,
   16478                                         0x7FFF);
   16479 }
   16480 
   16481 
   16482 THREADED_TEST(Uint32Array) {
   16483   TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
   16484                        v8::ArrayBuffer>(i::kExternalUint32Array, 0, UINT_MAX);
   16485 }
   16486 
   16487 
   16488 THREADED_TEST(Int32Array) {
   16489   TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
   16490                        v8::ArrayBuffer>(i::kExternalInt32Array, INT_MIN,
   16491                                         INT_MAX);
   16492 }
   16493 
   16494 
   16495 THREADED_TEST(Float32Array) {
   16496   TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
   16497                        v8::ArrayBuffer>(i::kExternalFloat32Array, -500, 500);
   16498 }
   16499 
   16500 
   16501 THREADED_TEST(Float64Array) {
   16502   TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
   16503                        v8::ArrayBuffer>(i::kExternalFloat64Array, -500, 500);
   16504 }
   16505 
   16506 
   16507 THREADED_TEST(Uint8ClampedArray) {
   16508   TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
   16509                        i::FixedUint8ClampedArray, v8::ArrayBuffer>(
   16510       i::kExternalUint8ClampedArray, 0, 0xFF);
   16511 }
   16512 
   16513 
   16514 THREADED_TEST(DataView) {
   16515   const int kSize = 50;
   16516 
   16517   i::ScopedVector<uint8_t> backing_store(kSize+2);
   16518 
   16519   LocalContext env;
   16520   v8::Isolate* isolate = env->GetIsolate();
   16521   v8::HandleScope handle_scope(isolate);
   16522 
   16523   Local<v8::ArrayBuffer> ab =
   16524       v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
   16525   Local<v8::DataView> dv = v8::DataView::New(ab, 2, kSize);
   16526   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
   16527   CHECK_EQ(2u, dv->ByteOffset());
   16528   CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
   16529   CHECK(ab->Equals(env.local(), dv->Buffer()).FromJust());
   16530 }
   16531 
   16532 
   16533 THREADED_TEST(SkipArrayBufferBackingStoreDuringGC) {
   16534   LocalContext env;
   16535   v8::Isolate* isolate = env->GetIsolate();
   16536   v8::HandleScope handle_scope(isolate);
   16537 
   16538   // Make sure the pointer looks like a heap object
   16539   uint8_t* store_ptr = reinterpret_cast<uint8_t*>(i::kHeapObjectTag);
   16540 
   16541   // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
   16542   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
   16543 
   16544   // Should not crash
   16545   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
   16546   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
   16547   CcTest::heap()->CollectAllGarbage();
   16548   CcTest::heap()->CollectAllGarbage();
   16549 
   16550   // Should not move the pointer
   16551   CHECK_EQ(ab->GetContents().Data(), store_ptr);
   16552 }
   16553 
   16554 
   16555 THREADED_TEST(SkipArrayBufferDuringScavenge) {
   16556   LocalContext env;
   16557   v8::Isolate* isolate = env->GetIsolate();
   16558   v8::HandleScope handle_scope(isolate);
   16559 
   16560   // Make sure the pointer looks like a heap object
   16561   Local<v8::Object> tmp = v8::Object::New(isolate);
   16562   uint8_t* store_ptr =
   16563       reinterpret_cast<uint8_t*>(*reinterpret_cast<uintptr_t*>(*tmp));
   16564 
   16565   // Make `store_ptr` point to from space
   16566   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
   16567 
   16568   // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
   16569   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
   16570 
   16571   // Should not crash,
   16572   // i.e. backing store pointer should not be treated as a heap object pointer
   16573   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
   16574   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
   16575 
   16576   // Use `ab` to silence compiler warning
   16577   CHECK_EQ(ab->GetContents().Data(), store_ptr);
   16578 }
   16579 
   16580 
   16581 THREADED_TEST(SharedUint8Array) {
   16582   i::FLAG_harmony_sharedarraybuffer = true;
   16583   TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
   16584                        v8::SharedArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
   16585 }
   16586 
   16587 
   16588 THREADED_TEST(SharedInt8Array) {
   16589   i::FLAG_harmony_sharedarraybuffer = true;
   16590   TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
   16591                        v8::SharedArrayBuffer>(i::kExternalInt8Array, -0x80,
   16592                                               0x7F);
   16593 }
   16594 
   16595 
   16596 THREADED_TEST(SharedUint16Array) {
   16597   i::FLAG_harmony_sharedarraybuffer = true;
   16598   TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
   16599                        v8::SharedArrayBuffer>(i::kExternalUint16Array, 0,
   16600                                               0xFFFF);
   16601 }
   16602 
   16603 
   16604 THREADED_TEST(SharedInt16Array) {
   16605   i::FLAG_harmony_sharedarraybuffer = true;
   16606   TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
   16607                        v8::SharedArrayBuffer>(i::kExternalInt16Array, -0x8000,
   16608                                               0x7FFF);
   16609 }
   16610 
   16611 
   16612 THREADED_TEST(SharedUint32Array) {
   16613   i::FLAG_harmony_sharedarraybuffer = true;
   16614   TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
   16615                        v8::SharedArrayBuffer>(i::kExternalUint32Array, 0,
   16616                                               UINT_MAX);
   16617 }
   16618 
   16619 
   16620 THREADED_TEST(SharedInt32Array) {
   16621   i::FLAG_harmony_sharedarraybuffer = true;
   16622   TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
   16623                        v8::SharedArrayBuffer>(i::kExternalInt32Array, INT_MIN,
   16624                                               INT_MAX);
   16625 }
   16626 
   16627 
   16628 THREADED_TEST(SharedFloat32Array) {
   16629   i::FLAG_harmony_sharedarraybuffer = true;
   16630   TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
   16631                        v8::SharedArrayBuffer>(i::kExternalFloat32Array, -500,
   16632                                               500);
   16633 }
   16634 
   16635 
   16636 THREADED_TEST(SharedFloat64Array) {
   16637   i::FLAG_harmony_sharedarraybuffer = true;
   16638   TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
   16639                        v8::SharedArrayBuffer>(i::kExternalFloat64Array, -500,
   16640                                               500);
   16641 }
   16642 
   16643 
   16644 THREADED_TEST(SharedUint8ClampedArray) {
   16645   i::FLAG_harmony_sharedarraybuffer = true;
   16646   TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
   16647                        i::FixedUint8ClampedArray, v8::SharedArrayBuffer>(
   16648       i::kExternalUint8ClampedArray, 0, 0xFF);
   16649 }
   16650 
   16651 
   16652 THREADED_TEST(SharedDataView) {
   16653   i::FLAG_harmony_sharedarraybuffer = true;
   16654   const int kSize = 50;
   16655 
   16656   i::ScopedVector<uint8_t> backing_store(kSize + 2);
   16657 
   16658   LocalContext env;
   16659   v8::Isolate* isolate = env->GetIsolate();
   16660   v8::HandleScope handle_scope(isolate);
   16661 
   16662   Local<v8::SharedArrayBuffer> ab =
   16663       v8::SharedArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
   16664   Local<v8::DataView> dv =
   16665       v8::DataView::New(ab, 2, kSize);
   16666   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
   16667   CHECK_EQ(2u, dv->ByteOffset());
   16668   CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
   16669   CHECK(ab->Equals(env.local(), dv->Buffer()).FromJust());
   16670 }
   16671 
   16672 
   16673 #define IS_ARRAY_BUFFER_VIEW_TEST(View)                                     \
   16674   THREADED_TEST(Is##View) {                                                 \
   16675     LocalContext env;                                                       \
   16676     v8::Isolate* isolate = env->GetIsolate();                               \
   16677     v8::HandleScope handle_scope(isolate);                                  \
   16678                                                                             \
   16679     Local<Value> result = CompileRun(                                       \
   16680         "var ab = new ArrayBuffer(128);"                                    \
   16681         "new " #View "(ab)");                                               \
   16682     CHECK(result->IsArrayBufferView());                                     \
   16683     CHECK(result->Is##View());                                              \
   16684     CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>()); \
   16685   }
   16686 
   16687 IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
   16688 IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
   16689 IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
   16690 IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
   16691 IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
   16692 IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
   16693 IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
   16694 IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
   16695 IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
   16696 IS_ARRAY_BUFFER_VIEW_TEST(DataView)
   16697 
   16698 #undef IS_ARRAY_BUFFER_VIEW_TEST
   16699 
   16700 
   16701 
   16702 THREADED_TEST(ScriptContextDependence) {
   16703   LocalContext c1;
   16704   v8::HandleScope scope(c1->GetIsolate());
   16705   const char *source = "foo";
   16706   v8::Local<v8::Script> dep = v8_compile(source);
   16707   v8::ScriptCompiler::Source script_source(
   16708       v8::String::NewFromUtf8(c1->GetIsolate(), source,
   16709                               v8::NewStringType::kNormal)
   16710           .ToLocalChecked());
   16711   v8::Local<v8::UnboundScript> indep =
   16712       v8::ScriptCompiler::CompileUnboundScript(c1->GetIsolate(), &script_source)
   16713           .ToLocalChecked();
   16714   c1->Global()
   16715       ->Set(c1.local(), v8::String::NewFromUtf8(c1->GetIsolate(), "foo",
   16716                                                 v8::NewStringType::kNormal)
   16717                             .ToLocalChecked(),
   16718             v8::Integer::New(c1->GetIsolate(), 100))
   16719       .FromJust();
   16720   CHECK_EQ(
   16721       dep->Run(c1.local()).ToLocalChecked()->Int32Value(c1.local()).FromJust(),
   16722       100);
   16723   CHECK_EQ(indep->BindToCurrentContext()
   16724                ->Run(c1.local())
   16725                .ToLocalChecked()
   16726                ->Int32Value(c1.local())
   16727                .FromJust(),
   16728            100);
   16729   LocalContext c2;
   16730   c2->Global()
   16731       ->Set(c2.local(), v8::String::NewFromUtf8(c2->GetIsolate(), "foo",
   16732                                                 v8::NewStringType::kNormal)
   16733                             .ToLocalChecked(),
   16734             v8::Integer::New(c2->GetIsolate(), 101))
   16735       .FromJust();
   16736   CHECK_EQ(
   16737       dep->Run(c2.local()).ToLocalChecked()->Int32Value(c2.local()).FromJust(),
   16738       100);
   16739   CHECK_EQ(indep->BindToCurrentContext()
   16740                ->Run(c2.local())
   16741                .ToLocalChecked()
   16742                ->Int32Value(c2.local())
   16743                .FromJust(),
   16744            101);
   16745 }
   16746 
   16747 
   16748 THREADED_TEST(StackTrace) {
   16749   LocalContext context;
   16750   v8::HandleScope scope(context->GetIsolate());
   16751   v8::TryCatch try_catch(context->GetIsolate());
   16752   const char *source = "function foo() { FAIL.FAIL; }; foo();";
   16753   v8::Local<v8::String> src = v8_str(source);
   16754   v8::Local<v8::String> origin = v8_str("stack-trace-test");
   16755   v8::ScriptCompiler::Source script_source(src, v8::ScriptOrigin(origin));
   16756   CHECK(v8::ScriptCompiler::CompileUnboundScript(context->GetIsolate(),
   16757                                                  &script_source)
   16758             .ToLocalChecked()
   16759             ->BindToCurrentContext()
   16760             ->Run(context.local())
   16761             .IsEmpty());
   16762   CHECK(try_catch.HasCaught());
   16763   v8::String::Utf8Value stack(
   16764       try_catch.StackTrace(context.local()).ToLocalChecked());
   16765   CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
   16766 }
   16767 
   16768 
   16769 // Checks that a StackFrame has certain expected values.
   16770 void checkStackFrame(const char* expected_script_name,
   16771                      const char* expected_func_name, int expected_line_number,
   16772                      int expected_column, bool is_eval, bool is_constructor,
   16773                      v8::Local<v8::StackFrame> frame) {
   16774   v8::HandleScope scope(CcTest::isolate());
   16775   v8::String::Utf8Value func_name(frame->GetFunctionName());
   16776   v8::String::Utf8Value script_name(frame->GetScriptName());
   16777   if (*script_name == NULL) {
   16778     // The situation where there is no associated script, like for evals.
   16779     CHECK(expected_script_name == NULL);
   16780   } else {
   16781     CHECK(strstr(*script_name, expected_script_name) != NULL);
   16782   }
   16783   CHECK(strstr(*func_name, expected_func_name) != NULL);
   16784   CHECK_EQ(expected_line_number, frame->GetLineNumber());
   16785   CHECK_EQ(expected_column, frame->GetColumn());
   16786   CHECK_EQ(is_eval, frame->IsEval());
   16787   CHECK_EQ(is_constructor, frame->IsConstructor());
   16788 }
   16789 
   16790 
   16791 void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
   16792   v8::HandleScope scope(args.GetIsolate());
   16793   const char* origin = "capture-stack-trace-test";
   16794   const int kOverviewTest = 1;
   16795   const int kDetailedTest = 2;
   16796   const int kFunctionName = 3;
   16797   const int kDisplayName = 4;
   16798   const int kFunctionNameAndDisplayName = 5;
   16799   const int kDisplayNameIsNotString = 6;
   16800   const int kFunctionNameIsNotString = 7;
   16801 
   16802   CHECK(args.Length() == 1);
   16803 
   16804   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   16805   int testGroup = args[0]->Int32Value(context).FromJust();
   16806   if (testGroup == kOverviewTest) {
   16807     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16808         args.GetIsolate(), 10, v8::StackTrace::kOverview);
   16809     CHECK_EQ(4, stackTrace->GetFrameCount());
   16810     checkStackFrame(origin, "bar", 2, 10, false, false,
   16811                     stackTrace->GetFrame(0));
   16812     checkStackFrame(origin, "foo", 6, 3, false, false,
   16813                     stackTrace->GetFrame(1));
   16814     // This is the source string inside the eval which has the call to foo.
   16815     checkStackFrame(NULL, "", 1, 1, false, false, stackTrace->GetFrame(2));
   16816     // The last frame is an anonymous function which has the initial eval call.
   16817     checkStackFrame(origin, "", 8, 7, false, false, stackTrace->GetFrame(3));
   16818 
   16819     CHECK(stackTrace->AsArray()->IsArray());
   16820   } else if (testGroup == kDetailedTest) {
   16821     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16822         args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   16823     CHECK_EQ(4, stackTrace->GetFrameCount());
   16824     checkStackFrame(origin, "bat", 4, 22, false, false,
   16825                     stackTrace->GetFrame(0));
   16826     checkStackFrame(origin, "baz", 8, 3, false, true,
   16827                     stackTrace->GetFrame(1));
   16828     bool is_eval = true;
   16829     // This is the source string inside the eval which has the call to baz.
   16830     checkStackFrame(NULL, "", 1, 1, is_eval, false, stackTrace->GetFrame(2));
   16831     // The last frame is an anonymous function which has the initial eval call.
   16832     checkStackFrame(origin, "", 10, 1, false, false, stackTrace->GetFrame(3));
   16833 
   16834     CHECK(stackTrace->AsArray()->IsArray());
   16835   } else if (testGroup == kFunctionName) {
   16836     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16837         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   16838     CHECK_EQ(3, stackTrace->GetFrameCount());
   16839     checkStackFrame(origin, "function.name", 2, 24, false, false,
   16840                     stackTrace->GetFrame(0));
   16841   } else if (testGroup == kDisplayName) {
   16842     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16843         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   16844     CHECK_EQ(3, stackTrace->GetFrameCount());
   16845     checkStackFrame(origin, "function.displayName", 2, 24, false, false,
   16846                     stackTrace->GetFrame(0));
   16847   } else if (testGroup == kFunctionNameAndDisplayName) {
   16848     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16849         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   16850     CHECK_EQ(3, stackTrace->GetFrameCount());
   16851     checkStackFrame(origin, "function.displayName", 2, 24, false, false,
   16852                     stackTrace->GetFrame(0));
   16853   } else if (testGroup == kDisplayNameIsNotString) {
   16854     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16855         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   16856     CHECK_EQ(3, stackTrace->GetFrameCount());
   16857     checkStackFrame(origin, "function.name", 2, 24, false, false,
   16858                     stackTrace->GetFrame(0));
   16859   } else if (testGroup == kFunctionNameIsNotString) {
   16860     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16861         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   16862     CHECK_EQ(3, stackTrace->GetFrameCount());
   16863     checkStackFrame(origin, "f", 2, 24, false, false, stackTrace->GetFrame(0));
   16864   }
   16865 }
   16866 
   16867 
   16868 // Tests the C++ StackTrace API.
   16869 // TODO(3074796): Reenable this as a THREADED_TEST once it passes.
   16870 // THREADED_TEST(CaptureStackTrace) {
   16871 TEST(CaptureStackTrace) {
   16872   v8::Isolate* isolate = CcTest::isolate();
   16873   v8::HandleScope scope(isolate);
   16874   v8::Local<v8::String> origin = v8_str("capture-stack-trace-test");
   16875   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   16876   templ->Set(v8_str("AnalyzeStackInNativeCode"),
   16877              v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
   16878   LocalContext context(0, templ);
   16879 
   16880   // Test getting OVERVIEW information. Should ignore information that is not
   16881   // script name, function name, line number, and column offset.
   16882   const char *overview_source =
   16883     "function bar() {\n"
   16884     "  var y; AnalyzeStackInNativeCode(1);\n"
   16885     "}\n"
   16886     "function foo() {\n"
   16887     "\n"
   16888     "  bar();\n"
   16889     "}\n"
   16890     "var x;eval('new foo();');";
   16891   v8::Local<v8::String> overview_src = v8_str(overview_source);
   16892   v8::ScriptCompiler::Source script_source(overview_src,
   16893                                            v8::ScriptOrigin(origin));
   16894   v8::Local<Value> overview_result(
   16895       v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source)
   16896           .ToLocalChecked()
   16897           ->BindToCurrentContext()
   16898           ->Run(context.local())
   16899           .ToLocalChecked());
   16900   CHECK(!overview_result.IsEmpty());
   16901   CHECK(overview_result->IsObject());
   16902 
   16903   // Test getting DETAILED information.
   16904   const char *detailed_source =
   16905     "function bat() {AnalyzeStackInNativeCode(2);\n"
   16906     "}\n"
   16907     "\n"
   16908     "function baz() {\n"
   16909     "  bat();\n"
   16910     "}\n"
   16911     "eval('new baz();');";
   16912   v8::Local<v8::String> detailed_src = v8_str(detailed_source);
   16913   // Make the script using a non-zero line and column offset.
   16914   v8::Local<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
   16915   v8::Local<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
   16916   v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
   16917   v8::ScriptCompiler::Source script_source2(detailed_src, detailed_origin);
   16918   v8::Local<v8::UnboundScript> detailed_script(
   16919       v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source2)
   16920           .ToLocalChecked());
   16921   v8::Local<Value> detailed_result(detailed_script->BindToCurrentContext()
   16922                                        ->Run(context.local())
   16923                                        .ToLocalChecked());
   16924   CHECK(!detailed_result.IsEmpty());
   16925   CHECK(detailed_result->IsObject());
   16926 
   16927   // Test using function.name and function.displayName in stack trace
   16928   const char* function_name_source =
   16929       "function bar(function_name, display_name, testGroup) {\n"
   16930       "  var f = function() { AnalyzeStackInNativeCode(testGroup); };\n"
   16931       "  if (function_name) {\n"
   16932       "    Object.defineProperty(f, 'name', { value: function_name });\n"
   16933       "  }\n"
   16934       "  if (display_name) {\n"
   16935       "    f.displayName = display_name;"
   16936       "  }\n"
   16937       "  f()\n"
   16938       "}\n"
   16939       "bar('function.name', undefined, 3);\n"
   16940       "bar(undefined, 'function.displayName', 4);\n"
   16941       "bar('function.name', 'function.displayName', 5);\n"
   16942       "bar('function.name', 239, 6);\n"
   16943       "bar(239, undefined, 7);\n";
   16944   v8::Local<v8::String> function_name_src =
   16945       v8::String::NewFromUtf8(isolate, function_name_source,
   16946                               v8::NewStringType::kNormal)
   16947           .ToLocalChecked();
   16948   v8::ScriptCompiler::Source script_source3(function_name_src,
   16949                                             v8::ScriptOrigin(origin));
   16950   v8::Local<Value> function_name_result(
   16951       v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source3)
   16952           .ToLocalChecked()
   16953           ->BindToCurrentContext()
   16954           ->Run(context.local())
   16955           .ToLocalChecked());
   16956   CHECK(!function_name_result.IsEmpty());
   16957 }
   16958 
   16959 
   16960 static void StackTraceForUncaughtExceptionListener(
   16961     v8::Local<v8::Message> message, v8::Local<Value>) {
   16962   report_count++;
   16963   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   16964   CHECK_EQ(2, stack_trace->GetFrameCount());
   16965   checkStackFrame("origin", "foo", 2, 3, false, false,
   16966                   stack_trace->GetFrame(0));
   16967   checkStackFrame("origin", "bar", 5, 3, false, false,
   16968                   stack_trace->GetFrame(1));
   16969 }
   16970 
   16971 
   16972 TEST(CaptureStackTraceForUncaughtException) {
   16973   report_count = 0;
   16974   LocalContext env;
   16975   v8::Isolate* isolate = env->GetIsolate();
   16976   v8::HandleScope scope(isolate);
   16977   isolate->AddMessageListener(StackTraceForUncaughtExceptionListener);
   16978   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   16979 
   16980   CompileRunWithOrigin(
   16981       "function foo() {\n"
   16982       "  throw 1;\n"
   16983       "};\n"
   16984       "function bar() {\n"
   16985       "  foo();\n"
   16986       "};",
   16987       "origin");
   16988   v8::Local<v8::Object> global = env->Global();
   16989   Local<Value> trouble =
   16990       global->Get(env.local(), v8_str("bar")).ToLocalChecked();
   16991   CHECK(trouble->IsFunction());
   16992   CHECK(Function::Cast(*trouble)->Call(env.local(), global, 0, NULL).IsEmpty());
   16993   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   16994   isolate->RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
   16995   CHECK_EQ(1, report_count);
   16996 }
   16997 
   16998 
   16999 TEST(GetStackTraceForUncaughtExceptionFromSimpleStackTrace) {
   17000   report_count = 0;
   17001   LocalContext env;
   17002   v8::Isolate* isolate = env->GetIsolate();
   17003   v8::HandleScope scope(isolate);
   17004 
   17005   // Create an Error object first.
   17006   CompileRunWithOrigin(
   17007       "function foo() {\n"
   17008       "e=new Error('err');\n"
   17009       "};\n"
   17010       "function bar() {\n"
   17011       "  foo();\n"
   17012       "};\n"
   17013       "var e;",
   17014       "origin");
   17015   v8::Local<v8::Object> global = env->Global();
   17016   Local<Value> trouble =
   17017       global->Get(env.local(), v8_str("bar")).ToLocalChecked();
   17018   CHECK(trouble->IsFunction());
   17019   Function::Cast(*trouble)->Call(env.local(), global, 0, NULL).ToLocalChecked();
   17020 
   17021   // Enable capturing detailed stack trace late, and throw the exception.
   17022   // The detailed stack trace should be extracted from the simple stack.
   17023   isolate->AddMessageListener(StackTraceForUncaughtExceptionListener);
   17024   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   17025   CompileRunWithOrigin("throw e", "origin");
   17026   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   17027   isolate->RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
   17028   CHECK_EQ(1, report_count);
   17029 }
   17030 
   17031 
   17032 TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
   17033   LocalContext env;
   17034   v8::Isolate* isolate = env->GetIsolate();
   17035   v8::HandleScope scope(isolate);
   17036   isolate->SetCaptureStackTraceForUncaughtExceptions(true, 1024,
   17037                                                      v8::StackTrace::kDetailed);
   17038 
   17039   CompileRun(
   17040       "var setters = ['column', 'lineNumber', 'scriptName',\n"
   17041       "    'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
   17042       "    'isConstructor'];\n"
   17043       "for (var i = 0; i < setters.length; i++) {\n"
   17044       "  var prop = setters[i];\n"
   17045       "  Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
   17046       "}\n");
   17047   CompileRun("throw 'exception';");
   17048   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   17049 }
   17050 
   17051 
   17052 static void StackTraceFunctionNameListener(v8::Local<v8::Message> message,
   17053                                            v8::Local<Value>) {
   17054   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   17055   CHECK_EQ(5, stack_trace->GetFrameCount());
   17056   checkStackFrame("origin", "foo:0", 4, 7, false, false,
   17057                   stack_trace->GetFrame(0));
   17058   checkStackFrame("origin", "foo:1", 5, 27, false, false,
   17059                   stack_trace->GetFrame(1));
   17060   checkStackFrame("origin", "foo", 5, 27, false, false,
   17061                   stack_trace->GetFrame(2));
   17062   checkStackFrame("origin", "foo", 5, 27, false, false,
   17063                   stack_trace->GetFrame(3));
   17064   checkStackFrame("origin", "", 1, 14, false, false, stack_trace->GetFrame(4));
   17065 }
   17066 
   17067 
   17068 TEST(GetStackTraceContainsFunctionsWithFunctionName) {
   17069   LocalContext env;
   17070   v8::Isolate* isolate = env->GetIsolate();
   17071   v8::HandleScope scope(isolate);
   17072 
   17073   CompileRunWithOrigin(
   17074       "function gen(name, counter) {\n"
   17075       "  var f = function foo() {\n"
   17076       "    if (counter === 0)\n"
   17077       "      throw 1;\n"
   17078       "    gen(name, counter - 1)();\n"
   17079       "  };\n"
   17080       "  if (counter == 3) {\n"
   17081       "    Object.defineProperty(f, 'name', {get: function(){ throw 239; }});\n"
   17082       "  } else {\n"
   17083       "    Object.defineProperty(f, 'name', {writable:true});\n"
   17084       "    if (counter == 2)\n"
   17085       "      f.name = 42;\n"
   17086       "    else\n"
   17087       "      f.name = name + ':' + counter;\n"
   17088       "  }\n"
   17089       "  return f;\n"
   17090       "};",
   17091       "origin");
   17092 
   17093   isolate->AddMessageListener(StackTraceFunctionNameListener);
   17094   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   17095   CompileRunWithOrigin("gen('foo', 3)();", "origin");
   17096   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   17097   isolate->RemoveMessageListeners(StackTraceFunctionNameListener);
   17098 }
   17099 
   17100 
   17101 static void RethrowStackTraceHandler(v8::Local<v8::Message> message,
   17102                                      v8::Local<v8::Value> data) {
   17103   // Use the frame where JavaScript is called from.
   17104   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   17105   CHECK(!stack_trace.IsEmpty());
   17106   int frame_count = stack_trace->GetFrameCount();
   17107   CHECK_EQ(3, frame_count);
   17108   int line_number[] = {1, 2, 5};
   17109   for (int i = 0; i < frame_count; i++) {
   17110     CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
   17111   }
   17112 }
   17113 
   17114 
   17115 // Test that we only return the stack trace at the site where the exception
   17116 // is first thrown (not where it is rethrown).
   17117 TEST(RethrowStackTrace) {
   17118   LocalContext env;
   17119   v8::Isolate* isolate = env->GetIsolate();
   17120   v8::HandleScope scope(isolate);
   17121   // We make sure that
   17122   // - the stack trace of the ReferenceError in g() is reported.
   17123   // - the stack trace is not overwritten when e1 is rethrown by t().
   17124   // - the stack trace of e2 does not overwrite that of e1.
   17125   const char* source =
   17126       "function g() { error; }          \n"
   17127       "function f() { g(); }            \n"
   17128       "function t(e) { throw e; }       \n"
   17129       "try {                            \n"
   17130       "  f();                           \n"
   17131       "} catch (e1) {                   \n"
   17132       "  try {                          \n"
   17133       "    error;                       \n"
   17134       "  } catch (e2) {                 \n"
   17135       "    t(e1);                       \n"
   17136       "  }                              \n"
   17137       "}                                \n";
   17138   isolate->AddMessageListener(RethrowStackTraceHandler);
   17139   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   17140   CompileRun(source);
   17141   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   17142   isolate->RemoveMessageListeners(RethrowStackTraceHandler);
   17143 }
   17144 
   17145 
   17146 static void RethrowPrimitiveStackTraceHandler(v8::Local<v8::Message> message,
   17147                                               v8::Local<v8::Value> data) {
   17148   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   17149   CHECK(!stack_trace.IsEmpty());
   17150   int frame_count = stack_trace->GetFrameCount();
   17151   CHECK_EQ(2, frame_count);
   17152   int line_number[] = {3, 7};
   17153   for (int i = 0; i < frame_count; i++) {
   17154     CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
   17155   }
   17156 }
   17157 
   17158 
   17159 // Test that we do not recognize identity for primitive exceptions.
   17160 TEST(RethrowPrimitiveStackTrace) {
   17161   LocalContext env;
   17162   v8::Isolate* isolate = env->GetIsolate();
   17163   v8::HandleScope scope(isolate);
   17164   // We do not capture stack trace for non Error objects on creation time.
   17165   // Instead, we capture the stack trace on last throw.
   17166   const char* source =
   17167       "function g() { throw 404; }      \n"
   17168       "function f() { g(); }            \n"
   17169       "function t(e) { throw e; }       \n"
   17170       "try {                            \n"
   17171       "  f();                           \n"
   17172       "} catch (e1) {                   \n"
   17173       "  t(e1)                          \n"
   17174       "}                                \n";
   17175   isolate->AddMessageListener(RethrowPrimitiveStackTraceHandler);
   17176   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   17177   CompileRun(source);
   17178   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   17179   isolate->RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
   17180 }
   17181 
   17182 
   17183 static void RethrowExistingStackTraceHandler(v8::Local<v8::Message> message,
   17184                                              v8::Local<v8::Value> data) {
   17185   // Use the frame where JavaScript is called from.
   17186   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   17187   CHECK(!stack_trace.IsEmpty());
   17188   CHECK_EQ(1, stack_trace->GetFrameCount());
   17189   CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
   17190 }
   17191 
   17192 
   17193 // Test that the stack trace is captured when the error object is created and
   17194 // not where it is thrown.
   17195 TEST(RethrowExistingStackTrace) {
   17196   LocalContext env;
   17197   v8::Isolate* isolate = env->GetIsolate();
   17198   v8::HandleScope scope(isolate);
   17199   const char* source =
   17200       "var e = new Error();           \n"
   17201       "throw e;                       \n";
   17202   isolate->AddMessageListener(RethrowExistingStackTraceHandler);
   17203   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   17204   CompileRun(source);
   17205   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   17206   isolate->RemoveMessageListeners(RethrowExistingStackTraceHandler);
   17207 }
   17208 
   17209 
   17210 static void RethrowBogusErrorStackTraceHandler(v8::Local<v8::Message> message,
   17211                                                v8::Local<v8::Value> data) {
   17212   // Use the frame where JavaScript is called from.
   17213   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   17214   CHECK(!stack_trace.IsEmpty());
   17215   CHECK_EQ(1, stack_trace->GetFrameCount());
   17216   CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
   17217 }
   17218 
   17219 
   17220 // Test that the stack trace is captured where the bogus Error object is thrown.
   17221 TEST(RethrowBogusErrorStackTrace) {
   17222   LocalContext env;
   17223   v8::Isolate* isolate = env->GetIsolate();
   17224   v8::HandleScope scope(isolate);
   17225   const char* source =
   17226       "var e = {__proto__: new Error()} \n"
   17227       "throw e;                         \n";
   17228   isolate->AddMessageListener(RethrowBogusErrorStackTraceHandler);
   17229   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   17230   CompileRun(source);
   17231   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   17232   isolate->RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
   17233 }
   17234 
   17235 
   17236 v8::PromiseRejectEvent reject_event = v8::kPromiseRejectWithNoHandler;
   17237 int promise_reject_counter = 0;
   17238 int promise_revoke_counter = 0;
   17239 int promise_reject_msg_line_number = -1;
   17240 int promise_reject_msg_column_number = -1;
   17241 int promise_reject_line_number = -1;
   17242 int promise_reject_column_number = -1;
   17243 int promise_reject_frame_count = -1;
   17244 
   17245 void PromiseRejectCallback(v8::PromiseRejectMessage reject_message) {
   17246   v8::Local<v8::Object> global = CcTest::global();
   17247   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   17248   if (reject_message.GetEvent() == v8::kPromiseRejectWithNoHandler) {
   17249     promise_reject_counter++;
   17250     global->Set(context, v8_str("rejected"), reject_message.GetPromise())
   17251         .FromJust();
   17252     global->Set(context, v8_str("value"), reject_message.GetValue()).FromJust();
   17253     v8::Local<v8::Message> message = v8::Exception::CreateMessage(
   17254         CcTest::isolate(), reject_message.GetValue());
   17255     v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   17256 
   17257     promise_reject_msg_line_number = message->GetLineNumber(context).FromJust();
   17258     promise_reject_msg_column_number =
   17259         message->GetStartColumn(context).FromJust() + 1;
   17260 
   17261     if (!stack_trace.IsEmpty()) {
   17262       promise_reject_frame_count = stack_trace->GetFrameCount();
   17263       if (promise_reject_frame_count > 0) {
   17264         CHECK(stack_trace->GetFrame(0)
   17265                   ->GetScriptName()
   17266                   ->Equals(context, v8_str("pro"))
   17267                   .FromJust());
   17268         promise_reject_line_number = stack_trace->GetFrame(0)->GetLineNumber();
   17269         promise_reject_column_number = stack_trace->GetFrame(0)->GetColumn();
   17270       } else {
   17271         promise_reject_line_number = -1;
   17272         promise_reject_column_number = -1;
   17273       }
   17274     }
   17275   } else {
   17276     promise_revoke_counter++;
   17277     global->Set(context, v8_str("revoked"), reject_message.GetPromise())
   17278         .FromJust();
   17279     CHECK(reject_message.GetValue().IsEmpty());
   17280   }
   17281 }
   17282 
   17283 
   17284 v8::Local<v8::Promise> GetPromise(const char* name) {
   17285   return v8::Local<v8::Promise>::Cast(
   17286       CcTest::global()
   17287           ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name))
   17288           .ToLocalChecked());
   17289 }
   17290 
   17291 
   17292 v8::Local<v8::Value> RejectValue() {
   17293   return CcTest::global()
   17294       ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
   17295       .ToLocalChecked();
   17296 }
   17297 
   17298 
   17299 void ResetPromiseStates() {
   17300   promise_reject_counter = 0;
   17301   promise_revoke_counter = 0;
   17302   promise_reject_msg_line_number = -1;
   17303   promise_reject_msg_column_number = -1;
   17304   promise_reject_line_number = -1;
   17305   promise_reject_column_number = -1;
   17306   promise_reject_frame_count = -1;
   17307 
   17308   v8::Local<v8::Object> global = CcTest::global();
   17309   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   17310   global->Set(context, v8_str("rejected"), v8_str("")).FromJust();
   17311   global->Set(context, v8_str("value"), v8_str("")).FromJust();
   17312   global->Set(context, v8_str("revoked"), v8_str("")).FromJust();
   17313 }
   17314 
   17315 
   17316 TEST(PromiseRejectCallback) {
   17317   LocalContext env;
   17318   v8::Isolate* isolate = env->GetIsolate();
   17319   v8::HandleScope scope(isolate);
   17320 
   17321   isolate->SetPromiseRejectCallback(PromiseRejectCallback);
   17322 
   17323   ResetPromiseStates();
   17324 
   17325   // Create promise p0.
   17326   CompileRun(
   17327       "var reject;            \n"
   17328       "var p0 = new Promise(  \n"
   17329       "  function(res, rej) { \n"
   17330       "    reject = rej;      \n"
   17331       "  }                    \n"
   17332       ");                     \n");
   17333   CHECK(!GetPromise("p0")->HasHandler());
   17334   CHECK_EQ(0, promise_reject_counter);
   17335   CHECK_EQ(0, promise_revoke_counter);
   17336 
   17337   // Add resolve handler (and default reject handler) to p0.
   17338   CompileRun("var p1 = p0.then(function(){});");
   17339   CHECK(GetPromise("p0")->HasHandler());
   17340   CHECK(!GetPromise("p1")->HasHandler());
   17341   CHECK_EQ(0, promise_reject_counter);
   17342   CHECK_EQ(0, promise_revoke_counter);
   17343 
   17344   // Reject p0.
   17345   CompileRun("reject('ppp');");
   17346   CHECK(GetPromise("p0")->HasHandler());
   17347   CHECK(!GetPromise("p1")->HasHandler());
   17348   CHECK_EQ(1, promise_reject_counter);
   17349   CHECK_EQ(0, promise_revoke_counter);
   17350   CHECK_EQ(v8::kPromiseRejectWithNoHandler, reject_event);
   17351   CHECK(
   17352       GetPromise("rejected")->Equals(env.local(), GetPromise("p1")).FromJust());
   17353   CHECK(RejectValue()->Equals(env.local(), v8_str("ppp")).FromJust());
   17354 
   17355   // Reject p0 again. Callback is not triggered again.
   17356   CompileRun("reject();");
   17357   CHECK(GetPromise("p0")->HasHandler());
   17358   CHECK(!GetPromise("p1")->HasHandler());
   17359   CHECK_EQ(1, promise_reject_counter);
   17360   CHECK_EQ(0, promise_revoke_counter);
   17361 
   17362   // Add resolve handler to p1.
   17363   CompileRun("var p2 = p1.then(function(){});");
   17364   CHECK(GetPromise("p0")->HasHandler());
   17365   CHECK(GetPromise("p1")->HasHandler());
   17366   CHECK(!GetPromise("p2")->HasHandler());
   17367   CHECK_EQ(2, promise_reject_counter);
   17368   CHECK_EQ(1, promise_revoke_counter);
   17369   CHECK(
   17370       GetPromise("rejected")->Equals(env.local(), GetPromise("p2")).FromJust());
   17371   CHECK(RejectValue()->Equals(env.local(), v8_str("ppp")).FromJust());
   17372   CHECK(
   17373       GetPromise("revoked")->Equals(env.local(), GetPromise("p1")).FromJust());
   17374 
   17375   ResetPromiseStates();
   17376 
   17377   // Create promise q0.
   17378   CompileRun(
   17379       "var q0 = new Promise(  \n"
   17380       "  function(res, rej) { \n"
   17381       "    reject = rej;      \n"
   17382       "  }                    \n"
   17383       ");                     \n");
   17384   CHECK(!GetPromise("q0")->HasHandler());
   17385   CHECK_EQ(0, promise_reject_counter);
   17386   CHECK_EQ(0, promise_revoke_counter);
   17387 
   17388   // Add reject handler to q0.
   17389   CompileRun("var q1 = q0.catch(function() {});");
   17390   CHECK(GetPromise("q0")->HasHandler());
   17391   CHECK(!GetPromise("q1")->HasHandler());
   17392   CHECK_EQ(0, promise_reject_counter);
   17393   CHECK_EQ(0, promise_revoke_counter);
   17394 
   17395   // Reject q0.
   17396   CompileRun("reject('qq')");
   17397   CHECK(GetPromise("q0")->HasHandler());
   17398   CHECK(!GetPromise("q1")->HasHandler());
   17399   CHECK_EQ(0, promise_reject_counter);
   17400   CHECK_EQ(0, promise_revoke_counter);
   17401 
   17402   // Add a new reject handler, which rejects by returning Promise.reject().
   17403   // The returned promise q_ triggers a reject callback at first, only to
   17404   // revoke it when returning it causes q2 to be rejected.
   17405   CompileRun(
   17406       "var q_;"
   17407       "var q2 = q0.catch(               \n"
   17408       "   function() {                  \n"
   17409       "     q_ = Promise.reject('qqq'); \n"
   17410       "     return q_;                  \n"
   17411       "   }                             \n"
   17412       ");                               \n");
   17413   CHECK(GetPromise("q0")->HasHandler());
   17414   CHECK(!GetPromise("q1")->HasHandler());
   17415   CHECK(!GetPromise("q2")->HasHandler());
   17416   CHECK(GetPromise("q_")->HasHandler());
   17417   CHECK_EQ(2, promise_reject_counter);
   17418   CHECK_EQ(1, promise_revoke_counter);
   17419   CHECK(
   17420       GetPromise("rejected")->Equals(env.local(), GetPromise("q2")).FromJust());
   17421   CHECK(
   17422       GetPromise("revoked")->Equals(env.local(), GetPromise("q_")).FromJust());
   17423   CHECK(RejectValue()->Equals(env.local(), v8_str("qqq")).FromJust());
   17424 
   17425   // Add a reject handler to the resolved q1, which rejects by throwing.
   17426   CompileRun(
   17427       "var q3 = q1.then(  \n"
   17428       "   function() {    \n"
   17429       "     throw 'qqqq'; \n"
   17430       "   }               \n"
   17431       ");                 \n");
   17432   CHECK(GetPromise("q0")->HasHandler());
   17433   CHECK(GetPromise("q1")->HasHandler());
   17434   CHECK(!GetPromise("q2")->HasHandler());
   17435   CHECK(!GetPromise("q3")->HasHandler());
   17436   CHECK_EQ(3, promise_reject_counter);
   17437   CHECK_EQ(1, promise_revoke_counter);
   17438   CHECK(
   17439       GetPromise("rejected")->Equals(env.local(), GetPromise("q3")).FromJust());
   17440   CHECK(RejectValue()->Equals(env.local(), v8_str("qqqq")).FromJust());
   17441 
   17442   ResetPromiseStates();
   17443 
   17444   // Create promise r0, which has three handlers, two of which handle rejects.
   17445   CompileRun(
   17446       "var r0 = new Promise(             \n"
   17447       "  function(res, rej) {            \n"
   17448       "    reject = rej;                 \n"
   17449       "  }                               \n"
   17450       ");                                \n"
   17451       "var r1 = r0.catch(function() {}); \n"
   17452       "var r2 = r0.then(function() {});  \n"
   17453       "var r3 = r0.then(function() {},   \n"
   17454       "                 function() {});  \n");
   17455   CHECK(GetPromise("r0")->HasHandler());
   17456   CHECK(!GetPromise("r1")->HasHandler());
   17457   CHECK(!GetPromise("r2")->HasHandler());
   17458   CHECK(!GetPromise("r3")->HasHandler());
   17459   CHECK_EQ(0, promise_reject_counter);
   17460   CHECK_EQ(0, promise_revoke_counter);
   17461 
   17462   // Reject r0.
   17463   CompileRun("reject('rrr')");
   17464   CHECK(GetPromise("r0")->HasHandler());
   17465   CHECK(!GetPromise("r1")->HasHandler());
   17466   CHECK(!GetPromise("r2")->HasHandler());
   17467   CHECK(!GetPromise("r3")->HasHandler());
   17468   CHECK_EQ(1, promise_reject_counter);
   17469   CHECK_EQ(0, promise_revoke_counter);
   17470   CHECK(
   17471       GetPromise("rejected")->Equals(env.local(), GetPromise("r2")).FromJust());
   17472   CHECK(RejectValue()->Equals(env.local(), v8_str("rrr")).FromJust());
   17473 
   17474   // Add reject handler to r2.
   17475   CompileRun("var r4 = r2.catch(function() {});");
   17476   CHECK(GetPromise("r0")->HasHandler());
   17477   CHECK(!GetPromise("r1")->HasHandler());
   17478   CHECK(GetPromise("r2")->HasHandler());
   17479   CHECK(!GetPromise("r3")->HasHandler());
   17480   CHECK(!GetPromise("r4")->HasHandler());
   17481   CHECK_EQ(1, promise_reject_counter);
   17482   CHECK_EQ(1, promise_revoke_counter);
   17483   CHECK(
   17484       GetPromise("revoked")->Equals(env.local(), GetPromise("r2")).FromJust());
   17485   CHECK(RejectValue()->Equals(env.local(), v8_str("rrr")).FromJust());
   17486 
   17487   // Add reject handlers to r4.
   17488   CompileRun("var r5 = r4.then(function() {}, function() {});");
   17489   CHECK(GetPromise("r0")->HasHandler());
   17490   CHECK(!GetPromise("r1")->HasHandler());
   17491   CHECK(GetPromise("r2")->HasHandler());
   17492   CHECK(!GetPromise("r3")->HasHandler());
   17493   CHECK(GetPromise("r4")->HasHandler());
   17494   CHECK(!GetPromise("r5")->HasHandler());
   17495   CHECK_EQ(1, promise_reject_counter);
   17496   CHECK_EQ(1, promise_revoke_counter);
   17497 
   17498   ResetPromiseStates();
   17499 
   17500   // Create promise s0, which has three handlers, none of which handle rejects.
   17501   CompileRun(
   17502       "var s0 = new Promise(            \n"
   17503       "  function(res, rej) {           \n"
   17504       "    reject = rej;                \n"
   17505       "  }                              \n"
   17506       ");                               \n"
   17507       "var s1 = s0.then(function() {}); \n"
   17508       "var s2 = s0.then(function() {}); \n"
   17509       "var s3 = s0.then(function() {}); \n");
   17510   CHECK(GetPromise("s0")->HasHandler());
   17511   CHECK(!GetPromise("s1")->HasHandler());
   17512   CHECK(!GetPromise("s2")->HasHandler());
   17513   CHECK(!GetPromise("s3")->HasHandler());
   17514   CHECK_EQ(0, promise_reject_counter);
   17515   CHECK_EQ(0, promise_revoke_counter);
   17516 
   17517   // Reject s0.
   17518   CompileRun("reject('sss')");
   17519   CHECK(GetPromise("s0")->HasHandler());
   17520   CHECK(!GetPromise("s1")->HasHandler());
   17521   CHECK(!GetPromise("s2")->HasHandler());
   17522   CHECK(!GetPromise("s3")->HasHandler());
   17523   CHECK_EQ(3, promise_reject_counter);
   17524   CHECK_EQ(0, promise_revoke_counter);
   17525   CHECK(RejectValue()->Equals(env.local(), v8_str("sss")).FromJust());
   17526 
   17527   // Test stack frames.
   17528   env->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(true);
   17529 
   17530   ResetPromiseStates();
   17531 
   17532   // Create promise t0, which is rejected in the constructor with an error.
   17533   CompileRunWithOrigin(
   17534       "var t0 = new Promise(  \n"
   17535       "  function(res, rej) { \n"
   17536       "    reference_error;   \n"
   17537       "  }                    \n"
   17538       ");                     \n",
   17539       "pro", 0, 0);
   17540   CHECK(!GetPromise("t0")->HasHandler());
   17541   CHECK_EQ(1, promise_reject_counter);
   17542   CHECK_EQ(0, promise_revoke_counter);
   17543   CHECK_EQ(2, promise_reject_frame_count);
   17544   CHECK_EQ(3, promise_reject_line_number);
   17545   CHECK_EQ(5, promise_reject_column_number);
   17546   CHECK_EQ(3, promise_reject_msg_line_number);
   17547   CHECK_EQ(5, promise_reject_msg_column_number);
   17548 
   17549   ResetPromiseStates();
   17550 
   17551   // Create promise u0 and chain u1 to it, which is rejected via throw.
   17552   CompileRunWithOrigin(
   17553       "var u0 = Promise.resolve();        \n"
   17554       "var u1 = u0.then(                  \n"
   17555       "           function() {            \n"
   17556       "             (function() {         \n"
   17557       "                throw new Error(); \n"
   17558       "              })();                \n"
   17559       "           }                       \n"
   17560       "         );                        \n",
   17561       "pro", 0, 0);
   17562   CHECK(GetPromise("u0")->HasHandler());
   17563   CHECK(!GetPromise("u1")->HasHandler());
   17564   CHECK_EQ(1, promise_reject_counter);
   17565   CHECK_EQ(0, promise_revoke_counter);
   17566   CHECK_EQ(2, promise_reject_frame_count);
   17567   CHECK_EQ(5, promise_reject_line_number);
   17568   CHECK_EQ(23, promise_reject_column_number);
   17569   CHECK_EQ(5, promise_reject_msg_line_number);
   17570   CHECK_EQ(23, promise_reject_msg_column_number);
   17571 
   17572   // Throw in u3, which handles u1's rejection.
   17573   CompileRunWithOrigin(
   17574       "function f() {                \n"
   17575       "  return (function() {        \n"
   17576       "    return new Error();       \n"
   17577       "  })();                       \n"
   17578       "}                             \n"
   17579       "var u2 = Promise.reject(f()); \n"
   17580       "var u3 = u1.catch(            \n"
   17581       "           function() {       \n"
   17582       "             return u2;       \n"
   17583       "           }                  \n"
   17584       "         );                   \n",
   17585       "pro", 0, 0);
   17586   CHECK(GetPromise("u0")->HasHandler());
   17587   CHECK(GetPromise("u1")->HasHandler());
   17588   CHECK(GetPromise("u2")->HasHandler());
   17589   CHECK(!GetPromise("u3")->HasHandler());
   17590   CHECK_EQ(3, promise_reject_counter);
   17591   CHECK_EQ(2, promise_revoke_counter);
   17592   CHECK_EQ(3, promise_reject_frame_count);
   17593   CHECK_EQ(3, promise_reject_line_number);
   17594   CHECK_EQ(12, promise_reject_column_number);
   17595   CHECK_EQ(3, promise_reject_msg_line_number);
   17596   CHECK_EQ(12, promise_reject_msg_column_number);
   17597 
   17598   ResetPromiseStates();
   17599 
   17600   // Create promise rejected promise v0, which is incorrectly handled by v1
   17601   // via chaining cycle.
   17602   CompileRunWithOrigin(
   17603       "var v0 = Promise.reject(); \n"
   17604       "var v1 = v0.catch(         \n"
   17605       "           function() {    \n"
   17606       "             return v1;    \n"
   17607       "           }               \n"
   17608       "         );                \n",
   17609       "pro", 0, 0);
   17610   CHECK(GetPromise("v0")->HasHandler());
   17611   CHECK(!GetPromise("v1")->HasHandler());
   17612   CHECK_EQ(2, promise_reject_counter);
   17613   CHECK_EQ(1, promise_revoke_counter);
   17614   CHECK_EQ(0, promise_reject_frame_count);
   17615   CHECK_EQ(-1, promise_reject_line_number);
   17616   CHECK_EQ(-1, promise_reject_column_number);
   17617 
   17618   ResetPromiseStates();
   17619 
   17620   // Create promise t1, which rejects by throwing syntax error from eval.
   17621   CompileRunWithOrigin(
   17622       "var t1 = new Promise(   \n"
   17623       "  function(res, rej) {  \n"
   17624       "    var content = '\\n\\\n"
   17625       "      }';               \n"
   17626       "    eval(content);      \n"
   17627       "  }                     \n"
   17628       ");                      \n",
   17629       "pro", 0, 0);
   17630   CHECK(!GetPromise("t1")->HasHandler());
   17631   CHECK_EQ(1, promise_reject_counter);
   17632   CHECK_EQ(0, promise_revoke_counter);
   17633   CHECK_EQ(2, promise_reject_frame_count);
   17634   CHECK_EQ(5, promise_reject_line_number);
   17635   CHECK_EQ(10, promise_reject_column_number);
   17636   CHECK_EQ(2, promise_reject_msg_line_number);
   17637   CHECK_EQ(7, promise_reject_msg_column_number);
   17638 }
   17639 
   17640 
   17641 void AnalyzeStackOfEvalWithSourceURL(
   17642     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17643   v8::HandleScope scope(args.GetIsolate());
   17644   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17645       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   17646   CHECK_EQ(5, stackTrace->GetFrameCount());
   17647   v8::Local<v8::String> url = v8_str("eval_url");
   17648   for (int i = 0; i < 3; i++) {
   17649     v8::Local<v8::String> name =
   17650         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
   17651     CHECK(!name.IsEmpty());
   17652     CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
   17653   }
   17654 }
   17655 
   17656 
   17657 TEST(SourceURLInStackTrace) {
   17658   v8::Isolate* isolate = CcTest::isolate();
   17659   v8::HandleScope scope(isolate);
   17660   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   17661   templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
   17662              v8::FunctionTemplate::New(isolate,
   17663                                        AnalyzeStackOfEvalWithSourceURL));
   17664   LocalContext context(0, templ);
   17665 
   17666   const char *source =
   17667     "function outer() {\n"
   17668     "function bar() {\n"
   17669     "  AnalyzeStackOfEvalWithSourceURL();\n"
   17670     "}\n"
   17671     "function foo() {\n"
   17672     "\n"
   17673     "  bar();\n"
   17674     "}\n"
   17675     "foo();\n"
   17676     "}\n"
   17677     "eval('(' + outer +')()%s');";
   17678 
   17679   i::ScopedVector<char> code(1024);
   17680   i::SNPrintF(code, source, "//# sourceURL=eval_url");
   17681   CHECK(CompileRun(code.start())->IsUndefined());
   17682   i::SNPrintF(code, source, "//@ sourceURL=eval_url");
   17683   CHECK(CompileRun(code.start())->IsUndefined());
   17684 }
   17685 
   17686 
   17687 static int scriptIdInStack[2];
   17688 
   17689 void AnalyzeScriptIdInStack(
   17690     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17691   v8::HandleScope scope(args.GetIsolate());
   17692   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17693       args.GetIsolate(), 10, v8::StackTrace::kScriptId);
   17694   CHECK_EQ(2, stackTrace->GetFrameCount());
   17695   for (int i = 0; i < 2; i++) {
   17696     scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
   17697   }
   17698 }
   17699 
   17700 
   17701 TEST(ScriptIdInStackTrace) {
   17702   v8::Isolate* isolate = CcTest::isolate();
   17703   v8::HandleScope scope(isolate);
   17704   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   17705   templ->Set(v8_str("AnalyzeScriptIdInStack"),
   17706              v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
   17707   LocalContext context(0, templ);
   17708 
   17709   v8::Local<v8::String> scriptSource = v8_str(
   17710       "function foo() {\n"
   17711       "  AnalyzeScriptIdInStack();"
   17712       "}\n"
   17713       "foo();\n");
   17714   v8::Local<v8::Script> script = CompileWithOrigin(scriptSource, "test");
   17715   script->Run(context.local()).ToLocalChecked();
   17716   for (int i = 0; i < 2; i++) {
   17717     CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
   17718     CHECK_EQ(scriptIdInStack[i], script->GetUnboundScript()->GetId());
   17719   }
   17720 }
   17721 
   17722 
   17723 void AnalyzeStackOfInlineScriptWithSourceURL(
   17724     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17725   v8::HandleScope scope(args.GetIsolate());
   17726   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17727       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   17728   CHECK_EQ(4, stackTrace->GetFrameCount());
   17729   v8::Local<v8::String> url = v8_str("source_url");
   17730   for (int i = 0; i < 3; i++) {
   17731     v8::Local<v8::String> name =
   17732         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
   17733     CHECK(!name.IsEmpty());
   17734     CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
   17735   }
   17736 }
   17737 
   17738 
   17739 TEST(InlineScriptWithSourceURLInStackTrace) {
   17740   v8::Isolate* isolate = CcTest::isolate();
   17741   v8::HandleScope scope(isolate);
   17742   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   17743   templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
   17744              v8::FunctionTemplate::New(
   17745                  CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
   17746   LocalContext context(0, templ);
   17747 
   17748   const char *source =
   17749     "function outer() {\n"
   17750     "function bar() {\n"
   17751     "  AnalyzeStackOfInlineScriptWithSourceURL();\n"
   17752     "}\n"
   17753     "function foo() {\n"
   17754     "\n"
   17755     "  bar();\n"
   17756     "}\n"
   17757     "foo();\n"
   17758     "}\n"
   17759     "outer()\n%s";
   17760 
   17761   i::ScopedVector<char> code(1024);
   17762   i::SNPrintF(code, source, "//# sourceURL=source_url");
   17763   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
   17764   i::SNPrintF(code, source, "//@ sourceURL=source_url");
   17765   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
   17766 }
   17767 
   17768 
   17769 void AnalyzeStackOfDynamicScriptWithSourceURL(
   17770     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17771   v8::HandleScope scope(args.GetIsolate());
   17772   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17773       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   17774   CHECK_EQ(4, stackTrace->GetFrameCount());
   17775   v8::Local<v8::String> url = v8_str("source_url");
   17776   for (int i = 0; i < 3; i++) {
   17777     v8::Local<v8::String> name =
   17778         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
   17779     CHECK(!name.IsEmpty());
   17780     CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
   17781   }
   17782 }
   17783 
   17784 
   17785 TEST(DynamicWithSourceURLInStackTrace) {
   17786   v8::Isolate* isolate = CcTest::isolate();
   17787   v8::HandleScope scope(isolate);
   17788   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   17789   templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
   17790              v8::FunctionTemplate::New(
   17791                  CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
   17792   LocalContext context(0, templ);
   17793 
   17794   const char *source =
   17795     "function outer() {\n"
   17796     "function bar() {\n"
   17797     "  AnalyzeStackOfDynamicScriptWithSourceURL();\n"
   17798     "}\n"
   17799     "function foo() {\n"
   17800     "\n"
   17801     "  bar();\n"
   17802     "}\n"
   17803     "foo();\n"
   17804     "}\n"
   17805     "outer()\n%s";
   17806 
   17807   i::ScopedVector<char> code(1024);
   17808   i::SNPrintF(code, source, "//# sourceURL=source_url");
   17809   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
   17810   i::SNPrintF(code, source, "//@ sourceURL=source_url");
   17811   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
   17812 }
   17813 
   17814 
   17815 TEST(DynamicWithSourceURLInStackTraceString) {
   17816   LocalContext context;
   17817   v8::HandleScope scope(context->GetIsolate());
   17818 
   17819   const char *source =
   17820     "function outer() {\n"
   17821     "  function foo() {\n"
   17822     "    FAIL.FAIL;\n"
   17823     "  }\n"
   17824     "  foo();\n"
   17825     "}\n"
   17826     "outer()\n%s";
   17827 
   17828   i::ScopedVector<char> code(1024);
   17829   i::SNPrintF(code, source, "//# sourceURL=source_url");
   17830   v8::TryCatch try_catch(context->GetIsolate());
   17831   CompileRunWithOrigin(code.start(), "", 0, 0);
   17832   CHECK(try_catch.HasCaught());
   17833   v8::String::Utf8Value stack(
   17834       try_catch.StackTrace(context.local()).ToLocalChecked());
   17835   CHECK(strstr(*stack, "at foo (source_url:3:5)") != NULL);
   17836 }
   17837 
   17838 
   17839 TEST(EvalWithSourceURLInMessageScriptResourceNameOrSourceURL) {
   17840   LocalContext context;
   17841   v8::HandleScope scope(context->GetIsolate());
   17842 
   17843   const char *source =
   17844     "function outer() {\n"
   17845     "  var scriptContents = \"function foo() { FAIL.FAIL; }\\\n"
   17846     "  //# sourceURL=source_url\";\n"
   17847     "  eval(scriptContents);\n"
   17848     "  foo(); }\n"
   17849     "outer();\n"
   17850     "//# sourceURL=outer_url";
   17851 
   17852   v8::TryCatch try_catch(context->GetIsolate());
   17853   CompileRun(source);
   17854   CHECK(try_catch.HasCaught());
   17855 
   17856   Local<v8::Message> message = try_catch.Message();
   17857   Local<Value> sourceURL = message->GetScriptOrigin().ResourceName();
   17858   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(sourceURL), "source_url"));
   17859 }
   17860 
   17861 
   17862 TEST(RecursionWithSourceURLInMessageScriptResourceNameOrSourceURL) {
   17863   LocalContext context;
   17864   v8::HandleScope scope(context->GetIsolate());
   17865 
   17866   const char *source =
   17867     "function outer() {\n"
   17868     "  var scriptContents = \"function boo(){ boo(); }\\\n"
   17869     "  //# sourceURL=source_url\";\n"
   17870     "  eval(scriptContents);\n"
   17871     "  boo(); }\n"
   17872     "outer();\n"
   17873     "//# sourceURL=outer_url";
   17874 
   17875   v8::TryCatch try_catch(context->GetIsolate());
   17876   CompileRun(source);
   17877   CHECK(try_catch.HasCaught());
   17878 
   17879   Local<v8::Message> message = try_catch.Message();
   17880   Local<Value> sourceURL = message->GetScriptOrigin().ResourceName();
   17881   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(sourceURL), "source_url"));
   17882 }
   17883 
   17884 
   17885 static void CreateGarbageInOldSpace() {
   17886   i::Factory* factory = CcTest::i_isolate()->factory();
   17887   v8::HandleScope scope(CcTest::isolate());
   17888   i::AlwaysAllocateScope always_allocate(CcTest::i_isolate());
   17889   for (int i = 0; i < 1000; i++) {
   17890     factory->NewFixedArray(1000, i::TENURED);
   17891   }
   17892 }
   17893 
   17894 
   17895 // Test that idle notification can be handled and eventually collects garbage.
   17896 TEST(TestIdleNotification) {
   17897   if (!i::FLAG_incremental_marking) return;
   17898   const intptr_t MB = 1024 * 1024;
   17899   const double IdlePauseInSeconds = 1.0;
   17900   LocalContext env;
   17901   v8::HandleScope scope(env->GetIsolate());
   17902   intptr_t initial_size = CcTest::heap()->SizeOfObjects();
   17903   CreateGarbageInOldSpace();
   17904   intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
   17905   CHECK_GT(size_with_garbage, initial_size + MB);
   17906   bool finished = false;
   17907   for (int i = 0; i < 200 && !finished; i++) {
   17908     if (i < 10 && CcTest::heap()->incremental_marking()->IsStopped()) {
   17909       CcTest::heap()->StartIdleIncrementalMarking();
   17910     }
   17911     finished = env->GetIsolate()->IdleNotificationDeadline(
   17912         (v8::base::TimeTicks::HighResolutionNow().ToInternalValue() /
   17913          static_cast<double>(v8::base::Time::kMicrosecondsPerSecond)) +
   17914         IdlePauseInSeconds);
   17915     if (CcTest::heap()->mark_compact_collector()->sweeping_in_progress()) {
   17916       CcTest::heap()->mark_compact_collector()->EnsureSweepingCompleted();
   17917     }
   17918   }
   17919   intptr_t final_size = CcTest::heap()->SizeOfObjects();
   17920   CHECK(finished);
   17921   CHECK_LT(final_size, initial_size + 1);
   17922 }
   17923 
   17924 
   17925 TEST(Regress2333) {
   17926   LocalContext env;
   17927   for (int i = 0; i < 3; i++) {
   17928     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
   17929   }
   17930 }
   17931 
   17932 static uint32_t* stack_limit;
   17933 
   17934 static void GetStackLimitCallback(
   17935     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17936   stack_limit = reinterpret_cast<uint32_t*>(
   17937       CcTest::i_isolate()->stack_guard()->real_climit());
   17938 }
   17939 
   17940 
   17941 // Uses the address of a local variable to determine the stack top now.
   17942 // Given a size, returns an address that is that far from the current
   17943 // top of stack.
   17944 static uint32_t* ComputeStackLimit(uint32_t size) {
   17945   uint32_t* answer = &size - (size / sizeof(size));
   17946   // If the size is very large and the stack is very near the bottom of
   17947   // memory then the calculation above may wrap around and give an address
   17948   // that is above the (downwards-growing) stack.  In that case we return
   17949   // a very low address.
   17950   if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
   17951   return answer;
   17952 }
   17953 
   17954 
   17955 // We need at least 165kB for an x64 debug build with clang and ASAN.
   17956 static const int stack_breathing_room = 256 * i::KB;
   17957 
   17958 
   17959 TEST(SetStackLimit) {
   17960   uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
   17961 
   17962   // Set stack limit.
   17963   CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
   17964 
   17965   // Execute a script.
   17966   LocalContext env;
   17967   v8::HandleScope scope(env->GetIsolate());
   17968   Local<v8::FunctionTemplate> fun_templ =
   17969       v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
   17970   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   17971   CHECK(env->Global()
   17972             ->Set(env.local(), v8_str("get_stack_limit"), fun)
   17973             .FromJust());
   17974   CompileRun("get_stack_limit();");
   17975 
   17976   CHECK(stack_limit == set_limit);
   17977 }
   17978 
   17979 
   17980 TEST(SetStackLimitInThread) {
   17981   uint32_t* set_limit;
   17982   {
   17983     v8::Locker locker(CcTest::isolate());
   17984     set_limit = ComputeStackLimit(stack_breathing_room);
   17985 
   17986     // Set stack limit.
   17987     CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
   17988 
   17989     // Execute a script.
   17990     v8::HandleScope scope(CcTest::isolate());
   17991     LocalContext env;
   17992     Local<v8::FunctionTemplate> fun_templ =
   17993         v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
   17994     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   17995     CHECK(env->Global()
   17996               ->Set(env.local(), v8_str("get_stack_limit"), fun)
   17997               .FromJust());
   17998     CompileRun("get_stack_limit();");
   17999 
   18000     CHECK(stack_limit == set_limit);
   18001   }
   18002   {
   18003     v8::Locker locker(CcTest::isolate());
   18004     CHECK(stack_limit == set_limit);
   18005   }
   18006 }
   18007 
   18008 
   18009 THREADED_TEST(GetHeapStatistics) {
   18010   LocalContext c1;
   18011   v8::HandleScope scope(c1->GetIsolate());
   18012   v8::HeapStatistics heap_statistics;
   18013   CHECK_EQ(0u, heap_statistics.total_heap_size());
   18014   CHECK_EQ(0u, heap_statistics.used_heap_size());
   18015   c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
   18016   CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
   18017   CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
   18018 }
   18019 
   18020 
   18021 class VisitorImpl : public v8::ExternalResourceVisitor {
   18022  public:
   18023   explicit VisitorImpl(TestResource** resource) {
   18024     for (int i = 0; i < 4; i++) {
   18025       resource_[i] = resource[i];
   18026       found_resource_[i] = false;
   18027     }
   18028   }
   18029   virtual ~VisitorImpl() {}
   18030   virtual void VisitExternalString(v8::Local<v8::String> string) {
   18031     if (!string->IsExternal()) {
   18032       CHECK(string->IsExternalOneByte());
   18033       return;
   18034     }
   18035     v8::String::ExternalStringResource* resource =
   18036         string->GetExternalStringResource();
   18037     CHECK(resource);
   18038     for (int i = 0; i < 4; i++) {
   18039       if (resource_[i] == resource) {
   18040         CHECK(!found_resource_[i]);
   18041         found_resource_[i] = true;
   18042       }
   18043     }
   18044   }
   18045   void CheckVisitedResources() {
   18046     for (int i = 0; i < 4; i++) {
   18047       CHECK(found_resource_[i]);
   18048     }
   18049   }
   18050 
   18051  private:
   18052   v8::String::ExternalStringResource* resource_[4];
   18053   bool found_resource_[4];
   18054 };
   18055 
   18056 
   18057 TEST(ExternalizeOldSpaceTwoByteCons) {
   18058   v8::Isolate* isolate = CcTest::isolate();
   18059   LocalContext env;
   18060   v8::HandleScope scope(isolate);
   18061   v8::Local<v8::String> cons =
   18062       CompileRun("'Romeo Montague ' + 'Juliet Capulet'")
   18063           ->ToString(env.local())
   18064           .ToLocalChecked();
   18065   CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
   18066   CcTest::heap()->CollectAllAvailableGarbage();
   18067   CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
   18068 
   18069   TestResource* resource = new TestResource(
   18070       AsciiToTwoByteString("Romeo Montague Juliet Capulet"));
   18071   cons->MakeExternal(resource);
   18072 
   18073   CHECK(cons->IsExternal());
   18074   CHECK_EQ(resource, cons->GetExternalStringResource());
   18075   String::Encoding encoding;
   18076   CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
   18077   CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
   18078 }
   18079 
   18080 
   18081 TEST(ExternalizeOldSpaceOneByteCons) {
   18082   v8::Isolate* isolate = CcTest::isolate();
   18083   LocalContext env;
   18084   v8::HandleScope scope(isolate);
   18085   v8::Local<v8::String> cons =
   18086       CompileRun("'Romeo Montague ' + 'Juliet Capulet'")
   18087           ->ToString(env.local())
   18088           .ToLocalChecked();
   18089   CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
   18090   CcTest::heap()->CollectAllAvailableGarbage();
   18091   CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
   18092 
   18093   TestOneByteResource* resource =
   18094       new TestOneByteResource(i::StrDup("Romeo Montague Juliet Capulet"));
   18095   cons->MakeExternal(resource);
   18096 
   18097   CHECK(cons->IsExternalOneByte());
   18098   CHECK_EQ(resource, cons->GetExternalOneByteStringResource());
   18099   String::Encoding encoding;
   18100   CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
   18101   CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
   18102 }
   18103 
   18104 
   18105 TEST(VisitExternalStrings) {
   18106   v8::Isolate* isolate = CcTest::isolate();
   18107   LocalContext env;
   18108   v8::HandleScope scope(isolate);
   18109   const char* string = "Some string";
   18110   uint16_t* two_byte_string = AsciiToTwoByteString(string);
   18111   TestResource* resource[4];
   18112   resource[0] = new TestResource(two_byte_string);
   18113   v8::Local<v8::String> string0 =
   18114       v8::String::NewExternalTwoByte(env->GetIsolate(), resource[0])
   18115           .ToLocalChecked();
   18116   resource[1] = new TestResource(two_byte_string, NULL, false);
   18117   v8::Local<v8::String> string1 =
   18118       v8::String::NewExternalTwoByte(env->GetIsolate(), resource[1])
   18119           .ToLocalChecked();
   18120 
   18121   // Externalized symbol.
   18122   resource[2] = new TestResource(two_byte_string, NULL, false);
   18123   v8::Local<v8::String> string2 =
   18124       v8::String::NewFromUtf8(env->GetIsolate(), string,
   18125                               v8::NewStringType::kInternalized)
   18126           .ToLocalChecked();
   18127   CHECK(string2->MakeExternal(resource[2]));
   18128 
   18129   // Symbolized External.
   18130   resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
   18131   v8::Local<v8::String> string3 =
   18132       v8::String::NewExternalTwoByte(env->GetIsolate(), resource[3])
   18133           .ToLocalChecked();
   18134   CcTest::heap()->CollectAllAvailableGarbage();  // Tenure string.
   18135   // Turn into a symbol.
   18136   i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
   18137   CHECK(!CcTest::i_isolate()->factory()->InternalizeString(
   18138       string3_i).is_null());
   18139   CHECK(string3_i->IsInternalizedString());
   18140 
   18141   // We need to add usages for string* to avoid warnings in GCC 4.7
   18142   CHECK(string0->IsExternal());
   18143   CHECK(string1->IsExternal());
   18144   CHECK(string2->IsExternal());
   18145   CHECK(string3->IsExternal());
   18146 
   18147   VisitorImpl visitor(resource);
   18148   isolate->VisitExternalResources(&visitor);
   18149   visitor.CheckVisitedResources();
   18150 }
   18151 
   18152 
   18153 TEST(ExternalStringCollectedAtTearDown) {
   18154   int destroyed = 0;
   18155   v8::Isolate::CreateParams create_params;
   18156   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   18157   v8::Isolate* isolate = v8::Isolate::New(create_params);
   18158   { v8::Isolate::Scope isolate_scope(isolate);
   18159     v8::HandleScope handle_scope(isolate);
   18160     const char* s = "One string to test them all, one string to find them.";
   18161     TestOneByteResource* inscription =
   18162         new TestOneByteResource(i::StrDup(s), &destroyed);
   18163     v8::Local<v8::String> ring =
   18164         v8::String::NewExternalOneByte(isolate, inscription).ToLocalChecked();
   18165     // Ring is still alive.  Orcs are roaming freely across our lands.
   18166     CHECK_EQ(0, destroyed);
   18167     USE(ring);
   18168   }
   18169 
   18170   isolate->Dispose();
   18171   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
   18172   CHECK_EQ(1, destroyed);
   18173 }
   18174 
   18175 
   18176 TEST(ExternalInternalizedStringCollectedAtTearDown) {
   18177   int destroyed = 0;
   18178   v8::Isolate::CreateParams create_params;
   18179   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   18180   v8::Isolate* isolate = v8::Isolate::New(create_params);
   18181   { v8::Isolate::Scope isolate_scope(isolate);
   18182     LocalContext env(isolate);
   18183     v8::HandleScope handle_scope(isolate);
   18184     CompileRun("var ring = 'One string to test them all';");
   18185     const char* s = "One string to test them all";
   18186     TestOneByteResource* inscription =
   18187         new TestOneByteResource(i::StrDup(s), &destroyed);
   18188     v8::Local<v8::String> ring =
   18189         CompileRun("ring")->ToString(env.local()).ToLocalChecked();
   18190     CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
   18191     ring->MakeExternal(inscription);
   18192     // Ring is still alive.  Orcs are roaming freely across our lands.
   18193     CHECK_EQ(0, destroyed);
   18194     USE(ring);
   18195   }
   18196 
   18197   isolate->Dispose();
   18198   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
   18199   CHECK_EQ(1, destroyed);
   18200 }
   18201 
   18202 
   18203 TEST(ExternalInternalizedStringCollectedAtGC) {
   18204   int destroyed = 0;
   18205   { LocalContext env;
   18206     v8::HandleScope handle_scope(env->GetIsolate());
   18207     CompileRun("var ring = 'One string to test them all';");
   18208     const char* s = "One string to test them all";
   18209     TestOneByteResource* inscription =
   18210         new TestOneByteResource(i::StrDup(s), &destroyed);
   18211     v8::Local<v8::String> ring = CompileRun("ring").As<v8::String>();
   18212     CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
   18213     ring->MakeExternal(inscription);
   18214     // Ring is still alive.  Orcs are roaming freely across our lands.
   18215     CHECK_EQ(0, destroyed);
   18216     USE(ring);
   18217   }
   18218 
   18219   // Garbage collector deals swift blows to evil.
   18220   CcTest::i_isolate()->compilation_cache()->Clear();
   18221   CcTest::heap()->CollectAllAvailableGarbage();
   18222 
   18223   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
   18224   CHECK_EQ(1, destroyed);
   18225 }
   18226 
   18227 
   18228 static double DoubleFromBits(uint64_t value) {
   18229   double target;
   18230   i::MemCopy(&target, &value, sizeof(target));
   18231   return target;
   18232 }
   18233 
   18234 
   18235 static uint64_t DoubleToBits(double value) {
   18236   uint64_t target;
   18237   i::MemCopy(&target, &value, sizeof(target));
   18238   return target;
   18239 }
   18240 
   18241 
   18242 static double DoubleToDateTime(double input) {
   18243   double date_limit = 864e13;
   18244   if (std::isnan(input) || input < -date_limit || input > date_limit) {
   18245     return std::numeric_limits<double>::quiet_NaN();
   18246   }
   18247   return (input < 0) ? -(std::floor(-input)) : std::floor(input);
   18248 }
   18249 
   18250 
   18251 // We don't have a consistent way to write 64-bit constants syntactically, so we
   18252 // split them into two 32-bit constants and combine them programmatically.
   18253 static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
   18254   return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
   18255 }
   18256 
   18257 
   18258 THREADED_TEST(QuietSignalingNaNs) {
   18259   LocalContext context;
   18260   v8::Isolate* isolate = context->GetIsolate();
   18261   v8::HandleScope scope(isolate);
   18262   v8::TryCatch try_catch(isolate);
   18263 
   18264   // Special double values.
   18265   double snan = DoubleFromBits(0x7ff00000, 0x00000001);
   18266   double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
   18267   double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
   18268   double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
   18269   double min_normal = DoubleFromBits(0x00100000, 0x00000000);
   18270   double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
   18271   double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
   18272 
   18273   // Date values are capped at +/-100000000 days (times 864e5 ms per day)
   18274   // on either side of the epoch.
   18275   double date_limit = 864e13;
   18276 
   18277   double test_values[] = {
   18278       snan,
   18279       qnan,
   18280       infinity,
   18281       max_normal,
   18282       date_limit + 1,
   18283       date_limit,
   18284       min_normal,
   18285       max_denormal,
   18286       min_denormal,
   18287       0,
   18288       -0,
   18289       -min_denormal,
   18290       -max_denormal,
   18291       -min_normal,
   18292       -date_limit,
   18293       -date_limit - 1,
   18294       -max_normal,
   18295       -infinity,
   18296       -qnan,
   18297       -snan
   18298   };
   18299   int num_test_values = 20;
   18300 
   18301   for (int i = 0; i < num_test_values; i++) {
   18302     double test_value = test_values[i];
   18303 
   18304     // Check that Number::New preserves non-NaNs and quiets SNaNs.
   18305     v8::Local<v8::Value> number = v8::Number::New(isolate, test_value);
   18306     double stored_number = number->NumberValue(context.local()).FromJust();
   18307     if (!std::isnan(test_value)) {
   18308       CHECK_EQ(test_value, stored_number);
   18309     } else {
   18310       uint64_t stored_bits = DoubleToBits(stored_number);
   18311       // Check if quiet nan (bits 51..62 all set).
   18312 #if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
   18313     !defined(_MIPS_ARCH_MIPS64R6) && !defined(_MIPS_ARCH_MIPS32R6) &&   \
   18314     !defined(USE_SIMULATOR)
   18315       // Most significant fraction bit for quiet nan is set to 0
   18316       // on MIPS architecture. Allowed by IEEE-754.
   18317       CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
   18318 #else
   18319       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
   18320 #endif
   18321     }
   18322 
   18323     // Check that Date::New preserves non-NaNs in the date range and
   18324     // quiets SNaNs.
   18325     v8::Local<v8::Value> date =
   18326         v8::Date::New(context.local(), test_value).ToLocalChecked();
   18327     double expected_stored_date = DoubleToDateTime(test_value);
   18328     double stored_date = date->NumberValue(context.local()).FromJust();
   18329     if (!std::isnan(expected_stored_date)) {
   18330       CHECK_EQ(expected_stored_date, stored_date);
   18331     } else {
   18332       uint64_t stored_bits = DoubleToBits(stored_date);
   18333       // Check if quiet nan (bits 51..62 all set).
   18334 #if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
   18335     !defined(_MIPS_ARCH_MIPS64R6) && !defined(_MIPS_ARCH_MIPS32R6) &&   \
   18336     !defined(USE_SIMULATOR)
   18337       // Most significant fraction bit for quiet nan is set to 0
   18338       // on MIPS architecture. Allowed by IEEE-754.
   18339       CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
   18340 #else
   18341       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
   18342 #endif
   18343     }
   18344   }
   18345 }
   18346 
   18347 
   18348 static void SpaghettiIncident(
   18349     const v8::FunctionCallbackInfo<v8::Value>& args) {
   18350   v8::HandleScope scope(args.GetIsolate());
   18351   v8::TryCatch tc(args.GetIsolate());
   18352   v8::MaybeLocal<v8::String> str(
   18353       args[0]->ToString(args.GetIsolate()->GetCurrentContext()));
   18354   USE(str);
   18355   if (tc.HasCaught())
   18356     tc.ReThrow();
   18357 }
   18358 
   18359 
   18360 // Test that an exception can be propagated down through a spaghetti
   18361 // stack using ReThrow.
   18362 THREADED_TEST(SpaghettiStackReThrow) {
   18363   v8::Isolate* isolate = CcTest::isolate();
   18364   v8::HandleScope scope(isolate);
   18365   LocalContext context;
   18366   context->Global()
   18367       ->Set(context.local(), v8_str("s"),
   18368             v8::FunctionTemplate::New(isolate, SpaghettiIncident)
   18369                 ->GetFunction(context.local())
   18370                 .ToLocalChecked())
   18371       .FromJust();
   18372   v8::TryCatch try_catch(isolate);
   18373   CompileRun(
   18374       "var i = 0;"
   18375       "var o = {"
   18376       "  toString: function () {"
   18377       "    if (i == 10) {"
   18378       "      throw 'Hey!';"
   18379       "    } else {"
   18380       "      i++;"
   18381       "      return s(o);"
   18382       "    }"
   18383       "  }"
   18384       "};"
   18385       "s(o);");
   18386   CHECK(try_catch.HasCaught());
   18387   v8::String::Utf8Value value(try_catch.Exception());
   18388   CHECK_EQ(0, strcmp(*value, "Hey!"));
   18389 }
   18390 
   18391 
   18392 TEST(Regress528) {
   18393   v8::V8::Initialize();
   18394   v8::Isolate* isolate = CcTest::isolate();
   18395   i::FLAG_retain_maps_for_n_gc = 0;
   18396   v8::HandleScope scope(isolate);
   18397   v8::Local<Context> other_context;
   18398   int gc_count;
   18399 
   18400   // Create a context used to keep the code from aging in the compilation
   18401   // cache.
   18402   other_context = Context::New(isolate);
   18403 
   18404   // Context-dependent context data creates reference from the compilation
   18405   // cache to the global object.
   18406   const char* source_simple = "1";
   18407   {
   18408     v8::HandleScope scope(isolate);
   18409     v8::Local<Context> context = Context::New(isolate);
   18410 
   18411     context->Enter();
   18412     Local<v8::String> obj = v8_str("");
   18413     context->SetEmbedderData(0, obj);
   18414     CompileRun(source_simple);
   18415     context->Exit();
   18416   }
   18417   isolate->ContextDisposedNotification();
   18418   for (gc_count = 1; gc_count < 10; gc_count++) {
   18419     other_context->Enter();
   18420     CompileRun(source_simple);
   18421     other_context->Exit();
   18422     CcTest::heap()->CollectAllGarbage();
   18423     if (GetGlobalObjectsCount() == 1) break;
   18424   }
   18425   CHECK_GE(2, gc_count);
   18426   CHECK_EQ(1, GetGlobalObjectsCount());
   18427 
   18428   // Eval in a function creates reference from the compilation cache to the
   18429   // global object.
   18430   const char* source_eval = "function f(){eval('1')}; f()";
   18431   {
   18432     v8::HandleScope scope(isolate);
   18433     v8::Local<Context> context = Context::New(isolate);
   18434 
   18435     context->Enter();
   18436     CompileRun(source_eval);
   18437     context->Exit();
   18438   }
   18439   isolate->ContextDisposedNotification();
   18440   for (gc_count = 1; gc_count < 10; gc_count++) {
   18441     other_context->Enter();
   18442     CompileRun(source_eval);
   18443     other_context->Exit();
   18444     CcTest::heap()->CollectAllGarbage();
   18445     if (GetGlobalObjectsCount() == 1) break;
   18446   }
   18447   CHECK_GE(2, gc_count);
   18448   CHECK_EQ(1, GetGlobalObjectsCount());
   18449 
   18450   // Looking up the line number for an exception creates reference from the
   18451   // compilation cache to the global object.
   18452   const char* source_exception = "function f(){throw 1;} f()";
   18453   {
   18454     v8::HandleScope scope(isolate);
   18455     v8::Local<Context> context = Context::New(isolate);
   18456 
   18457     context->Enter();
   18458     v8::TryCatch try_catch(isolate);
   18459     CompileRun(source_exception);
   18460     CHECK(try_catch.HasCaught());
   18461     v8::Local<v8::Message> message = try_catch.Message();
   18462     CHECK(!message.IsEmpty());
   18463     CHECK_EQ(1, message->GetLineNumber(context).FromJust());
   18464     context->Exit();
   18465   }
   18466   isolate->ContextDisposedNotification();
   18467   for (gc_count = 1; gc_count < 10; gc_count++) {
   18468     other_context->Enter();
   18469     CompileRun(source_exception);
   18470     other_context->Exit();
   18471     CcTest::heap()->CollectAllGarbage();
   18472     if (GetGlobalObjectsCount() == 1) break;
   18473   }
   18474   CHECK_GE(2, gc_count);
   18475   CHECK_EQ(1, GetGlobalObjectsCount());
   18476 
   18477   isolate->ContextDisposedNotification();
   18478 }
   18479 
   18480 
   18481 THREADED_TEST(ScriptOrigin) {
   18482   LocalContext env;
   18483   v8::HandleScope scope(env->GetIsolate());
   18484   v8::ScriptOrigin origin = v8::ScriptOrigin(
   18485       v8_str("test"), v8::Integer::New(env->GetIsolate(), 1),
   18486       v8::Integer::New(env->GetIsolate(), 1), v8::True(env->GetIsolate()),
   18487       v8::Local<v8::Integer>(), v8::True(env->GetIsolate()),
   18488       v8_str("http://sourceMapUrl"), v8::True(env->GetIsolate()));
   18489   v8::Local<v8::String> script = v8_str("function f() {}\n\nfunction g() {}");
   18490   v8::Script::Compile(env.local(), script, &origin)
   18491       .ToLocalChecked()
   18492       ->Run(env.local())
   18493       .ToLocalChecked();
   18494   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   18495       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   18496   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   18497       env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
   18498 
   18499   v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
   18500   CHECK_EQ(0, strcmp("test",
   18501                      *v8::String::Utf8Value(script_origin_f.ResourceName())));
   18502   CHECK_EQ(
   18503       1,
   18504       script_origin_f.ResourceLineOffset()->Int32Value(env.local()).FromJust());
   18505   CHECK(script_origin_f.Options().IsSharedCrossOrigin());
   18506   CHECK(script_origin_f.Options().IsEmbedderDebugScript());
   18507   CHECK(script_origin_f.Options().IsOpaque());
   18508   printf("is name = %d\n", script_origin_f.SourceMapUrl()->IsUndefined());
   18509 
   18510   CHECK_EQ(0, strcmp("http://sourceMapUrl",
   18511                      *v8::String::Utf8Value(script_origin_f.SourceMapUrl())));
   18512 
   18513   v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
   18514   CHECK_EQ(0, strcmp("test",
   18515                      *v8::String::Utf8Value(script_origin_g.ResourceName())));
   18516   CHECK_EQ(
   18517       1,
   18518       script_origin_g.ResourceLineOffset()->Int32Value(env.local()).FromJust());
   18519   CHECK(script_origin_g.Options().IsSharedCrossOrigin());
   18520   CHECK(script_origin_g.Options().IsEmbedderDebugScript());
   18521   CHECK(script_origin_g.Options().IsOpaque());
   18522   CHECK_EQ(0, strcmp("http://sourceMapUrl",
   18523                      *v8::String::Utf8Value(script_origin_g.SourceMapUrl())));
   18524 }
   18525 
   18526 
   18527 THREADED_TEST(FunctionGetInferredName) {
   18528   LocalContext env;
   18529   v8::HandleScope scope(env->GetIsolate());
   18530   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   18531   v8::Local<v8::String> script =
   18532       v8_str("var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
   18533   v8::Script::Compile(env.local(), script, &origin)
   18534       .ToLocalChecked()
   18535       ->Run(env.local())
   18536       .ToLocalChecked();
   18537   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   18538       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   18539   CHECK_EQ(0,
   18540            strcmp("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName())));
   18541 }
   18542 
   18543 
   18544 THREADED_TEST(FunctionGetDebugName) {
   18545   LocalContext env;
   18546   v8::HandleScope scope(env->GetIsolate());
   18547   const char* code =
   18548       "var error = false;"
   18549       "function a() { this.x = 1; };"
   18550       "a.displayName = 'display_a';"
   18551       "var b = (function() {"
   18552       "  var f = function() { this.x = 2; };"
   18553       "  f.displayName = 'display_b';"
   18554       "  return f;"
   18555       "})();"
   18556       "var c = function() {};"
   18557       "c.__defineGetter__('displayName', function() {"
   18558       "  error = true;"
   18559       "  throw new Error();"
   18560       "});"
   18561       "function d() {};"
   18562       "d.__defineGetter__('displayName', function() {"
   18563       "  error = true;"
   18564       "  return 'wrong_display_name';"
   18565       "});"
   18566       "function e() {};"
   18567       "e.displayName = 'wrong_display_name';"
   18568       "e.__defineSetter__('displayName', function() {"
   18569       "  error = true;"
   18570       "  throw new Error();"
   18571       "});"
   18572       "function f() {};"
   18573       "f.displayName = { 'foo': 6, toString: function() {"
   18574       "  error = true;"
   18575       "  return 'wrong_display_name';"
   18576       "}};"
   18577       "var g = function() {"
   18578       "  arguments.callee.displayName = 'set_in_runtime';"
   18579       "}; g();"
   18580       "var h = function() {};"
   18581       "h.displayName = 'displayName';"
   18582       "Object.defineProperty(h, 'name', { value: 'function.name' });"
   18583       "var i = function() {};"
   18584       "i.displayName = 239;"
   18585       "Object.defineProperty(i, 'name', { value: 'function.name' });"
   18586       "var j = function() {};"
   18587       "Object.defineProperty(j, 'name', { value: 'function.name' });"
   18588       "var foo = { bar : { baz : (0, function() {})}}; var k = foo.bar.baz;"
   18589       "var foo = { bar : { baz : function() {} }}; var l = foo.bar.baz;";
   18590   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   18591   v8::Script::Compile(env.local(), v8_str(code), &origin)
   18592       .ToLocalChecked()
   18593       ->Run(env.local())
   18594       .ToLocalChecked();
   18595   v8::Local<v8::Value> error =
   18596       env->Global()->Get(env.local(), v8_str("error")).ToLocalChecked();
   18597   CHECK_EQ(false, error->BooleanValue(env.local()).FromJust());
   18598   const char* functions[] = {"a", "display_a",
   18599                              "b", "display_b",
   18600                              "c", "c",
   18601                              "d", "d",
   18602                              "e", "e",
   18603                              "f", "f",
   18604                              "g", "set_in_runtime",
   18605                              "h", "displayName",
   18606                              "i", "function.name",
   18607                              "j", "function.name",
   18608                              "k", "foo.bar.baz",
   18609                              "l", "baz"};
   18610   for (size_t i = 0; i < sizeof(functions) / sizeof(functions[0]) / 2; ++i) {
   18611     v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   18612         env->Global()
   18613             ->Get(env.local(),
   18614                   v8::String::NewFromUtf8(env->GetIsolate(), functions[i * 2],
   18615                                           v8::NewStringType::kNormal)
   18616                       .ToLocalChecked())
   18617             .ToLocalChecked());
   18618     CHECK_EQ(0, strcmp(functions[i * 2 + 1],
   18619                        *v8::String::Utf8Value(f->GetDebugName())));
   18620   }
   18621 }
   18622 
   18623 
   18624 THREADED_TEST(FunctionGetDisplayName) {
   18625   LocalContext env;
   18626   v8::HandleScope scope(env->GetIsolate());
   18627   const char* code = "var error = false;"
   18628                      "function a() { this.x = 1; };"
   18629                      "a.displayName = 'display_a';"
   18630                      "var b = (function() {"
   18631                      "  var f = function() { this.x = 2; };"
   18632                      "  f.displayName = 'display_b';"
   18633                      "  return f;"
   18634                      "})();"
   18635                      "var c = function() {};"
   18636                      "c.__defineGetter__('displayName', function() {"
   18637                      "  error = true;"
   18638                      "  throw new Error();"
   18639                      "});"
   18640                      "function d() {};"
   18641                      "d.__defineGetter__('displayName', function() {"
   18642                      "  error = true;"
   18643                      "  return 'wrong_display_name';"
   18644                      "});"
   18645                      "function e() {};"
   18646                      "e.displayName = 'wrong_display_name';"
   18647                      "e.__defineSetter__('displayName', function() {"
   18648                      "  error = true;"
   18649                      "  throw new Error();"
   18650                      "});"
   18651                      "function f() {};"
   18652                      "f.displayName = { 'foo': 6, toString: function() {"
   18653                      "  error = true;"
   18654                      "  return 'wrong_display_name';"
   18655                      "}};"
   18656                      "var g = function() {"
   18657                      "  arguments.callee.displayName = 'set_in_runtime';"
   18658                      "}; g();";
   18659   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   18660   v8::Script::Compile(env.local(), v8_str(code), &origin)
   18661       .ToLocalChecked()
   18662       ->Run(env.local())
   18663       .ToLocalChecked();
   18664   v8::Local<v8::Value> error =
   18665       env->Global()->Get(env.local(), v8_str("error")).ToLocalChecked();
   18666   v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
   18667       env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
   18668   v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
   18669       env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
   18670   v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
   18671       env->Global()->Get(env.local(), v8_str("c")).ToLocalChecked());
   18672   v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
   18673       env->Global()->Get(env.local(), v8_str("d")).ToLocalChecked());
   18674   v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
   18675       env->Global()->Get(env.local(), v8_str("e")).ToLocalChecked());
   18676   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   18677       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   18678   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   18679       env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
   18680   CHECK_EQ(false, error->BooleanValue(env.local()).FromJust());
   18681   CHECK_EQ(0, strcmp("display_a", *v8::String::Utf8Value(a->GetDisplayName())));
   18682   CHECK_EQ(0, strcmp("display_b", *v8::String::Utf8Value(b->GetDisplayName())));
   18683   CHECK(c->GetDisplayName()->IsUndefined());
   18684   CHECK(d->GetDisplayName()->IsUndefined());
   18685   CHECK(e->GetDisplayName()->IsUndefined());
   18686   CHECK(f->GetDisplayName()->IsUndefined());
   18687   CHECK_EQ(
   18688       0, strcmp("set_in_runtime", *v8::String::Utf8Value(g->GetDisplayName())));
   18689 }
   18690 
   18691 
   18692 THREADED_TEST(ScriptLineNumber) {
   18693   LocalContext env;
   18694   v8::HandleScope scope(env->GetIsolate());
   18695   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   18696   v8::Local<v8::String> script = v8_str("function f() {}\n\nfunction g() {}");
   18697   v8::Script::Compile(env.local(), script, &origin)
   18698       .ToLocalChecked()
   18699       ->Run(env.local())
   18700       .ToLocalChecked();
   18701   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   18702       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   18703   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   18704       env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
   18705   CHECK_EQ(0, f->GetScriptLineNumber());
   18706   CHECK_EQ(2, g->GetScriptLineNumber());
   18707 }
   18708 
   18709 
   18710 THREADED_TEST(ScriptColumnNumber) {
   18711   LocalContext env;
   18712   v8::Isolate* isolate = env->GetIsolate();
   18713   v8::HandleScope scope(isolate);
   18714   v8::ScriptOrigin origin =
   18715       v8::ScriptOrigin(v8_str("test"), v8::Integer::New(isolate, 3),
   18716                        v8::Integer::New(isolate, 2));
   18717   v8::Local<v8::String> script =
   18718       v8_str("function foo() {}\n\n     function bar() {}");
   18719   v8::Script::Compile(env.local(), script, &origin)
   18720       .ToLocalChecked()
   18721       ->Run(env.local())
   18722       .ToLocalChecked();
   18723   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   18724       env->Global()->Get(env.local(), v8_str("foo")).ToLocalChecked());
   18725   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
   18726       env->Global()->Get(env.local(), v8_str("bar")).ToLocalChecked());
   18727   CHECK_EQ(14, foo->GetScriptColumnNumber());
   18728   CHECK_EQ(17, bar->GetScriptColumnNumber());
   18729 }
   18730 
   18731 
   18732 THREADED_TEST(FunctionIsBuiltin) {
   18733   LocalContext env;
   18734   v8::Isolate* isolate = env->GetIsolate();
   18735   v8::HandleScope scope(isolate);
   18736   v8::Local<v8::Function> f;
   18737   f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor"));
   18738   CHECK(f->IsBuiltin());
   18739   f = v8::Local<v8::Function>::Cast(CompileRun("Object"));
   18740   CHECK(f->IsBuiltin());
   18741   f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__"));
   18742   CHECK(f->IsBuiltin());
   18743   f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString"));
   18744   CHECK(f->IsBuiltin());
   18745   f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;"));
   18746   CHECK(!f->IsBuiltin());
   18747 }
   18748 
   18749 
   18750 THREADED_TEST(FunctionGetScriptId) {
   18751   LocalContext env;
   18752   v8::Isolate* isolate = env->GetIsolate();
   18753   v8::HandleScope scope(isolate);
   18754   v8::ScriptOrigin origin =
   18755       v8::ScriptOrigin(v8_str("test"), v8::Integer::New(isolate, 3),
   18756                        v8::Integer::New(isolate, 2));
   18757   v8::Local<v8::String> scriptSource =
   18758       v8_str("function foo() {}\n\n     function bar() {}");
   18759   v8::Local<v8::Script> script(
   18760       v8::Script::Compile(env.local(), scriptSource, &origin).ToLocalChecked());
   18761   script->Run(env.local()).ToLocalChecked();
   18762   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   18763       env->Global()->Get(env.local(), v8_str("foo")).ToLocalChecked());
   18764   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
   18765       env->Global()->Get(env.local(), v8_str("bar")).ToLocalChecked());
   18766   CHECK_EQ(script->GetUnboundScript()->GetId(), foo->ScriptId());
   18767   CHECK_EQ(script->GetUnboundScript()->GetId(), bar->ScriptId());
   18768 }
   18769 
   18770 
   18771 THREADED_TEST(FunctionGetBoundFunction) {
   18772   LocalContext env;
   18773   v8::HandleScope scope(env->GetIsolate());
   18774   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   18775   v8::Local<v8::String> script = v8_str(
   18776       "var a = new Object();\n"
   18777       "a.x = 1;\n"
   18778       "function f () { return this.x };\n"
   18779       "var g = f.bind(a);\n"
   18780       "var b = g();");
   18781   v8::Script::Compile(env.local(), script, &origin)
   18782       .ToLocalChecked()
   18783       ->Run(env.local())
   18784       .ToLocalChecked();
   18785   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   18786       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   18787   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   18788       env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
   18789   CHECK(g->GetBoundFunction()->IsFunction());
   18790   Local<v8::Function> original_function = Local<v8::Function>::Cast(
   18791       g->GetBoundFunction());
   18792   CHECK(f->GetName()
   18793             ->Equals(env.local(), original_function->GetName())
   18794             .FromJust());
   18795   CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
   18796   CHECK_EQ(f->GetScriptColumnNumber(),
   18797            original_function->GetScriptColumnNumber());
   18798 }
   18799 
   18800 
   18801 static void GetterWhichReturns42(
   18802     Local<String> name,
   18803     const v8::PropertyCallbackInfo<v8::Value>& info) {
   18804   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   18805   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   18806   info.GetReturnValue().Set(v8_num(42));
   18807 }
   18808 
   18809 
   18810 static void SetterWhichSetsYOnThisTo23(
   18811     Local<String> name,
   18812     Local<Value> value,
   18813     const v8::PropertyCallbackInfo<void>& info) {
   18814   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   18815   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   18816   Local<Object>::Cast(info.This())
   18817       ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
   18818       .FromJust();
   18819 }
   18820 
   18821 
   18822 void FooGetInterceptor(Local<Name> name,
   18823                        const v8::PropertyCallbackInfo<v8::Value>& info) {
   18824   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   18825   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   18826   if (!name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   18827            .FromJust()) {
   18828     return;
   18829   }
   18830   info.GetReturnValue().Set(v8_num(42));
   18831 }
   18832 
   18833 
   18834 void FooSetInterceptor(Local<Name> name, Local<Value> value,
   18835                        const v8::PropertyCallbackInfo<v8::Value>& info) {
   18836   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   18837   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   18838   if (!name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   18839            .FromJust()) {
   18840     return;
   18841   }
   18842   Local<Object>::Cast(info.This())
   18843       ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
   18844       .FromJust();
   18845   info.GetReturnValue().Set(v8_num(23));
   18846 }
   18847 
   18848 
   18849 TEST(SetterOnConstructorPrototype) {
   18850   v8::Isolate* isolate = CcTest::isolate();
   18851   v8::HandleScope scope(isolate);
   18852   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   18853   templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
   18854                      SetterWhichSetsYOnThisTo23);
   18855   LocalContext context;
   18856   CHECK(context->Global()
   18857             ->Set(context.local(), v8_str("P"),
   18858                   templ->NewInstance(context.local()).ToLocalChecked())
   18859             .FromJust());
   18860   CompileRun("function C1() {"
   18861              "  this.x = 23;"
   18862              "};"
   18863              "C1.prototype = P;"
   18864              "function C2() {"
   18865              "  this.x = 23"
   18866              "};"
   18867              "C2.prototype = { };"
   18868              "C2.prototype.__proto__ = P;");
   18869 
   18870   v8::Local<v8::Script> script;
   18871   script = v8_compile("new C1();");
   18872   for (int i = 0; i < 10; i++) {
   18873     v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
   18874         script->Run(context.local()).ToLocalChecked());
   18875     CHECK_EQ(42, c1->Get(context.local(), v8_str("x"))
   18876                      .ToLocalChecked()
   18877                      ->Int32Value(context.local())
   18878                      .FromJust());
   18879     CHECK_EQ(23, c1->Get(context.local(), v8_str("y"))
   18880                      .ToLocalChecked()
   18881                      ->Int32Value(context.local())
   18882                      .FromJust());
   18883   }
   18884 
   18885   script = v8_compile("new C2();");
   18886   for (int i = 0; i < 10; i++) {
   18887     v8::Local<v8::Object> c2 = v8::Local<v8::Object>::Cast(
   18888         script->Run(context.local()).ToLocalChecked());
   18889     CHECK_EQ(42, c2->Get(context.local(), v8_str("x"))
   18890                      .ToLocalChecked()
   18891                      ->Int32Value(context.local())
   18892                      .FromJust());
   18893     CHECK_EQ(23, c2->Get(context.local(), v8_str("y"))
   18894                      .ToLocalChecked()
   18895                      ->Int32Value(context.local())
   18896                      .FromJust());
   18897   }
   18898 }
   18899 
   18900 
   18901 static void NamedPropertySetterWhichSetsYOnThisTo23(
   18902     Local<Name> name, Local<Value> value,
   18903     const v8::PropertyCallbackInfo<v8::Value>& info) {
   18904   if (name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("x"))
   18905           .FromJust()) {
   18906     Local<Object>::Cast(info.This())
   18907         ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
   18908         .FromJust();
   18909   }
   18910 }
   18911 
   18912 
   18913 THREADED_TEST(InterceptorOnConstructorPrototype) {
   18914   v8::Isolate* isolate = CcTest::isolate();
   18915   v8::HandleScope scope(isolate);
   18916   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   18917   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   18918       NamedPropertyGetterWhichReturns42,
   18919       NamedPropertySetterWhichSetsYOnThisTo23));
   18920   LocalContext context;
   18921   CHECK(context->Global()
   18922             ->Set(context.local(), v8_str("P"),
   18923                   templ->NewInstance(context.local()).ToLocalChecked())
   18924             .FromJust());
   18925   CompileRun("function C1() {"
   18926              "  this.x = 23;"
   18927              "};"
   18928              "C1.prototype = P;"
   18929              "function C2() {"
   18930              "  this.x = 23"
   18931              "};"
   18932              "C2.prototype = { };"
   18933              "C2.prototype.__proto__ = P;");
   18934 
   18935   v8::Local<v8::Script> script;
   18936   script = v8_compile("new C1();");
   18937   for (int i = 0; i < 10; i++) {
   18938     v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
   18939         script->Run(context.local()).ToLocalChecked());
   18940     CHECK_EQ(23, c1->Get(context.local(), v8_str("x"))
   18941                      .ToLocalChecked()
   18942                      ->Int32Value(context.local())
   18943                      .FromJust());
   18944     CHECK_EQ(42, c1->Get(context.local(), v8_str("y"))
   18945                      .ToLocalChecked()
   18946                      ->Int32Value(context.local())
   18947                      .FromJust());
   18948   }
   18949 
   18950   script = v8_compile("new C2();");
   18951   for (int i = 0; i < 10; i++) {
   18952     v8::Local<v8::Object> c2 = v8::Local<v8::Object>::Cast(
   18953         script->Run(context.local()).ToLocalChecked());
   18954     CHECK_EQ(23, c2->Get(context.local(), v8_str("x"))
   18955                      .ToLocalChecked()
   18956                      ->Int32Value(context.local())
   18957                      .FromJust());
   18958     CHECK_EQ(42, c2->Get(context.local(), v8_str("y"))
   18959                      .ToLocalChecked()
   18960                      ->Int32Value(context.local())
   18961                      .FromJust());
   18962   }
   18963 }
   18964 
   18965 
   18966 TEST(Regress618) {
   18967   const char* source = "function C1() {"
   18968                        "  this.x = 23;"
   18969                        "};"
   18970                        "C1.prototype = P;";
   18971 
   18972   LocalContext context;
   18973   v8::Isolate* isolate = context->GetIsolate();
   18974   v8::HandleScope scope(isolate);
   18975   v8::Local<v8::Script> script;
   18976 
   18977   // Use a simple object as prototype.
   18978   v8::Local<v8::Object> prototype = v8::Object::New(isolate);
   18979   prototype->Set(context.local(), v8_str("y"), v8_num(42)).FromJust();
   18980   CHECK(context->Global()
   18981             ->Set(context.local(), v8_str("P"), prototype)
   18982             .FromJust());
   18983 
   18984   // This compile will add the code to the compilation cache.
   18985   CompileRun(source);
   18986 
   18987   script = v8_compile("new C1();");
   18988   // Allow enough iterations for the inobject slack tracking logic
   18989   // to finalize instance size and install the fast construct stub.
   18990   for (int i = 0; i < 256; i++) {
   18991     v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
   18992         script->Run(context.local()).ToLocalChecked());
   18993     CHECK_EQ(23, c1->Get(context.local(), v8_str("x"))
   18994                      .ToLocalChecked()
   18995                      ->Int32Value(context.local())
   18996                      .FromJust());
   18997     CHECK_EQ(42, c1->Get(context.local(), v8_str("y"))
   18998                      .ToLocalChecked()
   18999                      ->Int32Value(context.local())
   19000                      .FromJust());
   19001   }
   19002 
   19003   // Use an API object with accessors as prototype.
   19004   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   19005   templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
   19006                      SetterWhichSetsYOnThisTo23);
   19007   CHECK(context->Global()
   19008             ->Set(context.local(), v8_str("P"),
   19009                   templ->NewInstance(context.local()).ToLocalChecked())
   19010             .FromJust());
   19011 
   19012   // This compile will get the code from the compilation cache.
   19013   CompileRun(source);
   19014 
   19015   script = v8_compile("new C1();");
   19016   for (int i = 0; i < 10; i++) {
   19017     v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
   19018         script->Run(context.local()).ToLocalChecked());
   19019     CHECK_EQ(42, c1->Get(context.local(), v8_str("x"))
   19020                      .ToLocalChecked()
   19021                      ->Int32Value(context.local())
   19022                      .FromJust());
   19023     CHECK_EQ(23, c1->Get(context.local(), v8_str("y"))
   19024                      .ToLocalChecked()
   19025                      ->Int32Value(context.local())
   19026                      .FromJust());
   19027   }
   19028 }
   19029 
   19030 v8::Isolate* gc_callbacks_isolate = NULL;
   19031 int prologue_call_count = 0;
   19032 int epilogue_call_count = 0;
   19033 int prologue_call_count_second = 0;
   19034 int epilogue_call_count_second = 0;
   19035 int prologue_call_count_alloc = 0;
   19036 int epilogue_call_count_alloc = 0;
   19037 
   19038 void PrologueCallback(v8::Isolate* isolate,
   19039                       v8::GCType,
   19040                       v8::GCCallbackFlags flags) {
   19041   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19042   CHECK_EQ(gc_callbacks_isolate, isolate);
   19043   ++prologue_call_count;
   19044 }
   19045 
   19046 void EpilogueCallback(v8::Isolate* isolate,
   19047                       v8::GCType,
   19048                       v8::GCCallbackFlags flags) {
   19049   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19050   CHECK_EQ(gc_callbacks_isolate, isolate);
   19051   ++epilogue_call_count;
   19052 }
   19053 
   19054 
   19055 void PrologueCallbackSecond(v8::Isolate* isolate,
   19056                             v8::GCType,
   19057                             v8::GCCallbackFlags flags) {
   19058   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19059   CHECK_EQ(gc_callbacks_isolate, isolate);
   19060   ++prologue_call_count_second;
   19061 }
   19062 
   19063 
   19064 void EpilogueCallbackSecond(v8::Isolate* isolate,
   19065                             v8::GCType,
   19066                             v8::GCCallbackFlags flags) {
   19067   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19068   CHECK_EQ(gc_callbacks_isolate, isolate);
   19069   ++epilogue_call_count_second;
   19070 }
   19071 
   19072 
   19073 void PrologueCallbackAlloc(v8::Isolate* isolate,
   19074                            v8::GCType,
   19075                            v8::GCCallbackFlags flags) {
   19076   v8::HandleScope scope(isolate);
   19077 
   19078   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19079   CHECK_EQ(gc_callbacks_isolate, isolate);
   19080   ++prologue_call_count_alloc;
   19081 
   19082   // Simulate full heap to see if we will reenter this callback
   19083   i::heap::SimulateFullSpace(CcTest::heap()->new_space());
   19084 
   19085   Local<Object> obj = Object::New(isolate);
   19086   CHECK(!obj.IsEmpty());
   19087 
   19088   CcTest::heap()->CollectAllGarbage(
   19089       i::Heap::kAbortIncrementalMarkingMask);
   19090 }
   19091 
   19092 
   19093 void EpilogueCallbackAlloc(v8::Isolate* isolate,
   19094                            v8::GCType,
   19095                            v8::GCCallbackFlags flags) {
   19096   v8::HandleScope scope(isolate);
   19097 
   19098   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19099   CHECK_EQ(gc_callbacks_isolate, isolate);
   19100   ++epilogue_call_count_alloc;
   19101 
   19102   // Simulate full heap to see if we will reenter this callback
   19103   i::heap::SimulateFullSpace(CcTest::heap()->new_space());
   19104 
   19105   Local<Object> obj = Object::New(isolate);
   19106   CHECK(!obj.IsEmpty());
   19107 
   19108   CcTest::heap()->CollectAllGarbage(
   19109       i::Heap::kAbortIncrementalMarkingMask);
   19110 }
   19111 
   19112 
   19113 TEST(GCCallbacksOld) {
   19114   LocalContext context;
   19115 
   19116   gc_callbacks_isolate = context->GetIsolate();
   19117 
   19118   context->GetIsolate()->AddGCPrologueCallback(PrologueCallback);
   19119   context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallback);
   19120   CHECK_EQ(0, prologue_call_count);
   19121   CHECK_EQ(0, epilogue_call_count);
   19122   CcTest::heap()->CollectAllGarbage();
   19123   CHECK_EQ(1, prologue_call_count);
   19124   CHECK_EQ(1, epilogue_call_count);
   19125   context->GetIsolate()->AddGCPrologueCallback(PrologueCallbackSecond);
   19126   context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallbackSecond);
   19127   CcTest::heap()->CollectAllGarbage();
   19128   CHECK_EQ(2, prologue_call_count);
   19129   CHECK_EQ(2, epilogue_call_count);
   19130   CHECK_EQ(1, prologue_call_count_second);
   19131   CHECK_EQ(1, epilogue_call_count_second);
   19132   context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallback);
   19133   context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallback);
   19134   CcTest::heap()->CollectAllGarbage();
   19135   CHECK_EQ(2, prologue_call_count);
   19136   CHECK_EQ(2, epilogue_call_count);
   19137   CHECK_EQ(2, prologue_call_count_second);
   19138   CHECK_EQ(2, epilogue_call_count_second);
   19139   context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallbackSecond);
   19140   context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
   19141   CcTest::heap()->CollectAllGarbage();
   19142   CHECK_EQ(2, prologue_call_count);
   19143   CHECK_EQ(2, epilogue_call_count);
   19144   CHECK_EQ(2, prologue_call_count_second);
   19145   CHECK_EQ(2, epilogue_call_count_second);
   19146 }
   19147 
   19148 
   19149 TEST(GCCallbacks) {
   19150   LocalContext context;
   19151   v8::Isolate* isolate = context->GetIsolate();
   19152   gc_callbacks_isolate = isolate;
   19153   isolate->AddGCPrologueCallback(PrologueCallback);
   19154   isolate->AddGCEpilogueCallback(EpilogueCallback);
   19155   CHECK_EQ(0, prologue_call_count);
   19156   CHECK_EQ(0, epilogue_call_count);
   19157   CcTest::heap()->CollectAllGarbage();
   19158   CHECK_EQ(1, prologue_call_count);
   19159   CHECK_EQ(1, epilogue_call_count);
   19160   isolate->AddGCPrologueCallback(PrologueCallbackSecond);
   19161   isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
   19162   CcTest::heap()->CollectAllGarbage();
   19163   CHECK_EQ(2, prologue_call_count);
   19164   CHECK_EQ(2, epilogue_call_count);
   19165   CHECK_EQ(1, prologue_call_count_second);
   19166   CHECK_EQ(1, epilogue_call_count_second);
   19167   isolate->RemoveGCPrologueCallback(PrologueCallback);
   19168   isolate->RemoveGCEpilogueCallback(EpilogueCallback);
   19169   CcTest::heap()->CollectAllGarbage();
   19170   CHECK_EQ(2, prologue_call_count);
   19171   CHECK_EQ(2, epilogue_call_count);
   19172   CHECK_EQ(2, prologue_call_count_second);
   19173   CHECK_EQ(2, epilogue_call_count_second);
   19174   isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
   19175   isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
   19176   CcTest::heap()->CollectAllGarbage();
   19177   CHECK_EQ(2, prologue_call_count);
   19178   CHECK_EQ(2, epilogue_call_count);
   19179   CHECK_EQ(2, prologue_call_count_second);
   19180   CHECK_EQ(2, epilogue_call_count_second);
   19181 
   19182   CHECK_EQ(0, prologue_call_count_alloc);
   19183   CHECK_EQ(0, epilogue_call_count_alloc);
   19184   isolate->AddGCPrologueCallback(PrologueCallbackAlloc);
   19185   isolate->AddGCEpilogueCallback(EpilogueCallbackAlloc);
   19186   CcTest::heap()->CollectAllGarbage(
   19187       i::Heap::kAbortIncrementalMarkingMask);
   19188   CHECK_EQ(1, prologue_call_count_alloc);
   19189   CHECK_EQ(1, epilogue_call_count_alloc);
   19190   isolate->RemoveGCPrologueCallback(PrologueCallbackAlloc);
   19191   isolate->RemoveGCEpilogueCallback(EpilogueCallbackAlloc);
   19192 }
   19193 
   19194 
   19195 THREADED_TEST(TwoByteStringInOneByteCons) {
   19196   // See Chromium issue 47824.
   19197   LocalContext context;
   19198   v8::HandleScope scope(context->GetIsolate());
   19199 
   19200   const char* init_code =
   19201       "var str1 = 'abelspendabel';"
   19202       "var str2 = str1 + str1 + str1;"
   19203       "str2;";
   19204   Local<Value> result = CompileRun(init_code);
   19205 
   19206   Local<Value> indexof = CompileRun("str2.indexOf('els')");
   19207   Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
   19208 
   19209   CHECK(result->IsString());
   19210   i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
   19211   int length = string->length();
   19212   CHECK(string->IsOneByteRepresentation());
   19213 
   19214   i::Handle<i::String> flat_string = i::String::Flatten(string);
   19215 
   19216   CHECK(string->IsOneByteRepresentation());
   19217   CHECK(flat_string->IsOneByteRepresentation());
   19218 
   19219   // Create external resource.
   19220   uint16_t* uc16_buffer = new uint16_t[length + 1];
   19221 
   19222   i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
   19223   uc16_buffer[length] = 0;
   19224 
   19225   TestResource resource(uc16_buffer);
   19226 
   19227   flat_string->MakeExternal(&resource);
   19228 
   19229   CHECK(flat_string->IsTwoByteRepresentation());
   19230 
   19231   // If the cons string has been short-circuited, skip the following checks.
   19232   if (!string.is_identical_to(flat_string)) {
   19233     // At this point, we should have a Cons string which is flat and one-byte,
   19234     // with a first half that is a two-byte string (although it only contains
   19235     // one-byte characters). This is a valid sequence of steps, and it can
   19236     // happen in real pages.
   19237     CHECK(string->IsOneByteRepresentation());
   19238     i::ConsString* cons = i::ConsString::cast(*string);
   19239     CHECK_EQ(0, cons->second()->length());
   19240     CHECK(cons->first()->IsTwoByteRepresentation());
   19241   }
   19242 
   19243   // Check that some string operations work.
   19244 
   19245   // Atom RegExp.
   19246   Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
   19247   CHECK_EQ(6, reresult->Int32Value(context.local()).FromJust());
   19248 
   19249   // Nonatom RegExp.
   19250   reresult = CompileRun("str2.match(/abe./g).length;");
   19251   CHECK_EQ(6, reresult->Int32Value(context.local()).FromJust());
   19252 
   19253   reresult = CompileRun("str2.search(/bel/g);");
   19254   CHECK_EQ(1, reresult->Int32Value(context.local()).FromJust());
   19255 
   19256   reresult = CompileRun("str2.search(/be./g);");
   19257   CHECK_EQ(1, reresult->Int32Value(context.local()).FromJust());
   19258 
   19259   ExpectTrue("/bel/g.test(str2);");
   19260 
   19261   ExpectTrue("/be./g.test(str2);");
   19262 
   19263   reresult = CompileRun("/bel/g.exec(str2);");
   19264   CHECK(!reresult->IsNull());
   19265 
   19266   reresult = CompileRun("/be./g.exec(str2);");
   19267   CHECK(!reresult->IsNull());
   19268 
   19269   ExpectString("str2.substring(2, 10);", "elspenda");
   19270 
   19271   ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
   19272 
   19273   ExpectString("str2.charAt(2);", "e");
   19274 
   19275   ExpectObject("str2.indexOf('els');", indexof);
   19276 
   19277   ExpectObject("str2.lastIndexOf('dab');", lastindexof);
   19278 
   19279   reresult = CompileRun("str2.charCodeAt(2);");
   19280   CHECK_EQ(static_cast<int32_t>('e'),
   19281            reresult->Int32Value(context.local()).FromJust());
   19282 }
   19283 
   19284 
   19285 TEST(ContainsOnlyOneByte) {
   19286   v8::V8::Initialize();
   19287   v8::Isolate* isolate = CcTest::isolate();
   19288   v8::HandleScope scope(isolate);
   19289   // Make a buffer long enough that it won't automatically be converted.
   19290   const int length = 512;
   19291   // Ensure word aligned assignment.
   19292   const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
   19293   v8::base::SmartArrayPointer<uintptr_t> aligned_contents(
   19294       new uintptr_t[aligned_length]);
   19295   uint16_t* string_contents =
   19296       reinterpret_cast<uint16_t*>(aligned_contents.get());
   19297   // Set to contain only one byte.
   19298   for (int i = 0; i < length-1; i++) {
   19299     string_contents[i] = 0x41;
   19300   }
   19301   string_contents[length-1] = 0;
   19302   // Simple case.
   19303   Local<String> string =
   19304       String::NewExternalTwoByte(isolate,
   19305                                  new TestResource(string_contents, NULL, false))
   19306           .ToLocalChecked();
   19307   CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   19308   // Counter example.
   19309   string = String::NewFromTwoByte(isolate, string_contents,
   19310                                   v8::NewStringType::kNormal)
   19311                .ToLocalChecked();
   19312   CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
   19313   // Test left right and balanced cons strings.
   19314   Local<String> base = v8_str("a");
   19315   Local<String> left = base;
   19316   Local<String> right = base;
   19317   for (int i = 0; i < 1000; i++) {
   19318     left = String::Concat(base, left);
   19319     right = String::Concat(right, base);
   19320   }
   19321   Local<String> balanced = String::Concat(left, base);
   19322   balanced = String::Concat(balanced, right);
   19323   Local<String> cons_strings[] = {left, balanced, right};
   19324   Local<String> two_byte =
   19325       String::NewExternalTwoByte(isolate,
   19326                                  new TestResource(string_contents, NULL, false))
   19327           .ToLocalChecked();
   19328   USE(two_byte); USE(cons_strings);
   19329   for (size_t i = 0; i < arraysize(cons_strings); i++) {
   19330     // Base assumptions.
   19331     string = cons_strings[i];
   19332     CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
   19333     // Test left and right concatentation.
   19334     string = String::Concat(two_byte, cons_strings[i]);
   19335     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   19336     string = String::Concat(cons_strings[i], two_byte);
   19337     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   19338   }
   19339   // Set bits in different positions
   19340   // for strings of different lengths and alignments.
   19341   for (int alignment = 0; alignment < 7; alignment++) {
   19342     for (int size = 2; alignment + size < length; size *= 2) {
   19343       int zero_offset = size + alignment;
   19344       string_contents[zero_offset] = 0;
   19345       for (int i = 0; i < size; i++) {
   19346         int shift = 8 + (i % 7);
   19347         string_contents[alignment + i] = 1 << shift;
   19348         string = String::NewExternalTwoByte(
   19349                      isolate,
   19350                      new TestResource(string_contents + alignment, NULL, false))
   19351                      .ToLocalChecked();
   19352         CHECK_EQ(size, string->Length());
   19353         CHECK(!string->ContainsOnlyOneByte());
   19354         string_contents[alignment + i] = 0x41;
   19355       }
   19356       string_contents[zero_offset] = 0x41;
   19357     }
   19358   }
   19359 }
   19360 
   19361 
   19362 // Failed access check callback that performs a GC on each invocation.
   19363 void FailedAccessCheckCallbackGC(Local<v8::Object> target,
   19364                                  v8::AccessType type,
   19365                                  Local<v8::Value> data) {
   19366   CcTest::heap()->CollectAllGarbage();
   19367   CcTest::isolate()->ThrowException(
   19368       v8::Exception::Error(v8_str("cross context")));
   19369 }
   19370 
   19371 
   19372 TEST(GCInFailedAccessCheckCallback) {
   19373   // Install a failed access check callback that performs a GC on each
   19374   // invocation. Then force the callback to be called from va
   19375 
   19376   v8::V8::Initialize();
   19377   v8::Isolate* isolate = CcTest::isolate();
   19378 
   19379   isolate->SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
   19380 
   19381   v8::HandleScope scope(isolate);
   19382 
   19383   // Create an ObjectTemplate for global objects and install access
   19384   // check callbacks that will block access.
   19385   v8::Local<v8::ObjectTemplate> global_template =
   19386       v8::ObjectTemplate::New(isolate);
   19387   global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   19388 
   19389   // Create a context and set an x property on it's global object.
   19390   LocalContext context0(NULL, global_template);
   19391   CHECK(context0->Global()
   19392             ->Set(context0.local(), v8_str("x"), v8_num(42))
   19393             .FromJust());
   19394   v8::Local<v8::Object> global0 = context0->Global();
   19395 
   19396   // Create a context with a different security token so that the
   19397   // failed access check callback will be called on each access.
   19398   LocalContext context1(NULL, global_template);
   19399   CHECK(context1->Global()
   19400             ->Set(context1.local(), v8_str("other"), global0)
   19401             .FromJust());
   19402 
   19403   v8::TryCatch try_catch(isolate);
   19404 
   19405   // Get property with failed access check.
   19406   CHECK(CompileRun("other.x").IsEmpty());
   19407   CHECK(try_catch.HasCaught());
   19408   try_catch.Reset();
   19409 
   19410   // Get element with failed access check.
   19411   CHECK(CompileRun("other[0]").IsEmpty());
   19412   CHECK(try_catch.HasCaught());
   19413   try_catch.Reset();
   19414 
   19415   // Set property with failed access check.
   19416   CHECK(CompileRun("other.x = new Object()").IsEmpty());
   19417   CHECK(try_catch.HasCaught());
   19418   try_catch.Reset();
   19419 
   19420   // Set element with failed access check.
   19421   CHECK(CompileRun("other[0] = new Object()").IsEmpty());
   19422   CHECK(try_catch.HasCaught());
   19423   try_catch.Reset();
   19424 
   19425   // Get property attribute with failed access check.
   19426   CHECK(CompileRun("\'x\' in other").IsEmpty());
   19427   CHECK(try_catch.HasCaught());
   19428   try_catch.Reset();
   19429 
   19430   // Get property attribute for element with failed access check.
   19431   CHECK(CompileRun("0 in other").IsEmpty());
   19432   CHECK(try_catch.HasCaught());
   19433   try_catch.Reset();
   19434 
   19435   // Delete property.
   19436   CHECK(CompileRun("delete other.x").IsEmpty());
   19437   CHECK(try_catch.HasCaught());
   19438   try_catch.Reset();
   19439 
   19440   // Delete element.
   19441   CHECK(global0->Delete(context1.local(), 0).IsNothing());
   19442   CHECK(try_catch.HasCaught());
   19443   try_catch.Reset();
   19444 
   19445   // DefineAccessor.
   19446   CHECK(global0->SetAccessor(context1.local(), v8_str("x"), GetXValue, NULL,
   19447                              v8_str("x"))
   19448             .IsNothing());
   19449   CHECK(try_catch.HasCaught());
   19450   try_catch.Reset();
   19451 
   19452   // Define JavaScript accessor.
   19453   CHECK(CompileRun(
   19454             "Object.prototype.__defineGetter__.call("
   19455             "    other, \'x\', function() { return 42; })").IsEmpty());
   19456   CHECK(try_catch.HasCaught());
   19457   try_catch.Reset();
   19458 
   19459   // LookupAccessor.
   19460   CHECK(CompileRun(
   19461             "Object.prototype.__lookupGetter__.call("
   19462             "    other, \'x\')").IsEmpty());
   19463   CHECK(try_catch.HasCaught());
   19464   try_catch.Reset();
   19465 
   19466   // HasOwnElement.
   19467   CHECK(CompileRun(
   19468             "Object.prototype.hasOwnProperty.call("
   19469             "other, \'0\')").IsEmpty());
   19470   CHECK(try_catch.HasCaught());
   19471   try_catch.Reset();
   19472 
   19473   CHECK(global0->HasRealIndexedProperty(context1.local(), 0).IsNothing());
   19474   CHECK(try_catch.HasCaught());
   19475   try_catch.Reset();
   19476 
   19477   CHECK(
   19478       global0->HasRealNamedProperty(context1.local(), v8_str("x")).IsNothing());
   19479   CHECK(try_catch.HasCaught());
   19480   try_catch.Reset();
   19481 
   19482   CHECK(global0->HasRealNamedCallbackProperty(context1.local(), v8_str("x"))
   19483             .IsNothing());
   19484   CHECK(try_catch.HasCaught());
   19485   try_catch.Reset();
   19486 
   19487   // Reset the failed access check callback so it does not influence
   19488   // the other tests.
   19489   isolate->SetFailedAccessCheckCallbackFunction(NULL);
   19490 }
   19491 
   19492 
   19493 TEST(IsolateNewDispose) {
   19494   v8::Isolate* current_isolate = CcTest::isolate();
   19495   v8::Isolate::CreateParams create_params;
   19496   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   19497   v8::Isolate* isolate = v8::Isolate::New(create_params);
   19498   CHECK(isolate != NULL);
   19499   CHECK(current_isolate != isolate);
   19500   CHECK(current_isolate == CcTest::isolate());
   19501 
   19502   isolate->SetFatalErrorHandler(StoringErrorCallback);
   19503   last_location = last_message = NULL;
   19504   isolate->Dispose();
   19505   CHECK(!last_location);
   19506   CHECK(!last_message);
   19507 }
   19508 
   19509 
   19510 UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
   19511   v8::Isolate::CreateParams create_params;
   19512   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   19513   v8::Isolate* isolate = v8::Isolate::New(create_params);
   19514   {
   19515     v8::Isolate::Scope i_scope(isolate);
   19516     v8::HandleScope scope(isolate);
   19517     LocalContext context(isolate);
   19518     // Run something in this isolate.
   19519     ExpectTrue("true");
   19520     isolate->SetFatalErrorHandler(StoringErrorCallback);
   19521     last_location = last_message = NULL;
   19522     // Still entered, should fail.
   19523     isolate->Dispose();
   19524     CHECK(last_location);
   19525     CHECK(last_message);
   19526   }
   19527   isolate->Dispose();
   19528 }
   19529 
   19530 
   19531 static void BreakArrayGuarantees(const char* script) {
   19532   v8::Isolate::CreateParams create_params;
   19533   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   19534   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
   19535   isolate1->Enter();
   19536   v8::Persistent<v8::Context> context1;
   19537   {
   19538     v8::HandleScope scope(isolate1);
   19539     context1.Reset(isolate1, Context::New(isolate1));
   19540   }
   19541 
   19542   {
   19543     v8::HandleScope scope(isolate1);
   19544     v8::Local<v8::Context> context =
   19545         v8::Local<v8::Context>::New(isolate1, context1);
   19546     v8::Context::Scope context_scope(context);
   19547     v8::internal::Isolate* i_isolate =
   19548         reinterpret_cast<v8::internal::Isolate*>(isolate1);
   19549     CHECK_EQ(true, i_isolate->IsFastArrayConstructorPrototypeChainIntact());
   19550     // Run something in new isolate.
   19551     CompileRun(script);
   19552     CHECK_EQ(false, i_isolate->IsFastArrayConstructorPrototypeChainIntact());
   19553   }
   19554   isolate1->Exit();
   19555   isolate1->Dispose();
   19556 }
   19557 
   19558 
   19559 TEST(VerifyArrayPrototypeGuarantees) {
   19560   // Break fast array hole handling by element changes.
   19561   BreakArrayGuarantees("[].__proto__[1] = 3;");
   19562   BreakArrayGuarantees("Object.prototype[3] = 'three';");
   19563   BreakArrayGuarantees("Array.prototype.push(1);");
   19564   BreakArrayGuarantees("Array.prototype.unshift(1);");
   19565   // Break fast array hole handling by changing length.
   19566   BreakArrayGuarantees("Array.prototype.length = 30;");
   19567   // Break fast array hole handling by prototype structure changes.
   19568   BreakArrayGuarantees("[].__proto__.__proto__ = { funny: true };");
   19569   // By sending elements to dictionary mode.
   19570   BreakArrayGuarantees(
   19571       "Object.defineProperty(Array.prototype, 0, {"
   19572       "  get: function() { return 3; }});");
   19573   BreakArrayGuarantees(
   19574       "Object.defineProperty(Object.prototype, 0, {"
   19575       "  get: function() { return 3; }});");
   19576 }
   19577 
   19578 
   19579 TEST(RunTwoIsolatesOnSingleThread) {
   19580   // Run isolate 1.
   19581   v8::Isolate::CreateParams create_params;
   19582   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   19583   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
   19584   isolate1->Enter();
   19585   v8::Persistent<v8::Context> context1;
   19586   {
   19587     v8::HandleScope scope(isolate1);
   19588     context1.Reset(isolate1, Context::New(isolate1));
   19589   }
   19590 
   19591   {
   19592     v8::HandleScope scope(isolate1);
   19593     v8::Local<v8::Context> context =
   19594         v8::Local<v8::Context>::New(isolate1, context1);
   19595     v8::Context::Scope context_scope(context);
   19596     // Run something in new isolate.
   19597     CompileRun("var foo = 'isolate 1';");
   19598     ExpectString("function f() { return foo; }; f()", "isolate 1");
   19599   }
   19600 
   19601   // Run isolate 2.
   19602   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
   19603   v8::Persistent<v8::Context> context2;
   19604 
   19605   {
   19606     v8::Isolate::Scope iscope(isolate2);
   19607     v8::HandleScope scope(isolate2);
   19608     context2.Reset(isolate2, Context::New(isolate2));
   19609     v8::Local<v8::Context> context =
   19610         v8::Local<v8::Context>::New(isolate2, context2);
   19611     v8::Context::Scope context_scope(context);
   19612 
   19613     // Run something in new isolate.
   19614     CompileRun("var foo = 'isolate 2';");
   19615     ExpectString("function f() { return foo; }; f()", "isolate 2");
   19616   }
   19617 
   19618   {
   19619     v8::HandleScope scope(isolate1);
   19620     v8::Local<v8::Context> context =
   19621         v8::Local<v8::Context>::New(isolate1, context1);
   19622     v8::Context::Scope context_scope(context);
   19623     // Now again in isolate 1
   19624     ExpectString("function f() { return foo; }; f()", "isolate 1");
   19625   }
   19626 
   19627   isolate1->Exit();
   19628 
   19629   // Run some stuff in default isolate.
   19630   v8::Persistent<v8::Context> context_default;
   19631   {
   19632     v8::Isolate* isolate = CcTest::isolate();
   19633     v8::Isolate::Scope iscope(isolate);
   19634     v8::HandleScope scope(isolate);
   19635     context_default.Reset(isolate, Context::New(isolate));
   19636   }
   19637 
   19638   {
   19639     v8::HandleScope scope(CcTest::isolate());
   19640     v8::Local<v8::Context> context =
   19641         v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
   19642     v8::Context::Scope context_scope(context);
   19643     // Variables in other isolates should be not available, verify there
   19644     // is an exception.
   19645     ExpectTrue("function f() {"
   19646                "  try {"
   19647                "    foo;"
   19648                "    return false;"
   19649                "  } catch(e) {"
   19650                "    return true;"
   19651                "  }"
   19652                "};"
   19653                "var isDefaultIsolate = true;"
   19654                "f()");
   19655   }
   19656 
   19657   isolate1->Enter();
   19658 
   19659   {
   19660     v8::Isolate::Scope iscope(isolate2);
   19661     v8::HandleScope scope(isolate2);
   19662     v8::Local<v8::Context> context =
   19663         v8::Local<v8::Context>::New(isolate2, context2);
   19664     v8::Context::Scope context_scope(context);
   19665     ExpectString("function f() { return foo; }; f()", "isolate 2");
   19666   }
   19667 
   19668   {
   19669     v8::HandleScope scope(v8::Isolate::GetCurrent());
   19670     v8::Local<v8::Context> context =
   19671         v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
   19672     v8::Context::Scope context_scope(context);
   19673     ExpectString("function f() { return foo; }; f()", "isolate 1");
   19674   }
   19675 
   19676   {
   19677     v8::Isolate::Scope iscope(isolate2);
   19678     context2.Reset();
   19679   }
   19680 
   19681   context1.Reset();
   19682   isolate1->Exit();
   19683 
   19684   isolate2->SetFatalErrorHandler(StoringErrorCallback);
   19685   last_location = last_message = NULL;
   19686 
   19687   isolate1->Dispose();
   19688   CHECK(!last_location);
   19689   CHECK(!last_message);
   19690 
   19691   isolate2->Dispose();
   19692   CHECK(!last_location);
   19693   CHECK(!last_message);
   19694 
   19695   // Check that default isolate still runs.
   19696   {
   19697     v8::HandleScope scope(CcTest::isolate());
   19698     v8::Local<v8::Context> context =
   19699         v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
   19700     v8::Context::Scope context_scope(context);
   19701     ExpectTrue("function f() { return isDefaultIsolate; }; f()");
   19702   }
   19703 }
   19704 
   19705 
   19706 static int CalcFibonacci(v8::Isolate* isolate, int limit) {
   19707   v8::Isolate::Scope isolate_scope(isolate);
   19708   v8::HandleScope scope(isolate);
   19709   LocalContext context(isolate);
   19710   i::ScopedVector<char> code(1024);
   19711   i::SNPrintF(code, "function fib(n) {"
   19712                     "  if (n <= 2) return 1;"
   19713                     "  return fib(n-1) + fib(n-2);"
   19714                     "}"
   19715                     "fib(%d)", limit);
   19716   Local<Value> value = CompileRun(code.start());
   19717   CHECK(value->IsNumber());
   19718   return static_cast<int>(value->NumberValue(context.local()).FromJust());
   19719 }
   19720 
   19721 class IsolateThread : public v8::base::Thread {
   19722  public:
   19723   explicit IsolateThread(int fib_limit)
   19724       : Thread(Options("IsolateThread")), fib_limit_(fib_limit), result_(0) {}
   19725 
   19726   void Run() {
   19727     v8::Isolate::CreateParams create_params;
   19728     create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   19729     v8::Isolate* isolate = v8::Isolate::New(create_params);
   19730     result_ = CalcFibonacci(isolate, fib_limit_);
   19731     isolate->Dispose();
   19732   }
   19733 
   19734   int result() { return result_; }
   19735 
   19736  private:
   19737   int fib_limit_;
   19738   int result_;
   19739 };
   19740 
   19741 
   19742 TEST(MultipleIsolatesOnIndividualThreads) {
   19743   IsolateThread thread1(21);
   19744   IsolateThread thread2(12);
   19745 
   19746   // Compute some fibonacci numbers on 3 threads in 3 isolates.
   19747   thread1.Start();
   19748   thread2.Start();
   19749 
   19750   int result1 = CalcFibonacci(CcTest::isolate(), 21);
   19751   int result2 = CalcFibonacci(CcTest::isolate(), 12);
   19752 
   19753   thread1.Join();
   19754   thread2.Join();
   19755 
   19756   // Compare results. The actual fibonacci numbers for 12 and 21 are taken
   19757   // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
   19758   CHECK_EQ(result1, 10946);
   19759   CHECK_EQ(result2, 144);
   19760   CHECK_EQ(result1, thread1.result());
   19761   CHECK_EQ(result2, thread2.result());
   19762 }
   19763 
   19764 
   19765 TEST(IsolateDifferentContexts) {
   19766   v8::Isolate::CreateParams create_params;
   19767   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   19768   v8::Isolate* isolate = v8::Isolate::New(create_params);
   19769   Local<v8::Context> context;
   19770   {
   19771     v8::Isolate::Scope isolate_scope(isolate);
   19772     v8::HandleScope handle_scope(isolate);
   19773     context = v8::Context::New(isolate);
   19774     v8::Context::Scope context_scope(context);
   19775     Local<Value> v = CompileRun("2");
   19776     CHECK(v->IsNumber());
   19777     CHECK_EQ(2, static_cast<int>(v->NumberValue(context).FromJust()));
   19778   }
   19779   {
   19780     v8::Isolate::Scope isolate_scope(isolate);
   19781     v8::HandleScope handle_scope(isolate);
   19782     context = v8::Context::New(isolate);
   19783     v8::Context::Scope context_scope(context);
   19784     Local<Value> v = CompileRun("22");
   19785     CHECK(v->IsNumber());
   19786     CHECK_EQ(22, static_cast<int>(v->NumberValue(context).FromJust()));
   19787   }
   19788   isolate->Dispose();
   19789 }
   19790 
   19791 class InitDefaultIsolateThread : public v8::base::Thread {
   19792  public:
   19793   enum TestCase {
   19794     SetResourceConstraints,
   19795     SetFatalHandler,
   19796     SetCounterFunction,
   19797     SetCreateHistogramFunction,
   19798     SetAddHistogramSampleFunction
   19799   };
   19800 
   19801   explicit InitDefaultIsolateThread(TestCase testCase)
   19802       : Thread(Options("InitDefaultIsolateThread")),
   19803         testCase_(testCase),
   19804         result_(false) {}
   19805 
   19806   void Run() {
   19807     v8::Isolate::CreateParams create_params;
   19808     create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   19809     const intptr_t pageSizeMult =
   19810         v8::internal::Page::kPageSize / v8::internal::MB;
   19811     switch (testCase_) {
   19812       case SetResourceConstraints: {
   19813         create_params.constraints.set_max_semi_space_size(1 * pageSizeMult);
   19814         create_params.constraints.set_max_old_space_size(4 * pageSizeMult);
   19815         break;
   19816       }
   19817       default:
   19818         break;
   19819     }
   19820     v8::Isolate* isolate = v8::Isolate::New(create_params);
   19821     isolate->Enter();
   19822     switch (testCase_) {
   19823       case SetResourceConstraints:
   19824         // Already handled in pre-Isolate-creation block.
   19825         break;
   19826 
   19827       case SetFatalHandler:
   19828         isolate->SetFatalErrorHandler(NULL);
   19829         break;
   19830 
   19831       case SetCounterFunction:
   19832         CcTest::isolate()->SetCounterFunction(NULL);
   19833         break;
   19834 
   19835       case SetCreateHistogramFunction:
   19836         CcTest::isolate()->SetCreateHistogramFunction(NULL);
   19837         break;
   19838 
   19839       case SetAddHistogramSampleFunction:
   19840         CcTest::isolate()->SetAddHistogramSampleFunction(NULL);
   19841         break;
   19842     }
   19843     isolate->Exit();
   19844     isolate->Dispose();
   19845     result_ = true;
   19846   }
   19847 
   19848   bool result() { return result_; }
   19849 
   19850  private:
   19851   TestCase testCase_;
   19852   bool result_;
   19853 };
   19854 
   19855 
   19856 static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
   19857   InitDefaultIsolateThread thread(testCase);
   19858   thread.Start();
   19859   thread.Join();
   19860   CHECK_EQ(thread.result(), true);
   19861 }
   19862 
   19863 
   19864 TEST(InitializeDefaultIsolateOnSecondaryThread1) {
   19865   InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
   19866 }
   19867 
   19868 
   19869 TEST(InitializeDefaultIsolateOnSecondaryThread2) {
   19870   InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
   19871 }
   19872 
   19873 
   19874 TEST(InitializeDefaultIsolateOnSecondaryThread3) {
   19875   InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
   19876 }
   19877 
   19878 
   19879 TEST(InitializeDefaultIsolateOnSecondaryThread4) {
   19880   InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
   19881 }
   19882 
   19883 
   19884 TEST(InitializeDefaultIsolateOnSecondaryThread5) {
   19885   InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
   19886 }
   19887 
   19888 
   19889 TEST(StringCheckMultipleContexts) {
   19890   const char* code =
   19891       "(function() { return \"a\".charAt(0); })()";
   19892 
   19893   {
   19894     // Run the code twice in the first context to initialize the call IC.
   19895     LocalContext context1;
   19896     v8::HandleScope scope(context1->GetIsolate());
   19897     ExpectString(code, "a");
   19898     ExpectString(code, "a");
   19899   }
   19900 
   19901   {
   19902     // Change the String.prototype in the second context and check
   19903     // that the right function gets called.
   19904     LocalContext context2;
   19905     v8::HandleScope scope(context2->GetIsolate());
   19906     CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
   19907     ExpectString(code, "not a");
   19908   }
   19909 }
   19910 
   19911 
   19912 TEST(NumberCheckMultipleContexts) {
   19913   const char* code =
   19914       "(function() { return (42).toString(); })()";
   19915 
   19916   {
   19917     // Run the code twice in the first context to initialize the call IC.
   19918     LocalContext context1;
   19919     v8::HandleScope scope(context1->GetIsolate());
   19920     ExpectString(code, "42");
   19921     ExpectString(code, "42");
   19922   }
   19923 
   19924   {
   19925     // Change the Number.prototype in the second context and check
   19926     // that the right function gets called.
   19927     LocalContext context2;
   19928     v8::HandleScope scope(context2->GetIsolate());
   19929     CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
   19930     ExpectString(code, "not 42");
   19931   }
   19932 }
   19933 
   19934 
   19935 TEST(BooleanCheckMultipleContexts) {
   19936   const char* code =
   19937       "(function() { return true.toString(); })()";
   19938 
   19939   {
   19940     // Run the code twice in the first context to initialize the call IC.
   19941     LocalContext context1;
   19942     v8::HandleScope scope(context1->GetIsolate());
   19943     ExpectString(code, "true");
   19944     ExpectString(code, "true");
   19945   }
   19946 
   19947   {
   19948     // Change the Boolean.prototype in the second context and check
   19949     // that the right function gets called.
   19950     LocalContext context2;
   19951     v8::HandleScope scope(context2->GetIsolate());
   19952     CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
   19953     ExpectString(code, "");
   19954   }
   19955 }
   19956 
   19957 
   19958 TEST(DontDeleteCellLoadIC) {
   19959   const char* function_code =
   19960       "function readCell() { while (true) { return cell; } }";
   19961 
   19962   {
   19963     // Run the code twice in the first context to initialize the load
   19964     // IC for a don't delete cell.
   19965     LocalContext context1;
   19966     v8::HandleScope scope(context1->GetIsolate());
   19967     CompileRun("var cell = \"first\";");
   19968     ExpectBoolean("delete cell", false);
   19969     CompileRun(function_code);
   19970     ExpectString("readCell()", "first");
   19971     ExpectString("readCell()", "first");
   19972   }
   19973 
   19974   {
   19975     // Use a deletable cell in the second context.
   19976     LocalContext context2;
   19977     v8::HandleScope scope(context2->GetIsolate());
   19978     CompileRun("cell = \"second\";");
   19979     CompileRun(function_code);
   19980     ExpectString("readCell()", "second");
   19981     ExpectBoolean("delete cell", true);
   19982     ExpectString("(function() {"
   19983                  "  try {"
   19984                  "    return readCell();"
   19985                  "  } catch(e) {"
   19986                  "    return e.toString();"
   19987                  "  }"
   19988                  "})()",
   19989                  "ReferenceError: cell is not defined");
   19990     CompileRun("cell = \"new_second\";");
   19991     CcTest::heap()->CollectAllGarbage();
   19992     ExpectString("readCell()", "new_second");
   19993     ExpectString("readCell()", "new_second");
   19994   }
   19995 }
   19996 
   19997 
   19998 class Visitor42 : public v8::PersistentHandleVisitor {
   19999  public:
   20000   explicit Visitor42(v8::Persistent<v8::Object>* object)
   20001       : counter_(0), object_(object) { }
   20002 
   20003   virtual void VisitPersistentHandle(Persistent<Value>* value,
   20004                                      uint16_t class_id) {
   20005     if (class_id != 42) return;
   20006     CHECK_EQ(42, value->WrapperClassId());
   20007     v8::Isolate* isolate = CcTest::isolate();
   20008     v8::HandleScope handle_scope(isolate);
   20009     v8::Local<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
   20010     v8::Local<v8::Value> object = v8::Local<v8::Object>::New(isolate, *object_);
   20011     CHECK(handle->IsObject());
   20012     CHECK(Local<Object>::Cast(handle)
   20013               ->Equals(isolate->GetCurrentContext(), object)
   20014               .FromJust());
   20015     ++counter_;
   20016   }
   20017 
   20018   int counter_;
   20019   v8::Persistent<v8::Object>* object_;
   20020 };
   20021 
   20022 
   20023 TEST(PersistentHandleVisitor) {
   20024   LocalContext context;
   20025   v8::Isolate* isolate = context->GetIsolate();
   20026   v8::HandleScope scope(isolate);
   20027   v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
   20028   CHECK_EQ(0, object.WrapperClassId());
   20029   object.SetWrapperClassId(42);
   20030   CHECK_EQ(42, object.WrapperClassId());
   20031 
   20032   Visitor42 visitor(&object);
   20033   isolate->VisitHandlesWithClassIds(&visitor);
   20034   CHECK_EQ(1, visitor.counter_);
   20035 
   20036   object.Reset();
   20037 }
   20038 
   20039 
   20040 TEST(WrapperClassId) {
   20041   LocalContext context;
   20042   v8::Isolate* isolate = context->GetIsolate();
   20043   v8::HandleScope scope(isolate);
   20044   v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
   20045   CHECK_EQ(0, object.WrapperClassId());
   20046   object.SetWrapperClassId(65535);
   20047   CHECK_EQ(65535, object.WrapperClassId());
   20048   object.Reset();
   20049 }
   20050 
   20051 
   20052 TEST(PersistentHandleInNewSpaceVisitor) {
   20053   LocalContext context;
   20054   v8::Isolate* isolate = context->GetIsolate();
   20055   v8::HandleScope scope(isolate);
   20056   v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
   20057   CHECK_EQ(0, object1.WrapperClassId());
   20058   object1.SetWrapperClassId(42);
   20059   CHECK_EQ(42, object1.WrapperClassId());
   20060 
   20061   CcTest::heap()->CollectAllGarbage();
   20062   CcTest::heap()->CollectAllGarbage();
   20063 
   20064   v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
   20065   CHECK_EQ(0, object2.WrapperClassId());
   20066   object2.SetWrapperClassId(42);
   20067   CHECK_EQ(42, object2.WrapperClassId());
   20068 
   20069   Visitor42 visitor(&object2);
   20070   isolate->VisitHandlesForPartialDependence(&visitor);
   20071   CHECK_EQ(1, visitor.counter_);
   20072 
   20073   object1.Reset();
   20074   object2.Reset();
   20075 }
   20076 
   20077 
   20078 TEST(RegExp) {
   20079   LocalContext context;
   20080   v8::HandleScope scope(context->GetIsolate());
   20081 
   20082   v8::Local<v8::RegExp> re =
   20083       v8::RegExp::New(context.local(), v8_str("foo"), v8::RegExp::kNone)
   20084           .ToLocalChecked();
   20085   CHECK(re->IsRegExp());
   20086   CHECK(re->GetSource()->Equals(context.local(), v8_str("foo")).FromJust());
   20087   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   20088 
   20089   re = v8::RegExp::New(context.local(), v8_str("bar"),
   20090                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   20091                                                       v8::RegExp::kGlobal))
   20092            .ToLocalChecked();
   20093   CHECK(re->IsRegExp());
   20094   CHECK(re->GetSource()->Equals(context.local(), v8_str("bar")).FromJust());
   20095   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
   20096            static_cast<int>(re->GetFlags()));
   20097 
   20098   re = v8::RegExp::New(context.local(), v8_str("baz"),
   20099                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   20100                                                       v8::RegExp::kMultiline))
   20101            .ToLocalChecked();
   20102   CHECK(re->IsRegExp());
   20103   CHECK(re->GetSource()->Equals(context.local(), v8_str("baz")).FromJust());
   20104   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
   20105            static_cast<int>(re->GetFlags()));
   20106 
   20107   re = v8::RegExp::New(context.local(), v8_str("baz"),
   20108                        static_cast<v8::RegExp::Flags>(v8::RegExp::kUnicode |
   20109                                                       v8::RegExp::kSticky))
   20110            .ToLocalChecked();
   20111   CHECK(re->IsRegExp());
   20112   CHECK(re->GetSource()->Equals(context.local(), v8_str("baz")).FromJust());
   20113   CHECK_EQ(v8::RegExp::kUnicode | v8::RegExp::kSticky,
   20114            static_cast<int>(re->GetFlags()));
   20115 
   20116   re = CompileRun("/quux/").As<v8::RegExp>();
   20117   CHECK(re->IsRegExp());
   20118   CHECK(re->GetSource()->Equals(context.local(), v8_str("quux")).FromJust());
   20119   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   20120 
   20121   re = CompileRun("/quux/gm").As<v8::RegExp>();
   20122   CHECK(re->IsRegExp());
   20123   CHECK(re->GetSource()->Equals(context.local(), v8_str("quux")).FromJust());
   20124   CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
   20125            static_cast<int>(re->GetFlags()));
   20126 
   20127   // Override the RegExp constructor and check the API constructor
   20128   // still works.
   20129   CompileRun("RegExp = function() {}");
   20130 
   20131   re = v8::RegExp::New(context.local(), v8_str("foobar"), v8::RegExp::kNone)
   20132            .ToLocalChecked();
   20133   CHECK(re->IsRegExp());
   20134   CHECK(re->GetSource()->Equals(context.local(), v8_str("foobar")).FromJust());
   20135   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   20136 
   20137   re = v8::RegExp::New(context.local(), v8_str("foobarbaz"),
   20138                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   20139                                                       v8::RegExp::kMultiline))
   20140            .ToLocalChecked();
   20141   CHECK(re->IsRegExp());
   20142   CHECK(
   20143       re->GetSource()->Equals(context.local(), v8_str("foobarbaz")).FromJust());
   20144   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
   20145            static_cast<int>(re->GetFlags()));
   20146 
   20147   CHECK(context->Global()->Set(context.local(), v8_str("re"), re).FromJust());
   20148   ExpectTrue("re.test('FoobarbaZ')");
   20149 
   20150   // RegExps are objects on which you can set properties.
   20151   re->Set(context.local(), v8_str("property"),
   20152           v8::Integer::New(context->GetIsolate(), 32))
   20153       .FromJust();
   20154   v8::Local<v8::Value> value(CompileRun("re.property"));
   20155   CHECK_EQ(32, value->Int32Value(context.local()).FromJust());
   20156 
   20157   v8::TryCatch try_catch(context->GetIsolate());
   20158   CHECK(v8::RegExp::New(context.local(), v8_str("foo["), v8::RegExp::kNone)
   20159             .IsEmpty());
   20160   CHECK(try_catch.HasCaught());
   20161   CHECK(context->Global()
   20162             ->Set(context.local(), v8_str("ex"), try_catch.Exception())
   20163             .FromJust());
   20164   ExpectTrue("ex instanceof SyntaxError");
   20165 }
   20166 
   20167 
   20168 THREADED_TEST(Equals) {
   20169   LocalContext localContext;
   20170   v8::HandleScope handleScope(localContext->GetIsolate());
   20171 
   20172   v8::Local<v8::Object> globalProxy = localContext->Global();
   20173   v8::Local<Value> global = globalProxy->GetPrototype();
   20174 
   20175   CHECK(global->StrictEquals(global));
   20176   CHECK(!global->StrictEquals(globalProxy));
   20177   CHECK(!globalProxy->StrictEquals(global));
   20178   CHECK(globalProxy->StrictEquals(globalProxy));
   20179 
   20180   CHECK(global->Equals(localContext.local(), global).FromJust());
   20181   CHECK(!global->Equals(localContext.local(), globalProxy).FromJust());
   20182   CHECK(!globalProxy->Equals(localContext.local(), global).FromJust());
   20183   CHECK(globalProxy->Equals(localContext.local(), globalProxy).FromJust());
   20184 }
   20185 
   20186 
   20187 static void Getter(v8::Local<v8::Name> property,
   20188                    const v8::PropertyCallbackInfo<v8::Value>& info) {
   20189   info.GetReturnValue().Set(v8_str("42!"));
   20190 }
   20191 
   20192 
   20193 static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
   20194   v8::Local<v8::Array> result = v8::Array::New(info.GetIsolate());
   20195   result->Set(info.GetIsolate()->GetCurrentContext(), 0,
   20196               v8_str("universalAnswer"))
   20197       .FromJust();
   20198   info.GetReturnValue().Set(result);
   20199 }
   20200 
   20201 
   20202 TEST(NamedEnumeratorAndForIn) {
   20203   LocalContext context;
   20204   v8::Isolate* isolate = context->GetIsolate();
   20205   v8::HandleScope handle_scope(isolate);
   20206   v8::Context::Scope context_scope(context.local());
   20207 
   20208   v8::Local<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
   20209   tmpl->SetHandler(v8::NamedPropertyHandlerConfiguration(Getter, NULL, NULL,
   20210                                                          NULL, Enumerator));
   20211   CHECK(context->Global()
   20212             ->Set(context.local(), v8_str("o"),
   20213                   tmpl->NewInstance(context.local()).ToLocalChecked())
   20214             .FromJust());
   20215   v8::Local<v8::Array> result = v8::Local<v8::Array>::Cast(
   20216       CompileRun("var result = []; for (var k in o) result.push(k); result"));
   20217   CHECK_EQ(1u, result->Length());
   20218   CHECK(v8_str("universalAnswer")
   20219             ->Equals(context.local(),
   20220                      result->Get(context.local(), 0).ToLocalChecked())
   20221             .FromJust());
   20222 }
   20223 
   20224 
   20225 TEST(DefinePropertyPostDetach) {
   20226   LocalContext context;
   20227   v8::HandleScope scope(context->GetIsolate());
   20228   v8::Local<v8::Object> proxy = context->Global();
   20229   v8::Local<v8::Function> define_property =
   20230       CompileRun(
   20231           "(function() {"
   20232           "  Object.defineProperty("
   20233           "    this,"
   20234           "    1,"
   20235           "    { configurable: true, enumerable: true, value: 3 });"
   20236           "})")
   20237           .As<Function>();
   20238   context->DetachGlobal();
   20239   CHECK(define_property->Call(context.local(), proxy, 0, NULL).IsEmpty());
   20240 }
   20241 
   20242 
   20243 static void InstallContextId(v8::Local<Context> context, int id) {
   20244   Context::Scope scope(context);
   20245   CHECK(CompileRun("Object.prototype")
   20246             .As<Object>()
   20247             ->Set(context, v8_str("context_id"),
   20248                   v8::Integer::New(context->GetIsolate(), id))
   20249             .FromJust());
   20250 }
   20251 
   20252 
   20253 static void CheckContextId(v8::Local<Object> object, int expected) {
   20254   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   20255   CHECK_EQ(expected, object->Get(context, v8_str("context_id"))
   20256                          .ToLocalChecked()
   20257                          ->Int32Value(context)
   20258                          .FromJust());
   20259 }
   20260 
   20261 
   20262 THREADED_TEST(CreationContext) {
   20263   v8::Isolate* isolate = CcTest::isolate();
   20264   HandleScope handle_scope(isolate);
   20265   Local<Context> context1 = Context::New(isolate);
   20266   InstallContextId(context1, 1);
   20267   Local<Context> context2 = Context::New(isolate);
   20268   InstallContextId(context2, 2);
   20269   Local<Context> context3 = Context::New(isolate);
   20270   InstallContextId(context3, 3);
   20271 
   20272   Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
   20273 
   20274   Local<Object> object1;
   20275   Local<Function> func1;
   20276   {
   20277     Context::Scope scope(context1);
   20278     object1 = Object::New(isolate);
   20279     func1 = tmpl->GetFunction(context1).ToLocalChecked();
   20280   }
   20281 
   20282   Local<Object> object2;
   20283   Local<Function> func2;
   20284   {
   20285     Context::Scope scope(context2);
   20286     object2 = Object::New(isolate);
   20287     func2 = tmpl->GetFunction(context2).ToLocalChecked();
   20288   }
   20289 
   20290   Local<Object> instance1;
   20291   Local<Object> instance2;
   20292 
   20293   {
   20294     Context::Scope scope(context3);
   20295     instance1 = func1->NewInstance(context3).ToLocalChecked();
   20296     instance2 = func2->NewInstance(context3).ToLocalChecked();
   20297   }
   20298 
   20299   {
   20300     Local<Context> other_context = Context::New(isolate);
   20301     Context::Scope scope(other_context);
   20302     CHECK(object1->CreationContext() == context1);
   20303     CheckContextId(object1, 1);
   20304     CHECK(func1->CreationContext() == context1);
   20305     CheckContextId(func1, 1);
   20306     CHECK(instance1->CreationContext() == context1);
   20307     CheckContextId(instance1, 1);
   20308     CHECK(object2->CreationContext() == context2);
   20309     CheckContextId(object2, 2);
   20310     CHECK(func2->CreationContext() == context2);
   20311     CheckContextId(func2, 2);
   20312     CHECK(instance2->CreationContext() == context2);
   20313     CheckContextId(instance2, 2);
   20314   }
   20315 
   20316   {
   20317     Context::Scope scope(context1);
   20318     CHECK(object1->CreationContext() == context1);
   20319     CheckContextId(object1, 1);
   20320     CHECK(func1->CreationContext() == context1);
   20321     CheckContextId(func1, 1);
   20322     CHECK(instance1->CreationContext() == context1);
   20323     CheckContextId(instance1, 1);
   20324     CHECK(object2->CreationContext() == context2);
   20325     CheckContextId(object2, 2);
   20326     CHECK(func2->CreationContext() == context2);
   20327     CheckContextId(func2, 2);
   20328     CHECK(instance2->CreationContext() == context2);
   20329     CheckContextId(instance2, 2);
   20330   }
   20331 
   20332   {
   20333     Context::Scope scope(context2);
   20334     CHECK(object1->CreationContext() == context1);
   20335     CheckContextId(object1, 1);
   20336     CHECK(func1->CreationContext() == context1);
   20337     CheckContextId(func1, 1);
   20338     CHECK(instance1->CreationContext() == context1);
   20339     CheckContextId(instance1, 1);
   20340     CHECK(object2->CreationContext() == context2);
   20341     CheckContextId(object2, 2);
   20342     CHECK(func2->CreationContext() == context2);
   20343     CheckContextId(func2, 2);
   20344     CHECK(instance2->CreationContext() == context2);
   20345     CheckContextId(instance2, 2);
   20346   }
   20347 }
   20348 
   20349 
   20350 THREADED_TEST(CreationContextOfJsFunction) {
   20351   HandleScope handle_scope(CcTest::isolate());
   20352   Local<Context> context = Context::New(CcTest::isolate());
   20353   InstallContextId(context, 1);
   20354 
   20355   Local<Object> function;
   20356   {
   20357     Context::Scope scope(context);
   20358     function = CompileRun("function foo() {}; foo").As<Object>();
   20359   }
   20360 
   20361   Local<Context> other_context = Context::New(CcTest::isolate());
   20362   Context::Scope scope(other_context);
   20363   CHECK(function->CreationContext() == context);
   20364   CheckContextId(function, 1);
   20365 }
   20366 
   20367 
   20368 THREADED_TEST(CreationContextOfJsBoundFunction) {
   20369   HandleScope handle_scope(CcTest::isolate());
   20370   Local<Context> context1 = Context::New(CcTest::isolate());
   20371   InstallContextId(context1, 1);
   20372   Local<Context> context2 = Context::New(CcTest::isolate());
   20373   InstallContextId(context2, 2);
   20374 
   20375   Local<Function> target_function;
   20376   {
   20377     Context::Scope scope(context1);
   20378     target_function = CompileRun("function foo() {}; foo").As<Function>();
   20379   }
   20380 
   20381   Local<Function> bound_function1, bound_function2;
   20382   {
   20383     Context::Scope scope(context2);
   20384     CHECK(context2->Global()
   20385               ->Set(context2, v8_str("foo"), target_function)
   20386               .FromJust());
   20387     bound_function1 = CompileRun("foo.bind(1)").As<Function>();
   20388     bound_function2 =
   20389         CompileRun("Function.prototype.bind.call(foo, 2)").As<Function>();
   20390   }
   20391 
   20392   Local<Context> other_context = Context::New(CcTest::isolate());
   20393   Context::Scope scope(other_context);
   20394   CHECK(bound_function1->CreationContext() == context1);
   20395   CheckContextId(bound_function1, 1);
   20396   CHECK(bound_function2->CreationContext() == context1);
   20397   CheckContextId(bound_function2, 1);
   20398 }
   20399 
   20400 
   20401 void HasOwnPropertyIndexedPropertyGetter(
   20402     uint32_t index,
   20403     const v8::PropertyCallbackInfo<v8::Value>& info) {
   20404   if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
   20405 }
   20406 
   20407 
   20408 void HasOwnPropertyNamedPropertyGetter(
   20409     Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
   20410   if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   20411           .FromJust()) {
   20412     info.GetReturnValue().Set(v8_str("yes"));
   20413   }
   20414 }
   20415 
   20416 
   20417 void HasOwnPropertyIndexedPropertyQuery(
   20418     uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   20419   if (index == 42) info.GetReturnValue().Set(1);
   20420 }
   20421 
   20422 
   20423 void HasOwnPropertyNamedPropertyQuery(
   20424     Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   20425   if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   20426           .FromJust()) {
   20427     info.GetReturnValue().Set(1);
   20428   }
   20429 }
   20430 
   20431 
   20432 void HasOwnPropertyNamedPropertyQuery2(
   20433     Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   20434   if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("bar"))
   20435           .FromJust()) {
   20436     info.GetReturnValue().Set(1);
   20437   }
   20438 }
   20439 
   20440 
   20441 void HasOwnPropertyAccessorGetter(
   20442     Local<String> property,
   20443     const v8::PropertyCallbackInfo<v8::Value>& info) {
   20444   info.GetReturnValue().Set(v8_str("yes"));
   20445 }
   20446 
   20447 
   20448 TEST(HasOwnProperty) {
   20449   LocalContext env;
   20450   v8::Isolate* isolate = env->GetIsolate();
   20451   v8::HandleScope scope(isolate);
   20452   { // Check normal properties and defined getters.
   20453     Local<Value> value = CompileRun(
   20454         "function Foo() {"
   20455         "    this.foo = 11;"
   20456         "    this.__defineGetter__('baz', function() { return 1; });"
   20457         "};"
   20458         "function Bar() { "
   20459         "    this.bar = 13;"
   20460         "    this.__defineGetter__('bla', function() { return 2; });"
   20461         "};"
   20462         "Bar.prototype = new Foo();"
   20463         "new Bar();");
   20464     CHECK(value->IsObject());
   20465     Local<Object> object = value->ToObject(env.local()).ToLocalChecked();
   20466     CHECK(object->Has(env.local(), v8_str("foo")).FromJust());
   20467     CHECK(!object->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   20468     CHECK(object->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   20469     CHECK(object->Has(env.local(), v8_str("baz")).FromJust());
   20470     CHECK(!object->HasOwnProperty(env.local(), v8_str("baz")).FromJust());
   20471     CHECK(object->HasOwnProperty(env.local(), v8_str("bla")).FromJust());
   20472   }
   20473   { // Check named getter interceptors.
   20474     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20475     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   20476         HasOwnPropertyNamedPropertyGetter));
   20477     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   20478     CHECK(!instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
   20479     CHECK(!instance->HasOwnProperty(env.local(), 42).FromJust());
   20480     CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   20481     CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   20482   }
   20483   { // Check indexed getter interceptors.
   20484     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20485     templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
   20486         HasOwnPropertyIndexedPropertyGetter));
   20487     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   20488     CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
   20489     CHECK(instance->HasOwnProperty(env.local(), 42).FromJust());
   20490     CHECK(!instance->HasOwnProperty(env.local(), v8_str("43")).FromJust());
   20491     CHECK(!instance->HasOwnProperty(env.local(), 43).FromJust());
   20492     CHECK(!instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   20493   }
   20494   { // Check named query interceptors.
   20495     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20496     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   20497         0, 0, HasOwnPropertyNamedPropertyQuery));
   20498     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   20499     CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   20500     CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   20501   }
   20502   { // Check indexed query interceptors.
   20503     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20504     templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
   20505         0, 0, HasOwnPropertyIndexedPropertyQuery));
   20506     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   20507     CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
   20508     CHECK(instance->HasOwnProperty(env.local(), 42).FromJust());
   20509     CHECK(!instance->HasOwnProperty(env.local(), v8_str("41")).FromJust());
   20510     CHECK(!instance->HasOwnProperty(env.local(), 41).FromJust());
   20511   }
   20512   { // Check callbacks.
   20513     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20514     templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
   20515     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   20516     CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   20517     CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   20518   }
   20519   { // Check that query wins on disagreement.
   20520     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20521     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   20522         HasOwnPropertyNamedPropertyGetter, 0,
   20523         HasOwnPropertyNamedPropertyQuery2));
   20524     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   20525     CHECK(!instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   20526     CHECK(instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   20527   }
   20528 }
   20529 
   20530 
   20531 TEST(IndexedInterceptorWithStringProto) {
   20532   v8::Isolate* isolate = CcTest::isolate();
   20533   v8::HandleScope scope(isolate);
   20534   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20535   templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
   20536       NULL, NULL, HasOwnPropertyIndexedPropertyQuery));
   20537   LocalContext context;
   20538   CHECK(context->Global()
   20539             ->Set(context.local(), v8_str("obj"),
   20540                   templ->NewInstance(context.local()).ToLocalChecked())
   20541             .FromJust());
   20542   CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
   20543   // These should be intercepted.
   20544   CHECK(CompileRun("42 in obj")->BooleanValue(context.local()).FromJust());
   20545   CHECK(CompileRun("'42' in obj")->BooleanValue(context.local()).FromJust());
   20546   // These should fall through to the String prototype.
   20547   CHECK(CompileRun("0 in obj")->BooleanValue(context.local()).FromJust());
   20548   CHECK(CompileRun("'0' in obj")->BooleanValue(context.local()).FromJust());
   20549   // And these should both fail.
   20550   CHECK(!CompileRun("32 in obj")->BooleanValue(context.local()).FromJust());
   20551   CHECK(!CompileRun("'32' in obj")->BooleanValue(context.local()).FromJust());
   20552 }
   20553 
   20554 
   20555 void CheckCodeGenerationAllowed() {
   20556   Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   20557   Local<Value> result = CompileRun("eval('42')");
   20558   CHECK_EQ(42, result->Int32Value(context).FromJust());
   20559   result = CompileRun("(function(e) { return e('42'); })(eval)");
   20560   CHECK_EQ(42, result->Int32Value(context).FromJust());
   20561   result = CompileRun("var f = new Function('return 42'); f()");
   20562   CHECK_EQ(42, result->Int32Value(context).FromJust());
   20563 }
   20564 
   20565 
   20566 void CheckCodeGenerationDisallowed() {
   20567   TryCatch try_catch(CcTest::isolate());
   20568 
   20569   Local<Value> result = CompileRun("eval('42')");
   20570   CHECK(result.IsEmpty());
   20571   CHECK(try_catch.HasCaught());
   20572   try_catch.Reset();
   20573 
   20574   result = CompileRun("(function(e) { return e('42'); })(eval)");
   20575   CHECK(result.IsEmpty());
   20576   CHECK(try_catch.HasCaught());
   20577   try_catch.Reset();
   20578 
   20579   result = CompileRun("var f = new Function('return 42'); f()");
   20580   CHECK(result.IsEmpty());
   20581   CHECK(try_catch.HasCaught());
   20582 }
   20583 
   20584 
   20585 bool CodeGenerationAllowed(Local<Context> context) {
   20586   ApiTestFuzzer::Fuzz();
   20587   return true;
   20588 }
   20589 
   20590 
   20591 bool CodeGenerationDisallowed(Local<Context> context) {
   20592   ApiTestFuzzer::Fuzz();
   20593   return false;
   20594 }
   20595 
   20596 
   20597 THREADED_TEST(AllowCodeGenFromStrings) {
   20598   LocalContext context;
   20599   v8::HandleScope scope(context->GetIsolate());
   20600 
   20601   // eval and the Function constructor allowed by default.
   20602   CHECK(context->IsCodeGenerationFromStringsAllowed());
   20603   CheckCodeGenerationAllowed();
   20604 
   20605   // Disallow eval and the Function constructor.
   20606   context->AllowCodeGenerationFromStrings(false);
   20607   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   20608   CheckCodeGenerationDisallowed();
   20609 
   20610   // Allow again.
   20611   context->AllowCodeGenerationFromStrings(true);
   20612   CheckCodeGenerationAllowed();
   20613 
   20614   // Disallow but setting a global callback that will allow the calls.
   20615   context->AllowCodeGenerationFromStrings(false);
   20616   context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
   20617       &CodeGenerationAllowed);
   20618   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   20619   CheckCodeGenerationAllowed();
   20620 
   20621   // Set a callback that disallows the code generation.
   20622   context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
   20623       &CodeGenerationDisallowed);
   20624   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   20625   CheckCodeGenerationDisallowed();
   20626 }
   20627 
   20628 
   20629 TEST(SetErrorMessageForCodeGenFromStrings) {
   20630   LocalContext context;
   20631   v8::HandleScope scope(context->GetIsolate());
   20632   TryCatch try_catch(context->GetIsolate());
   20633 
   20634   Local<String> message = v8_str("Message");
   20635   Local<String> expected_message = v8_str("Uncaught EvalError: Message");
   20636   context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
   20637       &CodeGenerationDisallowed);
   20638   context->AllowCodeGenerationFromStrings(false);
   20639   context->SetErrorMessageForCodeGenerationFromStrings(message);
   20640   Local<Value> result = CompileRun("eval('42')");
   20641   CHECK(result.IsEmpty());
   20642   CHECK(try_catch.HasCaught());
   20643   Local<String> actual_message = try_catch.Message()->Get();
   20644   CHECK(expected_message->Equals(context.local(), actual_message).FromJust());
   20645 }
   20646 
   20647 
   20648 static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
   20649 }
   20650 
   20651 
   20652 THREADED_TEST(CallAPIFunctionOnNonObject) {
   20653   LocalContext context;
   20654   v8::Isolate* isolate = context->GetIsolate();
   20655   v8::HandleScope scope(isolate);
   20656   Local<FunctionTemplate> templ =
   20657       v8::FunctionTemplate::New(isolate, NonObjectThis);
   20658   Local<Function> function =
   20659       templ->GetFunction(context.local()).ToLocalChecked();
   20660   CHECK(context->Global()
   20661             ->Set(context.local(), v8_str("f"), function)
   20662             .FromJust());
   20663   TryCatch try_catch(isolate);
   20664   CompileRun("f.call(2)");
   20665 }
   20666 
   20667 
   20668 // Regression test for issue 1470.
   20669 THREADED_TEST(ReadOnlyIndexedProperties) {
   20670   v8::Isolate* isolate = CcTest::isolate();
   20671   v8::HandleScope scope(isolate);
   20672   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20673 
   20674   LocalContext context;
   20675   Local<v8::Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
   20676   CHECK(context->Global()->Set(context.local(), v8_str("obj"), obj).FromJust());
   20677   obj->DefineOwnProperty(context.local(), v8_str("1"), v8_str("DONT_CHANGE"),
   20678                          v8::ReadOnly)
   20679       .FromJust();
   20680   obj->Set(context.local(), v8_str("1"), v8_str("foobar")).FromJust();
   20681   CHECK(v8_str("DONT_CHANGE")
   20682             ->Equals(context.local(),
   20683                      obj->Get(context.local(), v8_str("1")).ToLocalChecked())
   20684             .FromJust());
   20685   obj->DefineOwnProperty(context.local(), v8_str("2"), v8_str("DONT_CHANGE"),
   20686                          v8::ReadOnly)
   20687       .FromJust();
   20688   obj->Set(context.local(), v8_num(2), v8_str("foobar")).FromJust();
   20689   CHECK(v8_str("DONT_CHANGE")
   20690             ->Equals(context.local(),
   20691                      obj->Get(context.local(), v8_num(2)).ToLocalChecked())
   20692             .FromJust());
   20693 
   20694   // Test non-smi case.
   20695   obj->DefineOwnProperty(context.local(), v8_str("2000000000"),
   20696                          v8_str("DONT_CHANGE"), v8::ReadOnly)
   20697       .FromJust();
   20698   obj->Set(context.local(), v8_str("2000000000"), v8_str("foobar")).FromJust();
   20699   CHECK(v8_str("DONT_CHANGE")
   20700             ->Equals(context.local(),
   20701                      obj->Get(context.local(), v8_str("2000000000"))
   20702                          .ToLocalChecked())
   20703             .FromJust());
   20704 }
   20705 
   20706 
   20707 static int CountLiveMapsInMapCache(i::Context* context) {
   20708   i::FixedArray* map_cache = i::FixedArray::cast(context->map_cache());
   20709   int length = map_cache->length();
   20710   int count = 0;
   20711   for (int i = 0; i < length; i++) {
   20712     i::Object* value = map_cache->get(i);
   20713     if (value->IsWeakCell() && !i::WeakCell::cast(value)->cleared()) count++;
   20714   }
   20715   return count;
   20716 }
   20717 
   20718 
   20719 THREADED_TEST(Regress1516) {
   20720   LocalContext context;
   20721   v8::HandleScope scope(context->GetIsolate());
   20722 
   20723   // Object with 20 properties is not a common case, so it should be removed
   20724   // from the cache after GC.
   20725   { v8::HandleScope temp_scope(context->GetIsolate());
   20726     CompileRun(
   20727         "({"
   20728         "'a00': 0, 'a01': 0, 'a02': 0, 'a03': 0, 'a04': 0, "
   20729         "'a05': 0, 'a06': 0, 'a07': 0, 'a08': 0, 'a09': 0, "
   20730         "'a10': 0, 'a11': 0, 'a12': 0, 'a13': 0, 'a14': 0, "
   20731         "'a15': 0, 'a16': 0, 'a17': 0, 'a18': 0, 'a19': 0, "
   20732         "})");
   20733   }
   20734 
   20735   int elements = CountLiveMapsInMapCache(CcTest::i_isolate()->context());
   20736   CHECK_LE(1, elements);
   20737 
   20738   // We have to abort incremental marking here to abandon black pages.
   20739   CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   20740 
   20741   CHECK_GT(elements, CountLiveMapsInMapCache(CcTest::i_isolate()->context()));
   20742 }
   20743 
   20744 
   20745 THREADED_TEST(Regress93759) {
   20746   v8::Isolate* isolate = CcTest::isolate();
   20747   HandleScope scope(isolate);
   20748 
   20749   // Template for object with security check.
   20750   Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
   20751   no_proto_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   20752 
   20753   // Templates for objects with hidden prototypes and possibly security check.
   20754   Local<FunctionTemplate> hidden_proto_template =
   20755       v8::FunctionTemplate::New(isolate);
   20756   hidden_proto_template->SetHiddenPrototype(true);
   20757 
   20758   Local<FunctionTemplate> protected_hidden_proto_template =
   20759       v8::FunctionTemplate::New(isolate);
   20760   protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallback(
   20761       AccessAlwaysBlocked);
   20762   protected_hidden_proto_template->SetHiddenPrototype(true);
   20763 
   20764   // Context for "foreign" objects used in test.
   20765   Local<Context> context = v8::Context::New(isolate);
   20766   context->Enter();
   20767 
   20768   // Plain object, no security check.
   20769   Local<Object> simple_object = Object::New(isolate);
   20770 
   20771   // Object with explicit security check.
   20772   Local<Object> protected_object =
   20773       no_proto_template->NewInstance(context).ToLocalChecked();
   20774 
   20775   // JSGlobalProxy object, always have security check.
   20776   Local<Object> proxy_object = context->Global();
   20777 
   20778   // Global object, the  prototype of proxy_object. No security checks.
   20779   Local<Object> global_object =
   20780       proxy_object->GetPrototype()->ToObject(context).ToLocalChecked();
   20781 
   20782   // Hidden prototype without security check.
   20783   Local<Object> hidden_prototype = hidden_proto_template->GetFunction(context)
   20784                                        .ToLocalChecked()
   20785                                        ->NewInstance(context)
   20786                                        .ToLocalChecked();
   20787   Local<Object> object_with_hidden =
   20788     Object::New(isolate);
   20789   object_with_hidden->SetPrototype(context, hidden_prototype).FromJust();
   20790 
   20791   context->Exit();
   20792 
   20793   LocalContext context2;
   20794   v8::Local<v8::Object> global = context2->Global();
   20795 
   20796   // Setup global variables.
   20797   CHECK(global->Set(context2.local(), v8_str("simple"), simple_object)
   20798             .FromJust());
   20799   CHECK(global->Set(context2.local(), v8_str("protected"), protected_object)
   20800             .FromJust());
   20801   CHECK(global->Set(context2.local(), v8_str("global"), global_object)
   20802             .FromJust());
   20803   CHECK(
   20804       global->Set(context2.local(), v8_str("proxy"), proxy_object).FromJust());
   20805   CHECK(global->Set(context2.local(), v8_str("hidden"), object_with_hidden)
   20806             .FromJust());
   20807 
   20808   Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
   20809   CHECK(result1->Equals(context2.local(), simple_object->GetPrototype())
   20810             .FromJust());
   20811 
   20812   Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
   20813   CHECK(result2->IsNull());
   20814 
   20815   Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
   20816   CHECK(result3->Equals(context2.local(), global_object->GetPrototype())
   20817             .FromJust());
   20818 
   20819   Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
   20820   CHECK(result4->IsNull());
   20821 
   20822   Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
   20823   CHECK(result5->Equals(context2.local(), object_with_hidden->GetPrototype()
   20824                                               ->ToObject(context2.local())
   20825                                               .ToLocalChecked()
   20826                                               ->GetPrototype())
   20827             .FromJust());
   20828 }
   20829 
   20830 
   20831 static void TestReceiver(Local<Value> expected_result,
   20832                          Local<Value> expected_receiver,
   20833                          const char* code) {
   20834   Local<Value> result = CompileRun(code);
   20835   Local<Context> context = CcTest::isolate()->GetCurrentContext();
   20836   CHECK(result->IsObject());
   20837   CHECK(expected_receiver
   20838             ->Equals(context,
   20839                      result.As<v8::Object>()->Get(context, 1).ToLocalChecked())
   20840             .FromJust());
   20841   CHECK(expected_result
   20842             ->Equals(context,
   20843                      result.As<v8::Object>()->Get(context, 0).ToLocalChecked())
   20844             .FromJust());
   20845 }
   20846 
   20847 
   20848 THREADED_TEST(ForeignFunctionReceiver) {
   20849   v8::Isolate* isolate = CcTest::isolate();
   20850   HandleScope scope(isolate);
   20851 
   20852   // Create two contexts with different "id" properties ('i' and 'o').
   20853   // Call a function both from its own context and from a the foreign
   20854   // context, and see what "this" is bound to (returning both "this"
   20855   // and "this.id" for comparison).
   20856 
   20857   Local<Context> foreign_context = v8::Context::New(isolate);
   20858   foreign_context->Enter();
   20859   Local<Value> foreign_function =
   20860     CompileRun("function func() { return { 0: this.id, "
   20861                "                           1: this, "
   20862                "                           toString: function() { "
   20863                "                               return this[0];"
   20864                "                           }"
   20865                "                         };"
   20866                "}"
   20867                "var id = 'i';"
   20868                "func;");
   20869   CHECK(foreign_function->IsFunction());
   20870   foreign_context->Exit();
   20871 
   20872   LocalContext context;
   20873 
   20874   Local<String> password = v8_str("Password");
   20875   // Don't get hit by security checks when accessing foreign_context's
   20876   // global receiver (aka. global proxy).
   20877   context->SetSecurityToken(password);
   20878   foreign_context->SetSecurityToken(password);
   20879 
   20880   Local<String> i = v8_str("i");
   20881   Local<String> o = v8_str("o");
   20882   Local<String> id = v8_str("id");
   20883 
   20884   CompileRun("function ownfunc() { return { 0: this.id, "
   20885              "                              1: this, "
   20886              "                              toString: function() { "
   20887              "                                  return this[0];"
   20888              "                              }"
   20889              "                             };"
   20890              "}"
   20891              "var id = 'o';"
   20892              "ownfunc");
   20893   CHECK(context->Global()
   20894             ->Set(context.local(), v8_str("func"), foreign_function)
   20895             .FromJust());
   20896 
   20897   // Sanity check the contexts.
   20898   CHECK(
   20899       i->Equals(
   20900            context.local(),
   20901            foreign_context->Global()->Get(context.local(), id).ToLocalChecked())
   20902           .FromJust());
   20903   CHECK(o->Equals(context.local(),
   20904                   context->Global()->Get(context.local(), id).ToLocalChecked())
   20905             .FromJust());
   20906 
   20907   // Checking local function's receiver.
   20908   // Calling function using its call/apply methods.
   20909   TestReceiver(o, context->Global(), "ownfunc.call()");
   20910   TestReceiver(o, context->Global(), "ownfunc.apply()");
   20911   // Making calls through built-in functions.
   20912   TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
   20913   CHECK(
   20914       o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/,ownfunc)[1]"))
   20915           .FromJust());
   20916   CHECK(
   20917       o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]"))
   20918           .FromJust());
   20919   CHECK(
   20920       o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]"))
   20921           .FromJust());
   20922   // Calling with environment record as base.
   20923   TestReceiver(o, context->Global(), "ownfunc()");
   20924   // Calling with no base.
   20925   TestReceiver(o, context->Global(), "(1,ownfunc)()");
   20926 
   20927   // Checking foreign function return value.
   20928   // Calling function using its call/apply methods.
   20929   TestReceiver(i, foreign_context->Global(), "func.call()");
   20930   TestReceiver(i, foreign_context->Global(), "func.apply()");
   20931   // Calling function using another context's call/apply methods.
   20932   TestReceiver(i, foreign_context->Global(),
   20933                "Function.prototype.call.call(func)");
   20934   TestReceiver(i, foreign_context->Global(),
   20935                "Function.prototype.call.apply(func)");
   20936   TestReceiver(i, foreign_context->Global(),
   20937                "Function.prototype.apply.call(func)");
   20938   TestReceiver(i, foreign_context->Global(),
   20939                "Function.prototype.apply.apply(func)");
   20940   // Making calls through built-in functions.
   20941   TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
   20942   // ToString(func()) is func()[0], i.e., the returned this.id.
   20943   CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/,func)[1]"))
   20944             .FromJust());
   20945   CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,func)[1]"))
   20946             .FromJust());
   20947   CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,func)[3]"))
   20948             .FromJust());
   20949 
   20950   // Calling with environment record as base.
   20951   TestReceiver(i, foreign_context->Global(), "func()");
   20952   // Calling with no base.
   20953   TestReceiver(i, foreign_context->Global(), "(1,func)()");
   20954 }
   20955 
   20956 
   20957 uint8_t callback_fired = 0;
   20958 uint8_t before_call_entered_callback_count1 = 0;
   20959 uint8_t before_call_entered_callback_count2 = 0;
   20960 
   20961 
   20962 void CallCompletedCallback1(v8::Isolate*) {
   20963   v8::base::OS::Print("Firing callback 1.\n");
   20964   callback_fired ^= 1;  // Toggle first bit.
   20965 }
   20966 
   20967 
   20968 void CallCompletedCallback2(v8::Isolate*) {
   20969   v8::base::OS::Print("Firing callback 2.\n");
   20970   callback_fired ^= 2;  // Toggle second bit.
   20971 }
   20972 
   20973 
   20974 void BeforeCallEnteredCallback1(v8::Isolate*) {
   20975   v8::base::OS::Print("Firing before call entered callback 1.\n");
   20976   before_call_entered_callback_count1++;
   20977 }
   20978 
   20979 
   20980 void BeforeCallEnteredCallback2(v8::Isolate*) {
   20981   v8::base::OS::Print("Firing before call entered callback 2.\n");
   20982   before_call_entered_callback_count2++;
   20983 }
   20984 
   20985 
   20986 void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
   20987   int32_t level =
   20988       args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
   20989   if (level < 3) {
   20990     level++;
   20991     v8::base::OS::Print("Entering recursion level %d.\n", level);
   20992     char script[64];
   20993     i::Vector<char> script_vector(script, sizeof(script));
   20994     i::SNPrintF(script_vector, "recursion(%d)", level);
   20995     CompileRun(script_vector.start());
   20996     v8::base::OS::Print("Leaving recursion level %d.\n", level);
   20997     CHECK_EQ(0, callback_fired);
   20998   } else {
   20999     v8::base::OS::Print("Recursion ends.\n");
   21000     CHECK_EQ(0, callback_fired);
   21001   }
   21002 }
   21003 
   21004 
   21005 TEST(CallCompletedCallback) {
   21006   LocalContext env;
   21007   v8::HandleScope scope(env->GetIsolate());
   21008   v8::Local<v8::FunctionTemplate> recursive_runtime =
   21009       v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
   21010   env->Global()
   21011       ->Set(env.local(), v8_str("recursion"),
   21012             recursive_runtime->GetFunction(env.local()).ToLocalChecked())
   21013       .FromJust();
   21014   // Adding the same callback a second time has no effect.
   21015   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
   21016   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
   21017   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback2);
   21018   env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback1);
   21019   env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback2);
   21020   env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback1);
   21021   v8::base::OS::Print("--- Script (1) ---\n");
   21022   callback_fired = 0;
   21023   before_call_entered_callback_count1 = 0;
   21024   before_call_entered_callback_count2 = 0;
   21025   Local<Script> script =
   21026       v8::Script::Compile(env.local(), v8_str("recursion(0)")).ToLocalChecked();
   21027   script->Run(env.local()).ToLocalChecked();
   21028   CHECK_EQ(3, callback_fired);
   21029   CHECK_EQ(4, before_call_entered_callback_count1);
   21030   CHECK_EQ(4, before_call_entered_callback_count2);
   21031 
   21032   v8::base::OS::Print("\n--- Script (2) ---\n");
   21033   callback_fired = 0;
   21034   before_call_entered_callback_count1 = 0;
   21035   before_call_entered_callback_count2 = 0;
   21036   env->GetIsolate()->RemoveCallCompletedCallback(CallCompletedCallback1);
   21037   env->GetIsolate()->RemoveBeforeCallEnteredCallback(
   21038       BeforeCallEnteredCallback1);
   21039   script->Run(env.local()).ToLocalChecked();
   21040   CHECK_EQ(2, callback_fired);
   21041   CHECK_EQ(0, before_call_entered_callback_count1);
   21042   CHECK_EQ(4, before_call_entered_callback_count2);
   21043 
   21044   v8::base::OS::Print("\n--- Function ---\n");
   21045   callback_fired = 0;
   21046   before_call_entered_callback_count1 = 0;
   21047   before_call_entered_callback_count2 = 0;
   21048   Local<Function> recursive_function = Local<Function>::Cast(
   21049       env->Global()->Get(env.local(), v8_str("recursion")).ToLocalChecked());
   21050   v8::Local<Value> args[] = {v8_num(0)};
   21051   recursive_function->Call(env.local(), env->Global(), 1, args)
   21052       .ToLocalChecked();
   21053   CHECK_EQ(2, callback_fired);
   21054   CHECK_EQ(0, before_call_entered_callback_count1);
   21055   CHECK_EQ(4, before_call_entered_callback_count2);
   21056 }
   21057 
   21058 
   21059 void CallCompletedCallbackNoException(v8::Isolate*) {
   21060   v8::HandleScope scope(CcTest::isolate());
   21061   CompileRun("1+1;");
   21062 }
   21063 
   21064 
   21065 void CallCompletedCallbackException(v8::Isolate*) {
   21066   v8::HandleScope scope(CcTest::isolate());
   21067   CompileRun("throw 'second exception';");
   21068 }
   21069 
   21070 
   21071 TEST(CallCompletedCallbackOneException) {
   21072   LocalContext env;
   21073   v8::HandleScope scope(env->GetIsolate());
   21074   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackNoException);
   21075   CompileRun("throw 'exception';");
   21076 }
   21077 
   21078 
   21079 TEST(CallCompletedCallbackTwoExceptions) {
   21080   LocalContext env;
   21081   v8::HandleScope scope(env->GetIsolate());
   21082   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackException);
   21083   CompileRun("throw 'first exception';");
   21084 }
   21085 
   21086 
   21087 static void MicrotaskOne(const v8::FunctionCallbackInfo<Value>& info) {
   21088   CHECK(v8::MicrotasksScope::IsRunningMicrotasks(info.GetIsolate()));
   21089   v8::HandleScope scope(info.GetIsolate());
   21090   v8::MicrotasksScope microtasks(info.GetIsolate(),
   21091                                  v8::MicrotasksScope::kDoNotRunMicrotasks);
   21092   CompileRun("ext1Calls++;");
   21093 }
   21094 
   21095 
   21096 static void MicrotaskTwo(const v8::FunctionCallbackInfo<Value>& info) {
   21097   CHECK(v8::MicrotasksScope::IsRunningMicrotasks(info.GetIsolate()));
   21098   v8::HandleScope scope(info.GetIsolate());
   21099   v8::MicrotasksScope microtasks(info.GetIsolate(),
   21100                                  v8::MicrotasksScope::kDoNotRunMicrotasks);
   21101   CompileRun("ext2Calls++;");
   21102 }
   21103 
   21104 
   21105 void* g_passed_to_three = NULL;
   21106 
   21107 
   21108 static void MicrotaskThree(void* data) {
   21109   g_passed_to_three = data;
   21110 }
   21111 
   21112 
   21113 TEST(EnqueueMicrotask) {
   21114   LocalContext env;
   21115   v8::HandleScope scope(env->GetIsolate());
   21116   CHECK(!v8::MicrotasksScope::IsRunningMicrotasks(env->GetIsolate()));
   21117   CompileRun(
   21118       "var ext1Calls = 0;"
   21119       "var ext2Calls = 0;");
   21120   CompileRun("1+1;");
   21121   CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21122   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21123 
   21124   env->GetIsolate()->EnqueueMicrotask(
   21125       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21126   CompileRun("1+1;");
   21127   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21128   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21129 
   21130   env->GetIsolate()->EnqueueMicrotask(
   21131       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21132   env->GetIsolate()->EnqueueMicrotask(
   21133       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21134   CompileRun("1+1;");
   21135   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21136   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21137 
   21138   env->GetIsolate()->EnqueueMicrotask(
   21139       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21140   CompileRun("1+1;");
   21141   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21142   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21143 
   21144   CompileRun("1+1;");
   21145   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21146   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21147 
   21148   g_passed_to_three = NULL;
   21149   env->GetIsolate()->EnqueueMicrotask(MicrotaskThree);
   21150   CompileRun("1+1;");
   21151   CHECK(!g_passed_to_three);
   21152   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21153   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21154 
   21155   int dummy;
   21156   env->GetIsolate()->EnqueueMicrotask(
   21157       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21158   env->GetIsolate()->EnqueueMicrotask(MicrotaskThree, &dummy);
   21159   env->GetIsolate()->EnqueueMicrotask(
   21160       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21161   CompileRun("1+1;");
   21162   CHECK_EQ(&dummy, g_passed_to_three);
   21163   CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21164   CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21165   g_passed_to_three = NULL;
   21166 }
   21167 
   21168 
   21169 static void MicrotaskExceptionOne(
   21170     const v8::FunctionCallbackInfo<Value>& info) {
   21171   v8::HandleScope scope(info.GetIsolate());
   21172   CompileRun("exception1Calls++;");
   21173   info.GetIsolate()->ThrowException(
   21174       v8::Exception::Error(v8_str("first")));
   21175 }
   21176 
   21177 
   21178 static void MicrotaskExceptionTwo(
   21179     const v8::FunctionCallbackInfo<Value>& info) {
   21180   v8::HandleScope scope(info.GetIsolate());
   21181   CompileRun("exception2Calls++;");
   21182   info.GetIsolate()->ThrowException(
   21183       v8::Exception::Error(v8_str("second")));
   21184 }
   21185 
   21186 
   21187 TEST(RunMicrotasksIgnoresThrownExceptions) {
   21188   LocalContext env;
   21189   v8::Isolate* isolate = env->GetIsolate();
   21190   v8::HandleScope scope(isolate);
   21191   CompileRun(
   21192       "var exception1Calls = 0;"
   21193       "var exception2Calls = 0;");
   21194   isolate->EnqueueMicrotask(
   21195       Function::New(env.local(), MicrotaskExceptionOne).ToLocalChecked());
   21196   isolate->EnqueueMicrotask(
   21197       Function::New(env.local(), MicrotaskExceptionTwo).ToLocalChecked());
   21198   TryCatch try_catch(isolate);
   21199   CompileRun("1+1;");
   21200   CHECK(!try_catch.HasCaught());
   21201   CHECK_EQ(1,
   21202            CompileRun("exception1Calls")->Int32Value(env.local()).FromJust());
   21203   CHECK_EQ(1,
   21204            CompileRun("exception2Calls")->Int32Value(env.local()).FromJust());
   21205 }
   21206 
   21207 
   21208 uint8_t microtasks_completed_callback_count = 0;
   21209 
   21210 
   21211 static void MicrotasksCompletedCallback(v8::Isolate* isolate) {
   21212   ++microtasks_completed_callback_count;
   21213 }
   21214 
   21215 
   21216 TEST(SetAutorunMicrotasks) {
   21217   LocalContext env;
   21218   v8::HandleScope scope(env->GetIsolate());
   21219   env->GetIsolate()->AddMicrotasksCompletedCallback(
   21220       &MicrotasksCompletedCallback);
   21221   CompileRun(
   21222       "var ext1Calls = 0;"
   21223       "var ext2Calls = 0;");
   21224   CompileRun("1+1;");
   21225   CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21226   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21227   CHECK_EQ(0u, microtasks_completed_callback_count);
   21228 
   21229   env->GetIsolate()->EnqueueMicrotask(
   21230       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21231   CompileRun("1+1;");
   21232   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21233   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21234   CHECK_EQ(1u, microtasks_completed_callback_count);
   21235 
   21236   env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
   21237   env->GetIsolate()->EnqueueMicrotask(
   21238       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21239   env->GetIsolate()->EnqueueMicrotask(
   21240       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21241   CompileRun("1+1;");
   21242   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21243   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21244   CHECK_EQ(1u, microtasks_completed_callback_count);
   21245 
   21246   env->GetIsolate()->RunMicrotasks();
   21247   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21248   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21249   CHECK_EQ(2u, microtasks_completed_callback_count);
   21250 
   21251   env->GetIsolate()->EnqueueMicrotask(
   21252       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21253   CompileRun("1+1;");
   21254   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21255   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21256   CHECK_EQ(2u, microtasks_completed_callback_count);
   21257 
   21258   env->GetIsolate()->RunMicrotasks();
   21259   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21260   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21261   CHECK_EQ(3u, microtasks_completed_callback_count);
   21262 
   21263   env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
   21264   env->GetIsolate()->EnqueueMicrotask(
   21265       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21266   CompileRun("1+1;");
   21267   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21268   CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21269   CHECK_EQ(4u, microtasks_completed_callback_count);
   21270 
   21271   env->GetIsolate()->EnqueueMicrotask(
   21272       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21273   {
   21274     v8::Isolate::SuppressMicrotaskExecutionScope scope(env->GetIsolate());
   21275     CompileRun("1+1;");
   21276     CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21277     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21278     CHECK_EQ(4u, microtasks_completed_callback_count);
   21279   }
   21280 
   21281   CompileRun("1+1;");
   21282   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21283   CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21284   CHECK_EQ(5u, microtasks_completed_callback_count);
   21285 
   21286   env->GetIsolate()->RemoveMicrotasksCompletedCallback(
   21287       &MicrotasksCompletedCallback);
   21288   env->GetIsolate()->EnqueueMicrotask(
   21289       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21290   CompileRun("1+1;");
   21291   CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21292   CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21293   CHECK_EQ(5u, microtasks_completed_callback_count);
   21294 }
   21295 
   21296 
   21297 TEST(RunMicrotasksWithoutEnteringContext) {
   21298   v8::Isolate* isolate = CcTest::isolate();
   21299   HandleScope handle_scope(isolate);
   21300   isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
   21301   Local<Context> context = Context::New(isolate);
   21302   {
   21303     Context::Scope context_scope(context);
   21304     CompileRun("var ext1Calls = 0;");
   21305     isolate->EnqueueMicrotask(
   21306         Function::New(context, MicrotaskOne).ToLocalChecked());
   21307   }
   21308   isolate->RunMicrotasks();
   21309   {
   21310     Context::Scope context_scope(context);
   21311     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(context).FromJust());
   21312   }
   21313   isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
   21314 }
   21315 
   21316 
   21317 TEST(ScopedMicrotasks) {
   21318   LocalContext env;
   21319   v8::HandleScope handles(env->GetIsolate());
   21320   env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kScoped);
   21321   {
   21322     v8::MicrotasksScope scope1(env->GetIsolate(),
   21323                                v8::MicrotasksScope::kDoNotRunMicrotasks);
   21324     env->GetIsolate()->EnqueueMicrotask(
   21325         Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21326     CompileRun(
   21327         "var ext1Calls = 0;"
   21328         "var ext2Calls = 0;");
   21329     CompileRun("1+1;");
   21330     CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21331     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21332     {
   21333       v8::MicrotasksScope scope2(env->GetIsolate(),
   21334                                  v8::MicrotasksScope::kRunMicrotasks);
   21335       CompileRun("1+1;");
   21336       CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21337       CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21338       {
   21339         v8::MicrotasksScope scope3(env->GetIsolate(),
   21340                                    v8::MicrotasksScope::kRunMicrotasks);
   21341         CompileRun("1+1;");
   21342         CHECK_EQ(0,
   21343                  CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21344         CHECK_EQ(0,
   21345                  CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21346       }
   21347       CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21348       CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21349     }
   21350     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21351     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21352     env->GetIsolate()->EnqueueMicrotask(
   21353         Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21354   }
   21355 
   21356   {
   21357     v8::MicrotasksScope scope(env->GetIsolate(),
   21358                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   21359     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21360     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21361   }
   21362 
   21363   {
   21364     v8::MicrotasksScope scope1(env->GetIsolate(),
   21365                                v8::MicrotasksScope::kRunMicrotasks);
   21366     CompileRun("1+1;");
   21367     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21368     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21369     {
   21370       v8::MicrotasksScope scope2(env->GetIsolate(),
   21371                                  v8::MicrotasksScope::kDoNotRunMicrotasks);
   21372     }
   21373     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21374     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21375   }
   21376 
   21377   {
   21378     v8::MicrotasksScope scope(env->GetIsolate(),
   21379                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   21380     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21381     CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21382     env->GetIsolate()->EnqueueMicrotask(
   21383         Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21384   }
   21385 
   21386   {
   21387     v8::Isolate::SuppressMicrotaskExecutionScope scope1(env->GetIsolate());
   21388     {
   21389       v8::MicrotasksScope scope2(env->GetIsolate(),
   21390                                  v8::MicrotasksScope::kRunMicrotasks);
   21391     }
   21392     v8::MicrotasksScope scope3(env->GetIsolate(),
   21393                                v8::MicrotasksScope::kDoNotRunMicrotasks);
   21394     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21395     CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21396   }
   21397 
   21398   {
   21399     v8::MicrotasksScope scope1(env->GetIsolate(),
   21400                                v8::MicrotasksScope::kRunMicrotasks);
   21401     v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   21402     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21403     CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21404   }
   21405 
   21406   {
   21407     v8::MicrotasksScope scope(env->GetIsolate(),
   21408                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   21409     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21410     CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21411   }
   21412 
   21413   v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   21414 
   21415   {
   21416     v8::MicrotasksScope scope(env->GetIsolate(),
   21417                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   21418     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21419     CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21420     env->GetIsolate()->EnqueueMicrotask(
   21421         Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21422   }
   21423 
   21424   v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   21425 
   21426   {
   21427     v8::MicrotasksScope scope(env->GetIsolate(),
   21428                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   21429     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21430     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21431   }
   21432 
   21433   env->GetIsolate()->EnqueueMicrotask(
   21434       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21435   {
   21436     v8::Isolate::SuppressMicrotaskExecutionScope scope1(env->GetIsolate());
   21437     v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   21438     v8::MicrotasksScope scope2(env->GetIsolate(),
   21439                                v8::MicrotasksScope::kDoNotRunMicrotasks);
   21440     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21441     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21442   }
   21443 
   21444   v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   21445 
   21446   {
   21447     v8::MicrotasksScope scope(env->GetIsolate(),
   21448                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   21449     CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21450     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21451   }
   21452 
   21453   env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
   21454 }
   21455 
   21456 #ifdef ENABLE_DISASSEMBLER
   21457 // FLAG_test_primary_stub_cache and FLAG_test_secondary_stub_cache are read
   21458 // only when ENABLE_DISASSEMBLER is not defined.
   21459 
   21460 namespace {
   21461 
   21462 int probes_counter = 0;
   21463 int misses_counter = 0;
   21464 int updates_counter = 0;
   21465 
   21466 int* LookupCounter(const char* name) {
   21467   if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
   21468     return &probes_counter;
   21469   } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
   21470     return &misses_counter;
   21471   } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
   21472     return &updates_counter;
   21473   }
   21474   return NULL;
   21475 }
   21476 
   21477 const char* kMegamorphicTestProgram =
   21478     "function CreateClass(name) {\n"
   21479     "  var src = \n"
   21480     "    `  function ${name}() {};` +\n"
   21481     "    `  ${name}.prototype.foo = function() {};` +\n"
   21482     "    `  ${name};\\n`;\n"
   21483     "  return (0, eval)(src);\n"
   21484     "}\n"
   21485     "function fooify(obj) { obj.foo(); };\n"
   21486     "var objs = [];\n"
   21487     "for (var i = 0; i < 6; i++) {\n"
   21488     "  var Class = CreateClass('Class' + i);\n"
   21489     "  var obj = new Class();\n"
   21490     "  objs.push(obj);\n"
   21491     "}\n"
   21492     "for (var i = 0; i < 10000; i++) {\n"
   21493     "  for (var obj of objs) {\n"
   21494     "    fooify(obj);\n"
   21495     "  }\n"
   21496     "}\n";
   21497 
   21498 void StubCacheHelper(bool primary) {
   21499   i::FLAG_native_code_counters = true;
   21500   if (primary) {
   21501     i::FLAG_test_primary_stub_cache = true;
   21502   } else {
   21503     i::FLAG_test_secondary_stub_cache = true;
   21504   }
   21505   i::FLAG_crankshaft = false;
   21506   i::FLAG_turbo = false;
   21507   v8::Isolate::CreateParams create_params;
   21508   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   21509   create_params.counter_lookup_callback = LookupCounter;
   21510   v8::Isolate* isolate = v8::Isolate::New(create_params);
   21511   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   21512 
   21513   if (!i_isolate->snapshot_available()) {
   21514     // The test is valid only for no-snapshot mode.
   21515     v8::Isolate::Scope isolate_scope(isolate);
   21516     LocalContext env(isolate);
   21517     v8::HandleScope scope(isolate);
   21518 
   21519     int initial_probes = probes_counter;
   21520     int initial_misses = misses_counter;
   21521     int initial_updates = updates_counter;
   21522     CompileRun(kMegamorphicTestProgram);
   21523     int probes = probes_counter - initial_probes;
   21524     int misses = misses_counter - initial_misses;
   21525     int updates = updates_counter - initial_updates;
   21526     const int kClassesCount = 6;
   21527     // Check that updates and misses counts are bounded.
   21528     CHECK_LE(kClassesCount, updates);
   21529     CHECK_LT(updates, kClassesCount * 3);
   21530     CHECK_LE(1, misses);
   21531     CHECK_LT(misses, kClassesCount * 2);
   21532     // 2 is for PREMONOMORPHIC and MONOMORPHIC states,
   21533     // 4 is for POLYMORPHIC states,
   21534     // and all the others probes are for MEGAMORPHIC state.
   21535     CHECK_EQ(10000 * kClassesCount - 2 - 4, probes);
   21536   }
   21537   isolate->Dispose();
   21538 }
   21539 
   21540 }  // namespace
   21541 
   21542 UNINITIALIZED_TEST(PrimaryStubCache) { StubCacheHelper(true); }
   21543 
   21544 UNINITIALIZED_TEST(SecondaryStubCache) { StubCacheHelper(false); }
   21545 
   21546 #endif  // ENABLE_DISASSEMBLER
   21547 
   21548 #ifdef DEBUG
   21549 static int cow_arrays_created_runtime = 0;
   21550 
   21551 
   21552 static int* LookupCounterCOWArrays(const char* name) {
   21553   if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) {
   21554     return &cow_arrays_created_runtime;
   21555   }
   21556   return NULL;
   21557 }
   21558 #endif
   21559 
   21560 
   21561 TEST(CheckCOWArraysCreatedRuntimeCounter) {
   21562 #ifdef DEBUG
   21563   i::FLAG_native_code_counters = true;
   21564   LocalContext env;
   21565   env->GetIsolate()->SetCounterFunction(LookupCounterCOWArrays);
   21566   v8::HandleScope scope(env->GetIsolate());
   21567   int initial_cow_arrays = cow_arrays_created_runtime;
   21568   CompileRun("var o = [1, 2, 3];");
   21569   CHECK_EQ(1, cow_arrays_created_runtime - initial_cow_arrays);
   21570   CompileRun("var o = {foo: [4, 5, 6], bar: [3, 0]};");
   21571   CHECK_EQ(3, cow_arrays_created_runtime - initial_cow_arrays);
   21572   CompileRun("var o = {foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'};");
   21573   CHECK_EQ(4, cow_arrays_created_runtime - initial_cow_arrays);
   21574 #endif
   21575 }
   21576 
   21577 
   21578 TEST(StaticGetters) {
   21579   LocalContext context;
   21580   i::Factory* factory = CcTest::i_isolate()->factory();
   21581   v8::Isolate* isolate = CcTest::isolate();
   21582   v8::HandleScope scope(isolate);
   21583   i::Handle<i::Object> undefined_value = factory->undefined_value();
   21584   CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
   21585   i::Handle<i::Object> null_value = factory->null_value();
   21586   CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
   21587   i::Handle<i::Object> true_value = factory->true_value();
   21588   CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
   21589   i::Handle<i::Object> false_value = factory->false_value();
   21590   CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
   21591 }
   21592 
   21593 
   21594 UNINITIALIZED_TEST(IsolateEmbedderData) {
   21595   CcTest::DisableAutomaticDispose();
   21596   v8::Isolate::CreateParams create_params;
   21597   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   21598   v8::Isolate* isolate = v8::Isolate::New(create_params);
   21599   isolate->Enter();
   21600   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   21601   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   21602     CHECK(!isolate->GetData(slot));
   21603     CHECK(!i_isolate->GetData(slot));
   21604   }
   21605   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   21606     void* data = reinterpret_cast<void*>(0xacce55ed + slot);
   21607     isolate->SetData(slot, data);
   21608   }
   21609   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   21610     void* data = reinterpret_cast<void*>(0xacce55ed + slot);
   21611     CHECK_EQ(data, isolate->GetData(slot));
   21612     CHECK_EQ(data, i_isolate->GetData(slot));
   21613   }
   21614   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   21615     void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
   21616     isolate->SetData(slot, data);
   21617   }
   21618   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   21619     void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
   21620     CHECK_EQ(data, isolate->GetData(slot));
   21621     CHECK_EQ(data, i_isolate->GetData(slot));
   21622   }
   21623   isolate->Exit();
   21624   isolate->Dispose();
   21625 }
   21626 
   21627 
   21628 TEST(StringEmpty) {
   21629   LocalContext context;
   21630   i::Factory* factory = CcTest::i_isolate()->factory();
   21631   v8::Isolate* isolate = CcTest::isolate();
   21632   v8::HandleScope scope(isolate);
   21633   i::Handle<i::Object> empty_string = factory->empty_string();
   21634   CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
   21635 }
   21636 
   21637 
   21638 static int instance_checked_getter_count = 0;
   21639 static void InstanceCheckedGetter(
   21640     Local<String> name,
   21641     const v8::PropertyCallbackInfo<v8::Value>& info) {
   21642   CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   21643             .FromJust());
   21644   instance_checked_getter_count++;
   21645   info.GetReturnValue().Set(v8_num(11));
   21646 }
   21647 
   21648 
   21649 static int instance_checked_setter_count = 0;
   21650 static void InstanceCheckedSetter(Local<String> name,
   21651                       Local<Value> value,
   21652                       const v8::PropertyCallbackInfo<void>& info) {
   21653   CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   21654             .FromJust());
   21655   CHECK(value->Equals(info.GetIsolate()->GetCurrentContext(), v8_num(23))
   21656             .FromJust());
   21657   instance_checked_setter_count++;
   21658 }
   21659 
   21660 
   21661 static void CheckInstanceCheckedResult(int getters, int setters,
   21662                                        bool expects_callbacks,
   21663                                        TryCatch* try_catch) {
   21664   if (expects_callbacks) {
   21665     CHECK(!try_catch->HasCaught());
   21666     CHECK_EQ(getters, instance_checked_getter_count);
   21667     CHECK_EQ(setters, instance_checked_setter_count);
   21668   } else {
   21669     CHECK(try_catch->HasCaught());
   21670     CHECK_EQ(0, instance_checked_getter_count);
   21671     CHECK_EQ(0, instance_checked_setter_count);
   21672   }
   21673   try_catch->Reset();
   21674 }
   21675 
   21676 
   21677 static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
   21678   instance_checked_getter_count = 0;
   21679   instance_checked_setter_count = 0;
   21680   TryCatch try_catch(CcTest::isolate());
   21681 
   21682   // Test path through generic runtime code.
   21683   CompileRun("obj.foo");
   21684   CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
   21685   CompileRun("obj.foo = 23");
   21686   CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
   21687 
   21688   // Test path through generated LoadIC and StoredIC.
   21689   CompileRun("function test_get(o) { o.foo; }"
   21690              "test_get(obj);");
   21691   CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
   21692   CompileRun("test_get(obj);");
   21693   CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
   21694   CompileRun("test_get(obj);");
   21695   CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
   21696   CompileRun("function test_set(o) { o.foo = 23; }"
   21697              "test_set(obj);");
   21698   CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
   21699   CompileRun("test_set(obj);");
   21700   CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
   21701   CompileRun("test_set(obj);");
   21702   CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
   21703 
   21704   // Test path through optimized code.
   21705   CompileRun("%OptimizeFunctionOnNextCall(test_get);"
   21706              "test_get(obj);");
   21707   CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
   21708   CompileRun("%OptimizeFunctionOnNextCall(test_set);"
   21709              "test_set(obj);");
   21710   CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
   21711 
   21712   // Cleanup so that closures start out fresh in next check.
   21713   CompileRun("%DeoptimizeFunction(test_get);"
   21714              "%ClearFunctionTypeFeedback(test_get);"
   21715              "%DeoptimizeFunction(test_set);"
   21716              "%ClearFunctionTypeFeedback(test_set);");
   21717 }
   21718 
   21719 
   21720 THREADED_TEST(InstanceCheckOnInstanceAccessor) {
   21721   v8::internal::FLAG_allow_natives_syntax = true;
   21722   LocalContext context;
   21723   v8::HandleScope scope(context->GetIsolate());
   21724 
   21725   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   21726   Local<ObjectTemplate> inst = templ->InstanceTemplate();
   21727   inst->SetAccessor(v8_str("foo"), InstanceCheckedGetter, InstanceCheckedSetter,
   21728                     Local<Value>(), v8::DEFAULT, v8::None,
   21729                     v8::AccessorSignature::New(context->GetIsolate(), templ));
   21730   CHECK(context->Global()
   21731             ->Set(context.local(), v8_str("f"),
   21732                   templ->GetFunction(context.local()).ToLocalChecked())
   21733             .FromJust());
   21734 
   21735   printf("Testing positive ...\n");
   21736   CompileRun("var obj = new f();");
   21737   CHECK(templ->HasInstance(
   21738       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   21739   CheckInstanceCheckedAccessors(true);
   21740 
   21741   printf("Testing negative ...\n");
   21742   CompileRun("var obj = {};"
   21743              "obj.__proto__ = new f();");
   21744   CHECK(!templ->HasInstance(
   21745       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   21746   CheckInstanceCheckedAccessors(false);
   21747 }
   21748 
   21749 
   21750 static void EmptyInterceptorGetter(
   21751     Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {}
   21752 
   21753 
   21754 static void EmptyInterceptorSetter(
   21755     Local<String> name, Local<Value> value,
   21756     const v8::PropertyCallbackInfo<v8::Value>& info) {}
   21757 
   21758 
   21759 THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
   21760   v8::internal::FLAG_allow_natives_syntax = true;
   21761   LocalContext context;
   21762   v8::HandleScope scope(context->GetIsolate());
   21763 
   21764   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   21765   Local<ObjectTemplate> inst = templ->InstanceTemplate();
   21766   templ->InstanceTemplate()->SetNamedPropertyHandler(EmptyInterceptorGetter,
   21767                                                      EmptyInterceptorSetter);
   21768   inst->SetAccessor(v8_str("foo"), InstanceCheckedGetter, InstanceCheckedSetter,
   21769                     Local<Value>(), v8::DEFAULT, v8::None,
   21770                     v8::AccessorSignature::New(context->GetIsolate(), templ));
   21771   CHECK(context->Global()
   21772             ->Set(context.local(), v8_str("f"),
   21773                   templ->GetFunction(context.local()).ToLocalChecked())
   21774             .FromJust());
   21775 
   21776   printf("Testing positive ...\n");
   21777   CompileRun("var obj = new f();");
   21778   CHECK(templ->HasInstance(
   21779       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   21780   CheckInstanceCheckedAccessors(true);
   21781 
   21782   printf("Testing negative ...\n");
   21783   CompileRun("var obj = {};"
   21784              "obj.__proto__ = new f();");
   21785   CHECK(!templ->HasInstance(
   21786       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   21787   CheckInstanceCheckedAccessors(false);
   21788 }
   21789 
   21790 
   21791 THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
   21792   v8::internal::FLAG_allow_natives_syntax = true;
   21793   LocalContext context;
   21794   v8::HandleScope scope(context->GetIsolate());
   21795 
   21796   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   21797   Local<ObjectTemplate> proto = templ->PrototypeTemplate();
   21798   proto->SetAccessor(v8_str("foo"), InstanceCheckedGetter,
   21799                      InstanceCheckedSetter, Local<Value>(), v8::DEFAULT,
   21800                      v8::None,
   21801                      v8::AccessorSignature::New(context->GetIsolate(), templ));
   21802   CHECK(context->Global()
   21803             ->Set(context.local(), v8_str("f"),
   21804                   templ->GetFunction(context.local()).ToLocalChecked())
   21805             .FromJust());
   21806 
   21807   printf("Testing positive ...\n");
   21808   CompileRun("var obj = new f();");
   21809   CHECK(templ->HasInstance(
   21810       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   21811   CheckInstanceCheckedAccessors(true);
   21812 
   21813   printf("Testing negative ...\n");
   21814   CompileRun("var obj = {};"
   21815              "obj.__proto__ = new f();");
   21816   CHECK(!templ->HasInstance(
   21817       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   21818   CheckInstanceCheckedAccessors(false);
   21819 
   21820   printf("Testing positive with modified prototype chain ...\n");
   21821   CompileRun("var obj = new f();"
   21822              "var pro = {};"
   21823              "pro.__proto__ = obj.__proto__;"
   21824              "obj.__proto__ = pro;");
   21825   CHECK(templ->HasInstance(
   21826       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   21827   CheckInstanceCheckedAccessors(true);
   21828 }
   21829 
   21830 
   21831 TEST(TryFinallyMessage) {
   21832   LocalContext context;
   21833   v8::HandleScope scope(context->GetIsolate());
   21834   {
   21835     // Test that the original error message is not lost if there is a
   21836     // recursive call into Javascript is done in the finally block, e.g. to
   21837     // initialize an IC. (crbug.com/129171)
   21838     TryCatch try_catch(context->GetIsolate());
   21839     const char* trigger_ic =
   21840         "try {                      \n"
   21841         "  throw new Error('test'); \n"
   21842         "} finally {                \n"
   21843         "  var x = 0;               \n"
   21844         "  x++;                     \n"  // Trigger an IC initialization here.
   21845         "}                          \n";
   21846     CompileRun(trigger_ic);
   21847     CHECK(try_catch.HasCaught());
   21848     Local<Message> message = try_catch.Message();
   21849     CHECK(!message.IsEmpty());
   21850     CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
   21851   }
   21852 
   21853   {
   21854     // Test that the original exception message is indeed overwritten if
   21855     // a new error is thrown in the finally block.
   21856     TryCatch try_catch(context->GetIsolate());
   21857     const char* throw_again =
   21858         "try {                       \n"
   21859         "  throw new Error('test');  \n"
   21860         "} finally {                 \n"
   21861         "  var x = 0;                \n"
   21862         "  x++;                      \n"
   21863         "  throw new Error('again'); \n"  // This is the new uncaught error.
   21864         "}                           \n";
   21865     CompileRun(throw_again);
   21866     CHECK(try_catch.HasCaught());
   21867     Local<Message> message = try_catch.Message();
   21868     CHECK(!message.IsEmpty());
   21869     CHECK_EQ(6, message->GetLineNumber(context.local()).FromJust());
   21870   }
   21871 }
   21872 
   21873 
   21874 static void Helper137002(bool do_store,
   21875                          bool polymorphic,
   21876                          bool remove_accessor,
   21877                          bool interceptor) {
   21878   LocalContext context;
   21879   Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
   21880   if (interceptor) {
   21881     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(FooGetInterceptor,
   21882                                                             FooSetInterceptor));
   21883   } else {
   21884     templ->SetAccessor(v8_str("foo"),
   21885                        GetterWhichReturns42,
   21886                        SetterWhichSetsYOnThisTo23);
   21887   }
   21888   CHECK(context->Global()
   21889             ->Set(context.local(), v8_str("obj"),
   21890                   templ->NewInstance(context.local()).ToLocalChecked())
   21891             .FromJust());
   21892 
   21893   // Turn monomorphic on slow object with native accessor, then turn
   21894   // polymorphic, finally optimize to create negative lookup and fail.
   21895   CompileRun(do_store ?
   21896              "function f(x) { x.foo = void 0; }" :
   21897              "function f(x) { return x.foo; }");
   21898   CompileRun("obj.y = void 0;");
   21899   if (!interceptor) {
   21900     CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
   21901   }
   21902   CompileRun("obj.__proto__ = null;"
   21903              "f(obj); f(obj); f(obj);");
   21904   if (polymorphic) {
   21905     CompileRun("f({});");
   21906   }
   21907   CompileRun("obj.y = void 0;"
   21908              "%OptimizeFunctionOnNextCall(f);");
   21909   if (remove_accessor) {
   21910     CompileRun("delete obj.foo;");
   21911   }
   21912   CompileRun("var result = f(obj);");
   21913   if (do_store) {
   21914     CompileRun("result = obj.y;");
   21915   }
   21916   if (remove_accessor && !interceptor) {
   21917     CHECK(context->Global()
   21918               ->Get(context.local(), v8_str("result"))
   21919               .ToLocalChecked()
   21920               ->IsUndefined());
   21921   } else {
   21922     CHECK_EQ(do_store ? 23 : 42, context->Global()
   21923                                      ->Get(context.local(), v8_str("result"))
   21924                                      .ToLocalChecked()
   21925                                      ->Int32Value(context.local())
   21926                                      .FromJust());
   21927   }
   21928 }
   21929 
   21930 
   21931 THREADED_TEST(Regress137002a) {
   21932   i::FLAG_allow_natives_syntax = true;
   21933   i::FLAG_compilation_cache = false;
   21934   v8::HandleScope scope(CcTest::isolate());
   21935   for (int i = 0; i < 16; i++) {
   21936     Helper137002(i & 8, i & 4, i & 2, i & 1);
   21937   }
   21938 }
   21939 
   21940 
   21941 THREADED_TEST(Regress137002b) {
   21942   i::FLAG_allow_natives_syntax = true;
   21943   LocalContext context;
   21944   v8::Isolate* isolate = context->GetIsolate();
   21945   v8::HandleScope scope(isolate);
   21946   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21947   templ->SetAccessor(v8_str("foo"),
   21948                      GetterWhichReturns42,
   21949                      SetterWhichSetsYOnThisTo23);
   21950   CHECK(context->Global()
   21951             ->Set(context.local(), v8_str("obj"),
   21952                   templ->NewInstance(context.local()).ToLocalChecked())
   21953             .FromJust());
   21954 
   21955   // Turn monomorphic on slow object with native accessor, then just
   21956   // delete the property and fail.
   21957   CompileRun("function load(x) { return x.foo; }"
   21958              "function store(x) { x.foo = void 0; }"
   21959              "function keyed_load(x, key) { return x[key]; }"
   21960              // Second version of function has a different source (add void 0)
   21961              // so that it does not share code with the first version.  This
   21962              // ensures that the ICs are monomorphic.
   21963              "function load2(x) { void 0; return x.foo; }"
   21964              "function store2(x) { void 0; x.foo = void 0; }"
   21965              "function keyed_load2(x, key) { void 0; return x[key]; }"
   21966 
   21967              "obj.y = void 0;"
   21968              "obj.__proto__ = null;"
   21969              "var subobj = {};"
   21970              "subobj.y = void 0;"
   21971              "subobj.__proto__ = obj;"
   21972              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
   21973 
   21974              // Make the ICs monomorphic.
   21975              "load(obj); load(obj);"
   21976              "load2(subobj); load2(subobj);"
   21977              "store(obj); store(obj);"
   21978              "store2(subobj); store2(subobj);"
   21979              "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
   21980              "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
   21981 
   21982              // Actually test the shiny new ICs and better not crash. This
   21983              // serves as a regression test for issue 142088 as well.
   21984              "load(obj);"
   21985              "load2(subobj);"
   21986              "store(obj);"
   21987              "store2(subobj);"
   21988              "keyed_load(obj, 'foo');"
   21989              "keyed_load2(subobj, 'foo');"
   21990 
   21991              // Delete the accessor.  It better not be called any more now.
   21992              "delete obj.foo;"
   21993              "obj.y = void 0;"
   21994              "subobj.y = void 0;"
   21995 
   21996              "var load_result = load(obj);"
   21997              "var load_result2 = load2(subobj);"
   21998              "var keyed_load_result = keyed_load(obj, 'foo');"
   21999              "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
   22000              "store(obj);"
   22001              "store2(subobj);"
   22002              "var y_from_obj = obj.y;"
   22003              "var y_from_subobj = subobj.y;");
   22004   CHECK(context->Global()
   22005             ->Get(context.local(), v8_str("load_result"))
   22006             .ToLocalChecked()
   22007             ->IsUndefined());
   22008   CHECK(context->Global()
   22009             ->Get(context.local(), v8_str("load_result2"))
   22010             .ToLocalChecked()
   22011             ->IsUndefined());
   22012   CHECK(context->Global()
   22013             ->Get(context.local(), v8_str("keyed_load_result"))
   22014             .ToLocalChecked()
   22015             ->IsUndefined());
   22016   CHECK(context->Global()
   22017             ->Get(context.local(), v8_str("keyed_load_result2"))
   22018             .ToLocalChecked()
   22019             ->IsUndefined());
   22020   CHECK(context->Global()
   22021             ->Get(context.local(), v8_str("y_from_obj"))
   22022             .ToLocalChecked()
   22023             ->IsUndefined());
   22024   CHECK(context->Global()
   22025             ->Get(context.local(), v8_str("y_from_subobj"))
   22026             .ToLocalChecked()
   22027             ->IsUndefined());
   22028 }
   22029 
   22030 
   22031 THREADED_TEST(Regress142088) {
   22032   i::FLAG_allow_natives_syntax = true;
   22033   LocalContext context;
   22034   v8::Isolate* isolate = context->GetIsolate();
   22035   v8::HandleScope scope(isolate);
   22036   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   22037   templ->SetAccessor(v8_str("foo"),
   22038                      GetterWhichReturns42,
   22039                      SetterWhichSetsYOnThisTo23);
   22040   CHECK(context->Global()
   22041             ->Set(context.local(), v8_str("obj"),
   22042                   templ->NewInstance(context.local()).ToLocalChecked())
   22043             .FromJust());
   22044 
   22045   CompileRun("function load(x) { return x.foo; }"
   22046              "var o = Object.create(obj);"
   22047              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
   22048              "load(o); load(o); load(o); load(o);");
   22049 }
   22050 
   22051 
   22052 THREADED_TEST(Regress137496) {
   22053   i::FLAG_expose_gc = true;
   22054   LocalContext context;
   22055   v8::HandleScope scope(context->GetIsolate());
   22056 
   22057   // Compile a try-finally clause where the finally block causes a GC
   22058   // while there still is a message pending for external reporting.
   22059   TryCatch try_catch(context->GetIsolate());
   22060   try_catch.SetVerbose(true);
   22061   CompileRun("try { throw new Error(); } finally { gc(); }");
   22062   CHECK(try_catch.HasCaught());
   22063 }
   22064 
   22065 
   22066 THREADED_TEST(Regress157124) {
   22067   LocalContext context;
   22068   v8::Isolate* isolate = context->GetIsolate();
   22069   v8::HandleScope scope(isolate);
   22070   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   22071   Local<Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
   22072   obj->GetIdentityHash();
   22073   obj->DeletePrivate(context.local(),
   22074                      v8::Private::ForApi(isolate, v8_str("Bug")))
   22075       .FromJust();
   22076 }
   22077 
   22078 
   22079 THREADED_TEST(Regress2535) {
   22080   LocalContext context;
   22081   v8::HandleScope scope(context->GetIsolate());
   22082   Local<Value> set_value = CompileRun("new Set();");
   22083   Local<Object> set_object(Local<Object>::Cast(set_value));
   22084   CHECK_EQ(0, set_object->InternalFieldCount());
   22085   Local<Value> map_value = CompileRun("new Map();");
   22086   Local<Object> map_object(Local<Object>::Cast(map_value));
   22087   CHECK_EQ(0, map_object->InternalFieldCount());
   22088 }
   22089 
   22090 
   22091 THREADED_TEST(Regress2746) {
   22092   LocalContext context;
   22093   v8::Isolate* isolate = context->GetIsolate();
   22094   v8::HandleScope scope(isolate);
   22095   Local<Object> obj = Object::New(isolate);
   22096   Local<v8::Private> key = v8::Private::New(isolate, v8_str("key"));
   22097   CHECK(
   22098       obj->SetPrivate(context.local(), key, v8::Undefined(isolate)).FromJust());
   22099   Local<Value> value = obj->GetPrivate(context.local(), key).ToLocalChecked();
   22100   CHECK(!value.IsEmpty());
   22101   CHECK(value->IsUndefined());
   22102 }
   22103 
   22104 
   22105 THREADED_TEST(Regress260106) {
   22106   LocalContext context;
   22107   v8::Isolate* isolate = context->GetIsolate();
   22108   v8::HandleScope scope(isolate);
   22109   Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
   22110                                                         DummyCallHandler);
   22111   CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
   22112   Local<Function> function =
   22113       templ->GetFunction(context.local()).ToLocalChecked();
   22114   CHECK(!function.IsEmpty());
   22115   CHECK(function->IsFunction());
   22116 }
   22117 
   22118 THREADED_TEST(JSONParseObject) {
   22119   LocalContext context;
   22120   HandleScope scope(context->GetIsolate());
   22121   Local<Value> obj =
   22122       v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
   22123   Local<Object> global = context->Global();
   22124   global->Set(context.local(), v8_str("obj"), obj).FromJust();
   22125   ExpectString("JSON.stringify(obj)", "{\"x\":42}");
   22126 }
   22127 
   22128 THREADED_TEST(JSONParseNumber) {
   22129   LocalContext context;
   22130   HandleScope scope(context->GetIsolate());
   22131   Local<Value> obj =
   22132       v8::JSON::Parse(context.local(), v8_str("42")).ToLocalChecked();
   22133   Local<Object> global = context->Global();
   22134   global->Set(context.local(), v8_str("obj"), obj).FromJust();
   22135   ExpectString("JSON.stringify(obj)", "42");
   22136 }
   22137 
   22138 THREADED_TEST(JSONStringifyObject) {
   22139   LocalContext context;
   22140   HandleScope scope(context->GetIsolate());
   22141   Local<Value> value =
   22142       v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
   22143   Local<Object> obj = value->ToObject(context.local()).ToLocalChecked();
   22144   Local<Object> global = context->Global();
   22145   global->Set(context.local(), v8_str("obj"), obj).FromJust();
   22146   Local<String> json =
   22147       v8::JSON::Stringify(context.local(), obj).ToLocalChecked();
   22148   v8::String::Utf8Value utf8(json);
   22149   ExpectString("JSON.stringify(obj)", *utf8);
   22150 }
   22151 
   22152 THREADED_TEST(JSONStringifyObjectWithGap) {
   22153   LocalContext context;
   22154   HandleScope scope(context->GetIsolate());
   22155   Local<Value> value =
   22156       v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
   22157   Local<Object> obj = value->ToObject(context.local()).ToLocalChecked();
   22158   Local<Object> global = context->Global();
   22159   global->Set(context.local(), v8_str("obj"), obj).FromJust();
   22160   Local<String> json =
   22161       v8::JSON::Stringify(context.local(), obj, v8_str("*")).ToLocalChecked();
   22162   v8::String::Utf8Value utf8(json);
   22163   ExpectString("JSON.stringify(obj, null,  '*')", *utf8);
   22164 }
   22165 
   22166 #if V8_OS_POSIX && !V8_OS_NACL
   22167 class ThreadInterruptTest {
   22168  public:
   22169   ThreadInterruptTest() : sem_(0), sem_value_(0) { }
   22170   ~ThreadInterruptTest() {}
   22171 
   22172   void RunTest() {
   22173     InterruptThread i_thread(this);
   22174     i_thread.Start();
   22175 
   22176     sem_.Wait();
   22177     CHECK_EQ(kExpectedValue, sem_value_);
   22178   }
   22179 
   22180  private:
   22181   static const int kExpectedValue = 1;
   22182 
   22183   class InterruptThread : public v8::base::Thread {
   22184    public:
   22185     explicit InterruptThread(ThreadInterruptTest* test)
   22186         : Thread(Options("InterruptThread")), test_(test) {}
   22187 
   22188     virtual void Run() {
   22189       struct sigaction action;
   22190 
   22191       // Ensure that we'll enter waiting condition
   22192       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
   22193 
   22194       // Setup signal handler
   22195       memset(&action, 0, sizeof(action));
   22196       action.sa_handler = SignalHandler;
   22197       sigaction(SIGCHLD, &action, NULL);
   22198 
   22199       // Send signal
   22200       kill(getpid(), SIGCHLD);
   22201 
   22202       // Ensure that if wait has returned because of error
   22203       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
   22204 
   22205       // Set value and signal semaphore
   22206       test_->sem_value_ = 1;
   22207       test_->sem_.Signal();
   22208     }
   22209 
   22210     static void SignalHandler(int signal) {
   22211     }
   22212 
   22213    private:
   22214      ThreadInterruptTest* test_;
   22215   };
   22216 
   22217   v8::base::Semaphore sem_;
   22218   volatile int sem_value_;
   22219 };
   22220 
   22221 
   22222 THREADED_TEST(SemaphoreInterruption) {
   22223   ThreadInterruptTest().RunTest();
   22224 }
   22225 
   22226 
   22227 #endif  // V8_OS_POSIX
   22228 
   22229 
   22230 void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   22231   CHECK(false);
   22232 }
   22233 
   22234 
   22235 TEST(JSONStringifyAccessCheck) {
   22236   v8::V8::Initialize();
   22237   v8::Isolate* isolate = CcTest::isolate();
   22238   v8::HandleScope scope(isolate);
   22239 
   22240   // Create an ObjectTemplate for global objects and install access
   22241   // check callbacks that will block access.
   22242   v8::Local<v8::ObjectTemplate> global_template =
   22243       v8::ObjectTemplate::New(isolate);
   22244   global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   22245 
   22246   // Create a context and set an x property on it's global object.
   22247   LocalContext context0(NULL, global_template);
   22248   v8::Local<v8::Object> global0 = context0->Global();
   22249   global0->Set(context0.local(), v8_str("x"), v8_num(42)).FromJust();
   22250   ExpectString("JSON.stringify(this)", "{\"x\":42}");
   22251 
   22252   for (int i = 0; i < 2; i++) {
   22253     if (i == 1) {
   22254       // Install a toJSON function on the second run.
   22255       v8::Local<v8::FunctionTemplate> toJSON =
   22256           v8::FunctionTemplate::New(isolate, UnreachableCallback);
   22257 
   22258       global0->Set(context0.local(), v8_str("toJSON"),
   22259                    toJSON->GetFunction(context0.local()).ToLocalChecked())
   22260           .FromJust();
   22261     }
   22262     // Create a context with a different security token so that the
   22263     // failed access check callback will be called on each access.
   22264     LocalContext context1(NULL, global_template);
   22265     CHECK(context1->Global()
   22266               ->Set(context1.local(), v8_str("other"), global0)
   22267               .FromJust());
   22268 
   22269     CHECK(CompileRun("JSON.stringify(other)").IsEmpty());
   22270     CHECK(CompileRun("JSON.stringify({ 'a' : other, 'b' : ['c'] })").IsEmpty());
   22271     CHECK(CompileRun("JSON.stringify([other, 'b', 'c'])").IsEmpty());
   22272   }
   22273 }
   22274 
   22275 
   22276 bool access_check_fail_thrown = false;
   22277 bool catch_callback_called = false;
   22278 
   22279 
   22280 // Failed access check callback that performs a GC on each invocation.
   22281 void FailedAccessCheckThrows(Local<v8::Object> target,
   22282                              v8::AccessType type,
   22283                              Local<v8::Value> data) {
   22284   access_check_fail_thrown = true;
   22285   i::PrintF("Access check failed. Error thrown.\n");
   22286   CcTest::isolate()->ThrowException(
   22287       v8::Exception::Error(v8_str("cross context")));
   22288 }
   22289 
   22290 
   22291 void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   22292   for (int i = 0; i < args.Length(); i++) {
   22293     i::PrintF("%s\n", *String::Utf8Value(args[i]));
   22294   }
   22295   catch_callback_called = true;
   22296 }
   22297 
   22298 
   22299 void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   22300   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   22301   CHECK(
   22302       args[0]
   22303           ->ToObject(context)
   22304           .ToLocalChecked()
   22305           ->HasOwnProperty(context, args[1]->ToString(context).ToLocalChecked())
   22306           .IsNothing());
   22307 }
   22308 
   22309 
   22310 void CheckCorrectThrow(const char* script) {
   22311   // Test that the script, when wrapped into a try-catch, triggers the catch
   22312   // clause due to failed access check throwing an exception.
   22313   // The subsequent try-catch should run without any exception.
   22314   access_check_fail_thrown = false;
   22315   catch_callback_called = false;
   22316   i::ScopedVector<char> source(1024);
   22317   i::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
   22318   CompileRun(source.start());
   22319   CHECK(access_check_fail_thrown);
   22320   CHECK(catch_callback_called);
   22321 
   22322   access_check_fail_thrown = false;
   22323   catch_callback_called = false;
   22324   CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
   22325   CHECK(!access_check_fail_thrown);
   22326   CHECK(!catch_callback_called);
   22327 }
   22328 
   22329 
   22330 TEST(AccessCheckThrows) {
   22331   i::FLAG_allow_natives_syntax = true;
   22332   v8::V8::Initialize();
   22333   v8::Isolate* isolate = CcTest::isolate();
   22334   isolate->SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
   22335   v8::HandleScope scope(isolate);
   22336 
   22337   // Create an ObjectTemplate for global objects and install access
   22338   // check callbacks that will block access.
   22339   v8::Local<v8::ObjectTemplate> global_template =
   22340       v8::ObjectTemplate::New(isolate);
   22341   global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   22342 
   22343   // Create a context and set an x property on it's global object.
   22344   LocalContext context0(NULL, global_template);
   22345   v8::Local<v8::Object> global0 = context0->Global();
   22346 
   22347   // Create a context with a different security token so that the
   22348   // failed access check callback will be called on each access.
   22349   LocalContext context1(NULL, global_template);
   22350   CHECK(context1->Global()
   22351             ->Set(context1.local(), v8_str("other"), global0)
   22352             .FromJust());
   22353 
   22354   v8::Local<v8::FunctionTemplate> catcher_fun =
   22355       v8::FunctionTemplate::New(isolate, CatcherCallback);
   22356   CHECK(context1->Global()
   22357             ->Set(context1.local(), v8_str("catcher"),
   22358                   catcher_fun->GetFunction(context1.local()).ToLocalChecked())
   22359             .FromJust());
   22360 
   22361   v8::Local<v8::FunctionTemplate> has_own_property_fun =
   22362       v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
   22363   CHECK(context1->Global()
   22364             ->Set(context1.local(), v8_str("has_own_property"),
   22365                   has_own_property_fun->GetFunction(context1.local())
   22366                       .ToLocalChecked())
   22367             .FromJust());
   22368 
   22369   {
   22370     v8::TryCatch try_catch(isolate);
   22371     access_check_fail_thrown = false;
   22372     CompileRun("other.x;");
   22373     CHECK(access_check_fail_thrown);
   22374     CHECK(try_catch.HasCaught());
   22375   }
   22376 
   22377   CheckCorrectThrow("other.x");
   22378   CheckCorrectThrow("other[1]");
   22379   CheckCorrectThrow("JSON.stringify(other)");
   22380   CheckCorrectThrow("has_own_property(other, 'x')");
   22381   CheckCorrectThrow("%GetProperty(other, 'x')");
   22382   CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 0)");
   22383   CheckCorrectThrow("%AddNamedProperty(other, 'x', 'foo', 1)");
   22384   CheckCorrectThrow("%DeleteProperty_Sloppy(other, 'x')");
   22385   CheckCorrectThrow("%DeleteProperty_Strict(other, 'x')");
   22386   CheckCorrectThrow("%DeleteProperty_Sloppy(other, '1')");
   22387   CheckCorrectThrow("%DeleteProperty_Strict(other, '1')");
   22388   CheckCorrectThrow("Object.prototype.hasOwnProperty.call(other, 'x')");
   22389   CheckCorrectThrow("%HasProperty('x', other)");
   22390   CheckCorrectThrow("%PropertyIsEnumerable(other, 'x')");
   22391   // PROPERTY_ATTRIBUTES_NONE = 0
   22392   CheckCorrectThrow("%DefineAccessorPropertyUnchecked("
   22393                         "other, 'x', null, null, 1)");
   22394 
   22395   // Reset the failed access check callback so it does not influence
   22396   // the other tests.
   22397   isolate->SetFailedAccessCheckCallbackFunction(NULL);
   22398 }
   22399 
   22400 
   22401 class RequestInterruptTestBase {
   22402  public:
   22403   RequestInterruptTestBase()
   22404       : env_(),
   22405         isolate_(env_->GetIsolate()),
   22406         sem_(0),
   22407         warmup_(20000),
   22408         should_continue_(true) {
   22409   }
   22410 
   22411   virtual ~RequestInterruptTestBase() { }
   22412 
   22413   virtual void StartInterruptThread() = 0;
   22414 
   22415   virtual void TestBody() = 0;
   22416 
   22417   void RunTest() {
   22418     StartInterruptThread();
   22419 
   22420     v8::HandleScope handle_scope(isolate_);
   22421 
   22422     TestBody();
   22423 
   22424     // Verify we arrived here because interruptor was called
   22425     // not due to a bug causing us to exit the loop too early.
   22426     CHECK(!should_continue());
   22427   }
   22428 
   22429   void WakeUpInterruptor() {
   22430     sem_.Signal();
   22431   }
   22432 
   22433   bool should_continue() const { return should_continue_; }
   22434 
   22435   bool ShouldContinue() {
   22436     if (warmup_ > 0) {
   22437       if (--warmup_ == 0) {
   22438         WakeUpInterruptor();
   22439       }
   22440     }
   22441 
   22442     return should_continue_;
   22443   }
   22444 
   22445   static void ShouldContinueCallback(
   22446       const v8::FunctionCallbackInfo<Value>& info) {
   22447     RequestInterruptTestBase* test =
   22448         reinterpret_cast<RequestInterruptTestBase*>(
   22449             info.Data().As<v8::External>()->Value());
   22450     info.GetReturnValue().Set(test->ShouldContinue());
   22451   }
   22452 
   22453   LocalContext env_;
   22454   v8::Isolate* isolate_;
   22455   v8::base::Semaphore sem_;
   22456   int warmup_;
   22457   bool should_continue_;
   22458 };
   22459 
   22460 
   22461 class RequestInterruptTestBaseWithSimpleInterrupt
   22462     : public RequestInterruptTestBase {
   22463  public:
   22464   RequestInterruptTestBaseWithSimpleInterrupt() : i_thread(this) { }
   22465 
   22466   virtual void StartInterruptThread() {
   22467     i_thread.Start();
   22468   }
   22469 
   22470  private:
   22471   class InterruptThread : public v8::base::Thread {
   22472    public:
   22473     explicit InterruptThread(RequestInterruptTestBase* test)
   22474         : Thread(Options("RequestInterruptTest")), test_(test) {}
   22475 
   22476     virtual void Run() {
   22477       test_->sem_.Wait();
   22478       test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
   22479     }
   22480 
   22481     static void OnInterrupt(v8::Isolate* isolate, void* data) {
   22482       reinterpret_cast<RequestInterruptTestBase*>(data)->
   22483           should_continue_ = false;
   22484     }
   22485 
   22486    private:
   22487      RequestInterruptTestBase* test_;
   22488   };
   22489 
   22490   InterruptThread i_thread;
   22491 };
   22492 
   22493 
   22494 class RequestInterruptTestWithFunctionCall
   22495     : public RequestInterruptTestBaseWithSimpleInterrupt {
   22496  public:
   22497   virtual void TestBody() {
   22498     Local<Function> func = Function::New(env_.local(), ShouldContinueCallback,
   22499                                          v8::External::New(isolate_, this))
   22500                                .ToLocalChecked();
   22501     CHECK(env_->Global()
   22502               ->Set(env_.local(), v8_str("ShouldContinue"), func)
   22503               .FromJust());
   22504 
   22505     CompileRun("while (ShouldContinue()) { }");
   22506   }
   22507 };
   22508 
   22509 
   22510 class RequestInterruptTestWithMethodCall
   22511     : public RequestInterruptTestBaseWithSimpleInterrupt {
   22512  public:
   22513   virtual void TestBody() {
   22514     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   22515     v8::Local<v8::Template> proto = t->PrototypeTemplate();
   22516     proto->Set(v8_str("shouldContinue"),
   22517                FunctionTemplate::New(isolate_, ShouldContinueCallback,
   22518                                      v8::External::New(isolate_, this)));
   22519     CHECK(env_->Global()
   22520               ->Set(env_.local(), v8_str("Klass"),
   22521                     t->GetFunction(env_.local()).ToLocalChecked())
   22522               .FromJust());
   22523 
   22524     CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
   22525   }
   22526 };
   22527 
   22528 
   22529 class RequestInterruptTestWithAccessor
   22530     : public RequestInterruptTestBaseWithSimpleInterrupt {
   22531  public:
   22532   virtual void TestBody() {
   22533     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   22534     v8::Local<v8::Template> proto = t->PrototypeTemplate();
   22535     proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
   22536         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
   22537     CHECK(env_->Global()
   22538               ->Set(env_.local(), v8_str("Klass"),
   22539                     t->GetFunction(env_.local()).ToLocalChecked())
   22540               .FromJust());
   22541 
   22542     CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
   22543   }
   22544 };
   22545 
   22546 
   22547 class RequestInterruptTestWithNativeAccessor
   22548     : public RequestInterruptTestBaseWithSimpleInterrupt {
   22549  public:
   22550   virtual void TestBody() {
   22551     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   22552     t->InstanceTemplate()->SetNativeDataProperty(
   22553         v8_str("shouldContinue"),
   22554         &ShouldContinueNativeGetter,
   22555         NULL,
   22556         v8::External::New(isolate_, this));
   22557     CHECK(env_->Global()
   22558               ->Set(env_.local(), v8_str("Klass"),
   22559                     t->GetFunction(env_.local()).ToLocalChecked())
   22560               .FromJust());
   22561 
   22562     CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
   22563   }
   22564 
   22565  private:
   22566   static void ShouldContinueNativeGetter(
   22567       Local<String> property,
   22568       const v8::PropertyCallbackInfo<v8::Value>& info) {
   22569     RequestInterruptTestBase* test =
   22570         reinterpret_cast<RequestInterruptTestBase*>(
   22571             info.Data().As<v8::External>()->Value());
   22572     info.GetReturnValue().Set(test->ShouldContinue());
   22573   }
   22574 };
   22575 
   22576 
   22577 class RequestInterruptTestWithMethodCallAndInterceptor
   22578     : public RequestInterruptTestBaseWithSimpleInterrupt {
   22579  public:
   22580   virtual void TestBody() {
   22581     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   22582     v8::Local<v8::Template> proto = t->PrototypeTemplate();
   22583     proto->Set(v8_str("shouldContinue"),
   22584                FunctionTemplate::New(isolate_, ShouldContinueCallback,
   22585                                      v8::External::New(isolate_, this)));
   22586     v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
   22587     instance_template->SetHandler(
   22588         v8::NamedPropertyHandlerConfiguration(EmptyInterceptor));
   22589 
   22590     CHECK(env_->Global()
   22591               ->Set(env_.local(), v8_str("Klass"),
   22592                     t->GetFunction(env_.local()).ToLocalChecked())
   22593               .FromJust());
   22594 
   22595     CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
   22596   }
   22597 
   22598  private:
   22599   static void EmptyInterceptor(
   22600       Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {}
   22601 };
   22602 
   22603 
   22604 class RequestInterruptTestWithMathAbs
   22605     : public RequestInterruptTestBaseWithSimpleInterrupt {
   22606  public:
   22607   virtual void TestBody() {
   22608     env_->Global()
   22609         ->Set(env_.local(), v8_str("WakeUpInterruptor"),
   22610               Function::New(env_.local(), WakeUpInterruptorCallback,
   22611                             v8::External::New(isolate_, this))
   22612                   .ToLocalChecked())
   22613         .FromJust();
   22614 
   22615     env_->Global()
   22616         ->Set(env_.local(), v8_str("ShouldContinue"),
   22617               Function::New(env_.local(), ShouldContinueCallback,
   22618                             v8::External::New(isolate_, this))
   22619                   .ToLocalChecked())
   22620         .FromJust();
   22621 
   22622     i::FLAG_allow_natives_syntax = true;
   22623     CompileRun("function loopish(o) {"
   22624                "  var pre = 10;"
   22625                "  while (o.abs(1) > 0) {"
   22626                "    if (o.abs(1) >= 0 && !ShouldContinue()) break;"
   22627                "    if (pre > 0) {"
   22628                "      if (--pre === 0) WakeUpInterruptor(o === Math);"
   22629                "    }"
   22630                "  }"
   22631                "}"
   22632                "var i = 50;"
   22633                "var obj = {abs: function () { return i-- }, x: null};"
   22634                "delete obj.x;"
   22635                "loopish(obj);"
   22636                "%OptimizeFunctionOnNextCall(loopish);"
   22637                "loopish(Math);");
   22638 
   22639     i::FLAG_allow_natives_syntax = false;
   22640   }
   22641 
   22642  private:
   22643   static void WakeUpInterruptorCallback(
   22644       const v8::FunctionCallbackInfo<Value>& info) {
   22645     if (!info[0]
   22646              ->BooleanValue(info.GetIsolate()->GetCurrentContext())
   22647              .FromJust()) {
   22648       return;
   22649     }
   22650 
   22651     RequestInterruptTestBase* test =
   22652         reinterpret_cast<RequestInterruptTestBase*>(
   22653             info.Data().As<v8::External>()->Value());
   22654     test->WakeUpInterruptor();
   22655   }
   22656 
   22657   static void ShouldContinueCallback(
   22658       const v8::FunctionCallbackInfo<Value>& info) {
   22659     RequestInterruptTestBase* test =
   22660         reinterpret_cast<RequestInterruptTestBase*>(
   22661             info.Data().As<v8::External>()->Value());
   22662     info.GetReturnValue().Set(test->should_continue());
   22663   }
   22664 };
   22665 
   22666 
   22667 TEST(RequestInterruptTestWithFunctionCall) {
   22668   RequestInterruptTestWithFunctionCall().RunTest();
   22669 }
   22670 
   22671 
   22672 TEST(RequestInterruptTestWithMethodCall) {
   22673   RequestInterruptTestWithMethodCall().RunTest();
   22674 }
   22675 
   22676 
   22677 TEST(RequestInterruptTestWithAccessor) {
   22678   RequestInterruptTestWithAccessor().RunTest();
   22679 }
   22680 
   22681 
   22682 TEST(RequestInterruptTestWithNativeAccessor) {
   22683   RequestInterruptTestWithNativeAccessor().RunTest();
   22684 }
   22685 
   22686 
   22687 TEST(RequestInterruptTestWithMethodCallAndInterceptor) {
   22688   RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
   22689 }
   22690 
   22691 
   22692 TEST(RequestInterruptTestWithMathAbs) {
   22693   RequestInterruptTestWithMathAbs().RunTest();
   22694 }
   22695 
   22696 
   22697 class RequestMultipleInterrupts : public RequestInterruptTestBase {
   22698  public:
   22699   RequestMultipleInterrupts() : i_thread(this), counter_(0) {}
   22700 
   22701   virtual void StartInterruptThread() {
   22702     i_thread.Start();
   22703   }
   22704 
   22705   virtual void TestBody() {
   22706     Local<Function> func = Function::New(env_.local(), ShouldContinueCallback,
   22707                                          v8::External::New(isolate_, this))
   22708                                .ToLocalChecked();
   22709     CHECK(env_->Global()
   22710               ->Set(env_.local(), v8_str("ShouldContinue"), func)
   22711               .FromJust());
   22712 
   22713     CompileRun("while (ShouldContinue()) { }");
   22714   }
   22715 
   22716  private:
   22717   class InterruptThread : public v8::base::Thread {
   22718    public:
   22719     enum { NUM_INTERRUPTS = 10 };
   22720     explicit InterruptThread(RequestMultipleInterrupts* test)
   22721         : Thread(Options("RequestInterruptTest")), test_(test) {}
   22722 
   22723     virtual void Run() {
   22724       test_->sem_.Wait();
   22725       for (int i = 0; i < NUM_INTERRUPTS; i++) {
   22726         test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
   22727       }
   22728     }
   22729 
   22730     static void OnInterrupt(v8::Isolate* isolate, void* data) {
   22731       RequestMultipleInterrupts* test =
   22732           reinterpret_cast<RequestMultipleInterrupts*>(data);
   22733       test->should_continue_ = ++test->counter_ < NUM_INTERRUPTS;
   22734     }
   22735 
   22736    private:
   22737     RequestMultipleInterrupts* test_;
   22738   };
   22739 
   22740   InterruptThread i_thread;
   22741   int counter_;
   22742 };
   22743 
   22744 
   22745 TEST(RequestMultipleInterrupts) { RequestMultipleInterrupts().RunTest(); }
   22746 
   22747 
   22748 static bool interrupt_was_called = false;
   22749 
   22750 
   22751 void SmallScriptsInterruptCallback(v8::Isolate* isolate, void* data) {
   22752   interrupt_was_called = true;
   22753 }
   22754 
   22755 
   22756 TEST(RequestInterruptSmallScripts) {
   22757   LocalContext env;
   22758   v8::Isolate* isolate = CcTest::isolate();
   22759   v8::HandleScope scope(isolate);
   22760 
   22761   interrupt_was_called = false;
   22762   isolate->RequestInterrupt(&SmallScriptsInterruptCallback, NULL);
   22763   CompileRun("(function(x){return x;})(1);");
   22764   CHECK(interrupt_was_called);
   22765 }
   22766 
   22767 
   22768 static Local<Value> function_new_expected_env;
   22769 static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
   22770   CHECK(
   22771       function_new_expected_env->Equals(info.GetIsolate()->GetCurrentContext(),
   22772                                         info.Data())
   22773           .FromJust());
   22774   info.GetReturnValue().Set(17);
   22775 }
   22776 
   22777 
   22778 THREADED_TEST(FunctionNew) {
   22779   LocalContext env;
   22780   v8::Isolate* isolate = env->GetIsolate();
   22781   v8::HandleScope scope(isolate);
   22782   Local<Object> data = v8::Object::New(isolate);
   22783   function_new_expected_env = data;
   22784   Local<Function> func =
   22785       Function::New(env.local(), FunctionNewCallback, data).ToLocalChecked();
   22786   CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   22787   Local<Value> result = CompileRun("func();");
   22788   CHECK(v8::Integer::New(isolate, 17)->Equals(env.local(), result).FromJust());
   22789   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   22790   // Verify function not cached
   22791   auto serial_number = handle(
   22792       i::Smi::cast(i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*func))
   22793                        ->shared()
   22794                        ->get_api_func_data()
   22795                        ->serial_number()),
   22796       i_isolate);
   22797   auto cache = i_isolate->template_instantiations_cache();
   22798   CHECK(cache->FindEntry(static_cast<uint32_t>(serial_number->value())) ==
   22799         i::UnseededNumberDictionary::kNotFound);
   22800   // Verify that each Function::New creates a new function instance
   22801   Local<Object> data2 = v8::Object::New(isolate);
   22802   function_new_expected_env = data2;
   22803   Local<Function> func2 =
   22804       Function::New(env.local(), FunctionNewCallback, data2).ToLocalChecked();
   22805   CHECK(!func2->IsNull());
   22806   CHECK(!func->Equals(env.local(), func2).FromJust());
   22807   CHECK(env->Global()->Set(env.local(), v8_str("func2"), func2).FromJust());
   22808   Local<Value> result2 = CompileRun("func2();");
   22809   CHECK(v8::Integer::New(isolate, 17)->Equals(env.local(), result2).FromJust());
   22810 }
   22811 
   22812 
   22813 TEST(EscapeableHandleScope) {
   22814   HandleScope outer_scope(CcTest::isolate());
   22815   LocalContext context;
   22816   const int runs = 10;
   22817   Local<String> values[runs];
   22818   for (int i = 0; i < runs; i++) {
   22819     v8::EscapableHandleScope inner_scope(CcTest::isolate());
   22820     Local<String> value;
   22821     if (i != 0) value = v8_str("escape value");
   22822     values[i] = inner_scope.Escape(value);
   22823   }
   22824   for (int i = 0; i < runs; i++) {
   22825     Local<String> expected;
   22826     if (i != 0) {
   22827       CHECK(v8_str("escape value")
   22828                 ->Equals(context.local(), values[i])
   22829                 .FromJust());
   22830     } else {
   22831       CHECK(values[i].IsEmpty());
   22832     }
   22833   }
   22834 }
   22835 
   22836 
   22837 static void SetterWhichExpectsThisAndHolderToDiffer(
   22838     Local<String>, Local<Value>, const v8::PropertyCallbackInfo<void>& info) {
   22839   CHECK(info.Holder() != info.This());
   22840 }
   22841 
   22842 
   22843 TEST(Regress239669) {
   22844   LocalContext context;
   22845   v8::Isolate* isolate = context->GetIsolate();
   22846   v8::HandleScope scope(isolate);
   22847   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   22848   templ->SetAccessor(v8_str("x"), 0, SetterWhichExpectsThisAndHolderToDiffer);
   22849   CHECK(context->Global()
   22850             ->Set(context.local(), v8_str("P"),
   22851                   templ->NewInstance(context.local()).ToLocalChecked())
   22852             .FromJust());
   22853   CompileRun(
   22854       "function C1() {"
   22855       "  this.x = 23;"
   22856       "};"
   22857       "C1.prototype = P;"
   22858       "for (var i = 0; i < 4; i++ ) {"
   22859       "  new C1();"
   22860       "}");
   22861 }
   22862 
   22863 
   22864 class ApiCallOptimizationChecker {
   22865  private:
   22866   static Local<Object> data;
   22867   static Local<Object> receiver;
   22868   static Local<Object> holder;
   22869   static Local<Object> callee;
   22870   static int count;
   22871 
   22872   static void OptimizationCallback(
   22873       const v8::FunctionCallbackInfo<v8::Value>& info) {
   22874     CHECK(data == info.Data());
   22875     CHECK(receiver == info.This());
   22876     if (info.Length() == 1) {
   22877       CHECK(v8_num(1)
   22878                 ->Equals(info.GetIsolate()->GetCurrentContext(), info[0])
   22879                 .FromJust());
   22880     }
   22881     CHECK(holder == info.Holder());
   22882     count++;
   22883     info.GetReturnValue().Set(v8_str("returned"));
   22884   }
   22885 
   22886  public:
   22887   enum SignatureType {
   22888     kNoSignature,
   22889     kSignatureOnReceiver,
   22890     kSignatureOnPrototype
   22891   };
   22892 
   22893   void RunAll() {
   22894     SignatureType signature_types[] =
   22895       {kNoSignature, kSignatureOnReceiver, kSignatureOnPrototype};
   22896     for (unsigned i = 0; i < arraysize(signature_types); i++) {
   22897       SignatureType signature_type = signature_types[i];
   22898       for (int j = 0; j < 2; j++) {
   22899         bool global = j == 0;
   22900         int key = signature_type +
   22901             arraysize(signature_types) * (global ? 1 : 0);
   22902         Run(signature_type, global, key);
   22903       }
   22904     }
   22905   }
   22906 
   22907   void Run(SignatureType signature_type, bool global, int key) {
   22908     v8::Isolate* isolate = CcTest::isolate();
   22909     v8::HandleScope scope(isolate);
   22910     // Build a template for signature checks.
   22911     Local<v8::ObjectTemplate> signature_template;
   22912     Local<v8::Signature> signature;
   22913     {
   22914       Local<v8::FunctionTemplate> parent_template =
   22915         FunctionTemplate::New(isolate);
   22916       parent_template->SetHiddenPrototype(true);
   22917       Local<v8::FunctionTemplate> function_template
   22918           = FunctionTemplate::New(isolate);
   22919       function_template->Inherit(parent_template);
   22920       switch (signature_type) {
   22921         case kNoSignature:
   22922           break;
   22923         case kSignatureOnReceiver:
   22924           signature = v8::Signature::New(isolate, function_template);
   22925           break;
   22926         case kSignatureOnPrototype:
   22927           signature = v8::Signature::New(isolate, parent_template);
   22928           break;
   22929       }
   22930       signature_template = function_template->InstanceTemplate();
   22931     }
   22932     // Global object must pass checks.
   22933     Local<v8::Context> context =
   22934         v8::Context::New(isolate, NULL, signature_template);
   22935     v8::Context::Scope context_scope(context);
   22936     // Install regular object that can pass signature checks.
   22937     Local<Object> function_receiver =
   22938         signature_template->NewInstance(context).ToLocalChecked();
   22939     CHECK(context->Global()
   22940               ->Set(context, v8_str("function_receiver"), function_receiver)
   22941               .FromJust());
   22942     // Get the holder objects.
   22943     Local<Object> inner_global =
   22944         Local<Object>::Cast(context->Global()->GetPrototype());
   22945     // Install functions on hidden prototype object if there is one.
   22946     data = Object::New(isolate);
   22947     Local<FunctionTemplate> function_template = FunctionTemplate::New(
   22948         isolate, OptimizationCallback, data, signature);
   22949     Local<Function> function =
   22950         function_template->GetFunction(context).ToLocalChecked();
   22951     Local<Object> global_holder = inner_global;
   22952     Local<Object> function_holder = function_receiver;
   22953     if (signature_type == kSignatureOnPrototype) {
   22954       function_holder = Local<Object>::Cast(function_holder->GetPrototype());
   22955       global_holder = Local<Object>::Cast(global_holder->GetPrototype());
   22956     }
   22957     global_holder->Set(context, v8_str("g_f"), function).FromJust();
   22958     global_holder->SetAccessorProperty(v8_str("g_acc"), function, function);
   22959     function_holder->Set(context, v8_str("f"), function).FromJust();
   22960     function_holder->SetAccessorProperty(v8_str("acc"), function, function);
   22961     // Initialize expected values.
   22962     callee = function;
   22963     count = 0;
   22964     if (global) {
   22965       receiver = context->Global();
   22966       holder = inner_global;
   22967     } else {
   22968       holder = function_receiver;
   22969       // If not using a signature, add something else to the prototype chain
   22970       // to test the case that holder != receiver
   22971       if (signature_type == kNoSignature) {
   22972         receiver = Local<Object>::Cast(CompileRun(
   22973             "var receiver_subclass = {};\n"
   22974             "receiver_subclass.__proto__ = function_receiver;\n"
   22975             "receiver_subclass"));
   22976       } else {
   22977         receiver = Local<Object>::Cast(CompileRun(
   22978           "var receiver_subclass = function_receiver;\n"
   22979           "receiver_subclass"));
   22980       }
   22981     }
   22982     // With no signature, the holder is not set.
   22983     if (signature_type == kNoSignature) holder = receiver;
   22984     // build wrap_function
   22985     i::ScopedVector<char> wrap_function(200);
   22986     if (global) {
   22987       i::SNPrintF(
   22988           wrap_function,
   22989           "function wrap_f_%d() { var f = g_f; return f(); }\n"
   22990           "function wrap_get_%d() { return this.g_acc; }\n"
   22991           "function wrap_set_%d() { return this.g_acc = 1; }\n",
   22992           key, key, key);
   22993     } else {
   22994       i::SNPrintF(
   22995           wrap_function,
   22996           "function wrap_f_%d() { return receiver_subclass.f(); }\n"
   22997           "function wrap_get_%d() { return receiver_subclass.acc; }\n"
   22998           "function wrap_set_%d() { return receiver_subclass.acc = 1; }\n",
   22999           key, key, key);
   23000     }
   23001     // build source string
   23002     i::ScopedVector<char> source(1000);
   23003     i::SNPrintF(
   23004         source,
   23005         "%s\n"  // wrap functions
   23006         "function wrap_f() { return wrap_f_%d(); }\n"
   23007         "function wrap_get() { return wrap_get_%d(); }\n"
   23008         "function wrap_set() { return wrap_set_%d(); }\n"
   23009         "check = function(returned) {\n"
   23010         "  if (returned !== 'returned') { throw returned; }\n"
   23011         "}\n"
   23012         "\n"
   23013         "check(wrap_f());\n"
   23014         "check(wrap_f());\n"
   23015         "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
   23016         "check(wrap_f());\n"
   23017         "\n"
   23018         "check(wrap_get());\n"
   23019         "check(wrap_get());\n"
   23020         "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
   23021         "check(wrap_get());\n"
   23022         "\n"
   23023         "check = function(returned) {\n"
   23024         "  if (returned !== 1) { throw returned; }\n"
   23025         "}\n"
   23026         "check(wrap_set());\n"
   23027         "check(wrap_set());\n"
   23028         "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
   23029         "check(wrap_set());\n",
   23030         wrap_function.start(), key, key, key, key, key, key);
   23031     v8::TryCatch try_catch(isolate);
   23032     CompileRun(source.start());
   23033     CHECK(!try_catch.HasCaught());
   23034     CHECK_EQ(9, count);
   23035   }
   23036 };
   23037 
   23038 
   23039 Local<Object> ApiCallOptimizationChecker::data;
   23040 Local<Object> ApiCallOptimizationChecker::receiver;
   23041 Local<Object> ApiCallOptimizationChecker::holder;
   23042 Local<Object> ApiCallOptimizationChecker::callee;
   23043 int ApiCallOptimizationChecker::count = 0;
   23044 
   23045 
   23046 TEST(FunctionCallOptimization) {
   23047   i::FLAG_allow_natives_syntax = true;
   23048   ApiCallOptimizationChecker checker;
   23049   checker.RunAll();
   23050 }
   23051 
   23052 
   23053 TEST(FunctionCallOptimizationMultipleArgs) {
   23054   i::FLAG_allow_natives_syntax = true;
   23055   LocalContext context;
   23056   v8::Isolate* isolate = context->GetIsolate();
   23057   v8::HandleScope scope(isolate);
   23058   Local<Object> global = context->Global();
   23059   Local<v8::Function> function =
   23060       Function::New(context.local(), Returns42).ToLocalChecked();
   23061   global->Set(context.local(), v8_str("x"), function).FromJust();
   23062   CompileRun(
   23063       "function x_wrap() {\n"
   23064       "  for (var i = 0; i < 5; i++) {\n"
   23065       "    x(1,2,3);\n"
   23066       "  }\n"
   23067       "}\n"
   23068       "x_wrap();\n"
   23069       "%OptimizeFunctionOnNextCall(x_wrap);"
   23070       "x_wrap();\n");
   23071 }
   23072 
   23073 
   23074 static void ReturnsSymbolCallback(
   23075     const v8::FunctionCallbackInfo<v8::Value>& info) {
   23076   info.GetReturnValue().Set(v8::Symbol::New(info.GetIsolate()));
   23077 }
   23078 
   23079 
   23080 TEST(ApiCallbackCanReturnSymbols) {
   23081   i::FLAG_allow_natives_syntax = true;
   23082   LocalContext context;
   23083   v8::Isolate* isolate = context->GetIsolate();
   23084   v8::HandleScope scope(isolate);
   23085   Local<Object> global = context->Global();
   23086   Local<v8::Function> function =
   23087       Function::New(context.local(), ReturnsSymbolCallback).ToLocalChecked();
   23088   global->Set(context.local(), v8_str("x"), function).FromJust();
   23089   CompileRun(
   23090       "function x_wrap() {\n"
   23091       "  for (var i = 0; i < 5; i++) {\n"
   23092       "    x();\n"
   23093       "  }\n"
   23094       "}\n"
   23095       "x_wrap();\n"
   23096       "%OptimizeFunctionOnNextCall(x_wrap);"
   23097       "x_wrap();\n");
   23098 }
   23099 
   23100 
   23101 TEST(EmptyApiCallback) {
   23102   LocalContext context;
   23103   auto isolate = context->GetIsolate();
   23104   v8::HandleScope scope(isolate);
   23105   auto global = context->Global();
   23106   auto function = FunctionTemplate::New(isolate)
   23107                       ->GetFunction(context.local())
   23108                       .ToLocalChecked();
   23109   global->Set(context.local(), v8_str("x"), function).FromJust();
   23110 
   23111   auto result = CompileRun("x()");
   23112   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
   23113 
   23114   result = CompileRun("x(1,2,3)");
   23115   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
   23116 
   23117   result = CompileRun("x.call(undefined)");
   23118   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
   23119 
   23120   result = CompileRun("x.call(null)");
   23121   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
   23122 
   23123   result = CompileRun("7 + x.call(3) + 11");
   23124   CHECK(result->IsInt32());
   23125   CHECK_EQ(21, result->Int32Value(context.local()).FromJust());
   23126 
   23127   result = CompileRun("7 + x.call(3, 101, 102, 103, 104) + 11");
   23128   CHECK(result->IsInt32());
   23129   CHECK_EQ(21, result->Int32Value(context.local()).FromJust());
   23130 
   23131   result = CompileRun("var y = []; x.call(y)");
   23132   CHECK(result->IsArray());
   23133 
   23134   result = CompileRun("x.call(y, 1, 2, 3, 4)");
   23135   CHECK(result->IsArray());
   23136 }
   23137 
   23138 
   23139 TEST(SimpleSignatureCheck) {
   23140   LocalContext context;
   23141   auto isolate = context->GetIsolate();
   23142   v8::HandleScope scope(isolate);
   23143   auto global = context->Global();
   23144   auto sig_obj = FunctionTemplate::New(isolate);
   23145   auto sig = v8::Signature::New(isolate, sig_obj);
   23146   auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
   23147   global->Set(context.local(), v8_str("sig_obj"),
   23148               sig_obj->GetFunction(context.local()).ToLocalChecked())
   23149       .FromJust();
   23150   global->Set(context.local(), v8_str("x"),
   23151               x->GetFunction(context.local()).ToLocalChecked())
   23152       .FromJust();
   23153   CompileRun("var s = new sig_obj();");
   23154   {
   23155     TryCatch try_catch(isolate);
   23156     CompileRun("x()");
   23157     CHECK(try_catch.HasCaught());
   23158   }
   23159   {
   23160     TryCatch try_catch(isolate);
   23161     CompileRun("x.call(1)");
   23162     CHECK(try_catch.HasCaught());
   23163   }
   23164   {
   23165     TryCatch try_catch(isolate);
   23166     auto result = CompileRun("s.x = x; s.x()");
   23167     CHECK(!try_catch.HasCaught());
   23168     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   23169   }
   23170   {
   23171     TryCatch try_catch(isolate);
   23172     auto result = CompileRun("x.call(s)");
   23173     CHECK(!try_catch.HasCaught());
   23174     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   23175   }
   23176 }
   23177 
   23178 
   23179 TEST(ChainSignatureCheck) {
   23180   LocalContext context;
   23181   auto isolate = context->GetIsolate();
   23182   v8::HandleScope scope(isolate);
   23183   auto global = context->Global();
   23184   auto sig_obj = FunctionTemplate::New(isolate);
   23185   auto sig = v8::Signature::New(isolate, sig_obj);
   23186   for (int i = 0; i < 4; ++i) {
   23187     auto temp = FunctionTemplate::New(isolate);
   23188     temp->Inherit(sig_obj);
   23189     sig_obj = temp;
   23190   }
   23191   auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
   23192   global->Set(context.local(), v8_str("sig_obj"),
   23193               sig_obj->GetFunction(context.local()).ToLocalChecked())
   23194       .FromJust();
   23195   global->Set(context.local(), v8_str("x"),
   23196               x->GetFunction(context.local()).ToLocalChecked())
   23197       .FromJust();
   23198   CompileRun("var s = new sig_obj();");
   23199   {
   23200     TryCatch try_catch(isolate);
   23201     CompileRun("x()");
   23202     CHECK(try_catch.HasCaught());
   23203   }
   23204   {
   23205     TryCatch try_catch(isolate);
   23206     CompileRun("x.call(1)");
   23207     CHECK(try_catch.HasCaught());
   23208   }
   23209   {
   23210     TryCatch try_catch(isolate);
   23211     auto result = CompileRun("s.x = x; s.x()");
   23212     CHECK(!try_catch.HasCaught());
   23213     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   23214   }
   23215   {
   23216     TryCatch try_catch(isolate);
   23217     auto result = CompileRun("x.call(s)");
   23218     CHECK(!try_catch.HasCaught());
   23219     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   23220   }
   23221 }
   23222 
   23223 
   23224 TEST(PrototypeSignatureCheck) {
   23225   LocalContext context;
   23226   auto isolate = context->GetIsolate();
   23227   v8::HandleScope scope(isolate);
   23228   auto global = context->Global();
   23229   auto sig_obj = FunctionTemplate::New(isolate);
   23230   sig_obj->SetHiddenPrototype(true);
   23231   auto sig = v8::Signature::New(isolate, sig_obj);
   23232   auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
   23233   global->Set(context.local(), v8_str("sig_obj"),
   23234               sig_obj->GetFunction(context.local()).ToLocalChecked())
   23235       .FromJust();
   23236   global->Set(context.local(), v8_str("x"),
   23237               x->GetFunction(context.local()).ToLocalChecked())
   23238       .FromJust();
   23239   CompileRun("s = {}; s.__proto__ = new sig_obj();");
   23240   {
   23241     TryCatch try_catch(isolate);
   23242     CompileRun("x()");
   23243     CHECK(try_catch.HasCaught());
   23244   }
   23245   {
   23246     TryCatch try_catch(isolate);
   23247     CompileRun("x.call(1)");
   23248     CHECK(try_catch.HasCaught());
   23249   }
   23250   {
   23251     TryCatch try_catch(isolate);
   23252     auto result = CompileRun("s.x = x; s.x()");
   23253     CHECK(!try_catch.HasCaught());
   23254     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   23255   }
   23256   {
   23257     TryCatch try_catch(isolate);
   23258     auto result = CompileRun("x.call(s)");
   23259     CHECK(!try_catch.HasCaught());
   23260     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   23261   }
   23262 }
   23263 
   23264 
   23265 static const char* last_event_message;
   23266 static int last_event_status;
   23267 void StoringEventLoggerCallback(const char* message, int status) {
   23268     last_event_message = message;
   23269     last_event_status = status;
   23270 }
   23271 
   23272 
   23273 TEST(EventLogging) {
   23274   v8::Isolate* isolate = CcTest::isolate();
   23275   isolate->SetEventLogger(StoringEventLoggerCallback);
   23276   v8::internal::HistogramTimer histogramTimer(
   23277       "V8.Test", 0, 10000, v8::internal::HistogramTimer::MILLISECOND, 50,
   23278       reinterpret_cast<v8::internal::Isolate*>(isolate));
   23279   histogramTimer.Start();
   23280   CHECK_EQ(0, strcmp("V8.Test", last_event_message));
   23281   CHECK_EQ(0, last_event_status);
   23282   histogramTimer.Stop();
   23283   CHECK_EQ(0, strcmp("V8.Test", last_event_message));
   23284   CHECK_EQ(1, last_event_status);
   23285 }
   23286 
   23287 
   23288 TEST(Promises) {
   23289   LocalContext context;
   23290   v8::Isolate* isolate = context->GetIsolate();
   23291   v8::HandleScope scope(isolate);
   23292 
   23293   // Creation.
   23294   Local<v8::Promise::Resolver> pr =
   23295       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   23296   Local<v8::Promise::Resolver> rr =
   23297       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   23298   Local<v8::Promise> p = pr->GetPromise();
   23299   Local<v8::Promise> r = rr->GetPromise();
   23300 
   23301   // IsPromise predicate.
   23302   CHECK(p->IsPromise());
   23303   CHECK(r->IsPromise());
   23304   Local<Value> o = v8::Object::New(isolate);
   23305   CHECK(!o->IsPromise());
   23306 
   23307   // Resolution and rejection.
   23308   pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
   23309   CHECK(p->IsPromise());
   23310   rr->Reject(context.local(), v8::Integer::New(isolate, 2)).FromJust();
   23311   CHECK(r->IsPromise());
   23312 }
   23313 
   23314 
   23315 TEST(PromiseThen) {
   23316   LocalContext context;
   23317   v8::Isolate* isolate = context->GetIsolate();
   23318   v8::HandleScope scope(isolate);
   23319   Local<Object> global = context->Global();
   23320 
   23321   // Creation.
   23322   Local<v8::Promise::Resolver> pr =
   23323       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   23324   Local<v8::Promise::Resolver> qr =
   23325       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   23326   Local<v8::Promise> p = pr->GetPromise();
   23327   Local<v8::Promise> q = qr->GetPromise();
   23328 
   23329   CHECK(p->IsPromise());
   23330   CHECK(q->IsPromise());
   23331 
   23332   pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
   23333   qr->Resolve(context.local(), p).FromJust();
   23334 
   23335   // Chaining non-pending promises.
   23336   CompileRun(
   23337       "var x1 = 0;\n"
   23338       "var x2 = 0;\n"
   23339       "function f1(x) { x1 = x; return x+1 };\n"
   23340       "function f2(x) { x2 = x; return x+1 };\n");
   23341   Local<Function> f1 = Local<Function>::Cast(
   23342       global->Get(context.local(), v8_str("f1")).ToLocalChecked());
   23343   Local<Function> f2 = Local<Function>::Cast(
   23344       global->Get(context.local(), v8_str("f2")).ToLocalChecked());
   23345 
   23346   // Then
   23347   CompileRun("x1 = x2 = 0;");
   23348   q->Then(context.local(), f1).ToLocalChecked();
   23349   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   23350                   .ToLocalChecked()
   23351                   ->Int32Value(context.local())
   23352                   .FromJust());
   23353   isolate->RunMicrotasks();
   23354   CHECK_EQ(1, global->Get(context.local(), v8_str("x1"))
   23355                   .ToLocalChecked()
   23356                   ->Int32Value(context.local())
   23357                   .FromJust());
   23358 
   23359   // Then
   23360   CompileRun("x1 = x2 = 0;");
   23361   pr = v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   23362   qr = v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   23363 
   23364   qr->Resolve(context.local(), pr).FromJust();
   23365   qr->GetPromise()
   23366       ->Then(context.local(), f1)
   23367       .ToLocalChecked()
   23368       ->Then(context.local(), f2)
   23369       .ToLocalChecked();
   23370 
   23371   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   23372                   .ToLocalChecked()
   23373                   ->Int32Value(context.local())
   23374                   .FromJust());
   23375   CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
   23376                   .ToLocalChecked()
   23377                   ->Int32Value(context.local())
   23378                   .FromJust());
   23379   isolate->RunMicrotasks();
   23380   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   23381                   .ToLocalChecked()
   23382                   ->Int32Value(context.local())
   23383                   .FromJust());
   23384   CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
   23385                   .ToLocalChecked()
   23386                   ->Int32Value(context.local())
   23387                   .FromJust());
   23388 
   23389   pr->Resolve(context.local(), v8::Integer::New(isolate, 3)).FromJust();
   23390 
   23391   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   23392                   .ToLocalChecked()
   23393                   ->Int32Value(context.local())
   23394                   .FromJust());
   23395   CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
   23396                   .ToLocalChecked()
   23397                   ->Int32Value(context.local())
   23398                   .FromJust());
   23399   isolate->RunMicrotasks();
   23400   CHECK_EQ(3, global->Get(context.local(), v8_str("x1"))
   23401                   .ToLocalChecked()
   23402                   ->Int32Value(context.local())
   23403                   .FromJust());
   23404   CHECK_EQ(4, global->Get(context.local(), v8_str("x2"))
   23405                   .ToLocalChecked()
   23406                   ->Int32Value(context.local())
   23407                   .FromJust());
   23408 }
   23409 
   23410 
   23411 TEST(DisallowJavascriptExecutionScope) {
   23412   LocalContext context;
   23413   v8::Isolate* isolate = context->GetIsolate();
   23414   v8::HandleScope scope(isolate);
   23415   v8::Isolate::DisallowJavascriptExecutionScope no_js(
   23416       isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
   23417   CompileRun("2+2");
   23418 }
   23419 
   23420 
   23421 TEST(AllowJavascriptExecutionScope) {
   23422   LocalContext context;
   23423   v8::Isolate* isolate = context->GetIsolate();
   23424   v8::HandleScope scope(isolate);
   23425   v8::Isolate::DisallowJavascriptExecutionScope no_js(
   23426       isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
   23427   v8::Isolate::DisallowJavascriptExecutionScope throw_js(
   23428       isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
   23429   { v8::Isolate::AllowJavascriptExecutionScope yes_js(isolate);
   23430     CompileRun("1+1");
   23431   }
   23432 }
   23433 
   23434 
   23435 TEST(ThrowOnJavascriptExecution) {
   23436   LocalContext context;
   23437   v8::Isolate* isolate = context->GetIsolate();
   23438   v8::HandleScope scope(isolate);
   23439   v8::TryCatch try_catch(isolate);
   23440   v8::Isolate::DisallowJavascriptExecutionScope throw_js(
   23441       isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
   23442   CompileRun("1+1");
   23443   CHECK(try_catch.HasCaught());
   23444 }
   23445 
   23446 
   23447 TEST(Regress354123) {
   23448   LocalContext current;
   23449   v8::Isolate* isolate = current->GetIsolate();
   23450   v8::HandleScope scope(isolate);
   23451 
   23452   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   23453   templ->SetAccessCheckCallback(AccessCounter);
   23454   CHECK(current->Global()
   23455             ->Set(current.local(), v8_str("friend"),
   23456                   templ->NewInstance(current.local()).ToLocalChecked())
   23457             .FromJust());
   23458 
   23459   // Test access using __proto__ from the prototype chain.
   23460   access_count = 0;
   23461   CompileRun("friend.__proto__ = {};");
   23462   CHECK_EQ(2, access_count);
   23463   CompileRun("friend.__proto__;");
   23464   CHECK_EQ(4, access_count);
   23465 
   23466   // Test access using __proto__ as a hijacked function (A).
   23467   access_count = 0;
   23468   CompileRun("var p = Object.prototype;"
   23469              "var f = Object.getOwnPropertyDescriptor(p, '__proto__').set;"
   23470              "f.call(friend, {});");
   23471   CHECK_EQ(1, access_count);
   23472   CompileRun("var p = Object.prototype;"
   23473              "var f = Object.getOwnPropertyDescriptor(p, '__proto__').get;"
   23474              "f.call(friend);");
   23475   CHECK_EQ(2, access_count);
   23476 
   23477   // Test access using __proto__ as a hijacked function (B).
   23478   access_count = 0;
   23479   CompileRun("var f = Object.prototype.__lookupSetter__('__proto__');"
   23480              "f.call(friend, {});");
   23481   CHECK_EQ(1, access_count);
   23482   CompileRun("var f = Object.prototype.__lookupGetter__('__proto__');"
   23483              "f.call(friend);");
   23484   CHECK_EQ(2, access_count);
   23485 
   23486   // Test access using Object.setPrototypeOf reflective method.
   23487   access_count = 0;
   23488   CompileRun("Object.setPrototypeOf(friend, {});");
   23489   CHECK_EQ(1, access_count);
   23490   CompileRun("Object.getPrototypeOf(friend);");
   23491   CHECK_EQ(2, access_count);
   23492 }
   23493 
   23494 
   23495 TEST(CaptureStackTraceForStackOverflow) {
   23496   v8::internal::FLAG_stack_size = 150;
   23497   LocalContext current;
   23498   v8::Isolate* isolate = current->GetIsolate();
   23499   v8::HandleScope scope(isolate);
   23500   isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10,
   23501                                                      v8::StackTrace::kDetailed);
   23502   v8::TryCatch try_catch(isolate);
   23503   CompileRun("(function f(x) { f(x+1); })(0)");
   23504   CHECK(try_catch.HasCaught());
   23505 }
   23506 
   23507 
   23508 TEST(ScriptNameAndLineNumber) {
   23509   LocalContext env;
   23510   v8::Isolate* isolate = env->GetIsolate();
   23511   v8::HandleScope scope(isolate);
   23512   const char* url = "http://www.foo.com/foo.js";
   23513   v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
   23514   v8::ScriptCompiler::Source script_source(v8_str("var foo;"), origin);
   23515   Local<Script> script =
   23516       v8::ScriptCompiler::Compile(env.local(), &script_source).ToLocalChecked();
   23517   Local<Value> script_name = script->GetUnboundScript()->GetScriptName();
   23518   CHECK(!script_name.IsEmpty());
   23519   CHECK(script_name->IsString());
   23520   String::Utf8Value utf8_name(script_name);
   23521   CHECK_EQ(0, strcmp(url, *utf8_name));
   23522   int line_number = script->GetUnboundScript()->GetLineNumber(0);
   23523   CHECK_EQ(13, line_number);
   23524 }
   23525 
   23526 TEST(ScriptPositionInfo) {
   23527   LocalContext env;
   23528   v8::Isolate* isolate = env->GetIsolate();
   23529   v8::HandleScope scope(isolate);
   23530   const char* url = "http://www.foo.com/foo.js";
   23531   v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
   23532   v8::ScriptCompiler::Source script_source(v8_str("var foo;\n"
   23533                                                   "var bar;\n"
   23534                                                   "var fisk = foo + bar;\n"),
   23535                                            origin);
   23536   Local<Script> script =
   23537       v8::ScriptCompiler::Compile(env.local(), &script_source).ToLocalChecked();
   23538 
   23539   i::Handle<i::SharedFunctionInfo> obj = i::Handle<i::SharedFunctionInfo>::cast(
   23540       v8::Utils::OpenHandle(*script->GetUnboundScript()));
   23541   CHECK(obj->script()->IsScript());
   23542 
   23543   i::Handle<i::Script> script1(i::Script::cast(obj->script()));
   23544 
   23545   v8::internal::Script::PositionInfo info;
   23546 
   23547   // With offset.
   23548 
   23549   // Behave as if 0 was passed if position is negative.
   23550   CHECK(script1->GetPositionInfo(-1, &info, script1->WITH_OFFSET));
   23551   CHECK_EQ(13, info.line);
   23552   CHECK_EQ(0, info.column);
   23553   CHECK_EQ(0, info.line_start);
   23554   CHECK_EQ(8, info.line_end);
   23555 
   23556   CHECK(script1->GetPositionInfo(0, &info, script1->WITH_OFFSET));
   23557   CHECK_EQ(13, info.line);
   23558   CHECK_EQ(0, info.column);
   23559   CHECK_EQ(0, info.line_start);
   23560   CHECK_EQ(8, info.line_end);
   23561 
   23562   CHECK(script1->GetPositionInfo(8, &info, script1->WITH_OFFSET));
   23563   CHECK_EQ(13, info.line);
   23564   CHECK_EQ(8, info.column);
   23565   CHECK_EQ(0, info.line_start);
   23566   CHECK_EQ(8, info.line_end);
   23567 
   23568   CHECK(script1->GetPositionInfo(9, &info, script1->WITH_OFFSET));
   23569   CHECK_EQ(14, info.line);
   23570   CHECK_EQ(0, info.column);
   23571   CHECK_EQ(9, info.line_start);
   23572   CHECK_EQ(17, info.line_end);
   23573 
   23574   // Fail when position is larger than script size.
   23575   CHECK(!script1->GetPositionInfo(220384, &info, script1->WITH_OFFSET));
   23576 
   23577   // Without offset.
   23578 
   23579   // Behave as if 0 was passed if position is negative.
   23580   CHECK(script1->GetPositionInfo(-1, &info, script1->NO_OFFSET));
   23581   CHECK_EQ(0, info.line);
   23582   CHECK_EQ(0, info.column);
   23583   CHECK_EQ(0, info.line_start);
   23584   CHECK_EQ(8, info.line_end);
   23585 
   23586   CHECK(script1->GetPositionInfo(0, &info, script1->NO_OFFSET));
   23587   CHECK_EQ(0, info.line);
   23588   CHECK_EQ(0, info.column);
   23589   CHECK_EQ(0, info.line_start);
   23590   CHECK_EQ(8, info.line_end);
   23591 
   23592   CHECK(script1->GetPositionInfo(8, &info, script1->NO_OFFSET));
   23593   CHECK_EQ(0, info.line);
   23594   CHECK_EQ(8, info.column);
   23595   CHECK_EQ(0, info.line_start);
   23596   CHECK_EQ(8, info.line_end);
   23597 
   23598   CHECK(script1->GetPositionInfo(9, &info, script1->NO_OFFSET));
   23599   CHECK_EQ(1, info.line);
   23600   CHECK_EQ(0, info.column);
   23601   CHECK_EQ(9, info.line_start);
   23602   CHECK_EQ(17, info.line_end);
   23603 
   23604   // Fail when position is larger than script size.
   23605   CHECK(!script1->GetPositionInfo(220384, &info, script1->NO_OFFSET));
   23606 }
   23607 
   23608 void CheckMagicComments(Local<Script> script, const char* expected_source_url,
   23609                         const char* expected_source_mapping_url) {
   23610   if (expected_source_url != NULL) {
   23611     v8::String::Utf8Value url(script->GetUnboundScript()->GetSourceURL());
   23612     CHECK_EQ(0, strcmp(expected_source_url, *url));
   23613   } else {
   23614     CHECK(script->GetUnboundScript()->GetSourceURL()->IsUndefined());
   23615   }
   23616   if (expected_source_mapping_url != NULL) {
   23617     v8::String::Utf8Value url(
   23618         script->GetUnboundScript()->GetSourceMappingURL());
   23619     CHECK_EQ(0, strcmp(expected_source_mapping_url, *url));
   23620   } else {
   23621     CHECK(script->GetUnboundScript()->GetSourceMappingURL()->IsUndefined());
   23622   }
   23623 }
   23624 
   23625 void SourceURLHelper(const char* source, const char* expected_source_url,
   23626                      const char* expected_source_mapping_url) {
   23627   Local<Script> script = v8_compile(source);
   23628   CheckMagicComments(script, expected_source_url, expected_source_mapping_url);
   23629 }
   23630 
   23631 
   23632 TEST(ScriptSourceURLAndSourceMappingURL) {
   23633   LocalContext env;
   23634   v8::Isolate* isolate = env->GetIsolate();
   23635   v8::HandleScope scope(isolate);
   23636   SourceURLHelper("function foo() {}\n"
   23637                   "//# sourceURL=bar1.js\n", "bar1.js", NULL);
   23638   SourceURLHelper("function foo() {}\n"
   23639                   "//# sourceMappingURL=bar2.js\n", NULL, "bar2.js");
   23640 
   23641   // Both sourceURL and sourceMappingURL.
   23642   SourceURLHelper("function foo() {}\n"
   23643                   "//# sourceURL=bar3.js\n"
   23644                   "//# sourceMappingURL=bar4.js\n", "bar3.js", "bar4.js");
   23645 
   23646   // Two source URLs; the first one is ignored.
   23647   SourceURLHelper("function foo() {}\n"
   23648                   "//# sourceURL=ignoreme.js\n"
   23649                   "//# sourceURL=bar5.js\n", "bar5.js", NULL);
   23650   SourceURLHelper("function foo() {}\n"
   23651                   "//# sourceMappingURL=ignoreme.js\n"
   23652                   "//# sourceMappingURL=bar6.js\n", NULL, "bar6.js");
   23653 
   23654   // SourceURL or sourceMappingURL in the middle of the script.
   23655   SourceURLHelper("function foo() {}\n"
   23656                   "//# sourceURL=bar7.js\n"
   23657                   "function baz() {}\n", "bar7.js", NULL);
   23658   SourceURLHelper("function foo() {}\n"
   23659                   "//# sourceMappingURL=bar8.js\n"
   23660                   "function baz() {}\n", NULL, "bar8.js");
   23661 
   23662   // Too much whitespace.
   23663   SourceURLHelper("function foo() {}\n"
   23664                   "//#  sourceURL=bar9.js\n"
   23665                   "//#  sourceMappingURL=bar10.js\n", NULL, NULL);
   23666   SourceURLHelper("function foo() {}\n"
   23667                   "//# sourceURL =bar11.js\n"
   23668                   "//# sourceMappingURL =bar12.js\n", NULL, NULL);
   23669 
   23670   // Disallowed characters in value.
   23671   SourceURLHelper("function foo() {}\n"
   23672                   "//# sourceURL=bar13 .js   \n"
   23673                   "//# sourceMappingURL=bar14 .js \n",
   23674                   NULL, NULL);
   23675   SourceURLHelper("function foo() {}\n"
   23676                   "//# sourceURL=bar15\t.js   \n"
   23677                   "//# sourceMappingURL=bar16\t.js \n",
   23678                   NULL, NULL);
   23679   SourceURLHelper("function foo() {}\n"
   23680                   "//# sourceURL=bar17'.js   \n"
   23681                   "//# sourceMappingURL=bar18'.js \n",
   23682                   NULL, NULL);
   23683   SourceURLHelper("function foo() {}\n"
   23684                   "//# sourceURL=bar19\".js   \n"
   23685                   "//# sourceMappingURL=bar20\".js \n",
   23686                   NULL, NULL);
   23687 
   23688   // Not too much whitespace.
   23689   SourceURLHelper("function foo() {}\n"
   23690                   "//# sourceURL=  bar21.js   \n"
   23691                   "//# sourceMappingURL=  bar22.js \n", "bar21.js", "bar22.js");
   23692 }
   23693 
   23694 
   23695 TEST(GetOwnPropertyDescriptor) {
   23696   LocalContext env;
   23697   v8::Isolate* isolate = env->GetIsolate();
   23698   v8::HandleScope scope(isolate);
   23699   CompileRun(
   23700     "var x = { value : 13};"
   23701     "Object.defineProperty(x, 'p0', {value : 12});"
   23702     "Object.defineProperty(x, 'p1', {"
   23703     "  set : function(value) { this.value = value; },"
   23704     "  get : function() { return this.value; },"
   23705     "});");
   23706   Local<Object> x = Local<Object>::Cast(
   23707       env->Global()->Get(env.local(), v8_str("x")).ToLocalChecked());
   23708   Local<Value> desc =
   23709       x->GetOwnPropertyDescriptor(env.local(), v8_str("no_prop"))
   23710           .ToLocalChecked();
   23711   CHECK(desc->IsUndefined());
   23712   desc =
   23713       x->GetOwnPropertyDescriptor(env.local(), v8_str("p0")).ToLocalChecked();
   23714   CHECK(v8_num(12)
   23715             ->Equals(env.local(), Local<Object>::Cast(desc)
   23716                                       ->Get(env.local(), v8_str("value"))
   23717                                       .ToLocalChecked())
   23718             .FromJust());
   23719   desc =
   23720       x->GetOwnPropertyDescriptor(env.local(), v8_str("p1")).ToLocalChecked();
   23721   Local<Function> set =
   23722       Local<Function>::Cast(Local<Object>::Cast(desc)
   23723                                 ->Get(env.local(), v8_str("set"))
   23724                                 .ToLocalChecked());
   23725   Local<Function> get =
   23726       Local<Function>::Cast(Local<Object>::Cast(desc)
   23727                                 ->Get(env.local(), v8_str("get"))
   23728                                 .ToLocalChecked());
   23729   CHECK(v8_num(13)
   23730             ->Equals(env.local(),
   23731                      get->Call(env.local(), x, 0, NULL).ToLocalChecked())
   23732             .FromJust());
   23733   Local<Value> args[] = {v8_num(14)};
   23734   set->Call(env.local(), x, 1, args).ToLocalChecked();
   23735   CHECK(v8_num(14)
   23736             ->Equals(env.local(),
   23737                      get->Call(env.local(), x, 0, NULL).ToLocalChecked())
   23738             .FromJust());
   23739 }
   23740 
   23741 
   23742 TEST(Regress411877) {
   23743   v8::Isolate* isolate = CcTest::isolate();
   23744   v8::HandleScope handle_scope(isolate);
   23745   v8::Local<v8::ObjectTemplate> object_template =
   23746       v8::ObjectTemplate::New(isolate);
   23747   object_template->SetAccessCheckCallback(AccessCounter);
   23748 
   23749   v8::Local<Context> context = Context::New(isolate);
   23750   v8::Context::Scope context_scope(context);
   23751 
   23752   CHECK(context->Global()
   23753             ->Set(context, v8_str("o"),
   23754                   object_template->NewInstance(context).ToLocalChecked())
   23755             .FromJust());
   23756   CompileRun("Object.getOwnPropertyNames(o)");
   23757 }
   23758 
   23759 
   23760 TEST(GetHiddenPropertyTableAfterAccessCheck) {
   23761   v8::Isolate* isolate = CcTest::isolate();
   23762   v8::HandleScope handle_scope(isolate);
   23763   v8::Local<v8::ObjectTemplate> object_template =
   23764       v8::ObjectTemplate::New(isolate);
   23765   object_template->SetAccessCheckCallback(AccessCounter);
   23766 
   23767   v8::Local<Context> context = Context::New(isolate);
   23768   v8::Context::Scope context_scope(context);
   23769 
   23770   v8::Local<v8::Object> obj =
   23771       object_template->NewInstance(context).ToLocalChecked();
   23772   obj->Set(context, v8_str("key"), v8_str("value")).FromJust();
   23773   obj->Delete(context, v8_str("key")).FromJust();
   23774 
   23775   obj->SetPrivate(context, v8::Private::New(isolate, v8_str("hidden key 2")),
   23776                   v8_str("hidden value 2"))
   23777       .FromJust();
   23778 }
   23779 
   23780 
   23781 TEST(Regress411793) {
   23782   v8::Isolate* isolate = CcTest::isolate();
   23783   v8::HandleScope handle_scope(isolate);
   23784   v8::Local<v8::ObjectTemplate> object_template =
   23785       v8::ObjectTemplate::New(isolate);
   23786   object_template->SetAccessCheckCallback(AccessCounter);
   23787 
   23788   v8::Local<Context> context = Context::New(isolate);
   23789   v8::Context::Scope context_scope(context);
   23790 
   23791   CHECK(context->Global()
   23792             ->Set(context, v8_str("o"),
   23793                   object_template->NewInstance(context).ToLocalChecked())
   23794             .FromJust());
   23795   CompileRun(
   23796       "Object.defineProperty(o, 'key', "
   23797       "    { get: function() {}, set: function() {} });");
   23798 }
   23799 
   23800 class TestSourceStream : public v8::ScriptCompiler::ExternalSourceStream {
   23801  public:
   23802   explicit TestSourceStream(const char** chunks) : chunks_(chunks), index_(0) {}
   23803 
   23804   virtual size_t GetMoreData(const uint8_t** src) {
   23805     // Unlike in real use cases, this function will never block.
   23806     if (chunks_[index_] == NULL) {
   23807       return 0;
   23808     }
   23809     // Copy the data, since the caller takes ownership of it.
   23810     size_t len = strlen(chunks_[index_]);
   23811     // We don't need to zero-terminate since we return the length.
   23812     uint8_t* copy = new uint8_t[len];
   23813     memcpy(copy, chunks_[index_], len);
   23814     *src = copy;
   23815     ++index_;
   23816     return len;
   23817   }
   23818 
   23819   // Helper for constructing a string from chunks (the compilation needs it
   23820   // too).
   23821   static char* FullSourceString(const char** chunks) {
   23822     size_t total_len = 0;
   23823     for (size_t i = 0; chunks[i] != NULL; ++i) {
   23824       total_len += strlen(chunks[i]);
   23825     }
   23826     char* full_string = new char[total_len + 1];
   23827     size_t offset = 0;
   23828     for (size_t i = 0; chunks[i] != NULL; ++i) {
   23829       size_t len = strlen(chunks[i]);
   23830       memcpy(full_string + offset, chunks[i], len);
   23831       offset += len;
   23832     }
   23833     full_string[total_len] = 0;
   23834     return full_string;
   23835   }
   23836 
   23837  private:
   23838   const char** chunks_;
   23839   unsigned index_;
   23840 };
   23841 
   23842 
   23843 // Helper function for running streaming tests.
   23844 void RunStreamingTest(const char** chunks,
   23845                       v8::ScriptCompiler::StreamedSource::Encoding encoding =
   23846                           v8::ScriptCompiler::StreamedSource::ONE_BYTE,
   23847                       bool expected_success = true,
   23848                       const char* expected_source_url = NULL,
   23849                       const char* expected_source_mapping_url = NULL) {
   23850   LocalContext env;
   23851   v8::Isolate* isolate = env->GetIsolate();
   23852   v8::HandleScope scope(isolate);
   23853   v8::TryCatch try_catch(isolate);
   23854 
   23855   v8::ScriptCompiler::StreamedSource source(new TestSourceStream(chunks),
   23856                                             encoding);
   23857   v8::ScriptCompiler::ScriptStreamingTask* task =
   23858       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
   23859 
   23860   // TestSourceStream::GetMoreData won't block, so it's OK to just run the
   23861   // task here in the main thread.
   23862   task->Run();
   23863   delete task;
   23864 
   23865   // Possible errors are only produced while compiling.
   23866   CHECK_EQ(false, try_catch.HasCaught());
   23867 
   23868   v8::ScriptOrigin origin(v8_str("http://foo.com"));
   23869   char* full_source = TestSourceStream::FullSourceString(chunks);
   23870   v8::MaybeLocal<Script> script = v8::ScriptCompiler::Compile(
   23871       env.local(), &source, v8_str(full_source), origin);
   23872   if (expected_success) {
   23873     CHECK(!script.IsEmpty());
   23874     v8::Local<Value> result(
   23875         script.ToLocalChecked()->Run(env.local()).ToLocalChecked());
   23876     // All scripts are supposed to return the fixed value 13 when ran.
   23877     CHECK_EQ(13, result->Int32Value(env.local()).FromJust());
   23878     CheckMagicComments(script.ToLocalChecked(), expected_source_url,
   23879                        expected_source_mapping_url);
   23880   } else {
   23881     CHECK(script.IsEmpty());
   23882     CHECK(try_catch.HasCaught());
   23883   }
   23884   delete[] full_source;
   23885 }
   23886 
   23887 
   23888 TEST(StreamingSimpleScript) {
   23889   // This script is unrealistically small, since no one chunk is enough to fill
   23890   // the backing buffer of Scanner, let alone overflow it.
   23891   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
   23892                           NULL};
   23893   RunStreamingTest(chunks);
   23894 }
   23895 
   23896 
   23897 TEST(StreamingBiggerScript) {
   23898   const char* chunk1 =
   23899       "function foo() {\n"
   23900       "  // Make this chunk sufficiently long so that it will overflow the\n"
   23901       "  // backing buffer of the Scanner.\n"
   23902       "  var i = 0;\n"
   23903       "  var result = 0;\n"
   23904       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   23905       "  result = 0;\n"
   23906       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   23907       "  result = 0;\n"
   23908       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   23909       "  result = 0;\n"
   23910       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   23911       "  return result;\n"
   23912       "}\n";
   23913   const char* chunks[] = {chunk1, "foo(); ", NULL};
   23914   RunStreamingTest(chunks);
   23915 }
   23916 
   23917 
   23918 TEST(StreamingScriptWithParseError) {
   23919   // Test that parse errors from streamed scripts are propagated correctly.
   23920   {
   23921     char chunk1[] =
   23922         "  // This will result in a parse error.\n"
   23923         "  var if else then foo";
   23924     char chunk2[] = "  13\n";
   23925     const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
   23926 
   23927     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::ONE_BYTE,
   23928                      false);
   23929   }
   23930   // Test that the next script succeeds normally.
   23931   {
   23932     char chunk1[] =
   23933         "  // This will be parsed successfully.\n"
   23934         "  function foo() { return ";
   23935     char chunk2[] = "  13; }\n";
   23936     const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
   23937 
   23938     RunStreamingTest(chunks);
   23939   }
   23940 }
   23941 
   23942 
   23943 TEST(StreamingUtf8Script) {
   23944   // We'd want to write \uc481 instead of \xec\x92\x81, but Windows compilers
   23945   // don't like it.
   23946   const char* chunk1 =
   23947       "function foo() {\n"
   23948       "  // This function will contain an UTF-8 character which is not in\n"
   23949       "  // ASCII.\n"
   23950       "  var foob\xec\x92\x81r = 13;\n"
   23951       "  return foob\xec\x92\x81r;\n"
   23952       "}\n";
   23953   const char* chunks[] = {chunk1, "foo(); ", NULL};
   23954   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   23955 }
   23956 
   23957 
   23958 TEST(StreamingUtf8ScriptWithSplitCharactersSanityCheck) {
   23959   // A sanity check to prove that the approach of splitting UTF-8
   23960   // characters is correct. Here is an UTF-8 character which will take three
   23961   // bytes.
   23962   const char* reference = "\xec\x92\x81";
   23963   CHECK(3u == strlen(reference));  // NOLINT - no CHECK_EQ for unsigned.
   23964 
   23965   char chunk1[] =
   23966       "function foo() {\n"
   23967       "  // This function will contain an UTF-8 character which is not in\n"
   23968       "  // ASCII.\n"
   23969       "  var foob";
   23970   char chunk2[] =
   23971       "XXXr = 13;\n"
   23972       "  return foob\xec\x92\x81r;\n"
   23973       "}\n";
   23974   for (int i = 0; i < 3; ++i) {
   23975     chunk2[i] = reference[i];
   23976   }
   23977   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
   23978   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   23979 }
   23980 
   23981 
   23982 TEST(StreamingUtf8ScriptWithSplitCharacters) {
   23983   // Stream data where a multi-byte UTF-8 character is split between two data
   23984   // chunks.
   23985   const char* reference = "\xec\x92\x81";
   23986   char chunk1[] =
   23987       "function foo() {\n"
   23988       "  // This function will contain an UTF-8 character which is not in\n"
   23989       "  // ASCII.\n"
   23990       "  var foobX";
   23991   char chunk2[] =
   23992       "XXr = 13;\n"
   23993       "  return foob\xec\x92\x81r;\n"
   23994       "}\n";
   23995   chunk1[strlen(chunk1) - 1] = reference[0];
   23996   chunk2[0] = reference[1];
   23997   chunk2[1] = reference[2];
   23998   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
   23999   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   24000 }
   24001 
   24002 
   24003 TEST(StreamingUtf8ScriptWithSplitCharactersValidEdgeCases) {
   24004   // Tests edge cases which should still be decoded correctly.
   24005 
   24006   // Case 1: a chunk contains only bytes for a split character (and no other
   24007   // data). This kind of a chunk would be exceptionally small, but we should
   24008   // still decode it correctly.
   24009   const char* reference = "\xec\x92\x81";
   24010   // The small chunk is at the beginning of the split character
   24011   {
   24012     char chunk1[] =
   24013         "function foo() {\n"
   24014         "  // This function will contain an UTF-8 character which is not in\n"
   24015         "  // ASCII.\n"
   24016         "  var foob";
   24017     char chunk2[] = "XX";
   24018     char chunk3[] =
   24019         "Xr = 13;\n"
   24020         "  return foob\xec\x92\x81r;\n"
   24021         "}\n";
   24022     chunk2[0] = reference[0];
   24023     chunk2[1] = reference[1];
   24024     chunk3[0] = reference[2];
   24025     const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
   24026     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   24027   }
   24028   // The small chunk is at the end of a character
   24029   {
   24030     char chunk1[] =
   24031         "function foo() {\n"
   24032         "  // This function will contain an UTF-8 character which is not in\n"
   24033         "  // ASCII.\n"
   24034         "  var foobX";
   24035     char chunk2[] = "XX";
   24036     char chunk3[] =
   24037         "r = 13;\n"
   24038         "  return foob\xec\x92\x81r;\n"
   24039         "}\n";
   24040     chunk1[strlen(chunk1) - 1] = reference[0];
   24041     chunk2[0] = reference[1];
   24042     chunk2[1] = reference[2];
   24043     const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
   24044     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   24045   }
   24046   // Case 2: the script ends with a multi-byte character. Make sure that it's
   24047   // decoded correctly and not just ignored.
   24048   {
   24049     char chunk1[] =
   24050         "var foob\xec\x92\x81 = 13;\n"
   24051         "foob\xec\x92\x81";
   24052     const char* chunks[] = {chunk1, NULL};
   24053     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   24054   }
   24055 }
   24056 
   24057 
   24058 TEST(StreamingUtf8ScriptWithSplitCharactersInvalidEdgeCases) {
   24059   // Test cases where a UTF-8 character is split over several chunks. Those
   24060   // cases are not supported (the embedder should give the data in big enough
   24061   // chunks), but we shouldn't crash, just produce a parse error.
   24062   const char* reference = "\xec\x92\x81";
   24063   char chunk1[] =
   24064       "function foo() {\n"
   24065       "  // This function will contain an UTF-8 character which is not in\n"
   24066       "  // ASCII.\n"
   24067       "  var foobX";
   24068   char chunk2[] = "X";
   24069   char chunk3[] =
   24070       "Xr = 13;\n"
   24071       "  return foob\xec\x92\x81r;\n"
   24072       "}\n";
   24073   chunk1[strlen(chunk1) - 1] = reference[0];
   24074   chunk2[0] = reference[1];
   24075   chunk3[0] = reference[2];
   24076   const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
   24077 
   24078   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
   24079 }
   24080 
   24081 
   24082 TEST(StreamingProducesParserCache) {
   24083   i::FLAG_min_preparse_length = 0;
   24084   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
   24085                           NULL};
   24086 
   24087   LocalContext env;
   24088   v8::Isolate* isolate = env->GetIsolate();
   24089   v8::HandleScope scope(isolate);
   24090 
   24091   v8::ScriptCompiler::StreamedSource source(
   24092       new TestSourceStream(chunks),
   24093       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
   24094   v8::ScriptCompiler::ScriptStreamingTask* task =
   24095       v8::ScriptCompiler::StartStreamingScript(
   24096           isolate, &source, v8::ScriptCompiler::kProduceParserCache);
   24097 
   24098   // TestSourceStream::GetMoreData won't block, so it's OK to just run the
   24099   // task here in the main thread.
   24100   task->Run();
   24101   delete task;
   24102 
   24103   const v8::ScriptCompiler::CachedData* cached_data = source.GetCachedData();
   24104   CHECK(cached_data != NULL);
   24105   CHECK(cached_data->data != NULL);
   24106   CHECK(!cached_data->rejected);
   24107   CHECK_GT(cached_data->length, 0);
   24108 }
   24109 
   24110 
   24111 TEST(StreamingWithDebuggingEnabledLate) {
   24112   // The streaming parser can only parse lazily, i.e. inner functions are not
   24113   // fully parsed. However, we may compile inner functions eagerly when
   24114   // debugging. Make sure that we can deal with this when turning on debugging
   24115   // after streaming parser has already finished parsing.
   24116   i::FLAG_min_preparse_length = 0;
   24117   const char* chunks[] = {"with({x:1}) {",
   24118                           "  var foo = function foo(y) {",
   24119                           "    return x + y;",
   24120                           "  };",
   24121                           "  foo(2);",
   24122                           "}",
   24123                           NULL};
   24124 
   24125   LocalContext env;
   24126   v8::Isolate* isolate = env->GetIsolate();
   24127   v8::HandleScope scope(isolate);
   24128   v8::TryCatch try_catch(isolate);
   24129 
   24130   v8::ScriptCompiler::StreamedSource source(
   24131       new TestSourceStream(chunks),
   24132       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
   24133   v8::ScriptCompiler::ScriptStreamingTask* task =
   24134       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
   24135 
   24136   task->Run();
   24137   delete task;
   24138 
   24139   CHECK(!try_catch.HasCaught());
   24140 
   24141   v8::ScriptOrigin origin(v8_str("http://foo.com"));
   24142   char* full_source = TestSourceStream::FullSourceString(chunks);
   24143 
   24144   EnableDebugger(isolate);
   24145 
   24146   v8::Local<Script> script =
   24147       v8::ScriptCompiler::Compile(env.local(), &source, v8_str(full_source),
   24148                                   origin)
   24149           .ToLocalChecked();
   24150 
   24151   Maybe<uint32_t> result =
   24152       script->Run(env.local()).ToLocalChecked()->Uint32Value(env.local());
   24153   CHECK_EQ(3U, result.FromMaybe(0));
   24154 
   24155   delete[] full_source;
   24156 
   24157   DisableDebugger(isolate);
   24158 }
   24159 
   24160 
   24161 TEST(StreamingScriptWithInvalidUtf8) {
   24162   // Regression test for a crash: test that invalid UTF-8 bytes in the end of a
   24163   // chunk don't produce a crash.
   24164   const char* reference = "\xec\x92\x81\x80\x80";
   24165   char chunk1[] =
   24166       "function foo() {\n"
   24167       "  // This function will contain an UTF-8 character which is not in\n"
   24168       "  // ASCII.\n"
   24169       "  var foobXXXXX";  // Too many bytes which look like incomplete chars!
   24170   char chunk2[] =
   24171       "r = 13;\n"
   24172       "  return foob\xec\x92\x81\x80\x80r;\n"
   24173       "}\n";
   24174   for (int i = 0; i < 5; ++i) chunk1[strlen(chunk1) - 5 + i] = reference[i];
   24175 
   24176   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
   24177   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
   24178 }
   24179 
   24180 
   24181 TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit) {
   24182   // Regression test: Stream data where there are several multi-byte UTF-8
   24183   // characters in a sequence and one of them is split between two data chunks.
   24184   const char* reference = "\xec\x92\x81";
   24185   char chunk1[] =
   24186       "function foo() {\n"
   24187       "  // This function will contain an UTF-8 character which is not in\n"
   24188       "  // ASCII.\n"
   24189       "  var foob\xec\x92\x81X";
   24190   char chunk2[] =
   24191       "XXr = 13;\n"
   24192       "  return foob\xec\x92\x81\xec\x92\x81r;\n"
   24193       "}\n";
   24194   chunk1[strlen(chunk1) - 1] = reference[0];
   24195   chunk2[0] = reference[1];
   24196   chunk2[1] = reference[2];
   24197   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
   24198   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   24199 }
   24200 
   24201 
   24202 TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit2) {
   24203   // Another regression test, similar to the previous one. The difference is
   24204   // that the split character is not the last one in the sequence.
   24205   const char* reference = "\xec\x92\x81";
   24206   char chunk1[] =
   24207       "function foo() {\n"
   24208       "  // This function will contain an UTF-8 character which is not in\n"
   24209       "  // ASCII.\n"
   24210       "  var foobX";
   24211   char chunk2[] =
   24212       "XX\xec\x92\x81r = 13;\n"
   24213       "  return foob\xec\x92\x81\xec\x92\x81r;\n"
   24214       "}\n";
   24215   chunk1[strlen(chunk1) - 1] = reference[0];
   24216   chunk2[0] = reference[1];
   24217   chunk2[1] = reference[2];
   24218   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
   24219   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   24220 }
   24221 
   24222 
   24223 TEST(StreamingWithHarmonyScopes) {
   24224   // Don't use RunStreamingTest here so that both scripts get to use the same
   24225   // LocalContext and HandleScope.
   24226   LocalContext env;
   24227   v8::Isolate* isolate = env->GetIsolate();
   24228   v8::HandleScope scope(isolate);
   24229 
   24230   // First, run a script with a let variable.
   24231   CompileRun("\"use strict\"; let x = 1;");
   24232 
   24233   // Then stream a script which (erroneously) tries to introduce the same
   24234   // variable again.
   24235   const char* chunks[] = {"\"use strict\"; let x = 2;", NULL};
   24236 
   24237   v8::TryCatch try_catch(isolate);
   24238   v8::ScriptCompiler::StreamedSource source(
   24239       new TestSourceStream(chunks),
   24240       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
   24241   v8::ScriptCompiler::ScriptStreamingTask* task =
   24242       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
   24243   task->Run();
   24244   delete task;
   24245 
   24246   // Parsing should succeed (the script will be parsed and compiled in a context
   24247   // independent way, so the error is not detected).
   24248   CHECK_EQ(false, try_catch.HasCaught());
   24249 
   24250   v8::ScriptOrigin origin(v8_str("http://foo.com"));
   24251   char* full_source = TestSourceStream::FullSourceString(chunks);
   24252   v8::Local<Script> script =
   24253       v8::ScriptCompiler::Compile(env.local(), &source, v8_str(full_source),
   24254                                   origin)
   24255           .ToLocalChecked();
   24256   CHECK(!script.IsEmpty());
   24257   CHECK_EQ(false, try_catch.HasCaught());
   24258 
   24259   // Running the script exposes the error.
   24260   CHECK(script->Run(env.local()).IsEmpty());
   24261   CHECK(try_catch.HasCaught());
   24262   delete[] full_source;
   24263 }
   24264 
   24265 
   24266 TEST(CodeCache) {
   24267   v8::Isolate::CreateParams create_params;
   24268   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   24269 
   24270   const char* source = "Math.sqrt(4)";
   24271   const char* origin = "code cache test";
   24272   v8::ScriptCompiler::CachedData* cache;
   24273 
   24274   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
   24275   {
   24276     v8::Isolate::Scope iscope(isolate1);
   24277     v8::HandleScope scope(isolate1);
   24278     v8::Local<v8::Context> context = v8::Context::New(isolate1);
   24279     v8::Context::Scope cscope(context);
   24280     v8::Local<v8::String> source_string = v8_str(source);
   24281     v8::ScriptOrigin script_origin(v8_str(origin));
   24282     v8::ScriptCompiler::Source source(source_string, script_origin);
   24283     v8::ScriptCompiler::CompileOptions option =
   24284         v8::ScriptCompiler::kProduceCodeCache;
   24285     v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
   24286     int length = source.GetCachedData()->length;
   24287     uint8_t* cache_data = new uint8_t[length];
   24288     memcpy(cache_data, source.GetCachedData()->data, length);
   24289     cache = new v8::ScriptCompiler::CachedData(
   24290         cache_data, length, v8::ScriptCompiler::CachedData::BufferOwned);
   24291   }
   24292   isolate1->Dispose();
   24293 
   24294   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
   24295   {
   24296     v8::Isolate::Scope iscope(isolate2);
   24297     v8::HandleScope scope(isolate2);
   24298     v8::Local<v8::Context> context = v8::Context::New(isolate2);
   24299     v8::Context::Scope cscope(context);
   24300     v8::Local<v8::String> source_string = v8_str(source);
   24301     v8::ScriptOrigin script_origin(v8_str(origin));
   24302     v8::ScriptCompiler::Source source(source_string, script_origin, cache);
   24303     v8::ScriptCompiler::CompileOptions option =
   24304         v8::ScriptCompiler::kConsumeCodeCache;
   24305     v8::Local<v8::Script> script;
   24306     {
   24307       i::DisallowCompilation no_compile(
   24308           reinterpret_cast<i::Isolate*>(isolate2));
   24309       script = v8::ScriptCompiler::Compile(context, &source, option)
   24310                    .ToLocalChecked();
   24311     }
   24312     CHECK_EQ(2, script->Run(context)
   24313                     .ToLocalChecked()
   24314                     ->ToInt32(context)
   24315                     .ToLocalChecked()
   24316                     ->Int32Value(context)
   24317                     .FromJust());
   24318   }
   24319   isolate2->Dispose();
   24320 }
   24321 
   24322 
   24323 void TestInvalidCacheData(v8::ScriptCompiler::CompileOptions option) {
   24324   const char* garbage = "garbage garbage garbage garbage garbage garbage";
   24325   const uint8_t* data = reinterpret_cast<const uint8_t*>(garbage);
   24326   int length = 16;
   24327   v8::ScriptCompiler::CachedData* cached_data =
   24328       new v8::ScriptCompiler::CachedData(data, length);
   24329   CHECK(!cached_data->rejected);
   24330   v8::ScriptOrigin origin(v8_str("origin"));
   24331   v8::ScriptCompiler::Source source(v8_str("42"), origin, cached_data);
   24332   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   24333   v8::Local<v8::Script> script =
   24334       v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
   24335   CHECK(cached_data->rejected);
   24336   CHECK_EQ(
   24337       42,
   24338       script->Run(context).ToLocalChecked()->Int32Value(context).FromJust());
   24339 }
   24340 
   24341 TEST(InvalidParserCacheData) {
   24342   v8::V8::Initialize();
   24343   v8::HandleScope scope(CcTest::isolate());
   24344   LocalContext context;
   24345   if (i::FLAG_lazy && !(i::FLAG_ignition && i::FLAG_ignition_eager)) {
   24346     // Cached parser data is not consumed while parsing eagerly.
   24347     TestInvalidCacheData(v8::ScriptCompiler::kConsumeParserCache);
   24348   }
   24349 }
   24350 
   24351 TEST(InvalidCodeCacheData) {
   24352   v8::V8::Initialize();
   24353   v8::HandleScope scope(CcTest::isolate());
   24354   LocalContext context;
   24355   TestInvalidCacheData(v8::ScriptCompiler::kConsumeCodeCache);
   24356 }
   24357 
   24358 
   24359 TEST(ParserCacheRejectedGracefully) {
   24360   // Producing cached parser data while parsing eagerly is not supported.
   24361   if (!i::FLAG_lazy || (i::FLAG_ignition && i::FLAG_ignition_eager)) return;
   24362 
   24363   i::FLAG_min_preparse_length = 0;
   24364   v8::V8::Initialize();
   24365   v8::HandleScope scope(CcTest::isolate());
   24366   LocalContext context;
   24367   // Produce valid cached data.
   24368   v8::ScriptOrigin origin(v8_str("origin"));
   24369   v8::Local<v8::String> source_str = v8_str("function foo() {}");
   24370   v8::ScriptCompiler::Source source(source_str, origin);
   24371   v8::Local<v8::Script> script =
   24372       v8::ScriptCompiler::Compile(context.local(), &source,
   24373                                   v8::ScriptCompiler::kProduceParserCache)
   24374           .ToLocalChecked();
   24375   USE(script);
   24376   const v8::ScriptCompiler::CachedData* original_cached_data =
   24377       source.GetCachedData();
   24378   CHECK(original_cached_data != NULL);
   24379   CHECK(original_cached_data->data != NULL);
   24380   CHECK(!original_cached_data->rejected);
   24381   CHECK_GT(original_cached_data->length, 0);
   24382   // Recompiling the same script with it won't reject the data.
   24383   {
   24384     v8::ScriptCompiler::Source source_with_cached_data(
   24385         source_str, origin,
   24386         new v8::ScriptCompiler::CachedData(original_cached_data->data,
   24387                                            original_cached_data->length));
   24388     v8::Local<v8::Script> script =
   24389         v8::ScriptCompiler::Compile(context.local(), &source_with_cached_data,
   24390                                     v8::ScriptCompiler::kConsumeParserCache)
   24391             .ToLocalChecked();
   24392     USE(script);
   24393     const v8::ScriptCompiler::CachedData* new_cached_data =
   24394         source_with_cached_data.GetCachedData();
   24395     CHECK(new_cached_data != NULL);
   24396     CHECK(!new_cached_data->rejected);
   24397   }
   24398   // Compile an incompatible script with the cached data. The new script doesn't
   24399   // have the same starting position for the function as the old one, so the old
   24400   // cached data will be incompatible with it and will be rejected.
   24401   {
   24402     v8::Local<v8::String> incompatible_source_str =
   24403         v8_str("   function foo() {}");
   24404     v8::ScriptCompiler::Source source_with_cached_data(
   24405         incompatible_source_str, origin,
   24406         new v8::ScriptCompiler::CachedData(original_cached_data->data,
   24407                                            original_cached_data->length));
   24408     v8::Local<v8::Script> script =
   24409         v8::ScriptCompiler::Compile(context.local(), &source_with_cached_data,
   24410                                     v8::ScriptCompiler::kConsumeParserCache)
   24411             .ToLocalChecked();
   24412     USE(script);
   24413     const v8::ScriptCompiler::CachedData* new_cached_data =
   24414         source_with_cached_data.GetCachedData();
   24415     CHECK(new_cached_data != NULL);
   24416     CHECK(new_cached_data->rejected);
   24417   }
   24418 }
   24419 
   24420 
   24421 TEST(StringConcatOverflow) {
   24422   v8::V8::Initialize();
   24423   v8::HandleScope scope(CcTest::isolate());
   24424   RandomLengthOneByteResource* r =
   24425       new RandomLengthOneByteResource(i::String::kMaxLength);
   24426   v8::Local<v8::String> str =
   24427       v8::String::NewExternalOneByte(CcTest::isolate(), r).ToLocalChecked();
   24428   CHECK(!str.IsEmpty());
   24429   v8::TryCatch try_catch(CcTest::isolate());
   24430   v8::Local<v8::String> result = v8::String::Concat(str, str);
   24431   CHECK(result.IsEmpty());
   24432   CHECK(!try_catch.HasCaught());
   24433 }
   24434 
   24435 
   24436 TEST(TurboAsmDisablesNeuter) {
   24437   i::FLAG_allow_natives_syntax = true;
   24438   v8::V8::Initialize();
   24439   v8::HandleScope scope(CcTest::isolate());
   24440   LocalContext context;
   24441   bool should_be_neuterable = !i::FLAG_turbo_asm;
   24442   const char* load =
   24443       "function Module(stdlib, foreign, heap) {"
   24444       "  'use asm';"
   24445       "  var MEM32 = new stdlib.Int32Array(heap);"
   24446       "  function load() { return MEM32[0]; }"
   24447       "  return { load: load };"
   24448       "}"
   24449       "var buffer = new ArrayBuffer(4);"
   24450       "var module = Module(this, {}, buffer);"
   24451       "%OptimizeFunctionOnNextCall(module.load);"
   24452       "module.load();"
   24453       "buffer";
   24454 
   24455   v8::Local<v8::ArrayBuffer> result = CompileRun(load).As<v8::ArrayBuffer>();
   24456   CHECK_EQ(should_be_neuterable, result->IsNeuterable());
   24457 
   24458   const char* store =
   24459       "function Module(stdlib, foreign, heap) {"
   24460       "  'use asm';"
   24461       "  var MEM32 = new stdlib.Int32Array(heap);"
   24462       "  function store() { MEM32[0] = 0; }"
   24463       "  return { store: store };"
   24464       "}"
   24465       "var buffer = new ArrayBuffer(4);"
   24466       "var module = Module(this, {}, buffer);"
   24467       "%OptimizeFunctionOnNextCall(module.store);"
   24468       "module.store();"
   24469       "buffer";
   24470 
   24471   result = CompileRun(store).As<v8::ArrayBuffer>();
   24472   CHECK_EQ(should_be_neuterable, result->IsNeuterable());
   24473 }
   24474 
   24475 
   24476 TEST(GetPrototypeAccessControl) {
   24477   i::FLAG_allow_natives_syntax = true;
   24478   v8::Isolate* isolate = CcTest::isolate();
   24479   v8::HandleScope handle_scope(isolate);
   24480   LocalContext env;
   24481 
   24482   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   24483   obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   24484 
   24485   CHECK(env->Global()
   24486             ->Set(env.local(), v8_str("prohibited"),
   24487                   obj_template->NewInstance(env.local()).ToLocalChecked())
   24488             .FromJust());
   24489 
   24490   CHECK(CompileRun(
   24491             "function f() { return %_GetPrototype(prohibited); }"
   24492             "%OptimizeFunctionOnNextCall(f);"
   24493             "f();")->IsNull());
   24494 }
   24495 
   24496 
   24497 TEST(GetPrototypeHidden) {
   24498   i::FLAG_allow_natives_syntax = true;
   24499   v8::Isolate* isolate = CcTest::isolate();
   24500   v8::HandleScope handle_scope(isolate);
   24501   LocalContext env;
   24502 
   24503   Local<FunctionTemplate> t = FunctionTemplate::New(isolate);
   24504   t->SetHiddenPrototype(true);
   24505   Local<Object> proto = t->GetFunction(env.local())
   24506                             .ToLocalChecked()
   24507                             ->NewInstance(env.local())
   24508                             .ToLocalChecked();
   24509   Local<Object> object = Object::New(isolate);
   24510   Local<Object> proto2 = Object::New(isolate);
   24511   object->SetPrototype(env.local(), proto).FromJust();
   24512   proto->SetPrototype(env.local(), proto2).FromJust();
   24513 
   24514   CHECK(env->Global()->Set(env.local(), v8_str("object"), object).FromJust());
   24515   CHECK(env->Global()->Set(env.local(), v8_str("proto"), proto).FromJust());
   24516   CHECK(env->Global()->Set(env.local(), v8_str("proto2"), proto2).FromJust());
   24517 
   24518   v8::Local<v8::Value> result = CompileRun("%_GetPrototype(object)");
   24519   CHECK(result->Equals(env.local(), proto2).FromJust());
   24520 
   24521   result = CompileRun(
   24522       "function f() { return %_GetPrototype(object); }"
   24523       "%OptimizeFunctionOnNextCall(f);"
   24524       "f()");
   24525   CHECK(result->Equals(env.local(), proto2).FromJust());
   24526 }
   24527 
   24528 
   24529 TEST(ClassPrototypeCreationContext) {
   24530   v8::Isolate* isolate = CcTest::isolate();
   24531   v8::HandleScope handle_scope(isolate);
   24532   LocalContext env;
   24533 
   24534   Local<Object> result = Local<Object>::Cast(
   24535       CompileRun("'use strict'; class Example { }; Example.prototype"));
   24536   CHECK(env.local() == result->CreationContext());
   24537 }
   24538 
   24539 
   24540 TEST(SimpleStreamingScriptWithSourceURL) {
   24541   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo();\n",
   24542                           "//# sourceURL=bar2.js\n", NULL};
   24543   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
   24544                    "bar2.js");
   24545 }
   24546 
   24547 
   24548 TEST(StreamingScriptWithSplitSourceURL) {
   24549   const char* chunks[] = {"function foo() { ret", "urn 13; } f",
   24550                           "oo();\n//# sourceURL=b", "ar2.js\n", NULL};
   24551   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
   24552                    "bar2.js");
   24553 }
   24554 
   24555 
   24556 TEST(StreamingScriptWithSourceMappingURLInTheMiddle) {
   24557   const char* chunks[] = {"function foo() { ret", "urn 13; }\n//#",
   24558                           " sourceMappingURL=bar2.js\n", "foo();", NULL};
   24559   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true, NULL,
   24560                    "bar2.js");
   24561 }
   24562 
   24563 
   24564 TEST(NewStringRangeError) {
   24565   v8::Isolate* isolate = CcTest::isolate();
   24566   v8::HandleScope handle_scope(isolate);
   24567   const int length = i::String::kMaxLength + 1;
   24568   const int buffer_size = length * sizeof(uint16_t);
   24569   void* buffer = malloc(buffer_size);
   24570   if (buffer == NULL) return;
   24571   memset(buffer, 'A', buffer_size);
   24572   {
   24573     v8::TryCatch try_catch(isolate);
   24574     char* data = reinterpret_cast<char*>(buffer);
   24575     CHECK(v8::String::NewFromUtf8(isolate, data, v8::NewStringType::kNormal,
   24576                                   length)
   24577               .IsEmpty());
   24578     CHECK(!try_catch.HasCaught());
   24579   }
   24580   {
   24581     v8::TryCatch try_catch(isolate);
   24582     uint8_t* data = reinterpret_cast<uint8_t*>(buffer);
   24583     CHECK(v8::String::NewFromOneByte(isolate, data, v8::NewStringType::kNormal,
   24584                                      length)
   24585               .IsEmpty());
   24586     CHECK(!try_catch.HasCaught());
   24587   }
   24588   {
   24589     v8::TryCatch try_catch(isolate);
   24590     uint16_t* data = reinterpret_cast<uint16_t*>(buffer);
   24591     CHECK(v8::String::NewFromTwoByte(isolate, data, v8::NewStringType::kNormal,
   24592                                      length)
   24593               .IsEmpty());
   24594     CHECK(!try_catch.HasCaught());
   24595   }
   24596   free(buffer);
   24597 }
   24598 
   24599 
   24600 TEST(SealHandleScope) {
   24601   v8::Isolate* isolate = CcTest::isolate();
   24602   v8::HandleScope handle_scope(isolate);
   24603   LocalContext env;
   24604 
   24605   v8::SealHandleScope seal(isolate);
   24606 
   24607   // Should fail
   24608   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   24609 
   24610   USE(obj);
   24611 }
   24612 
   24613 
   24614 TEST(SealHandleScopeNested) {
   24615   v8::Isolate* isolate = CcTest::isolate();
   24616   v8::HandleScope handle_scope(isolate);
   24617   LocalContext env;
   24618 
   24619   v8::SealHandleScope seal(isolate);
   24620 
   24621   {
   24622     v8::HandleScope handle_scope(isolate);
   24623 
   24624     // Should work
   24625     v8::Local<v8::Object> obj = v8::Object::New(isolate);
   24626 
   24627     USE(obj);
   24628   }
   24629 }
   24630 
   24631 
   24632 static void ExtrasBindingTestRuntimeFunction(
   24633     const v8::FunctionCallbackInfo<v8::Value>& args) {
   24634   CHECK_EQ(
   24635       3,
   24636       args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust());
   24637   args.GetReturnValue().Set(v8_num(7));
   24638 }
   24639 
   24640 TEST(ExtrasFunctionSource) {
   24641   v8::Isolate* isolate = CcTest::isolate();
   24642   v8::HandleScope handle_scope(isolate);
   24643   LocalContext env;
   24644 
   24645   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   24646 
   24647   // Functions defined in extras do not expose source code.
   24648   auto func = binding->Get(env.local(), v8_str("testFunctionToString"))
   24649                   .ToLocalChecked()
   24650                   .As<v8::Function>();
   24651   auto undefined = v8::Undefined(isolate);
   24652   auto result = func->Call(env.local(), undefined, 0, {})
   24653                     .ToLocalChecked()
   24654                     .As<v8::String>();
   24655   CHECK(result->StrictEquals(v8_str("function foo() { [native code] }")));
   24656 
   24657   // Functions defined in extras do not show up in the stack trace.
   24658   auto wrapper = binding->Get(env.local(), v8_str("testStackTrace"))
   24659                      .ToLocalChecked()
   24660                      .As<v8::Function>();
   24661   CHECK(env->Global()->Set(env.local(), v8_str("wrapper"), wrapper).FromJust());
   24662   ExpectString(
   24663       "function f(x) { return wrapper(x) }"
   24664       "function g() { return new Error().stack; }"
   24665       "f(g)",
   24666       "Error\n"
   24667       "    at g (<anonymous>:1:58)\n"
   24668       "    at f (<anonymous>:1:24)\n"
   24669       "    at <anonymous>:1:78");
   24670 }
   24671 
   24672 TEST(ExtrasBindingObject) {
   24673   v8::Isolate* isolate = CcTest::isolate();
   24674   v8::HandleScope handle_scope(isolate);
   24675   LocalContext env;
   24676 
   24677   // standalone.gypi ensures we include the test-extra.js file, which should
   24678   // export the tested functions.
   24679   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   24680 
   24681   auto func = binding->Get(env.local(), v8_str("testExtraShouldReturnFive"))
   24682                   .ToLocalChecked()
   24683                   .As<v8::Function>();
   24684   auto undefined = v8::Undefined(isolate);
   24685   auto result = func->Call(env.local(), undefined, 0, {})
   24686                     .ToLocalChecked()
   24687                     .As<v8::Number>();
   24688   CHECK_EQ(5, result->Int32Value(env.local()).FromJust());
   24689 
   24690   v8::Local<v8::FunctionTemplate> runtimeFunction =
   24691       v8::FunctionTemplate::New(isolate, ExtrasBindingTestRuntimeFunction);
   24692   binding->Set(env.local(), v8_str("runtime"),
   24693                runtimeFunction->GetFunction(env.local()).ToLocalChecked())
   24694       .FromJust();
   24695   func = binding->Get(env.local(), v8_str("testExtraShouldCallToRuntime"))
   24696              .ToLocalChecked()
   24697              .As<v8::Function>();
   24698   result = func->Call(env.local(), undefined, 0, {})
   24699                .ToLocalChecked()
   24700                .As<v8::Number>();
   24701   CHECK_EQ(7, result->Int32Value(env.local()).FromJust());
   24702 }
   24703 
   24704 
   24705 TEST(ExperimentalExtras) {
   24706   i::FLAG_experimental_extras = true;
   24707 
   24708   v8::Isolate* isolate = CcTest::isolate();
   24709   v8::HandleScope handle_scope(isolate);
   24710   LocalContext env;
   24711 
   24712   // standalone.gypi ensures we include the test-experimental-extra.js file,
   24713   // which should export the tested functions.
   24714   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   24715 
   24716   auto func =
   24717       binding->Get(env.local(), v8_str("testExperimentalExtraShouldReturnTen"))
   24718           .ToLocalChecked()
   24719           .As<v8::Function>();
   24720   auto undefined = v8::Undefined(isolate);
   24721   auto result = func->Call(env.local(), undefined, 0, {})
   24722                     .ToLocalChecked()
   24723                     .As<v8::Number>();
   24724   CHECK_EQ(10, result->Int32Value(env.local()).FromJust());
   24725 
   24726   v8::Local<v8::FunctionTemplate> runtimeFunction =
   24727       v8::FunctionTemplate::New(isolate, ExtrasBindingTestRuntimeFunction);
   24728   binding->Set(env.local(), v8_str("runtime"),
   24729                runtimeFunction->GetFunction(env.local()).ToLocalChecked())
   24730       .FromJust();
   24731   func = binding->Get(env.local(),
   24732                       v8_str("testExperimentalExtraShouldCallToRuntime"))
   24733              .ToLocalChecked()
   24734              .As<v8::Function>();
   24735   result = func->Call(env.local(), undefined, 0, {})
   24736                .ToLocalChecked()
   24737                .As<v8::Number>();
   24738   CHECK_EQ(7, result->Int32Value(env.local()).FromJust());
   24739 }
   24740 
   24741 
   24742 TEST(ExtrasUtilsObject) {
   24743   LocalContext context;
   24744   v8::Isolate* isolate = context->GetIsolate();
   24745   v8::HandleScope handle_scope(isolate);
   24746 
   24747   LocalContext env;
   24748   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   24749 
   24750   auto func = binding->Get(env.local(), v8_str("testExtraCanUseUtils"))
   24751                   .ToLocalChecked()
   24752                   .As<v8::Function>();
   24753   auto undefined = v8::Undefined(isolate);
   24754   auto result = func->Call(env.local(), undefined, 0, {})
   24755                     .ToLocalChecked()
   24756                     .As<v8::Object>();
   24757 
   24758   auto private_symbol = result->Get(env.local(), v8_str("privateSymbol"))
   24759                             .ToLocalChecked()
   24760                             .As<v8::Symbol>();
   24761   i::Handle<i::Symbol> ips = v8::Utils::OpenHandle(*private_symbol);
   24762   CHECK_EQ(true, ips->IsPrivate());
   24763 
   24764   CompileRun("var result = 0; function store(x) { result = x; }");
   24765   auto store = CompileRun("store").As<v8::Function>();
   24766 
   24767   auto fulfilled_promise = result->Get(env.local(), v8_str("fulfilledPromise"))
   24768                                .ToLocalChecked()
   24769                                .As<v8::Promise>();
   24770   fulfilled_promise->Then(env.local(), store).ToLocalChecked();
   24771   isolate->RunMicrotasks();
   24772   CHECK_EQ(1, CompileRun("result")->Int32Value(env.local()).FromJust());
   24773 
   24774   auto fulfilled_promise_2 =
   24775       result->Get(env.local(), v8_str("fulfilledPromise2"))
   24776           .ToLocalChecked()
   24777           .As<v8::Promise>();
   24778   fulfilled_promise_2->Then(env.local(), store).ToLocalChecked();
   24779   isolate->RunMicrotasks();
   24780   CHECK_EQ(2, CompileRun("result")->Int32Value(env.local()).FromJust());
   24781 
   24782   auto rejected_promise = result->Get(env.local(), v8_str("rejectedPromise"))
   24783                               .ToLocalChecked()
   24784                               .As<v8::Promise>();
   24785   rejected_promise->Catch(env.local(), store).ToLocalChecked();
   24786   isolate->RunMicrotasks();
   24787   CHECK_EQ(3, CompileRun("result")->Int32Value(env.local()).FromJust());
   24788 }
   24789 
   24790 
   24791 TEST(Map) {
   24792   v8::Isolate* isolate = CcTest::isolate();
   24793   v8::HandleScope handle_scope(isolate);
   24794   LocalContext env;
   24795 
   24796   v8::Local<v8::Map> map = v8::Map::New(isolate);
   24797   CHECK(map->IsObject());
   24798   CHECK(map->IsMap());
   24799   CHECK(map->GetPrototype()->StrictEquals(CompileRun("Map.prototype")));
   24800   CHECK_EQ(0U, map->Size());
   24801 
   24802   v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4]])");
   24803   CHECK(val->IsMap());
   24804   map = v8::Local<v8::Map>::Cast(val);
   24805   CHECK_EQ(2U, map->Size());
   24806 
   24807   v8::Local<v8::Array> contents = map->AsArray();
   24808   CHECK_EQ(4U, contents->Length());
   24809   CHECK_EQ(
   24810       1,
   24811       contents->Get(env.local(), 0).ToLocalChecked().As<v8::Int32>()->Value());
   24812   CHECK_EQ(
   24813       2,
   24814       contents->Get(env.local(), 1).ToLocalChecked().As<v8::Int32>()->Value());
   24815   CHECK_EQ(
   24816       3,
   24817       contents->Get(env.local(), 2).ToLocalChecked().As<v8::Int32>()->Value());
   24818   CHECK_EQ(
   24819       4,
   24820       contents->Get(env.local(), 3).ToLocalChecked().As<v8::Int32>()->Value());
   24821 
   24822   CHECK_EQ(2U, map->Size());
   24823 
   24824   CHECK(map->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
   24825   CHECK(map->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
   24826 
   24827   CHECK(!map->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
   24828   CHECK(!map->Has(env.local(), map).FromJust());
   24829 
   24830   CHECK_EQ(2, map->Get(env.local(), v8::Integer::New(isolate, 1))
   24831                   .ToLocalChecked()
   24832                   ->Int32Value(env.local())
   24833                   .FromJust());
   24834   CHECK_EQ(4, map->Get(env.local(), v8::Integer::New(isolate, 3))
   24835                   .ToLocalChecked()
   24836                   ->Int32Value(env.local())
   24837                   .FromJust());
   24838 
   24839   CHECK(map->Get(env.local(), v8::Integer::New(isolate, 42))
   24840             .ToLocalChecked()
   24841             ->IsUndefined());
   24842 
   24843   CHECK(!map->Set(env.local(), map, map).IsEmpty());
   24844   CHECK_EQ(3U, map->Size());
   24845   CHECK(map->Has(env.local(), map).FromJust());
   24846 
   24847   CHECK(map->Delete(env.local(), map).FromJust());
   24848   CHECK_EQ(2U, map->Size());
   24849   CHECK(!map->Has(env.local(), map).FromJust());
   24850   CHECK(!map->Delete(env.local(), map).FromJust());
   24851 
   24852   map->Clear();
   24853   CHECK_EQ(0U, map->Size());
   24854 }
   24855 
   24856 
   24857 TEST(Set) {
   24858   v8::Isolate* isolate = CcTest::isolate();
   24859   v8::HandleScope handle_scope(isolate);
   24860   LocalContext env;
   24861 
   24862   v8::Local<v8::Set> set = v8::Set::New(isolate);
   24863   CHECK(set->IsObject());
   24864   CHECK(set->IsSet());
   24865   CHECK(set->GetPrototype()->StrictEquals(CompileRun("Set.prototype")));
   24866   CHECK_EQ(0U, set->Size());
   24867 
   24868   v8::Local<v8::Value> val = CompileRun("new Set([1, 2])");
   24869   CHECK(val->IsSet());
   24870   set = v8::Local<v8::Set>::Cast(val);
   24871   CHECK_EQ(2U, set->Size());
   24872 
   24873   v8::Local<v8::Array> keys = set->AsArray();
   24874   CHECK_EQ(2U, keys->Length());
   24875   CHECK_EQ(1,
   24876            keys->Get(env.local(), 0).ToLocalChecked().As<v8::Int32>()->Value());
   24877   CHECK_EQ(2,
   24878            keys->Get(env.local(), 1).ToLocalChecked().As<v8::Int32>()->Value());
   24879 
   24880   CHECK_EQ(2U, set->Size());
   24881 
   24882   CHECK(set->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
   24883   CHECK(set->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
   24884 
   24885   CHECK(!set->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
   24886   CHECK(!set->Has(env.local(), set).FromJust());
   24887 
   24888   CHECK(!set->Add(env.local(), set).IsEmpty());
   24889   CHECK_EQ(3U, set->Size());
   24890   CHECK(set->Has(env.local(), set).FromJust());
   24891 
   24892   CHECK(set->Delete(env.local(), set).FromJust());
   24893   CHECK_EQ(2U, set->Size());
   24894   CHECK(!set->Has(env.local(), set).FromJust());
   24895   CHECK(!set->Delete(env.local(), set).FromJust());
   24896 
   24897   set->Clear();
   24898   CHECK_EQ(0U, set->Size());
   24899 }
   24900 
   24901 TEST(SetDeleteThenAsArray) {
   24902   // https://bugs.chromium.org/p/v8/issues/detail?id=4946
   24903   v8::Isolate* isolate = CcTest::isolate();
   24904   v8::HandleScope handle_scope(isolate);
   24905   LocalContext env;
   24906 
   24907   // make a Set
   24908   v8::Local<v8::Value> val = CompileRun("new Set([1, 2, 3])");
   24909   v8::Local<v8::Set> set = v8::Local<v8::Set>::Cast(val);
   24910   CHECK_EQ(3U, set->Size());
   24911 
   24912   // delete the "middle" element (using AsArray to
   24913   // determine which element is the "middle" element)
   24914   v8::Local<v8::Array> array1 = set->AsArray();
   24915   CHECK_EQ(3U, array1->Length());
   24916   CHECK(set->Delete(env.local(), array1->Get(env.local(), 1).ToLocalChecked())
   24917             .FromJust());
   24918 
   24919   // make sure there are no undefined values when we convert to an array again.
   24920   v8::Local<v8::Array> array2 = set->AsArray();
   24921   uint32_t length = array2->Length();
   24922   CHECK_EQ(2U, length);
   24923   for (uint32_t i = 0; i < length; i++) {
   24924     CHECK(!array2->Get(env.local(), i).ToLocalChecked()->IsUndefined());
   24925   }
   24926 }
   24927 
   24928 TEST(MapDeleteThenAsArray) {
   24929   // https://bugs.chromium.org/p/v8/issues/detail?id=4946
   24930   v8::Isolate* isolate = CcTest::isolate();
   24931   v8::HandleScope handle_scope(isolate);
   24932   LocalContext env;
   24933 
   24934   // make a Map
   24935   v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4], [5, 6]])");
   24936   v8::Local<v8::Map> map = v8::Local<v8::Map>::Cast(val);
   24937   CHECK_EQ(3U, map->Size());
   24938 
   24939   // delete the "middle" element (using AsArray to
   24940   // determine which element is the "middle" element)
   24941   v8::Local<v8::Array> array1 = map->AsArray();
   24942   CHECK_EQ(6U, array1->Length());
   24943   // Map::AsArray returns a flat array, so the second key is at index 2.
   24944   v8::Local<v8::Value> key = array1->Get(env.local(), 2).ToLocalChecked();
   24945   CHECK(map->Delete(env.local(), key).FromJust());
   24946 
   24947   // make sure there are no undefined values when we convert to an array again.
   24948   v8::Local<v8::Array> array2 = map->AsArray();
   24949   uint32_t length = array2->Length();
   24950   CHECK_EQ(4U, length);
   24951   for (uint32_t i = 0; i < length; i++) {
   24952     CHECK(!array2->Get(env.local(), i).ToLocalChecked()->IsUndefined());
   24953   }
   24954 }
   24955 
   24956 TEST(CompatibleReceiverCheckOnCachedICHandler) {
   24957   v8::Isolate* isolate = CcTest::isolate();
   24958   v8::HandleScope scope(isolate);
   24959   v8::Local<v8::FunctionTemplate> parent = FunctionTemplate::New(isolate);
   24960   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, parent);
   24961   auto returns_42 =
   24962       v8::FunctionTemplate::New(isolate, Returns42, Local<Value>(), signature);
   24963   parent->PrototypeTemplate()->SetAccessorProperty(v8_str("age"), returns_42);
   24964   v8::Local<v8::FunctionTemplate> child = v8::FunctionTemplate::New(isolate);
   24965   child->Inherit(parent);
   24966   LocalContext env;
   24967   CHECK(env->Global()
   24968             ->Set(env.local(), v8_str("Child"),
   24969                   child->GetFunction(env.local()).ToLocalChecked())
   24970             .FromJust());
   24971 
   24972   // Make sure there's a compiled stub for "Child.prototype.age" in the cache.
   24973   CompileRun(
   24974       "var real = new Child();\n"
   24975       "for (var i = 0; i < 3; ++i) {\n"
   24976       "  real.age;\n"
   24977       "}\n");
   24978 
   24979   // Check that the cached stub is never used.
   24980   ExpectInt32(
   24981       "var fake = Object.create(Child.prototype);\n"
   24982       "var result = 0;\n"
   24983       "function test(d) {\n"
   24984       "  if (d == 3) return;\n"
   24985       "  try {\n"
   24986       "    fake.age;\n"
   24987       "    result = 1;\n"
   24988       "  } catch (e) {\n"
   24989       "  }\n"
   24990       "  test(d+1);\n"
   24991       "}\n"
   24992       "test(0);\n"
   24993       "result;\n",
   24994       0);
   24995 }
   24996 
   24997 THREADED_TEST(ReceiverConversionForAccessors) {
   24998   LocalContext env;
   24999   v8::Isolate* isolate = CcTest::isolate();
   25000   v8::HandleScope scope(isolate);
   25001   Local<v8::FunctionTemplate> acc =
   25002       v8::FunctionTemplate::New(isolate, Returns42);
   25003   CHECK(env->Global()
   25004             ->Set(env.local(), v8_str("acc"),
   25005                   acc->GetFunction(env.local()).ToLocalChecked())
   25006             .FromJust());
   25007 
   25008   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   25009   templ->SetAccessorProperty(v8_str("acc"), acc, acc);
   25010   Local<v8::Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   25011 
   25012   CHECK(env->Global()->Set(env.local(), v8_str("p"), instance).FromJust());
   25013   CHECK(CompileRun("(p.acc == 42)")->BooleanValue(env.local()).FromJust());
   25014   CHECK(CompileRun("(p.acc = 7) == 7")->BooleanValue(env.local()).FromJust());
   25015 
   25016   CHECK(!CompileRun("Number.prototype.__proto__ = p;"
   25017                     "var a = 1;")
   25018              .IsEmpty());
   25019   CHECK(CompileRun("(a.acc == 42)")->BooleanValue(env.local()).FromJust());
   25020   CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(env.local()).FromJust());
   25021 
   25022   CHECK(!CompileRun("Boolean.prototype.__proto__ = p;"
   25023                     "var a = true;")
   25024              .IsEmpty());
   25025   CHECK(CompileRun("(a.acc == 42)")->BooleanValue(env.local()).FromJust());
   25026   CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(env.local()).FromJust());
   25027 
   25028   CHECK(!CompileRun("String.prototype.__proto__ = p;"
   25029                     "var a = 'foo';")
   25030              .IsEmpty());
   25031   CHECK(CompileRun("(a.acc == 42)")->BooleanValue(env.local()).FromJust());
   25032   CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(env.local()).FromJust());
   25033 
   25034   CHECK(CompileRun("acc.call(1) == 42")->BooleanValue(env.local()).FromJust());
   25035   CHECK(CompileRun("acc.call(true)==42")->BooleanValue(env.local()).FromJust());
   25036   CHECK(CompileRun("acc.call('aa')==42")->BooleanValue(env.local()).FromJust());
   25037   CHECK(
   25038       CompileRun("acc.call(null) == 42")->BooleanValue(env.local()).FromJust());
   25039   CHECK(CompileRun("acc.call(undefined) == 42")
   25040             ->BooleanValue(env.local())
   25041             .FromJust());
   25042 }
   25043 
   25044 class FutexInterruptionThread : public v8::base::Thread {
   25045  public:
   25046   explicit FutexInterruptionThread(v8::Isolate* isolate)
   25047       : Thread(Options("FutexInterruptionThread")), isolate_(isolate) {}
   25048 
   25049   virtual void Run() {
   25050     // Wait a bit before terminating.
   25051     v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
   25052     isolate_->TerminateExecution();
   25053   }
   25054 
   25055  private:
   25056   v8::Isolate* isolate_;
   25057 };
   25058 
   25059 
   25060 TEST(FutexInterruption) {
   25061   i::FLAG_harmony_sharedarraybuffer = true;
   25062   v8::Isolate* isolate = CcTest::isolate();
   25063   v8::HandleScope scope(isolate);
   25064   LocalContext env;
   25065 
   25066   FutexInterruptionThread timeout_thread(isolate);
   25067 
   25068   v8::TryCatch try_catch(CcTest::isolate());
   25069   timeout_thread.Start();
   25070 
   25071   CompileRun(
   25072       "var ab = new SharedArrayBuffer(4);"
   25073       "var i32a = new Int32Array(ab);"
   25074       "Atomics.futexWait(i32a, 0, 0);");
   25075   CHECK(try_catch.HasTerminated());
   25076   timeout_thread.Join();
   25077 }
   25078 
   25079 
   25080 TEST(EstimatedContextSize) {
   25081   v8::Isolate* isolate = CcTest::isolate();
   25082   v8::HandleScope scope(isolate);
   25083   LocalContext env;
   25084   CHECK(50000 < env->EstimatedSize());
   25085 }
   25086 
   25087 
   25088 static int nb_uncaught_exception_callback_calls = 0;
   25089 
   25090 
   25091 bool NoAbortOnUncaughtException(v8::Isolate* isolate) {
   25092   ++nb_uncaught_exception_callback_calls;
   25093   return false;
   25094 }
   25095 
   25096 
   25097 TEST(AbortOnUncaughtExceptionNoAbort) {
   25098   v8::Isolate* isolate = CcTest::isolate();
   25099   v8::HandleScope handle_scope(isolate);
   25100   v8::Local<v8::ObjectTemplate> global_template =
   25101       v8::ObjectTemplate::New(isolate);
   25102   LocalContext env(NULL, global_template);
   25103 
   25104   i::FLAG_abort_on_uncaught_exception = true;
   25105   isolate->SetAbortOnUncaughtExceptionCallback(NoAbortOnUncaughtException);
   25106 
   25107   CompileRun("function boom() { throw new Error(\"boom\") }");
   25108 
   25109   v8::Local<v8::Object> global_object = env->Global();
   25110   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   25111       global_object->Get(env.local(), v8_str("boom")).ToLocalChecked());
   25112 
   25113   CHECK(foo->Call(env.local(), global_object, 0, NULL).IsEmpty());
   25114 
   25115   CHECK_EQ(1, nb_uncaught_exception_callback_calls);
   25116 }
   25117 
   25118 
   25119 TEST(AccessCheckedIsConcatSpreadable) {
   25120   v8::Isolate* isolate = CcTest::isolate();
   25121   HandleScope scope(isolate);
   25122   LocalContext env;
   25123 
   25124   // Object with access check
   25125   Local<ObjectTemplate> spreadable_template = v8::ObjectTemplate::New(isolate);
   25126   spreadable_template->SetAccessCheckCallback(AccessBlocker);
   25127   spreadable_template->Set(v8::Symbol::GetIsConcatSpreadable(isolate),
   25128                            v8::Boolean::New(isolate, true));
   25129   Local<Object> object =
   25130       spreadable_template->NewInstance(env.local()).ToLocalChecked();
   25131 
   25132   allowed_access = true;
   25133   CHECK(env->Global()->Set(env.local(), v8_str("object"), object).FromJust());
   25134   object->Set(env.local(), v8_str("length"), v8_num(2)).FromJust();
   25135   object->Set(env.local(), 0U, v8_str("a")).FromJust();
   25136   object->Set(env.local(), 1U, v8_str("b")).FromJust();
   25137 
   25138   // Access check is allowed, and the object is spread
   25139   CompileRun("var result = [].concat(object)");
   25140   ExpectTrue("Array.isArray(result)");
   25141   ExpectString("result[0]", "a");
   25142   ExpectString("result[1]", "b");
   25143   ExpectTrue("result.length === 2");
   25144   ExpectTrue("object[Symbol.isConcatSpreadable]");
   25145 
   25146   // If access check fails, the value of @@isConcatSpreadable is ignored
   25147   allowed_access = false;
   25148   CompileRun("var result = [].concat(object)");
   25149   ExpectTrue("Array.isArray(result)");
   25150   ExpectTrue("result[0] === object");
   25151   ExpectTrue("result.length === 1");
   25152   ExpectTrue("object[Symbol.isConcatSpreadable] === undefined");
   25153 }
   25154 
   25155 
   25156 TEST(AccessCheckedToStringTag) {
   25157   v8::Isolate* isolate = CcTest::isolate();
   25158   HandleScope scope(isolate);
   25159   LocalContext env;
   25160 
   25161   // Object with access check
   25162   Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
   25163   object_template->SetAccessCheckCallback(AccessBlocker);
   25164   Local<Object> object =
   25165       object_template->NewInstance(env.local()).ToLocalChecked();
   25166 
   25167   allowed_access = true;
   25168   env->Global()->Set(env.local(), v8_str("object"), object).FromJust();
   25169   object->Set(env.local(), v8::Symbol::GetToStringTag(isolate), v8_str("hello"))
   25170       .FromJust();
   25171 
   25172   // Access check is allowed, and the toStringTag is read
   25173   CompileRun("var result = Object.prototype.toString.call(object)");
   25174   ExpectString("result", "[object hello]");
   25175   ExpectString("object[Symbol.toStringTag]", "hello");
   25176 
   25177   // ToString through the API should succeed too.
   25178   String::Utf8Value result_allowed(
   25179       object->ObjectProtoToString(env.local()).ToLocalChecked());
   25180   CHECK_EQ(0, strcmp(*result_allowed, "[object hello]"));
   25181 
   25182   // If access check fails, the value of @@toStringTag is ignored
   25183   allowed_access = false;
   25184   CompileRun("var result = Object.prototype.toString.call(object)");
   25185   ExpectString("result", "[object Object]");
   25186   ExpectTrue("object[Symbol.toStringTag] === undefined");
   25187 
   25188   // ToString through the API should also fail.
   25189   String::Utf8Value result_denied(
   25190       object->ObjectProtoToString(env.local()).ToLocalChecked());
   25191   CHECK_EQ(0, strcmp(*result_denied, "[object Object]"));
   25192 }
   25193 
   25194 
   25195 TEST(ObjectTemplateIntrinsics) {
   25196   v8::Isolate* isolate = CcTest::isolate();
   25197   v8::HandleScope scope(isolate);
   25198   LocalContext env;
   25199 
   25200   Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
   25201   object_template->SetIntrinsicDataProperty(v8_str("values"),
   25202                                             v8::kArrayProto_values);
   25203   Local<Object> object =
   25204       object_template->NewInstance(env.local()).ToLocalChecked();
   25205 
   25206   CHECK(env->Global()->Set(env.local(), v8_str("obj1"), object).FromJust());
   25207   ExpectString("typeof obj1.values", "function");
   25208 
   25209   auto values = Local<Function>::Cast(
   25210       object->Get(env.local(), v8_str("values")).ToLocalChecked());
   25211   auto fn = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*values));
   25212   auto ctx = v8::Utils::OpenHandle(*env.local());
   25213   CHECK_EQ(fn->GetCreationContext(), *ctx);
   25214 
   25215   {
   25216     LocalContext env2;
   25217     Local<Object> object2 =
   25218         object_template->NewInstance(env2.local()).ToLocalChecked();
   25219     CHECK(
   25220         env2->Global()->Set(env2.local(), v8_str("obj2"), object2).FromJust());
   25221     ExpectString("typeof obj2.values", "function");
   25222     CHECK_NE(*object->Get(env2.local(), v8_str("values")).ToLocalChecked(),
   25223              *object2->Get(env2.local(), v8_str("values")).ToLocalChecked());
   25224 
   25225     auto values2 = Local<Function>::Cast(
   25226         object2->Get(env2.local(), v8_str("values")).ToLocalChecked());
   25227     auto fn2 = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*values2));
   25228     auto ctx2 = v8::Utils::OpenHandle(*env2.local());
   25229     CHECK_EQ(fn2->GetCreationContext(), *ctx2);
   25230   }
   25231 }
   25232 
   25233 
   25234 TEST(Proxy) {
   25235   LocalContext context;
   25236   v8::Isolate* isolate = CcTest::isolate();
   25237   v8::HandleScope scope(isolate);
   25238   v8::Local<v8::Object> target = CompileRun("({})").As<v8::Object>();
   25239   v8::Local<v8::Object> handler = CompileRun("({})").As<v8::Object>();
   25240 
   25241   v8::Local<v8::Proxy> proxy =
   25242       v8::Proxy::New(context.local(), target, handler).ToLocalChecked();
   25243   CHECK(proxy->IsProxy());
   25244   CHECK(!target->IsProxy());
   25245   CHECK(!proxy->IsRevoked());
   25246   CHECK(proxy->GetTarget()->SameValue(target));
   25247   CHECK(proxy->GetHandler()->SameValue(handler));
   25248 
   25249   proxy->Revoke();
   25250   CHECK(proxy->IsProxy());
   25251   CHECK(!target->IsProxy());
   25252   CHECK(proxy->IsRevoked());
   25253   CHECK(proxy->GetTarget()->SameValue(target));
   25254   CHECK(proxy->GetHandler()->IsNull());
   25255 }
   25256 
   25257 WeakCallCounterAndPersistent<Value>* CreateGarbageWithWeakCallCounter(
   25258     v8::Isolate* isolate, WeakCallCounter* counter) {
   25259   v8::Locker locker(isolate);
   25260   LocalContext env;
   25261   HandleScope scope(isolate);
   25262   WeakCallCounterAndPersistent<Value>* val =
   25263       new WeakCallCounterAndPersistent<Value>(counter);
   25264   val->handle.Reset(isolate, Object::New(isolate));
   25265   val->handle.SetWeak(val, &WeakPointerCallback,
   25266                       v8::WeakCallbackType::kParameter);
   25267   return val;
   25268 }
   25269 
   25270 class MemoryPressureThread : public v8::base::Thread {
   25271  public:
   25272   explicit MemoryPressureThread(v8::Isolate* isolate,
   25273                                 v8::MemoryPressureLevel level)
   25274       : Thread(Options("MemoryPressureThread")),
   25275         isolate_(isolate),
   25276         level_(level) {}
   25277 
   25278   virtual void Run() { isolate_->MemoryPressureNotification(level_); }
   25279 
   25280  private:
   25281   v8::Isolate* isolate_;
   25282   v8::MemoryPressureLevel level_;
   25283 };
   25284 
   25285 TEST(MemoryPressure) {
   25286   v8::Isolate* isolate = CcTest::isolate();
   25287   WeakCallCounter counter(1234);
   25288 
   25289   // Check that critical memory pressure notification sets GC interrupt.
   25290   auto garbage = CreateGarbageWithWeakCallCounter(isolate, &counter);
   25291   CHECK(!v8::Locker::IsLocked(isolate));
   25292   {
   25293     v8::Locker locker(isolate);
   25294     v8::HandleScope scope(isolate);
   25295     LocalContext env;
   25296     MemoryPressureThread memory_pressure_thread(
   25297         isolate, v8::MemoryPressureLevel::kCritical);
   25298     memory_pressure_thread.Start();
   25299     memory_pressure_thread.Join();
   25300     // This should trigger GC.
   25301     CHECK_EQ(0, counter.NumberOfWeakCalls());
   25302     CompileRun("(function noop() { return 0; })()");
   25303     CHECK_EQ(1, counter.NumberOfWeakCalls());
   25304   }
   25305   delete garbage;
   25306   // Check that critical memory pressure notification triggers GC.
   25307   garbage = CreateGarbageWithWeakCallCounter(isolate, &counter);
   25308   {
   25309     v8::Locker locker(isolate);
   25310     // If isolate is locked, memory pressure notification should trigger GC.
   25311     CHECK_EQ(1, counter.NumberOfWeakCalls());
   25312     isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kCritical);
   25313     CHECK_EQ(2, counter.NumberOfWeakCalls());
   25314   }
   25315   delete garbage;
   25316   // Check that moderate memory pressure notification sets GC into memory
   25317   // optimizing mode.
   25318   isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kModerate);
   25319   CHECK(CcTest::i_isolate()->heap()->ShouldOptimizeForMemoryUsage());
   25320   // Check that disabling memory pressure returns GC into normal mode.
   25321   isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kNone);
   25322   CHECK(!CcTest::i_isolate()->heap()->ShouldOptimizeForMemoryUsage());
   25323 }
   25324 
   25325 TEST(SetIntegrityLevel) {
   25326   LocalContext context;
   25327   v8::Isolate* isolate = CcTest::isolate();
   25328   v8::HandleScope scope(isolate);
   25329 
   25330   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   25331   CHECK(context->Global()->Set(context.local(), v8_str("o"), obj).FromJust());
   25332 
   25333   v8::Local<v8::Value> is_frozen = CompileRun("Object.isFrozen(o)");
   25334   CHECK(!is_frozen->BooleanValue(context.local()).FromJust());
   25335 
   25336   CHECK(obj->SetIntegrityLevel(context.local(), v8::IntegrityLevel::kFrozen)
   25337             .FromJust());
   25338 
   25339   is_frozen = CompileRun("Object.isFrozen(o)");
   25340   CHECK(is_frozen->BooleanValue(context.local()).FromJust());
   25341 }
   25342 
   25343 TEST(PrivateForApiIsNumber) {
   25344   LocalContext context;
   25345   v8::Isolate* isolate = CcTest::isolate();
   25346   v8::HandleScope scope(isolate);
   25347 
   25348   // Shouldn't crash.
   25349   v8::Private::ForApi(isolate, v8_str("42"));
   25350 }
   25351