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/unicode-inl.h"
     51 #include "src/utils.h"
     52 #include "src/vm-state.h"
     53 #include "test/cctest/heap/heap-tester.h"
     54 #include "test/cctest/heap/utils-inl.h"
     55 
     56 static const bool kLogThreading = false;
     57 
     58 using ::v8::Boolean;
     59 using ::v8::BooleanObject;
     60 using ::v8::Context;
     61 using ::v8::Extension;
     62 using ::v8::Function;
     63 using ::v8::FunctionTemplate;
     64 using ::v8::HandleScope;
     65 using ::v8::Local;
     66 using ::v8::Maybe;
     67 using ::v8::Message;
     68 using ::v8::MessageCallback;
     69 using ::v8::Name;
     70 using ::v8::None;
     71 using ::v8::Object;
     72 using ::v8::ObjectTemplate;
     73 using ::v8::Persistent;
     74 using ::v8::PropertyAttribute;
     75 using ::v8::Script;
     76 using ::v8::StackTrace;
     77 using ::v8::String;
     78 using ::v8::Symbol;
     79 using ::v8::TryCatch;
     80 using ::v8::Undefined;
     81 using ::v8::UniqueId;
     82 using ::v8::V8;
     83 using ::v8::Value;
     84 
     85 
     86 #define THREADED_PROFILED_TEST(Name)                                 \
     87   static void Test##Name();                                          \
     88   TEST(Name##WithProfiler) {                                         \
     89     RunWithProfiler(&Test##Name);                                    \
     90   }                                                                  \
     91   THREADED_TEST(Name)
     92 
     93 
     94 void RunWithProfiler(void (*test)()) {
     95   LocalContext env;
     96   v8::HandleScope scope(env->GetIsolate());
     97   v8::Local<v8::String> profile_name = v8_str("my_profile1");
     98   v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
     99 
    100   cpu_profiler->StartProfiling(profile_name);
    101   (*test)();
    102   reinterpret_cast<i::CpuProfiler*>(cpu_profiler)->DeleteAllProfiles();
    103 }
    104 
    105 
    106 static int signature_callback_count;
    107 static Local<Value> signature_expected_receiver;
    108 static void IncrementingSignatureCallback(
    109     const v8::FunctionCallbackInfo<v8::Value>& args) {
    110   ApiTestFuzzer::Fuzz();
    111   signature_callback_count++;
    112   CHECK(signature_expected_receiver->Equals(
    113                                        args.GetIsolate()->GetCurrentContext(),
    114                                        args.Holder())
    115             .FromJust());
    116   CHECK(signature_expected_receiver->Equals(
    117                                        args.GetIsolate()->GetCurrentContext(),
    118                                        args.This())
    119             .FromJust());
    120   v8::Local<v8::Array> result =
    121       v8::Array::New(args.GetIsolate(), args.Length());
    122   for (int i = 0; i < args.Length(); i++) {
    123     CHECK(result->Set(args.GetIsolate()->GetCurrentContext(),
    124                       v8::Integer::New(args.GetIsolate(), i), args[i])
    125               .FromJust());
    126   }
    127   args.GetReturnValue().Set(result);
    128 }
    129 
    130 
    131 static void Returns42(const v8::FunctionCallbackInfo<v8::Value>& info) {
    132   info.GetReturnValue().Set(42);
    133 }
    134 
    135 
    136 // Tests that call v8::V8::Dispose() cannot be threaded.
    137 UNINITIALIZED_TEST(InitializeAndDisposeOnce) {
    138   CHECK(v8::V8::Initialize());
    139   CHECK(v8::V8::Dispose());
    140 }
    141 
    142 
    143 // Tests that call v8::V8::Dispose() cannot be threaded.
    144 UNINITIALIZED_TEST(InitializeAndDisposeMultiple) {
    145   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
    146   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
    147   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
    148   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
    149   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
    150 }
    151 
    152 
    153 THREADED_TEST(Handles) {
    154   v8::HandleScope scope(CcTest::isolate());
    155   Local<Context> local_env;
    156   {
    157     LocalContext env;
    158     local_env = env.local();
    159   }
    160 
    161   // Local context should still be live.
    162   CHECK(!local_env.IsEmpty());
    163   local_env->Enter();
    164 
    165   v8::Local<v8::Primitive> undef = v8::Undefined(CcTest::isolate());
    166   CHECK(!undef.IsEmpty());
    167   CHECK(undef->IsUndefined());
    168 
    169   const char* source = "1 + 2 + 3";
    170   Local<Script> script = v8_compile(source);
    171   CHECK_EQ(6, v8_run_int32value(script));
    172 
    173   local_env->Exit();
    174 }
    175 
    176 
    177 THREADED_TEST(IsolateOfContext) {
    178   v8::HandleScope scope(CcTest::isolate());
    179   v8::Local<Context> env = Context::New(CcTest::isolate());
    180 
    181   CHECK(!env->GetIsolate()->InContext());
    182   CHECK(env->GetIsolate() == CcTest::isolate());
    183   env->Enter();
    184   CHECK(env->GetIsolate()->InContext());
    185   CHECK(env->GetIsolate() == CcTest::isolate());
    186   env->Exit();
    187   CHECK(!env->GetIsolate()->InContext());
    188   CHECK(env->GetIsolate() == CcTest::isolate());
    189 }
    190 
    191 
    192 static void TestSignature(const char* loop_js, Local<Value> receiver,
    193                           v8::Isolate* isolate) {
    194   i::ScopedVector<char> source(200);
    195   i::SNPrintF(source,
    196               "for (var i = 0; i < 10; i++) {"
    197               "  %s"
    198               "}",
    199               loop_js);
    200   signature_callback_count = 0;
    201   signature_expected_receiver = receiver;
    202   bool expected_to_throw = receiver.IsEmpty();
    203   v8::TryCatch try_catch(isolate);
    204   CompileRun(source.start());
    205   CHECK_EQ(expected_to_throw, try_catch.HasCaught());
    206   if (!expected_to_throw) {
    207     CHECK_EQ(10, signature_callback_count);
    208   } else {
    209     CHECK(v8_str("TypeError: Illegal invocation")
    210               ->Equals(isolate->GetCurrentContext(),
    211                        try_catch.Exception()
    212                            ->ToString(isolate->GetCurrentContext())
    213                            .ToLocalChecked())
    214               .FromJust());
    215   }
    216 }
    217 
    218 
    219 THREADED_TEST(ReceiverSignature) {
    220   LocalContext env;
    221   v8::Isolate* isolate = env->GetIsolate();
    222   v8::HandleScope scope(isolate);
    223   // Setup templates.
    224   v8::Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
    225   v8::Local<v8::Signature> sig = v8::Signature::New(isolate, fun);
    226   v8::Local<v8::FunctionTemplate> callback_sig = v8::FunctionTemplate::New(
    227       isolate, IncrementingSignatureCallback, Local<Value>(), sig);
    228   v8::Local<v8::FunctionTemplate> callback =
    229       v8::FunctionTemplate::New(isolate, IncrementingSignatureCallback);
    230   v8::Local<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New(isolate);
    231   sub_fun->Inherit(fun);
    232   v8::Local<v8::FunctionTemplate> unrel_fun =
    233       v8::FunctionTemplate::New(isolate);
    234   // Install properties.
    235   v8::Local<v8::ObjectTemplate> fun_proto = fun->PrototypeTemplate();
    236   fun_proto->Set(v8_str("prop_sig"), callback_sig);
    237   fun_proto->Set(v8_str("prop"), callback);
    238   fun_proto->SetAccessorProperty(
    239       v8_str("accessor_sig"), callback_sig, callback_sig);
    240   fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback);
    241   // Instantiate templates.
    242   Local<Value> fun_instance =
    243       fun->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
    244   Local<Value> sub_fun_instance =
    245       sub_fun->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
    246   // Setup global variables.
    247   CHECK(env->Global()
    248             ->Set(env.local(), v8_str("Fun"),
    249                   fun->GetFunction(env.local()).ToLocalChecked())
    250             .FromJust());
    251   CHECK(env->Global()
    252             ->Set(env.local(), v8_str("UnrelFun"),
    253                   unrel_fun->GetFunction(env.local()).ToLocalChecked())
    254             .FromJust());
    255   CHECK(env->Global()
    256             ->Set(env.local(), v8_str("fun_instance"), fun_instance)
    257             .FromJust());
    258   CHECK(env->Global()
    259             ->Set(env.local(), v8_str("sub_fun_instance"), sub_fun_instance)
    260             .FromJust());
    261   CompileRun(
    262       "var accessor_sig_key = 'accessor_sig';"
    263       "var accessor_key = 'accessor';"
    264       "var prop_sig_key = 'prop_sig';"
    265       "var prop_key = 'prop';"
    266       ""
    267       "function copy_props(obj) {"
    268       "  var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];"
    269       "  var source = Fun.prototype;"
    270       "  for (var i in keys) {"
    271       "    var key = keys[i];"
    272       "    var desc = Object.getOwnPropertyDescriptor(source, key);"
    273       "    Object.defineProperty(obj, key, desc);"
    274       "  }"
    275       "}"
    276       ""
    277       "var obj = {};"
    278       "copy_props(obj);"
    279       "var unrel = new UnrelFun();"
    280       "copy_props(unrel);");
    281   // Test with and without ICs
    282   const char* test_objects[] = {
    283       "fun_instance", "sub_fun_instance", "obj", "unrel" };
    284   unsigned bad_signature_start_offset = 2;
    285   for (unsigned i = 0; i < arraysize(test_objects); i++) {
    286     i::ScopedVector<char> source(200);
    287     i::SNPrintF(
    288         source, "var test_object = %s; test_object", test_objects[i]);
    289     Local<Value> test_object = CompileRun(source.start());
    290     TestSignature("test_object.prop();", test_object, isolate);
    291     TestSignature("test_object.accessor;", test_object, isolate);
    292     TestSignature("test_object[accessor_key];", test_object, isolate);
    293     TestSignature("test_object.accessor = 1;", test_object, isolate);
    294     TestSignature("test_object[accessor_key] = 1;", test_object, isolate);
    295     if (i >= bad_signature_start_offset) test_object = Local<Value>();
    296     TestSignature("test_object.prop_sig();", test_object, isolate);
    297     TestSignature("test_object.accessor_sig;", test_object, isolate);
    298     TestSignature("test_object[accessor_sig_key];", test_object, isolate);
    299     TestSignature("test_object.accessor_sig = 1;", test_object, isolate);
    300     TestSignature("test_object[accessor_sig_key] = 1;", test_object, isolate);
    301   }
    302 }
    303 
    304 
    305 THREADED_TEST(HulIgennem) {
    306   LocalContext env;
    307   v8::Isolate* isolate = env->GetIsolate();
    308   v8::HandleScope scope(isolate);
    309   v8::Local<v8::Primitive> undef = v8::Undefined(isolate);
    310   Local<String> undef_str = undef->ToString(env.local()).ToLocalChecked();
    311   char* value = i::NewArray<char>(undef_str->Utf8Length() + 1);
    312   undef_str->WriteUtf8(value);
    313   CHECK_EQ(0, strcmp(value, "undefined"));
    314   i::DeleteArray(value);
    315 }
    316 
    317 
    318 THREADED_TEST(Access) {
    319   LocalContext env;
    320   v8::Isolate* isolate = env->GetIsolate();
    321   v8::HandleScope scope(isolate);
    322   Local<v8::Object> obj = v8::Object::New(isolate);
    323   Local<Value> foo_before =
    324       obj->Get(env.local(), v8_str("foo")).ToLocalChecked();
    325   CHECK(foo_before->IsUndefined());
    326   Local<String> bar_str = v8_str("bar");
    327   CHECK(obj->Set(env.local(), v8_str("foo"), bar_str).FromJust());
    328   Local<Value> foo_after =
    329       obj->Get(env.local(), v8_str("foo")).ToLocalChecked();
    330   CHECK(!foo_after->IsUndefined());
    331   CHECK(foo_after->IsString());
    332   CHECK(bar_str->Equals(env.local(), foo_after).FromJust());
    333 }
    334 
    335 
    336 THREADED_TEST(AccessElement) {
    337   LocalContext env;
    338   v8::HandleScope scope(env->GetIsolate());
    339   Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
    340   Local<Value> before = obj->Get(env.local(), 1).ToLocalChecked();
    341   CHECK(before->IsUndefined());
    342   Local<String> bar_str = v8_str("bar");
    343   CHECK(obj->Set(env.local(), 1, bar_str).FromJust());
    344   Local<Value> after = obj->Get(env.local(), 1).ToLocalChecked();
    345   CHECK(!after->IsUndefined());
    346   CHECK(after->IsString());
    347   CHECK(bar_str->Equals(env.local(), after).FromJust());
    348 
    349   Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
    350   CHECK(v8_str("a")
    351             ->Equals(env.local(), value->Get(env.local(), 0).ToLocalChecked())
    352             .FromJust());
    353   CHECK(v8_str("b")
    354             ->Equals(env.local(), value->Get(env.local(), 1).ToLocalChecked())
    355             .FromJust());
    356 }
    357 
    358 
    359 THREADED_TEST(Script) {
    360   LocalContext env;
    361   v8::HandleScope scope(env->GetIsolate());
    362   const char* source = "1 + 2 + 3";
    363   Local<Script> script = v8_compile(source);
    364   CHECK_EQ(6, v8_run_int32value(script));
    365 }
    366 
    367 
    368 class TestResource: public String::ExternalStringResource {
    369  public:
    370   explicit TestResource(uint16_t* data, int* counter = NULL,
    371                         bool owning_data = true)
    372       : data_(data), length_(0), counter_(counter), owning_data_(owning_data) {
    373     while (data[length_]) ++length_;
    374   }
    375 
    376   ~TestResource() {
    377     if (owning_data_) i::DeleteArray(data_);
    378     if (counter_ != NULL) ++*counter_;
    379   }
    380 
    381   const uint16_t* data() const {
    382     return data_;
    383   }
    384 
    385   size_t length() const {
    386     return length_;
    387   }
    388 
    389  private:
    390   uint16_t* data_;
    391   size_t length_;
    392   int* counter_;
    393   bool owning_data_;
    394 };
    395 
    396 
    397 class TestOneByteResource : public String::ExternalOneByteStringResource {
    398  public:
    399   explicit TestOneByteResource(const char* data, int* counter = NULL,
    400                                size_t offset = 0)
    401       : orig_data_(data),
    402         data_(data + offset),
    403         length_(strlen(data) - offset),
    404         counter_(counter) {}
    405 
    406   ~TestOneByteResource() {
    407     i::DeleteArray(orig_data_);
    408     if (counter_ != NULL) ++*counter_;
    409   }
    410 
    411   const char* data() const {
    412     return data_;
    413   }
    414 
    415   size_t length() const {
    416     return length_;
    417   }
    418 
    419  private:
    420   const char* orig_data_;
    421   const char* data_;
    422   size_t length_;
    423   int* counter_;
    424 };
    425 
    426 
    427 THREADED_TEST(ScriptUsingStringResource) {
    428   int dispose_count = 0;
    429   const char* c_source = "1 + 2 * 3";
    430   uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
    431   {
    432     LocalContext env;
    433     v8::HandleScope scope(env->GetIsolate());
    434     TestResource* resource = new TestResource(two_byte_source, &dispose_count);
    435     Local<String> source =
    436         String::NewExternalTwoByte(env->GetIsolate(), resource)
    437             .ToLocalChecked();
    438     Local<Script> script = v8_compile(source);
    439     Local<Value> value = script->Run(env.local()).ToLocalChecked();
    440     CHECK(value->IsNumber());
    441     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
    442     CHECK(source->IsExternal());
    443     CHECK_EQ(resource,
    444              static_cast<TestResource*>(source->GetExternalStringResource()));
    445     String::Encoding encoding = String::UNKNOWN_ENCODING;
    446     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
    447              source->GetExternalStringResourceBase(&encoding));
    448     CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
    449     CcTest::heap()->CollectAllGarbage();
    450     CHECK_EQ(0, dispose_count);
    451   }
    452   CcTest::i_isolate()->compilation_cache()->Clear();
    453   CcTest::heap()->CollectAllAvailableGarbage();
    454   CHECK_EQ(1, dispose_count);
    455 }
    456 
    457 
    458 THREADED_TEST(ScriptUsingOneByteStringResource) {
    459   int dispose_count = 0;
    460   const char* c_source = "1 + 2 * 3";
    461   {
    462     LocalContext env;
    463     v8::HandleScope scope(env->GetIsolate());
    464     TestOneByteResource* resource =
    465         new TestOneByteResource(i::StrDup(c_source), &dispose_count);
    466     Local<String> source =
    467         String::NewExternalOneByte(env->GetIsolate(), resource)
    468             .ToLocalChecked();
    469     CHECK(source->IsExternalOneByte());
    470     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
    471              source->GetExternalOneByteStringResource());
    472     String::Encoding encoding = String::UNKNOWN_ENCODING;
    473     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
    474              source->GetExternalStringResourceBase(&encoding));
    475     CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
    476     Local<Script> script = v8_compile(source);
    477     Local<Value> value = script->Run(env.local()).ToLocalChecked();
    478     CHECK(value->IsNumber());
    479     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
    480     CcTest::heap()->CollectAllGarbage();
    481     CHECK_EQ(0, dispose_count);
    482   }
    483   CcTest::i_isolate()->compilation_cache()->Clear();
    484   CcTest::heap()->CollectAllAvailableGarbage();
    485   CHECK_EQ(1, dispose_count);
    486 }
    487 
    488 
    489 THREADED_TEST(ScriptMakingExternalString) {
    490   int dispose_count = 0;
    491   uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
    492   {
    493     LocalContext env;
    494     v8::HandleScope scope(env->GetIsolate());
    495     Local<String> source =
    496         String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
    497                                v8::NewStringType::kNormal)
    498             .ToLocalChecked();
    499     // Trigger GCs so that the newly allocated string moves to old gen.
    500     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    501     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    502     CHECK_EQ(source->IsExternal(), false);
    503     CHECK_EQ(source->IsExternalOneByte(), false);
    504     String::Encoding encoding = String::UNKNOWN_ENCODING;
    505     CHECK(!source->GetExternalStringResourceBase(&encoding));
    506     CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
    507     bool success = source->MakeExternal(new TestResource(two_byte_source,
    508                                                          &dispose_count));
    509     CHECK(success);
    510     Local<Script> script = v8_compile(source);
    511     Local<Value> value = script->Run(env.local()).ToLocalChecked();
    512     CHECK(value->IsNumber());
    513     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
    514     CcTest::heap()->CollectAllGarbage();
    515     CHECK_EQ(0, dispose_count);
    516   }
    517   CcTest::i_isolate()->compilation_cache()->Clear();
    518   CcTest::heap()->CollectAllGarbage();
    519   CHECK_EQ(1, dispose_count);
    520 }
    521 
    522 
    523 THREADED_TEST(ScriptMakingExternalOneByteString) {
    524   int dispose_count = 0;
    525   const char* c_source = "1 + 2 * 3";
    526   {
    527     LocalContext env;
    528     v8::HandleScope scope(env->GetIsolate());
    529     Local<String> source = v8_str(c_source);
    530     // Trigger GCs so that the newly allocated string moves to old gen.
    531     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    532     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    533     bool success = source->MakeExternal(
    534         new TestOneByteResource(i::StrDup(c_source), &dispose_count));
    535     CHECK(success);
    536     Local<Script> script = v8_compile(source);
    537     Local<Value> value = script->Run(env.local()).ToLocalChecked();
    538     CHECK(value->IsNumber());
    539     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
    540     CcTest::heap()->CollectAllGarbage();
    541     CHECK_EQ(0, dispose_count);
    542   }
    543   CcTest::i_isolate()->compilation_cache()->Clear();
    544   CcTest::heap()->CollectAllGarbage();
    545   CHECK_EQ(1, dispose_count);
    546 }
    547 
    548 
    549 TEST(MakingExternalStringConditions) {
    550   LocalContext env;
    551   v8::HandleScope scope(env->GetIsolate());
    552 
    553   // Free some space in the new space so that we can check freshness.
    554   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
    555   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
    556 
    557   uint16_t* two_byte_string = AsciiToTwoByteString("s1");
    558   Local<String> small_string =
    559       String::NewFromTwoByte(env->GetIsolate(), two_byte_string,
    560                              v8::NewStringType::kNormal)
    561           .ToLocalChecked();
    562   i::DeleteArray(two_byte_string);
    563 
    564   // We should refuse to externalize small strings.
    565   CHECK(!small_string->CanMakeExternal());
    566   // Trigger GCs so that the newly allocated string moves to old gen.
    567   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    568   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    569   // Old space strings should be accepted.
    570   CHECK(small_string->CanMakeExternal());
    571 
    572   two_byte_string = AsciiToTwoByteString("small string 2");
    573   small_string = String::NewFromTwoByte(env->GetIsolate(), two_byte_string,
    574                                         v8::NewStringType::kNormal)
    575                      .ToLocalChecked();
    576   i::DeleteArray(two_byte_string);
    577 
    578   const int buf_size = 10 * 1024;
    579   char* buf = i::NewArray<char>(buf_size);
    580   memset(buf, 'a', buf_size);
    581   buf[buf_size - 1] = '\0';
    582 
    583   two_byte_string = AsciiToTwoByteString(buf);
    584   Local<String> large_string =
    585       String::NewFromTwoByte(env->GetIsolate(), two_byte_string,
    586                              v8::NewStringType::kNormal)
    587           .ToLocalChecked();
    588   i::DeleteArray(buf);
    589   i::DeleteArray(two_byte_string);
    590   // Large strings should be immediately accepted.
    591   CHECK(large_string->CanMakeExternal());
    592 }
    593 
    594 
    595 TEST(MakingExternalOneByteStringConditions) {
    596   LocalContext env;
    597   v8::HandleScope scope(env->GetIsolate());
    598 
    599   // Free some space in the new space so that we can check freshness.
    600   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
    601   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
    602 
    603   Local<String> small_string = v8_str("s1");
    604   // We should refuse to externalize small strings.
    605   CHECK(!small_string->CanMakeExternal());
    606   // Trigger GCs so that the newly allocated string moves to old gen.
    607   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    608   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    609   // Old space strings should be accepted.
    610   CHECK(small_string->CanMakeExternal());
    611 
    612   const int buf_size = 10 * 1024;
    613   char* buf = i::NewArray<char>(buf_size);
    614   memset(buf, 'a', buf_size);
    615   buf[buf_size - 1] = '\0';
    616   Local<String> large_string = v8_str(buf);
    617   i::DeleteArray(buf);
    618   // Large strings should be immediately accepted.
    619   CHECK(large_string->CanMakeExternal());
    620 }
    621 
    622 
    623 TEST(MakingExternalUnalignedOneByteString) {
    624   LocalContext env;
    625   v8::HandleScope scope(env->GetIsolate());
    626 
    627   CompileRun("function cons(a, b) { return a + b; }"
    628              "function slice(a) { return a.substring(1); }");
    629   // Create a cons string that will land in old pointer space.
    630   Local<String> cons = Local<String>::Cast(CompileRun(
    631       "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
    632   // Create a sliced string that will land in old pointer space.
    633   Local<String> slice = Local<String>::Cast(CompileRun(
    634       "slice('abcdefghijklmnopqrstuvwxyz');"));
    635 
    636   // Trigger GCs so that the newly allocated string moves to old gen.
    637   SimulateFullSpace(CcTest::heap()->old_space());
    638   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    639   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    640 
    641   // Turn into external string with unaligned resource data.
    642   const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
    643   bool success =
    644       cons->MakeExternal(new TestOneByteResource(i::StrDup(c_cons), NULL, 1));
    645   CHECK(success);
    646   const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
    647   success =
    648       slice->MakeExternal(new TestOneByteResource(i::StrDup(c_slice), NULL, 1));
    649   CHECK(success);
    650 
    651   // Trigger GCs and force evacuation.
    652   CcTest::heap()->CollectAllGarbage();
    653   CcTest::heap()->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask);
    654 }
    655 
    656 
    657 THREADED_TEST(UsingExternalString) {
    658   i::Factory* factory = CcTest::i_isolate()->factory();
    659   {
    660     v8::HandleScope scope(CcTest::isolate());
    661     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
    662     Local<String> string =
    663         String::NewExternalTwoByte(CcTest::isolate(),
    664                                    new TestResource(two_byte_string))
    665             .ToLocalChecked();
    666     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    667     // Trigger GCs so that the newly allocated string moves to old gen.
    668     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    669     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    670     i::Handle<i::String> isymbol =
    671         factory->InternalizeString(istring);
    672     CHECK(isymbol->IsInternalizedString());
    673   }
    674   CcTest::heap()->CollectAllGarbage();
    675   CcTest::heap()->CollectAllGarbage();
    676 }
    677 
    678 
    679 THREADED_TEST(UsingExternalOneByteString) {
    680   i::Factory* factory = CcTest::i_isolate()->factory();
    681   {
    682     v8::HandleScope scope(CcTest::isolate());
    683     const char* one_byte_string = "test string";
    684     Local<String> string =
    685         String::NewExternalOneByte(
    686             CcTest::isolate(),
    687             new TestOneByteResource(i::StrDup(one_byte_string)))
    688             .ToLocalChecked();
    689     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    690     // Trigger GCs so that the newly allocated string moves to old gen.
    691     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
    692     CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
    693     i::Handle<i::String> isymbol =
    694         factory->InternalizeString(istring);
    695     CHECK(isymbol->IsInternalizedString());
    696   }
    697   CcTest::heap()->CollectAllGarbage();
    698   CcTest::heap()->CollectAllGarbage();
    699 }
    700 
    701 
    702 class RandomLengthResource : public v8::String::ExternalStringResource {
    703  public:
    704   explicit RandomLengthResource(int length) : length_(length) {}
    705   virtual const uint16_t* data() const { return string_; }
    706   virtual size_t length() const { return length_; }
    707 
    708  private:
    709   uint16_t string_[10];
    710   int length_;
    711 };
    712 
    713 
    714 class RandomLengthOneByteResource
    715     : public v8::String::ExternalOneByteStringResource {
    716  public:
    717   explicit RandomLengthOneByteResource(int length) : length_(length) {}
    718   virtual const char* data() const { return string_; }
    719   virtual size_t length() const { return length_; }
    720 
    721  private:
    722   char string_[10];
    723   int length_;
    724 };
    725 
    726 
    727 THREADED_TEST(NewExternalForVeryLongString) {
    728   auto isolate = CcTest::isolate();
    729   {
    730     v8::HandleScope scope(isolate);
    731     v8::TryCatch try_catch(isolate);
    732     RandomLengthOneByteResource r(1 << 30);
    733     v8::MaybeLocal<v8::String> maybe_str =
    734         v8::String::NewExternalOneByte(isolate, &r);
    735     CHECK(maybe_str.IsEmpty());
    736     CHECK(!try_catch.HasCaught());
    737   }
    738 
    739   {
    740     v8::HandleScope scope(isolate);
    741     v8::TryCatch try_catch(isolate);
    742     RandomLengthResource r(1 << 30);
    743     v8::MaybeLocal<v8::String> maybe_str =
    744         v8::String::NewExternalTwoByte(isolate, &r);
    745     CHECK(maybe_str.IsEmpty());
    746     CHECK(!try_catch.HasCaught());
    747   }
    748 }
    749 
    750 
    751 THREADED_TEST(ScavengeExternalString) {
    752   i::FLAG_stress_compaction = false;
    753   i::FLAG_gc_global = false;
    754   int dispose_count = 0;
    755   bool in_new_space = false;
    756   {
    757     v8::HandleScope scope(CcTest::isolate());
    758     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
    759     Local<String> string =
    760         String::NewExternalTwoByte(
    761             CcTest::isolate(),
    762             new TestResource(two_byte_string, &dispose_count))
    763             .ToLocalChecked();
    764     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    765     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
    766     in_new_space = CcTest::heap()->InNewSpace(*istring);
    767     CHECK(in_new_space || CcTest::heap()->old_space()->Contains(*istring));
    768     CHECK_EQ(0, dispose_count);
    769   }
    770   CcTest::heap()->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_SPACE);
    771   CHECK_EQ(1, dispose_count);
    772 }
    773 
    774 
    775 THREADED_TEST(ScavengeExternalOneByteString) {
    776   i::FLAG_stress_compaction = false;
    777   i::FLAG_gc_global = false;
    778   int dispose_count = 0;
    779   bool in_new_space = false;
    780   {
    781     v8::HandleScope scope(CcTest::isolate());
    782     const char* one_byte_string = "test string";
    783     Local<String> string =
    784         String::NewExternalOneByte(
    785             CcTest::isolate(),
    786             new TestOneByteResource(i::StrDup(one_byte_string), &dispose_count))
    787             .ToLocalChecked();
    788     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
    789     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
    790     in_new_space = CcTest::heap()->InNewSpace(*istring);
    791     CHECK(in_new_space || CcTest::heap()->old_space()->Contains(*istring));
    792     CHECK_EQ(0, dispose_count);
    793   }
    794   CcTest::heap()->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_SPACE);
    795   CHECK_EQ(1, dispose_count);
    796 }
    797 
    798 
    799 class TestOneByteResourceWithDisposeControl : public TestOneByteResource {
    800  public:
    801   // Only used by non-threaded tests, so it can use static fields.
    802   static int dispose_calls;
    803   static int dispose_count;
    804 
    805   TestOneByteResourceWithDisposeControl(const char* data, bool dispose)
    806       : TestOneByteResource(data, &dispose_count), dispose_(dispose) {}
    807 
    808   void Dispose() {
    809     ++dispose_calls;
    810     if (dispose_) delete this;
    811   }
    812  private:
    813   bool dispose_;
    814 };
    815 
    816 
    817 int TestOneByteResourceWithDisposeControl::dispose_count = 0;
    818 int TestOneByteResourceWithDisposeControl::dispose_calls = 0;
    819 
    820 
    821 TEST(ExternalStringWithDisposeHandling) {
    822   const char* c_source = "1 + 2 * 3";
    823 
    824   // Use a stack allocated external string resource allocated object.
    825   TestOneByteResourceWithDisposeControl::dispose_count = 0;
    826   TestOneByteResourceWithDisposeControl::dispose_calls = 0;
    827   TestOneByteResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
    828   {
    829     LocalContext env;
    830     v8::HandleScope scope(env->GetIsolate());
    831     Local<String> source =
    832         String::NewExternalOneByte(env->GetIsolate(), &res_stack)
    833             .ToLocalChecked();
    834     Local<Script> script = v8_compile(source);
    835     Local<Value> value = script->Run(env.local()).ToLocalChecked();
    836     CHECK(value->IsNumber());
    837     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
    838     CcTest::heap()->CollectAllAvailableGarbage();
    839     CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
    840   }
    841   CcTest::i_isolate()->compilation_cache()->Clear();
    842   CcTest::heap()->CollectAllAvailableGarbage();
    843   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
    844   CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
    845 
    846   // Use a heap allocated external string resource allocated object.
    847   TestOneByteResourceWithDisposeControl::dispose_count = 0;
    848   TestOneByteResourceWithDisposeControl::dispose_calls = 0;
    849   TestOneByteResource* res_heap =
    850       new TestOneByteResourceWithDisposeControl(i::StrDup(c_source), true);
    851   {
    852     LocalContext env;
    853     v8::HandleScope scope(env->GetIsolate());
    854     Local<String> source =
    855         String::NewExternalOneByte(env->GetIsolate(), res_heap)
    856             .ToLocalChecked();
    857     Local<Script> script = v8_compile(source);
    858     Local<Value> value = script->Run(env.local()).ToLocalChecked();
    859     CHECK(value->IsNumber());
    860     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
    861     CcTest::heap()->CollectAllAvailableGarbage();
    862     CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
    863   }
    864   CcTest::i_isolate()->compilation_cache()->Clear();
    865   CcTest::heap()->CollectAllAvailableGarbage();
    866   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
    867   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_count);
    868 }
    869 
    870 
    871 THREADED_TEST(StringConcat) {
    872   {
    873     LocalContext env;
    874     v8::HandleScope scope(env->GetIsolate());
    875     const char* one_byte_string_1 = "function a_times_t";
    876     const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
    877     const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
    878     const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
    879     const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
    880     const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
    881     const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
    882     Local<String> left = v8_str(one_byte_string_1);
    883 
    884     uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
    885     Local<String> right =
    886         String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
    887                                v8::NewStringType::kNormal)
    888             .ToLocalChecked();
    889     i::DeleteArray(two_byte_source);
    890 
    891     Local<String> source = String::Concat(left, right);
    892     right = String::NewExternalOneByte(
    893                 env->GetIsolate(),
    894                 new TestOneByteResource(i::StrDup(one_byte_extern_1)))
    895                 .ToLocalChecked();
    896     source = String::Concat(source, right);
    897     right = String::NewExternalTwoByte(
    898                 env->GetIsolate(),
    899                 new TestResource(AsciiToTwoByteString(two_byte_extern_1)))
    900                 .ToLocalChecked();
    901     source = String::Concat(source, right);
    902     right = v8_str(one_byte_string_2);
    903     source = String::Concat(source, right);
    904 
    905     two_byte_source = AsciiToTwoByteString(two_byte_string_2);
    906     right = String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
    907                                    v8::NewStringType::kNormal)
    908                 .ToLocalChecked();
    909     i::DeleteArray(two_byte_source);
    910 
    911     source = String::Concat(source, right);
    912     right = String::NewExternalTwoByte(
    913                 env->GetIsolate(),
    914                 new TestResource(AsciiToTwoByteString(two_byte_extern_2)))
    915                 .ToLocalChecked();
    916     source = String::Concat(source, right);
    917     Local<Script> script = v8_compile(source);
    918     Local<Value> value = script->Run(env.local()).ToLocalChecked();
    919     CHECK(value->IsNumber());
    920     CHECK_EQ(68, value->Int32Value(env.local()).FromJust());
    921   }
    922   CcTest::i_isolate()->compilation_cache()->Clear();
    923   CcTest::heap()->CollectAllGarbage();
    924   CcTest::heap()->CollectAllGarbage();
    925 }
    926 
    927 
    928 THREADED_TEST(GlobalProperties) {
    929   LocalContext env;
    930   v8::HandleScope scope(env->GetIsolate());
    931   v8::Local<v8::Object> global = env->Global();
    932   CHECK(global->Set(env.local(), v8_str("pi"), v8_num(3.1415926)).FromJust());
    933   Local<Value> pi = global->Get(env.local(), v8_str("pi")).ToLocalChecked();
    934   CHECK_EQ(3.1415926, pi->NumberValue(env.local()).FromJust());
    935 }
    936 
    937 
    938 static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
    939                                  i::Address callback) {
    940   ApiTestFuzzer::Fuzz();
    941   CheckReturnValue(info, callback);
    942   info.GetReturnValue().Set(v8_str("bad value"));
    943   info.GetReturnValue().Set(v8_num(102));
    944 }
    945 
    946 
    947 static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
    948   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
    949 }
    950 
    951 
    952 static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
    953   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
    954 }
    955 
    956 static void construct_callback(
    957     const v8::FunctionCallbackInfo<Value>& info) {
    958   ApiTestFuzzer::Fuzz();
    959   CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
    960   CHECK(
    961       info.This()
    962           ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("x"), v8_num(1))
    963           .FromJust());
    964   CHECK(
    965       info.This()
    966           ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(2))
    967           .FromJust());
    968   info.GetReturnValue().Set(v8_str("bad value"));
    969   info.GetReturnValue().Set(info.This());
    970 }
    971 
    972 
    973 static void Return239Callback(
    974     Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
    975   ApiTestFuzzer::Fuzz();
    976   CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
    977   info.GetReturnValue().Set(v8_str("bad value"));
    978   info.GetReturnValue().Set(v8_num(239));
    979 }
    980 
    981 
    982 template<typename Handler>
    983 static void TestFunctionTemplateInitializer(Handler handler,
    984                                             Handler handler_2) {
    985   // Test constructor calls.
    986   {
    987     LocalContext env;
    988     v8::Isolate* isolate = env->GetIsolate();
    989     v8::HandleScope scope(isolate);
    990 
    991     Local<v8::FunctionTemplate> fun_templ =
    992         v8::FunctionTemplate::New(isolate, handler);
    993     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    994     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    995     Local<Script> script = v8_compile("obj()");
    996     for (int i = 0; i < 30; i++) {
    997       CHECK_EQ(102, v8_run_int32value(script));
    998     }
    999   }
   1000   // Use SetCallHandler to initialize a function template, should work like
   1001   // the previous one.
   1002   {
   1003     LocalContext env;
   1004     v8::Isolate* isolate = env->GetIsolate();
   1005     v8::HandleScope scope(isolate);
   1006 
   1007     Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
   1008     fun_templ->SetCallHandler(handler_2);
   1009     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   1010     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
   1011     Local<Script> script = v8_compile("obj()");
   1012     for (int i = 0; i < 30; i++) {
   1013       CHECK_EQ(102, v8_run_int32value(script));
   1014     }
   1015   }
   1016 }
   1017 
   1018 
   1019 template<typename Constructor, typename Accessor>
   1020 static void TestFunctionTemplateAccessor(Constructor constructor,
   1021                                          Accessor accessor) {
   1022   LocalContext env;
   1023   v8::HandleScope scope(env->GetIsolate());
   1024 
   1025   Local<v8::FunctionTemplate> fun_templ =
   1026       v8::FunctionTemplate::New(env->GetIsolate(), constructor);
   1027   fun_templ->SetClassName(v8_str("funky"));
   1028   fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
   1029   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   1030   CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
   1031   Local<Value> result =
   1032       v8_compile("(new obj()).toString()")->Run(env.local()).ToLocalChecked();
   1033   CHECK(v8_str("[object funky]")->Equals(env.local(), result).FromJust());
   1034   CompileRun("var obj_instance = new obj();");
   1035   Local<Script> script;
   1036   script = v8_compile("obj_instance.x");
   1037   for (int i = 0; i < 30; i++) {
   1038     CHECK_EQ(1, v8_run_int32value(script));
   1039   }
   1040   script = v8_compile("obj_instance.m");
   1041   for (int i = 0; i < 30; i++) {
   1042     CHECK_EQ(239, v8_run_int32value(script));
   1043   }
   1044 }
   1045 
   1046 
   1047 THREADED_PROFILED_TEST(FunctionTemplate) {
   1048   TestFunctionTemplateInitializer(handle_callback, handle_callback_2);
   1049   TestFunctionTemplateAccessor(construct_callback, Return239Callback);
   1050 }
   1051 
   1052 
   1053 static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
   1054   ApiTestFuzzer::Fuzz();
   1055   CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
   1056   info.GetReturnValue().Set(v8_num(51423 + info.Length()));
   1057 }
   1058 
   1059 
   1060 template<typename Callback>
   1061 static void TestSimpleCallback(Callback callback) {
   1062   LocalContext env;
   1063   v8::Isolate* isolate = env->GetIsolate();
   1064   v8::HandleScope scope(isolate);
   1065 
   1066   v8::Local<v8::ObjectTemplate> object_template =
   1067       v8::ObjectTemplate::New(isolate);
   1068   object_template->Set(isolate, "callback",
   1069                        v8::FunctionTemplate::New(isolate, callback));
   1070   v8::Local<v8::Object> object =
   1071       object_template->NewInstance(env.local()).ToLocalChecked();
   1072   CHECK((*env)
   1073             ->Global()
   1074             ->Set(env.local(), v8_str("callback_object"), object)
   1075             .FromJust());
   1076   v8::Local<v8::Script> script;
   1077   script = v8_compile("callback_object.callback(17)");
   1078   for (int i = 0; i < 30; i++) {
   1079     CHECK_EQ(51424, v8_run_int32value(script));
   1080   }
   1081   script = v8_compile("callback_object.callback(17, 24)");
   1082   for (int i = 0; i < 30; i++) {
   1083     CHECK_EQ(51425, v8_run_int32value(script));
   1084   }
   1085 }
   1086 
   1087 
   1088 THREADED_PROFILED_TEST(SimpleCallback) {
   1089   TestSimpleCallback(SimpleCallback);
   1090 }
   1091 
   1092 
   1093 template<typename T>
   1094 void FastReturnValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
   1095 
   1096 // constant return values
   1097 static int32_t fast_return_value_int32 = 471;
   1098 static uint32_t fast_return_value_uint32 = 571;
   1099 static const double kFastReturnValueDouble = 2.7;
   1100 // variable return values
   1101 static bool fast_return_value_bool = false;
   1102 enum ReturnValueOddball {
   1103   kNullReturnValue,
   1104   kUndefinedReturnValue,
   1105   kEmptyStringReturnValue
   1106 };
   1107 static ReturnValueOddball fast_return_value_void;
   1108 static bool fast_return_value_object_is_empty = false;
   1109 
   1110 // Helper function to avoid compiler error: insufficient contextual information
   1111 // to determine type when applying FUNCTION_ADDR to a template function.
   1112 static i::Address address_of(v8::FunctionCallback callback) {
   1113   return FUNCTION_ADDR(callback);
   1114 }
   1115 
   1116 template<>
   1117 void FastReturnValueCallback<int32_t>(
   1118     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1119   CheckReturnValue(info, address_of(FastReturnValueCallback<int32_t>));
   1120   info.GetReturnValue().Set(fast_return_value_int32);
   1121 }
   1122 
   1123 template<>
   1124 void FastReturnValueCallback<uint32_t>(
   1125     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1126   CheckReturnValue(info, address_of(FastReturnValueCallback<uint32_t>));
   1127   info.GetReturnValue().Set(fast_return_value_uint32);
   1128 }
   1129 
   1130 template<>
   1131 void FastReturnValueCallback<double>(
   1132     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1133   CheckReturnValue(info, address_of(FastReturnValueCallback<double>));
   1134   info.GetReturnValue().Set(kFastReturnValueDouble);
   1135 }
   1136 
   1137 template<>
   1138 void FastReturnValueCallback<bool>(
   1139     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1140   CheckReturnValue(info, address_of(FastReturnValueCallback<bool>));
   1141   info.GetReturnValue().Set(fast_return_value_bool);
   1142 }
   1143 
   1144 template<>
   1145 void FastReturnValueCallback<void>(
   1146     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1147   CheckReturnValue(info, address_of(FastReturnValueCallback<void>));
   1148   switch (fast_return_value_void) {
   1149     case kNullReturnValue:
   1150       info.GetReturnValue().SetNull();
   1151       break;
   1152     case kUndefinedReturnValue:
   1153       info.GetReturnValue().SetUndefined();
   1154       break;
   1155     case kEmptyStringReturnValue:
   1156       info.GetReturnValue().SetEmptyString();
   1157       break;
   1158   }
   1159 }
   1160 
   1161 template<>
   1162 void FastReturnValueCallback<Object>(
   1163     const v8::FunctionCallbackInfo<v8::Value>& info) {
   1164   v8::Local<v8::Object> object;
   1165   if (!fast_return_value_object_is_empty) {
   1166     object = Object::New(info.GetIsolate());
   1167   }
   1168   info.GetReturnValue().Set(object);
   1169 }
   1170 
   1171 template <typename T>
   1172 Local<Value> TestFastReturnValues() {
   1173   LocalContext env;
   1174   v8::Isolate* isolate = env->GetIsolate();
   1175   v8::EscapableHandleScope scope(isolate);
   1176   v8::Local<v8::ObjectTemplate> object_template =
   1177       v8::ObjectTemplate::New(isolate);
   1178   v8::FunctionCallback callback = &FastReturnValueCallback<T>;
   1179   object_template->Set(isolate, "callback",
   1180                        v8::FunctionTemplate::New(isolate, callback));
   1181   v8::Local<v8::Object> object =
   1182       object_template->NewInstance(env.local()).ToLocalChecked();
   1183   CHECK((*env)
   1184             ->Global()
   1185             ->Set(env.local(), v8_str("callback_object"), object)
   1186             .FromJust());
   1187   return scope.Escape(CompileRun("callback_object.callback()"));
   1188 }
   1189 
   1190 
   1191 THREADED_PROFILED_TEST(FastReturnValues) {
   1192   LocalContext env;
   1193   v8::Isolate* isolate = env->GetIsolate();
   1194   v8::HandleScope scope(isolate);
   1195   v8::Local<v8::Value> value;
   1196   // check int32_t and uint32_t
   1197   int32_t int_values[] = {
   1198       0, 234, -723,
   1199       i::Smi::kMinValue, i::Smi::kMaxValue
   1200   };
   1201   for (size_t i = 0; i < arraysize(int_values); i++) {
   1202     for (int modifier = -1; modifier <= 1; modifier++) {
   1203       int int_value = int_values[i] + modifier;
   1204       // check int32_t
   1205       fast_return_value_int32 = int_value;
   1206       value = TestFastReturnValues<int32_t>();
   1207       CHECK(value->IsInt32());
   1208       CHECK_EQ(fast_return_value_int32,
   1209                value->Int32Value(env.local()).FromJust());
   1210       // check uint32_t
   1211       fast_return_value_uint32 = static_cast<uint32_t>(int_value);
   1212       value = TestFastReturnValues<uint32_t>();
   1213       CHECK(value->IsUint32());
   1214       CHECK_EQ(fast_return_value_uint32,
   1215                value->Uint32Value(env.local()).FromJust());
   1216     }
   1217   }
   1218   // check double
   1219   value = TestFastReturnValues<double>();
   1220   CHECK(value->IsNumber());
   1221   CHECK_EQ(kFastReturnValueDouble,
   1222            value->ToNumber(env.local()).ToLocalChecked()->Value());
   1223   // check bool values
   1224   for (int i = 0; i < 2; i++) {
   1225     fast_return_value_bool = i == 0;
   1226     value = TestFastReturnValues<bool>();
   1227     CHECK(value->IsBoolean());
   1228     CHECK_EQ(fast_return_value_bool,
   1229              value->ToBoolean(env.local()).ToLocalChecked()->Value());
   1230   }
   1231   // check oddballs
   1232   ReturnValueOddball oddballs[] = {
   1233       kNullReturnValue,
   1234       kUndefinedReturnValue,
   1235       kEmptyStringReturnValue
   1236   };
   1237   for (size_t i = 0; i < arraysize(oddballs); i++) {
   1238     fast_return_value_void = oddballs[i];
   1239     value = TestFastReturnValues<void>();
   1240     switch (fast_return_value_void) {
   1241       case kNullReturnValue:
   1242         CHECK(value->IsNull());
   1243         break;
   1244       case kUndefinedReturnValue:
   1245         CHECK(value->IsUndefined());
   1246         break;
   1247       case kEmptyStringReturnValue:
   1248         CHECK(value->IsString());
   1249         CHECK_EQ(0, v8::String::Cast(*value)->Length());
   1250         break;
   1251     }
   1252   }
   1253   // check handles
   1254   fast_return_value_object_is_empty = false;
   1255   value = TestFastReturnValues<Object>();
   1256   CHECK(value->IsObject());
   1257   fast_return_value_object_is_empty = true;
   1258   value = TestFastReturnValues<Object>();
   1259   CHECK(value->IsUndefined());
   1260 }
   1261 
   1262 
   1263 THREADED_TEST(FunctionTemplateSetLength) {
   1264   LocalContext env;
   1265   v8::Isolate* isolate = env->GetIsolate();
   1266   v8::HandleScope scope(isolate);
   1267   {
   1268     Local<v8::FunctionTemplate> fun_templ =
   1269         v8::FunctionTemplate::New(isolate, handle_callback, Local<v8::Value>(),
   1270                                   Local<v8::Signature>(), 23);
   1271     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   1272     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
   1273     Local<Script> script = v8_compile("obj.length");
   1274     CHECK_EQ(23, v8_run_int32value(script));
   1275   }
   1276   {
   1277     Local<v8::FunctionTemplate> fun_templ =
   1278         v8::FunctionTemplate::New(isolate, handle_callback);
   1279     fun_templ->SetLength(22);
   1280     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   1281     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
   1282     Local<Script> script = v8_compile("obj.length");
   1283     CHECK_EQ(22, v8_run_int32value(script));
   1284   }
   1285   {
   1286     // Without setting length it defaults to 0.
   1287     Local<v8::FunctionTemplate> fun_templ =
   1288         v8::FunctionTemplate::New(isolate, handle_callback);
   1289     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   1290     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
   1291     Local<Script> script = v8_compile("obj.length");
   1292     CHECK_EQ(0, v8_run_int32value(script));
   1293   }
   1294 }
   1295 
   1296 
   1297 static void* expected_ptr;
   1298 static void callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   1299   void* ptr = v8::External::Cast(*args.Data())->Value();
   1300   CHECK_EQ(expected_ptr, ptr);
   1301   args.GetReturnValue().Set(true);
   1302 }
   1303 
   1304 
   1305 static void TestExternalPointerWrapping() {
   1306   LocalContext env;
   1307   v8::Isolate* isolate = env->GetIsolate();
   1308   v8::HandleScope scope(isolate);
   1309 
   1310   v8::Local<v8::Value> data = v8::External::New(isolate, expected_ptr);
   1311 
   1312   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   1313   CHECK(obj->Set(env.local(), v8_str("func"),
   1314                  v8::FunctionTemplate::New(isolate, callback, data)
   1315                      ->GetFunction(env.local())
   1316                      .ToLocalChecked())
   1317             .FromJust());
   1318   CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
   1319 
   1320   CHECK(CompileRun("function foo() {\n"
   1321                    "  for (var i = 0; i < 13; i++) obj.func();\n"
   1322                    "}\n"
   1323                    "foo(), true")
   1324             ->BooleanValue(env.local())
   1325             .FromJust());
   1326 }
   1327 
   1328 
   1329 THREADED_TEST(ExternalWrap) {
   1330   // Check heap allocated object.
   1331   int* ptr = new int;
   1332   expected_ptr = ptr;
   1333   TestExternalPointerWrapping();
   1334   delete ptr;
   1335 
   1336   // Check stack allocated object.
   1337   int foo;
   1338   expected_ptr = &foo;
   1339   TestExternalPointerWrapping();
   1340 
   1341   // Check not aligned addresses.
   1342   const int n = 100;
   1343   char* s = new char[n];
   1344   for (int i = 0; i < n; i++) {
   1345     expected_ptr = s + i;
   1346     TestExternalPointerWrapping();
   1347   }
   1348 
   1349   delete[] s;
   1350 
   1351   // Check several invalid addresses.
   1352   expected_ptr = reinterpret_cast<void*>(1);
   1353   TestExternalPointerWrapping();
   1354 
   1355   expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
   1356   TestExternalPointerWrapping();
   1357 
   1358   expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
   1359   TestExternalPointerWrapping();
   1360 
   1361 #if defined(V8_HOST_ARCH_X64)
   1362   // Check a value with a leading 1 bit in x64 Smi encoding.
   1363   expected_ptr = reinterpret_cast<void*>(0x400000000);
   1364   TestExternalPointerWrapping();
   1365 
   1366   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
   1367   TestExternalPointerWrapping();
   1368 
   1369   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
   1370   TestExternalPointerWrapping();
   1371 #endif
   1372 }
   1373 
   1374 
   1375 THREADED_TEST(FindInstanceInPrototypeChain) {
   1376   LocalContext env;
   1377   v8::Isolate* isolate = env->GetIsolate();
   1378   v8::HandleScope scope(isolate);
   1379 
   1380   Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New(isolate);
   1381   Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New(isolate);
   1382   Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New(isolate);
   1383   derived->Inherit(base);
   1384 
   1385   Local<v8::Function> base_function =
   1386       base->GetFunction(env.local()).ToLocalChecked();
   1387   Local<v8::Function> derived_function =
   1388       derived->GetFunction(env.local()).ToLocalChecked();
   1389   Local<v8::Function> other_function =
   1390       other->GetFunction(env.local()).ToLocalChecked();
   1391 
   1392   Local<v8::Object> base_instance =
   1393       base_function->NewInstance(env.local()).ToLocalChecked();
   1394   Local<v8::Object> derived_instance =
   1395       derived_function->NewInstance(env.local()).ToLocalChecked();
   1396   Local<v8::Object> derived_instance2 =
   1397       derived_function->NewInstance(env.local()).ToLocalChecked();
   1398   Local<v8::Object> other_instance =
   1399       other_function->NewInstance(env.local()).ToLocalChecked();
   1400   CHECK(
   1401       derived_instance2->Set(env.local(), v8_str("__proto__"), derived_instance)
   1402           .FromJust());
   1403   CHECK(other_instance->Set(env.local(), v8_str("__proto__"), derived_instance2)
   1404             .FromJust());
   1405 
   1406   // base_instance is only an instance of base.
   1407   CHECK(base_instance->Equals(env.local(),
   1408                               base_instance->FindInstanceInPrototypeChain(base))
   1409             .FromJust());
   1410   CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
   1411   CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
   1412 
   1413   // derived_instance is an instance of base and derived.
   1414   CHECK(derived_instance->Equals(env.local(),
   1415                                  derived_instance->FindInstanceInPrototypeChain(
   1416                                      base))
   1417             .FromJust());
   1418   CHECK(derived_instance->Equals(env.local(),
   1419                                  derived_instance->FindInstanceInPrototypeChain(
   1420                                      derived))
   1421             .FromJust());
   1422   CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
   1423 
   1424   // other_instance is an instance of other and its immediate
   1425   // prototype derived_instance2 is an instance of base and derived.
   1426   // Note, derived_instance is an instance of base and derived too,
   1427   // but it comes after derived_instance2 in the prototype chain of
   1428   // other_instance.
   1429   CHECK(derived_instance2->Equals(
   1430                              env.local(),
   1431                              other_instance->FindInstanceInPrototypeChain(base))
   1432             .FromJust());
   1433   CHECK(derived_instance2->Equals(env.local(),
   1434                                   other_instance->FindInstanceInPrototypeChain(
   1435                                       derived))
   1436             .FromJust());
   1437   CHECK(other_instance->Equals(
   1438                           env.local(),
   1439                           other_instance->FindInstanceInPrototypeChain(other))
   1440             .FromJust());
   1441 }
   1442 
   1443 
   1444 THREADED_TEST(TinyInteger) {
   1445   LocalContext env;
   1446   v8::Isolate* isolate = env->GetIsolate();
   1447   v8::HandleScope scope(isolate);
   1448 
   1449   int32_t value = 239;
   1450   Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
   1451   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1452 
   1453   value_obj = v8::Integer::New(isolate, value);
   1454   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1455 }
   1456 
   1457 
   1458 THREADED_TEST(BigSmiInteger) {
   1459   LocalContext env;
   1460   v8::HandleScope scope(env->GetIsolate());
   1461   v8::Isolate* isolate = CcTest::isolate();
   1462 
   1463   int32_t value = i::Smi::kMaxValue;
   1464   // We cannot add one to a Smi::kMaxValue without wrapping.
   1465   if (i::SmiValuesAre31Bits()) {
   1466     CHECK(i::Smi::IsValid(value));
   1467     CHECK(!i::Smi::IsValid(value + 1));
   1468 
   1469     Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
   1470     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1471 
   1472     value_obj = v8::Integer::New(isolate, value);
   1473     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1474   }
   1475 }
   1476 
   1477 
   1478 THREADED_TEST(BigInteger) {
   1479   LocalContext env;
   1480   v8::HandleScope scope(env->GetIsolate());
   1481   v8::Isolate* isolate = CcTest::isolate();
   1482 
   1483   // We cannot add one to a Smi::kMaxValue without wrapping.
   1484   if (i::SmiValuesAre31Bits()) {
   1485     // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
   1486     // The code will not be run in that case, due to the "if" guard.
   1487     int32_t value =
   1488         static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
   1489     CHECK(value > i::Smi::kMaxValue);
   1490     CHECK(!i::Smi::IsValid(value));
   1491 
   1492     Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
   1493     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1494 
   1495     value_obj = v8::Integer::New(isolate, value);
   1496     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1497   }
   1498 }
   1499 
   1500 
   1501 THREADED_TEST(TinyUnsignedInteger) {
   1502   LocalContext env;
   1503   v8::HandleScope scope(env->GetIsolate());
   1504   v8::Isolate* isolate = CcTest::isolate();
   1505 
   1506   uint32_t value = 239;
   1507 
   1508   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
   1509   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1510 
   1511   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
   1512   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1513 }
   1514 
   1515 
   1516 THREADED_TEST(BigUnsignedSmiInteger) {
   1517   LocalContext env;
   1518   v8::HandleScope scope(env->GetIsolate());
   1519   v8::Isolate* isolate = CcTest::isolate();
   1520 
   1521   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
   1522   CHECK(i::Smi::IsValid(value));
   1523   CHECK(!i::Smi::IsValid(value + 1));
   1524 
   1525   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
   1526   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1527 
   1528   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
   1529   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1530 }
   1531 
   1532 
   1533 THREADED_TEST(BigUnsignedInteger) {
   1534   LocalContext env;
   1535   v8::HandleScope scope(env->GetIsolate());
   1536   v8::Isolate* isolate = CcTest::isolate();
   1537 
   1538   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
   1539   CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
   1540   CHECK(!i::Smi::IsValid(value));
   1541 
   1542   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
   1543   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1544 
   1545   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
   1546   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1547 }
   1548 
   1549 
   1550 THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
   1551   LocalContext env;
   1552   v8::HandleScope scope(env->GetIsolate());
   1553   v8::Isolate* isolate = CcTest::isolate();
   1554 
   1555   uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
   1556   uint32_t value = INT32_MAX_AS_UINT + 1;
   1557   CHECK(value > INT32_MAX_AS_UINT);  // No overflow.
   1558 
   1559   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
   1560   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1561 
   1562   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
   1563   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
   1564 }
   1565 
   1566 
   1567 THREADED_TEST(IsNativeError) {
   1568   LocalContext env;
   1569   v8::HandleScope scope(env->GetIsolate());
   1570   v8::Local<Value> syntax_error = CompileRun(
   1571       "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
   1572   CHECK(syntax_error->IsNativeError());
   1573   v8::Local<Value> not_error = CompileRun("{a:42}");
   1574   CHECK(!not_error->IsNativeError());
   1575   v8::Local<Value> not_object = CompileRun("42");
   1576   CHECK(!not_object->IsNativeError());
   1577 }
   1578 
   1579 
   1580 THREADED_TEST(IsGeneratorFunctionOrObject) {
   1581   LocalContext env;
   1582   v8::HandleScope scope(env->GetIsolate());
   1583 
   1584   CompileRun("function *gen() { yield 1; }\nfunction func() {}");
   1585   v8::Local<Value> gen = CompileRun("gen");
   1586   v8::Local<Value> genObj = CompileRun("gen()");
   1587   v8::Local<Value> object = CompileRun("{a:42}");
   1588   v8::Local<Value> func = CompileRun("func");
   1589 
   1590   CHECK(gen->IsGeneratorFunction());
   1591   CHECK(gen->IsFunction());
   1592   CHECK(!gen->IsGeneratorObject());
   1593 
   1594   CHECK(!genObj->IsGeneratorFunction());
   1595   CHECK(!genObj->IsFunction());
   1596   CHECK(genObj->IsGeneratorObject());
   1597 
   1598   CHECK(!object->IsGeneratorFunction());
   1599   CHECK(!object->IsFunction());
   1600   CHECK(!object->IsGeneratorObject());
   1601 
   1602   CHECK(!func->IsGeneratorFunction());
   1603   CHECK(func->IsFunction());
   1604   CHECK(!func->IsGeneratorObject());
   1605 }
   1606 
   1607 
   1608 THREADED_TEST(ArgumentsObject) {
   1609   LocalContext env;
   1610   v8::HandleScope scope(env->GetIsolate());
   1611   v8::Local<Value> arguments_object =
   1612       CompileRun("var out = 0; (function(){ out = arguments; })(1,2,3); out;");
   1613   CHECK(arguments_object->IsArgumentsObject());
   1614   v8::Local<Value> array = CompileRun("[1,2,3]");
   1615   CHECK(!array->IsArgumentsObject());
   1616   v8::Local<Value> object = CompileRun("{a:42}");
   1617   CHECK(!object->IsArgumentsObject());
   1618 }
   1619 
   1620 
   1621 THREADED_TEST(IsMapOrSet) {
   1622   LocalContext env;
   1623   v8::HandleScope scope(env->GetIsolate());
   1624   v8::Local<Value> map = CompileRun("new Map()");
   1625   v8::Local<Value> set = CompileRun("new Set()");
   1626   v8::Local<Value> weak_map = CompileRun("new WeakMap()");
   1627   v8::Local<Value> weak_set = CompileRun("new WeakSet()");
   1628   CHECK(map->IsMap());
   1629   CHECK(set->IsSet());
   1630   CHECK(weak_map->IsWeakMap());
   1631   CHECK(weak_set->IsWeakSet());
   1632 
   1633   CHECK(!map->IsSet());
   1634   CHECK(!map->IsWeakMap());
   1635   CHECK(!map->IsWeakSet());
   1636 
   1637   CHECK(!set->IsMap());
   1638   CHECK(!set->IsWeakMap());
   1639   CHECK(!set->IsWeakSet());
   1640 
   1641   CHECK(!weak_map->IsMap());
   1642   CHECK(!weak_map->IsSet());
   1643   CHECK(!weak_map->IsWeakSet());
   1644 
   1645   CHECK(!weak_set->IsMap());
   1646   CHECK(!weak_set->IsSet());
   1647   CHECK(!weak_set->IsWeakMap());
   1648 
   1649   v8::Local<Value> object = CompileRun("{a:42}");
   1650   CHECK(!object->IsMap());
   1651   CHECK(!object->IsSet());
   1652   CHECK(!object->IsWeakMap());
   1653   CHECK(!object->IsWeakSet());
   1654 }
   1655 
   1656 
   1657 THREADED_TEST(StringObject) {
   1658   LocalContext env;
   1659   v8::HandleScope scope(env->GetIsolate());
   1660   v8::Local<Value> boxed_string = CompileRun("new String(\"test\")");
   1661   CHECK(boxed_string->IsStringObject());
   1662   v8::Local<Value> unboxed_string = CompileRun("\"test\"");
   1663   CHECK(!unboxed_string->IsStringObject());
   1664   v8::Local<Value> boxed_not_string = CompileRun("new Number(42)");
   1665   CHECK(!boxed_not_string->IsStringObject());
   1666   v8::Local<Value> not_object = CompileRun("0");
   1667   CHECK(!not_object->IsStringObject());
   1668   v8::Local<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
   1669   CHECK(!as_boxed.IsEmpty());
   1670   Local<v8::String> the_string = as_boxed->ValueOf();
   1671   CHECK(!the_string.IsEmpty());
   1672   ExpectObject("\"test\"", the_string);
   1673   v8::Local<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
   1674   CHECK(new_boxed_string->IsStringObject());
   1675   as_boxed = new_boxed_string.As<v8::StringObject>();
   1676   the_string = as_boxed->ValueOf();
   1677   CHECK(!the_string.IsEmpty());
   1678   ExpectObject("\"test\"", the_string);
   1679 }
   1680 
   1681 
   1682 TEST(StringObjectDelete) {
   1683   LocalContext context;
   1684   v8::HandleScope scope(context->GetIsolate());
   1685   v8::Local<Value> boxed_string = CompileRun("new String(\"test\")");
   1686   CHECK(boxed_string->IsStringObject());
   1687   v8::Local<v8::Object> str_obj = boxed_string.As<v8::Object>();
   1688   CHECK(!str_obj->Delete(context.local(), 2).FromJust());
   1689   CHECK(!str_obj->Delete(context.local(), v8_num(2)).FromJust());
   1690 }
   1691 
   1692 
   1693 THREADED_TEST(NumberObject) {
   1694   LocalContext env;
   1695   v8::HandleScope scope(env->GetIsolate());
   1696   v8::Local<Value> boxed_number = CompileRun("new Number(42)");
   1697   CHECK(boxed_number->IsNumberObject());
   1698   v8::Local<Value> unboxed_number = CompileRun("42");
   1699   CHECK(!unboxed_number->IsNumberObject());
   1700   v8::Local<Value> boxed_not_number = CompileRun("new Boolean(false)");
   1701   CHECK(!boxed_not_number->IsNumberObject());
   1702   v8::Local<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
   1703   CHECK(!as_boxed.IsEmpty());
   1704   double the_number = as_boxed->ValueOf();
   1705   CHECK_EQ(42.0, the_number);
   1706   v8::Local<v8::Value> new_boxed_number =
   1707       v8::NumberObject::New(env->GetIsolate(), 43);
   1708   CHECK(new_boxed_number->IsNumberObject());
   1709   as_boxed = new_boxed_number.As<v8::NumberObject>();
   1710   the_number = as_boxed->ValueOf();
   1711   CHECK_EQ(43.0, the_number);
   1712 }
   1713 
   1714 
   1715 THREADED_TEST(BooleanObject) {
   1716   LocalContext env;
   1717   v8::HandleScope scope(env->GetIsolate());
   1718   v8::Local<Value> boxed_boolean = CompileRun("new Boolean(true)");
   1719   CHECK(boxed_boolean->IsBooleanObject());
   1720   v8::Local<Value> unboxed_boolean = CompileRun("true");
   1721   CHECK(!unboxed_boolean->IsBooleanObject());
   1722   v8::Local<Value> boxed_not_boolean = CompileRun("new Number(42)");
   1723   CHECK(!boxed_not_boolean->IsBooleanObject());
   1724   v8::Local<v8::BooleanObject> as_boxed = boxed_boolean.As<v8::BooleanObject>();
   1725   CHECK(!as_boxed.IsEmpty());
   1726   bool the_boolean = as_boxed->ValueOf();
   1727   CHECK_EQ(true, the_boolean);
   1728   v8::Local<v8::Value> boxed_true =
   1729       v8::BooleanObject::New(env->GetIsolate(), true);
   1730   v8::Local<v8::Value> boxed_false =
   1731       v8::BooleanObject::New(env->GetIsolate(), false);
   1732   CHECK(boxed_true->IsBooleanObject());
   1733   CHECK(boxed_false->IsBooleanObject());
   1734   as_boxed = boxed_true.As<v8::BooleanObject>();
   1735   CHECK_EQ(true, as_boxed->ValueOf());
   1736   as_boxed = boxed_false.As<v8::BooleanObject>();
   1737   CHECK_EQ(false, as_boxed->ValueOf());
   1738 }
   1739 
   1740 
   1741 THREADED_TEST(PrimitiveAndWrappedBooleans) {
   1742   LocalContext env;
   1743   v8::HandleScope scope(env->GetIsolate());
   1744 
   1745   Local<Value> primitive_false = Boolean::New(env->GetIsolate(), false);
   1746   CHECK(primitive_false->IsBoolean());
   1747   CHECK(!primitive_false->IsBooleanObject());
   1748   CHECK(!primitive_false->BooleanValue(env.local()).FromJust());
   1749   CHECK(!primitive_false->IsTrue());
   1750   CHECK(primitive_false->IsFalse());
   1751 
   1752   Local<Value> false_value = BooleanObject::New(env->GetIsolate(), false);
   1753   CHECK(!false_value->IsBoolean());
   1754   CHECK(false_value->IsBooleanObject());
   1755   CHECK(false_value->BooleanValue(env.local()).FromJust());
   1756   CHECK(!false_value->IsTrue());
   1757   CHECK(!false_value->IsFalse());
   1758 
   1759   Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
   1760   CHECK(!false_boolean_object->IsBoolean());
   1761   CHECK(false_boolean_object->IsBooleanObject());
   1762   CHECK(false_boolean_object->BooleanValue(env.local()).FromJust());
   1763   CHECK(!false_boolean_object->ValueOf());
   1764   CHECK(!false_boolean_object->IsTrue());
   1765   CHECK(!false_boolean_object->IsFalse());
   1766 
   1767   Local<Value> primitive_true = Boolean::New(env->GetIsolate(), true);
   1768   CHECK(primitive_true->IsBoolean());
   1769   CHECK(!primitive_true->IsBooleanObject());
   1770   CHECK(primitive_true->BooleanValue(env.local()).FromJust());
   1771   CHECK(primitive_true->IsTrue());
   1772   CHECK(!primitive_true->IsFalse());
   1773 
   1774   Local<Value> true_value = BooleanObject::New(env->GetIsolate(), true);
   1775   CHECK(!true_value->IsBoolean());
   1776   CHECK(true_value->IsBooleanObject());
   1777   CHECK(true_value->BooleanValue(env.local()).FromJust());
   1778   CHECK(!true_value->IsTrue());
   1779   CHECK(!true_value->IsFalse());
   1780 
   1781   Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
   1782   CHECK(!true_boolean_object->IsBoolean());
   1783   CHECK(true_boolean_object->IsBooleanObject());
   1784   CHECK(true_boolean_object->BooleanValue(env.local()).FromJust());
   1785   CHECK(true_boolean_object->ValueOf());
   1786   CHECK(!true_boolean_object->IsTrue());
   1787   CHECK(!true_boolean_object->IsFalse());
   1788 }
   1789 
   1790 
   1791 THREADED_TEST(Number) {
   1792   LocalContext env;
   1793   v8::HandleScope scope(env->GetIsolate());
   1794   double PI = 3.1415926;
   1795   Local<v8::Number> pi_obj = v8::Number::New(env->GetIsolate(), PI);
   1796   CHECK_EQ(PI, pi_obj->NumberValue(env.local()).FromJust());
   1797 }
   1798 
   1799 
   1800 THREADED_TEST(ToNumber) {
   1801   LocalContext env;
   1802   v8::Isolate* isolate = CcTest::isolate();
   1803   v8::HandleScope scope(isolate);
   1804   Local<String> str = v8_str("3.1415926");
   1805   CHECK_EQ(3.1415926, str->NumberValue(env.local()).FromJust());
   1806   v8::Local<v8::Boolean> t = v8::True(isolate);
   1807   CHECK_EQ(1.0, t->NumberValue(env.local()).FromJust());
   1808   v8::Local<v8::Boolean> f = v8::False(isolate);
   1809   CHECK_EQ(0.0, f->NumberValue(env.local()).FromJust());
   1810 }
   1811 
   1812 
   1813 THREADED_TEST(Date) {
   1814   LocalContext env;
   1815   v8::HandleScope scope(env->GetIsolate());
   1816   double PI = 3.1415926;
   1817   Local<Value> date = v8::Date::New(env.local(), PI).ToLocalChecked();
   1818   CHECK_EQ(3.0, date->NumberValue(env.local()).FromJust());
   1819   CHECK(date.As<v8::Date>()
   1820             ->Set(env.local(), v8_str("property"),
   1821                   v8::Integer::New(env->GetIsolate(), 42))
   1822             .FromJust());
   1823   CHECK_EQ(42, date.As<v8::Date>()
   1824                    ->Get(env.local(), v8_str("property"))
   1825                    .ToLocalChecked()
   1826                    ->Int32Value(env.local())
   1827                    .FromJust());
   1828 }
   1829 
   1830 
   1831 THREADED_TEST(Boolean) {
   1832   LocalContext env;
   1833   v8::Isolate* isolate = env->GetIsolate();
   1834   v8::HandleScope scope(isolate);
   1835   v8::Local<v8::Boolean> t = v8::True(isolate);
   1836   CHECK(t->Value());
   1837   v8::Local<v8::Boolean> f = v8::False(isolate);
   1838   CHECK(!f->Value());
   1839   v8::Local<v8::Primitive> u = v8::Undefined(isolate);
   1840   CHECK(!u->BooleanValue(env.local()).FromJust());
   1841   v8::Local<v8::Primitive> n = v8::Null(isolate);
   1842   CHECK(!n->BooleanValue(env.local()).FromJust());
   1843   v8::Local<String> str1 = v8_str("");
   1844   CHECK(!str1->BooleanValue(env.local()).FromJust());
   1845   v8::Local<String> str2 = v8_str("x");
   1846   CHECK(str2->BooleanValue(env.local()).FromJust());
   1847   CHECK(!v8::Number::New(isolate, 0)->BooleanValue(env.local()).FromJust());
   1848   CHECK(v8::Number::New(isolate, -1)->BooleanValue(env.local()).FromJust());
   1849   CHECK(v8::Number::New(isolate, 1)->BooleanValue(env.local()).FromJust());
   1850   CHECK(v8::Number::New(isolate, 42)->BooleanValue(env.local()).FromJust());
   1851   CHECK(!v8_compile("NaN")
   1852              ->Run(env.local())
   1853              .ToLocalChecked()
   1854              ->BooleanValue(env.local())
   1855              .FromJust());
   1856 }
   1857 
   1858 
   1859 static void DummyCallHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
   1860   ApiTestFuzzer::Fuzz();
   1861   args.GetReturnValue().Set(v8_num(13.4));
   1862 }
   1863 
   1864 
   1865 static void GetM(Local<String> name,
   1866                  const v8::PropertyCallbackInfo<v8::Value>& info) {
   1867   ApiTestFuzzer::Fuzz();
   1868   info.GetReturnValue().Set(v8_num(876));
   1869 }
   1870 
   1871 
   1872 THREADED_TEST(GlobalPrototype) {
   1873   v8::Isolate* isolate = CcTest::isolate();
   1874   v8::HandleScope scope(isolate);
   1875   v8::Local<v8::FunctionTemplate> func_templ =
   1876       v8::FunctionTemplate::New(isolate);
   1877   func_templ->PrototypeTemplate()->Set(
   1878       isolate, "dummy", v8::FunctionTemplate::New(isolate, DummyCallHandler));
   1879   v8::Local<ObjectTemplate> templ = func_templ->InstanceTemplate();
   1880   templ->Set(isolate, "x", v8_num(200));
   1881   templ->SetAccessor(v8_str("m"), GetM);
   1882   LocalContext env(0, templ);
   1883   v8::Local<Script> script(v8_compile("dummy()"));
   1884   v8::Local<Value> result(script->Run(env.local()).ToLocalChecked());
   1885   CHECK_EQ(13.4, result->NumberValue(env.local()).FromJust());
   1886   CHECK_EQ(200, v8_run_int32value(v8_compile("x")));
   1887   CHECK_EQ(876, v8_run_int32value(v8_compile("m")));
   1888 }
   1889 
   1890 
   1891 THREADED_TEST(ObjectTemplate) {
   1892   v8::Isolate* isolate = CcTest::isolate();
   1893   v8::HandleScope scope(isolate);
   1894   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
   1895   v8::Local<v8::String> class_name = v8_str("the_class_name");
   1896   fun->SetClassName(class_name);
   1897   Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate, fun);
   1898   templ1->Set(isolate, "x", v8_num(10));
   1899   templ1->Set(isolate, "y", v8_num(13));
   1900   LocalContext env;
   1901   Local<v8::Object> instance1 =
   1902       templ1->NewInstance(env.local()).ToLocalChecked();
   1903   CHECK(class_name->StrictEquals(instance1->GetConstructorName()));
   1904   CHECK(env->Global()->Set(env.local(), v8_str("p"), instance1).FromJust());
   1905   CHECK(v8_compile("(p.x == 10)")
   1906             ->Run(env.local())
   1907             .ToLocalChecked()
   1908             ->BooleanValue(env.local())
   1909             .FromJust());
   1910   CHECK(v8_compile("(p.y == 13)")
   1911             ->Run(env.local())
   1912             .ToLocalChecked()
   1913             ->BooleanValue(env.local())
   1914             .FromJust());
   1915   Local<v8::FunctionTemplate> fun2 = v8::FunctionTemplate::New(isolate);
   1916   fun2->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
   1917   Local<ObjectTemplate> templ2 = fun2->InstanceTemplate();
   1918   templ2->Set(isolate, "a", v8_num(12));
   1919   templ2->Set(isolate, "b", templ1);
   1920   Local<v8::Object> instance2 =
   1921       templ2->NewInstance(env.local()).ToLocalChecked();
   1922   CHECK(env->Global()->Set(env.local(), v8_str("q"), instance2).FromJust());
   1923   CHECK(v8_compile("(q.nirk == 123)")
   1924             ->Run(env.local())
   1925             .ToLocalChecked()
   1926             ->BooleanValue(env.local())
   1927             .FromJust());
   1928   CHECK(v8_compile("(q.a == 12)")
   1929             ->Run(env.local())
   1930             .ToLocalChecked()
   1931             ->BooleanValue(env.local())
   1932             .FromJust());
   1933   CHECK(v8_compile("(q.b.x == 10)")
   1934             ->Run(env.local())
   1935             .ToLocalChecked()
   1936             ->BooleanValue(env.local())
   1937             .FromJust());
   1938   CHECK(v8_compile("(q.b.y == 13)")
   1939             ->Run(env.local())
   1940             .ToLocalChecked()
   1941             ->BooleanValue(env.local())
   1942             .FromJust());
   1943 }
   1944 
   1945 
   1946 static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
   1947   ApiTestFuzzer::Fuzz();
   1948   args.GetReturnValue().Set(v8_num(17.2));
   1949 }
   1950 
   1951 
   1952 static void GetKnurd(Local<String> property,
   1953                      const v8::PropertyCallbackInfo<v8::Value>& info) {
   1954   ApiTestFuzzer::Fuzz();
   1955   info.GetReturnValue().Set(v8_num(15.2));
   1956 }
   1957 
   1958 
   1959 THREADED_TEST(DescriptorInheritance) {
   1960   v8::Isolate* isolate = CcTest::isolate();
   1961   v8::HandleScope scope(isolate);
   1962   v8::Local<v8::FunctionTemplate> super = v8::FunctionTemplate::New(isolate);
   1963   super->PrototypeTemplate()->Set(isolate, "flabby",
   1964                                   v8::FunctionTemplate::New(isolate,
   1965                                                             GetFlabby));
   1966   super->PrototypeTemplate()->Set(isolate, "PI", v8_num(3.14));
   1967 
   1968   super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
   1969 
   1970   v8::Local<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New(isolate);
   1971   base1->Inherit(super);
   1972   base1->PrototypeTemplate()->Set(isolate, "v1", v8_num(20.1));
   1973 
   1974   v8::Local<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New(isolate);
   1975   base2->Inherit(super);
   1976   base2->PrototypeTemplate()->Set(isolate, "v2", v8_num(10.1));
   1977 
   1978   LocalContext env;
   1979 
   1980   CHECK(env->Global()
   1981             ->Set(env.local(), v8_str("s"),
   1982                   super->GetFunction(env.local()).ToLocalChecked())
   1983             .FromJust());
   1984   CHECK(env->Global()
   1985             ->Set(env.local(), v8_str("base1"),
   1986                   base1->GetFunction(env.local()).ToLocalChecked())
   1987             .FromJust());
   1988   CHECK(env->Global()
   1989             ->Set(env.local(), v8_str("base2"),
   1990                   base2->GetFunction(env.local()).ToLocalChecked())
   1991             .FromJust());
   1992 
   1993   // Checks right __proto__ chain.
   1994   CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")
   1995             ->BooleanValue(env.local())
   1996             .FromJust());
   1997   CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")
   1998             ->BooleanValue(env.local())
   1999             .FromJust());
   2000 
   2001   CHECK(v8_compile("s.prototype.PI == 3.14")
   2002             ->Run(env.local())
   2003             .ToLocalChecked()
   2004             ->BooleanValue(env.local())
   2005             .FromJust());
   2006 
   2007   // Instance accessor should not be visible on function object or its prototype
   2008   CHECK(
   2009       CompileRun("s.knurd == undefined")->BooleanValue(env.local()).FromJust());
   2010   CHECK(CompileRun("s.prototype.knurd == undefined")
   2011             ->BooleanValue(env.local())
   2012             .FromJust());
   2013   CHECK(CompileRun("base1.prototype.knurd == undefined")
   2014             ->BooleanValue(env.local())
   2015             .FromJust());
   2016 
   2017   CHECK(env->Global()
   2018             ->Set(env.local(), v8_str("obj"), base1->GetFunction(env.local())
   2019                                                   .ToLocalChecked()
   2020                                                   ->NewInstance(env.local())
   2021                                                   .ToLocalChecked())
   2022             .FromJust());
   2023   CHECK_EQ(17.2, v8_compile("obj.flabby()")
   2024                      ->Run(env.local())
   2025                      .ToLocalChecked()
   2026                      ->NumberValue(env.local())
   2027                      .FromJust());
   2028   CHECK(v8_compile("'flabby' in obj")
   2029             ->Run(env.local())
   2030             .ToLocalChecked()
   2031             ->BooleanValue(env.local())
   2032             .FromJust());
   2033   CHECK_EQ(15.2, v8_compile("obj.knurd")
   2034                      ->Run(env.local())
   2035                      .ToLocalChecked()
   2036                      ->NumberValue(env.local())
   2037                      .FromJust());
   2038   CHECK(v8_compile("'knurd' in obj")
   2039             ->Run(env.local())
   2040             .ToLocalChecked()
   2041             ->BooleanValue(env.local())
   2042             .FromJust());
   2043   CHECK_EQ(20.1, v8_compile("obj.v1")
   2044                      ->Run(env.local())
   2045                      .ToLocalChecked()
   2046                      ->NumberValue(env.local())
   2047                      .FromJust());
   2048 
   2049   CHECK(env->Global()
   2050             ->Set(env.local(), v8_str("obj2"), base2->GetFunction(env.local())
   2051                                                    .ToLocalChecked()
   2052                                                    ->NewInstance(env.local())
   2053                                                    .ToLocalChecked())
   2054             .FromJust());
   2055   CHECK_EQ(17.2, v8_compile("obj2.flabby()")
   2056                      ->Run(env.local())
   2057                      .ToLocalChecked()
   2058                      ->NumberValue(env.local())
   2059                      .FromJust());
   2060   CHECK(v8_compile("'flabby' in obj2")
   2061             ->Run(env.local())
   2062             .ToLocalChecked()
   2063             ->BooleanValue(env.local())
   2064             .FromJust());
   2065   CHECK_EQ(15.2, v8_compile("obj2.knurd")
   2066                      ->Run(env.local())
   2067                      .ToLocalChecked()
   2068                      ->NumberValue(env.local())
   2069                      .FromJust());
   2070   CHECK(v8_compile("'knurd' in obj2")
   2071             ->Run(env.local())
   2072             .ToLocalChecked()
   2073             ->BooleanValue(env.local())
   2074             .FromJust());
   2075   CHECK_EQ(10.1, v8_compile("obj2.v2")
   2076                      ->Run(env.local())
   2077                      .ToLocalChecked()
   2078                      ->NumberValue(env.local())
   2079                      .FromJust());
   2080 
   2081   // base1 and base2 cannot cross reference to each's prototype
   2082   CHECK(v8_compile("obj.v2")->Run(env.local()).ToLocalChecked()->IsUndefined());
   2083   CHECK(
   2084       v8_compile("obj2.v1")->Run(env.local()).ToLocalChecked()->IsUndefined());
   2085 }
   2086 
   2087 
   2088 // Helper functions for Interceptor/Accessor interaction tests
   2089 
   2090 void SimpleAccessorGetter(Local<String> name,
   2091                           const v8::PropertyCallbackInfo<v8::Value>& info) {
   2092   Local<Object> self = Local<Object>::Cast(info.This());
   2093   info.GetReturnValue().Set(self->Get(info.GetIsolate()->GetCurrentContext(),
   2094                                       String::Concat(v8_str("accessor_"), name))
   2095                                 .ToLocalChecked());
   2096 }
   2097 
   2098 void SimpleAccessorSetter(Local<String> name, Local<Value> value,
   2099                           const v8::PropertyCallbackInfo<void>& info) {
   2100   Local<Object> self = Local<Object>::Cast(info.This());
   2101   CHECK(self->Set(info.GetIsolate()->GetCurrentContext(),
   2102                   String::Concat(v8_str("accessor_"), name), value)
   2103             .FromJust());
   2104 }
   2105 
   2106 void SymbolAccessorGetter(Local<Name> name,
   2107                           const v8::PropertyCallbackInfo<v8::Value>& info) {
   2108   CHECK(name->IsSymbol());
   2109   Local<Symbol> sym = Local<Symbol>::Cast(name);
   2110   if (sym->Name()->IsUndefined())
   2111     return;
   2112   SimpleAccessorGetter(Local<String>::Cast(sym->Name()), info);
   2113 }
   2114 
   2115 void SymbolAccessorSetter(Local<Name> name, Local<Value> value,
   2116                           const v8::PropertyCallbackInfo<void>& info) {
   2117   CHECK(name->IsSymbol());
   2118   Local<Symbol> sym = Local<Symbol>::Cast(name);
   2119   if (sym->Name()->IsUndefined())
   2120     return;
   2121   SimpleAccessorSetter(Local<String>::Cast(sym->Name()), value, info);
   2122 }
   2123 
   2124 void SymbolAccessorGetterReturnsDefault(
   2125     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   2126   CHECK(name->IsSymbol());
   2127   Local<Symbol> sym = Local<Symbol>::Cast(name);
   2128   if (sym->Name()->IsUndefined()) return;
   2129   info.GetReturnValue().Set(info.Data());
   2130 }
   2131 
   2132 static void ThrowingSymbolAccessorGetter(
   2133     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   2134   info.GetReturnValue().Set(info.GetIsolate()->ThrowException(name));
   2135 }
   2136 
   2137 
   2138 THREADED_TEST(ExecutableAccessorIsPreservedOnAttributeChange) {
   2139   v8::Isolate* isolate = CcTest::isolate();
   2140   v8::HandleScope scope(isolate);
   2141   LocalContext env;
   2142   v8::Local<v8::Value> res = CompileRun("var a = []; a;");
   2143   i::Handle<i::JSReceiver> a(v8::Utils::OpenHandle(v8::Object::Cast(*res)));
   2144   CHECK(a->map()->instance_descriptors()->IsFixedArray());
   2145   CHECK_GT(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
   2146   CompileRun("Object.defineProperty(a, 'length', { writable: false });");
   2147   CHECK_EQ(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
   2148   // But we should still have an ExecutableAccessorInfo.
   2149   i::Handle<i::String> name(v8::Utils::OpenHandle(*v8_str("length")));
   2150   i::LookupIterator it(a, name, i::LookupIterator::OWN_SKIP_INTERCEPTOR);
   2151   CHECK_EQ(i::LookupIterator::ACCESSOR, it.state());
   2152   CHECK(it.GetAccessors()->IsExecutableAccessorInfo());
   2153 }
   2154 
   2155 
   2156 THREADED_TEST(UndefinedIsNotEnumerable) {
   2157   LocalContext env;
   2158   v8::HandleScope scope(env->GetIsolate());
   2159   v8::Local<Value> result = CompileRun("this.propertyIsEnumerable(undefined)");
   2160   CHECK(result->IsFalse());
   2161 }
   2162 
   2163 
   2164 v8::Local<Script> call_recursively_script;
   2165 static const int kTargetRecursionDepth = 150;  // near maximum
   2166 
   2167 
   2168 static void CallScriptRecursivelyCall(
   2169     const v8::FunctionCallbackInfo<v8::Value>& args) {
   2170   ApiTestFuzzer::Fuzz();
   2171   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   2172   int depth = args.This()
   2173                   ->Get(context, v8_str("depth"))
   2174                   .ToLocalChecked()
   2175                   ->Int32Value(context)
   2176                   .FromJust();
   2177   if (depth == kTargetRecursionDepth) return;
   2178   CHECK(args.This()
   2179             ->Set(context, v8_str("depth"),
   2180                   v8::Integer::New(args.GetIsolate(), depth + 1))
   2181             .FromJust());
   2182   args.GetReturnValue().Set(
   2183       call_recursively_script->Run(context).ToLocalChecked());
   2184 }
   2185 
   2186 
   2187 static void CallFunctionRecursivelyCall(
   2188     const v8::FunctionCallbackInfo<v8::Value>& args) {
   2189   ApiTestFuzzer::Fuzz();
   2190   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   2191   int depth = args.This()
   2192                   ->Get(context, v8_str("depth"))
   2193                   .ToLocalChecked()
   2194                   ->Int32Value(context)
   2195                   .FromJust();
   2196   if (depth == kTargetRecursionDepth) {
   2197     printf("[depth = %d]\n", depth);
   2198     return;
   2199   }
   2200   CHECK(args.This()
   2201             ->Set(context, v8_str("depth"),
   2202                   v8::Integer::New(args.GetIsolate(), depth + 1))
   2203             .FromJust());
   2204   v8::Local<Value> function =
   2205       args.This()
   2206           ->Get(context, v8_str("callFunctionRecursively"))
   2207           .ToLocalChecked();
   2208   args.GetReturnValue().Set(function.As<Function>()
   2209                                 ->Call(context, args.This(), 0, NULL)
   2210                                 .ToLocalChecked());
   2211 }
   2212 
   2213 
   2214 THREADED_TEST(DeepCrossLanguageRecursion) {
   2215   v8::Isolate* isolate = CcTest::isolate();
   2216   v8::HandleScope scope(isolate);
   2217   v8::Local<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
   2218   global->Set(v8_str("callScriptRecursively"),
   2219               v8::FunctionTemplate::New(isolate, CallScriptRecursivelyCall));
   2220   global->Set(v8_str("callFunctionRecursively"),
   2221               v8::FunctionTemplate::New(isolate, CallFunctionRecursivelyCall));
   2222   LocalContext env(NULL, global);
   2223 
   2224   CHECK(env->Global()
   2225             ->Set(env.local(), v8_str("depth"), v8::Integer::New(isolate, 0))
   2226             .FromJust());
   2227   call_recursively_script = v8_compile("callScriptRecursively()");
   2228   call_recursively_script->Run(env.local()).ToLocalChecked();
   2229   call_recursively_script = v8::Local<Script>();
   2230 
   2231   CHECK(env->Global()
   2232             ->Set(env.local(), v8_str("depth"), v8::Integer::New(isolate, 0))
   2233             .FromJust());
   2234   CompileRun("callFunctionRecursively()");
   2235 }
   2236 
   2237 
   2238 static void ThrowingPropertyHandlerGet(
   2239     Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
   2240   // Since this interceptor is used on "with" objects, the runtime will look up
   2241   // @@unscopables.  Punt.
   2242   if (key->IsSymbol()) return;
   2243   ApiTestFuzzer::Fuzz();
   2244   info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
   2245 }
   2246 
   2247 
   2248 static void ThrowingPropertyHandlerSet(
   2249     Local<Name> key, Local<Value>,
   2250     const v8::PropertyCallbackInfo<v8::Value>& info) {
   2251   info.GetIsolate()->ThrowException(key);
   2252   info.GetReturnValue().SetUndefined();  // not the same as empty handle
   2253 }
   2254 
   2255 
   2256 THREADED_TEST(CallbackExceptionRegression) {
   2257   v8::Isolate* isolate = CcTest::isolate();
   2258   v8::HandleScope scope(isolate);
   2259   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
   2260   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(
   2261       ThrowingPropertyHandlerGet, ThrowingPropertyHandlerSet));
   2262   LocalContext env;
   2263   CHECK(env->Global()
   2264             ->Set(env.local(), v8_str("obj"),
   2265                   obj->NewInstance(env.local()).ToLocalChecked())
   2266             .FromJust());
   2267   v8::Local<Value> otto =
   2268       CompileRun("try { with (obj) { otto; } } catch (e) { e; }");
   2269   CHECK(v8_str("otto")->Equals(env.local(), otto).FromJust());
   2270   v8::Local<Value> netto =
   2271       CompileRun("try { with (obj) { netto = 4; } } catch (e) { e; }");
   2272   CHECK(v8_str("netto")->Equals(env.local(), netto).FromJust());
   2273 }
   2274 
   2275 
   2276 THREADED_TEST(FunctionPrototype) {
   2277   v8::Isolate* isolate = CcTest::isolate();
   2278   v8::HandleScope scope(isolate);
   2279   Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(isolate);
   2280   Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
   2281   LocalContext env;
   2282   CHECK(env->Global()
   2283             ->Set(env.local(), v8_str("Foo"),
   2284                   Foo->GetFunction(env.local()).ToLocalChecked())
   2285             .FromJust());
   2286   Local<Script> script = v8_compile("Foo.prototype.plak");
   2287   CHECK_EQ(v8_run_int32value(script), 321);
   2288 }
   2289 
   2290 
   2291 THREADED_TEST(InternalFields) {
   2292   LocalContext env;
   2293   v8::Isolate* isolate = env->GetIsolate();
   2294   v8::HandleScope scope(isolate);
   2295 
   2296   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   2297   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
   2298   instance_templ->SetInternalFieldCount(1);
   2299   Local<v8::Object> obj = templ->GetFunction(env.local())
   2300                               .ToLocalChecked()
   2301                               ->NewInstance(env.local())
   2302                               .ToLocalChecked();
   2303   CHECK_EQ(1, obj->InternalFieldCount());
   2304   CHECK(obj->GetInternalField(0)->IsUndefined());
   2305   obj->SetInternalField(0, v8_num(17));
   2306   CHECK_EQ(17, obj->GetInternalField(0)->Int32Value(env.local()).FromJust());
   2307 }
   2308 
   2309 
   2310 THREADED_TEST(GlobalObjectInternalFields) {
   2311   v8::Isolate* isolate = CcTest::isolate();
   2312   v8::HandleScope scope(isolate);
   2313   Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
   2314   global_template->SetInternalFieldCount(1);
   2315   LocalContext env(NULL, global_template);
   2316   v8::Local<v8::Object> global_proxy = env->Global();
   2317   v8::Local<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
   2318   CHECK_EQ(1, global->InternalFieldCount());
   2319   CHECK(global->GetInternalField(0)->IsUndefined());
   2320   global->SetInternalField(0, v8_num(17));
   2321   CHECK_EQ(17, global->GetInternalField(0)->Int32Value(env.local()).FromJust());
   2322 }
   2323 
   2324 
   2325 THREADED_TEST(GlobalObjectHasRealIndexedProperty) {
   2326   LocalContext env;
   2327   v8::HandleScope scope(CcTest::isolate());
   2328 
   2329   v8::Local<v8::Object> global = env->Global();
   2330   CHECK(global->Set(env.local(), 0, v8_str("value")).FromJust());
   2331   CHECK(global->HasRealIndexedProperty(env.local(), 0).FromJust());
   2332 }
   2333 
   2334 
   2335 static void CheckAlignedPointerInInternalField(Local<v8::Object> obj,
   2336                                                void* value) {
   2337   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
   2338   obj->SetAlignedPointerInInternalField(0, value);
   2339   CcTest::heap()->CollectAllGarbage();
   2340   CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
   2341 }
   2342 
   2343 
   2344 THREADED_TEST(InternalFieldsAlignedPointers) {
   2345   LocalContext env;
   2346   v8::Isolate* isolate = env->GetIsolate();
   2347   v8::HandleScope scope(isolate);
   2348 
   2349   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   2350   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
   2351   instance_templ->SetInternalFieldCount(1);
   2352   Local<v8::Object> obj = templ->GetFunction(env.local())
   2353                               .ToLocalChecked()
   2354                               ->NewInstance(env.local())
   2355                               .ToLocalChecked();
   2356   CHECK_EQ(1, obj->InternalFieldCount());
   2357 
   2358   CheckAlignedPointerInInternalField(obj, NULL);
   2359 
   2360   int* heap_allocated = new int[100];
   2361   CheckAlignedPointerInInternalField(obj, heap_allocated);
   2362   delete[] heap_allocated;
   2363 
   2364   int stack_allocated[100];
   2365   CheckAlignedPointerInInternalField(obj, stack_allocated);
   2366 
   2367   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
   2368   CheckAlignedPointerInInternalField(obj, huge);
   2369 
   2370   v8::Global<v8::Object> persistent(isolate, obj);
   2371   CHECK_EQ(1, Object::InternalFieldCount(persistent));
   2372   CHECK_EQ(huge, Object::GetAlignedPointerFromInternalField(persistent, 0));
   2373 }
   2374 
   2375 
   2376 static void CheckAlignedPointerInEmbedderData(LocalContext* env, int index,
   2377                                               void* value) {
   2378   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
   2379   (*env)->SetAlignedPointerInEmbedderData(index, value);
   2380   CcTest::heap()->CollectAllGarbage();
   2381   CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
   2382 }
   2383 
   2384 
   2385 static void* AlignedTestPointer(int i) {
   2386   return reinterpret_cast<void*>(i * 1234);
   2387 }
   2388 
   2389 
   2390 THREADED_TEST(EmbedderDataAlignedPointers) {
   2391   LocalContext env;
   2392   v8::HandleScope scope(env->GetIsolate());
   2393 
   2394   CheckAlignedPointerInEmbedderData(&env, 0, NULL);
   2395 
   2396   int* heap_allocated = new int[100];
   2397   CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
   2398   delete[] heap_allocated;
   2399 
   2400   int stack_allocated[100];
   2401   CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
   2402 
   2403   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
   2404   CheckAlignedPointerInEmbedderData(&env, 3, huge);
   2405 
   2406   // Test growing of the embedder data's backing store.
   2407   for (int i = 0; i < 100; i++) {
   2408     env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
   2409   }
   2410   CcTest::heap()->CollectAllGarbage();
   2411   for (int i = 0; i < 100; i++) {
   2412     CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
   2413   }
   2414 }
   2415 
   2416 
   2417 static void CheckEmbedderData(LocalContext* env, int index,
   2418                               v8::Local<Value> data) {
   2419   (*env)->SetEmbedderData(index, data);
   2420   CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
   2421 }
   2422 
   2423 
   2424 THREADED_TEST(EmbedderData) {
   2425   LocalContext env;
   2426   v8::Isolate* isolate = env->GetIsolate();
   2427   v8::HandleScope scope(isolate);
   2428 
   2429   CheckEmbedderData(&env, 3, v8_str("The quick brown fox jumps"));
   2430   CheckEmbedderData(&env, 2, v8_str("over the lazy dog."));
   2431   CheckEmbedderData(&env, 1, v8::Number::New(isolate, 1.2345));
   2432   CheckEmbedderData(&env, 0, v8::Boolean::New(isolate, true));
   2433 }
   2434 
   2435 
   2436 THREADED_TEST(IdentityHash) {
   2437   LocalContext env;
   2438   v8::Isolate* isolate = env->GetIsolate();
   2439   v8::HandleScope scope(isolate);
   2440 
   2441   // Ensure that the test starts with an fresh heap to test whether the hash
   2442   // code is based on the address.
   2443   CcTest::heap()->CollectAllGarbage();
   2444   Local<v8::Object> obj = v8::Object::New(isolate);
   2445   int hash = obj->GetIdentityHash();
   2446   int hash1 = obj->GetIdentityHash();
   2447   CHECK_EQ(hash, hash1);
   2448   int hash2 = v8::Object::New(isolate)->GetIdentityHash();
   2449   // Since the identity hash is essentially a random number two consecutive
   2450   // objects should not be assigned the same hash code. If the test below fails
   2451   // the random number generator should be evaluated.
   2452   CHECK_NE(hash, hash2);
   2453   CcTest::heap()->CollectAllGarbage();
   2454   int hash3 = v8::Object::New(isolate)->GetIdentityHash();
   2455   // Make sure that the identity hash is not based on the initial address of
   2456   // the object alone. If the test below fails the random number generator
   2457   // should be evaluated.
   2458   CHECK_NE(hash, hash3);
   2459   int hash4 = obj->GetIdentityHash();
   2460   CHECK_EQ(hash, hash4);
   2461 
   2462   // Check identity hashes behaviour in the presence of JS accessors.
   2463   // Put a getter for 'v8::IdentityHash' on the Object's prototype:
   2464   {
   2465     CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
   2466     Local<v8::Object> o1 = v8::Object::New(isolate);
   2467     Local<v8::Object> o2 = v8::Object::New(isolate);
   2468     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
   2469   }
   2470   {
   2471     CompileRun(
   2472         "function cnst() { return 42; };\n"
   2473         "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
   2474     Local<v8::Object> o1 = v8::Object::New(isolate);
   2475     Local<v8::Object> o2 = v8::Object::New(isolate);
   2476     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
   2477   }
   2478 }
   2479 
   2480 
   2481 void GlobalProxyIdentityHash(bool set_in_js) {
   2482   LocalContext env;
   2483   v8::Isolate* isolate = env->GetIsolate();
   2484   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   2485   v8::HandleScope scope(isolate);
   2486   Local<Object> global_proxy = env->Global();
   2487   i::Handle<i::Object> i_global_proxy = v8::Utils::OpenHandle(*global_proxy);
   2488   CHECK(env->Global()
   2489             ->Set(env.local(), v8_str("global"), global_proxy)
   2490             .FromJust());
   2491   i::Handle<i::Object> original_hash;
   2492   if (set_in_js) {
   2493     CompileRun("var m = new Set(); m.add(global);");
   2494     original_hash = i::Handle<i::Object>(i_global_proxy->GetHash(), i_isolate);
   2495   } else {
   2496     original_hash = i::Handle<i::Object>(
   2497         i::Object::GetOrCreateHash(i_isolate, i_global_proxy));
   2498   }
   2499   CHECK(original_hash->IsSmi());
   2500   int32_t hash1 = i::Handle<i::Smi>::cast(original_hash)->value();
   2501   // Hash should be retained after being detached.
   2502   env->DetachGlobal();
   2503   int hash2 = global_proxy->GetIdentityHash();
   2504   CHECK_EQ(hash1, hash2);
   2505   {
   2506     // Re-attach global proxy to a new context, hash should stay the same.
   2507     LocalContext env2(NULL, Local<ObjectTemplate>(), global_proxy);
   2508     int hash3 = global_proxy->GetIdentityHash();
   2509     CHECK_EQ(hash1, hash3);
   2510   }
   2511 }
   2512 
   2513 
   2514 THREADED_TEST(GlobalProxyIdentityHash) {
   2515   GlobalProxyIdentityHash(true);
   2516   GlobalProxyIdentityHash(false);
   2517 }
   2518 
   2519 
   2520 TEST(SymbolIdentityHash) {
   2521   LocalContext env;
   2522   v8::Isolate* isolate = env->GetIsolate();
   2523   v8::HandleScope scope(isolate);
   2524 
   2525   {
   2526     Local<v8::Symbol> symbol = v8::Symbol::New(isolate);
   2527     int hash = symbol->GetIdentityHash();
   2528     int hash1 = symbol->GetIdentityHash();
   2529     CHECK_EQ(hash, hash1);
   2530     CcTest::heap()->CollectAllGarbage();
   2531     int hash3 = symbol->GetIdentityHash();
   2532     CHECK_EQ(hash, hash3);
   2533   }
   2534 
   2535   {
   2536     v8::Local<v8::Symbol> js_symbol =
   2537         CompileRun("Symbol('foo')").As<v8::Symbol>();
   2538     int hash = js_symbol->GetIdentityHash();
   2539     int hash1 = js_symbol->GetIdentityHash();
   2540     CHECK_EQ(hash, hash1);
   2541     CcTest::heap()->CollectAllGarbage();
   2542     int hash3 = js_symbol->GetIdentityHash();
   2543     CHECK_EQ(hash, hash3);
   2544   }
   2545 }
   2546 
   2547 
   2548 TEST(StringIdentityHash) {
   2549   LocalContext env;
   2550   v8::Isolate* isolate = env->GetIsolate();
   2551   v8::HandleScope scope(isolate);
   2552 
   2553   Local<v8::String> str = v8_str("str1");
   2554   int hash = str->GetIdentityHash();
   2555   int hash1 = str->GetIdentityHash();
   2556   CHECK_EQ(hash, hash1);
   2557   CcTest::heap()->CollectAllGarbage();
   2558   int hash3 = str->GetIdentityHash();
   2559   CHECK_EQ(hash, hash3);
   2560 
   2561   Local<v8::String> str2 = v8_str("str1");
   2562   int hash4 = str2->GetIdentityHash();
   2563   CHECK_EQ(hash, hash4);
   2564 }
   2565 
   2566 
   2567 THREADED_TEST(SymbolProperties) {
   2568   LocalContext env;
   2569   v8::Isolate* isolate = env->GetIsolate();
   2570   v8::HandleScope scope(isolate);
   2571 
   2572   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   2573   v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
   2574   v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, v8_str("my-symbol"));
   2575   v8::Local<v8::Symbol> sym3 = v8::Symbol::New(isolate, v8_str("sym3"));
   2576 
   2577   CcTest::heap()->CollectAllGarbage();
   2578 
   2579   // Check basic symbol functionality.
   2580   CHECK(sym1->IsSymbol());
   2581   CHECK(sym2->IsSymbol());
   2582   CHECK(!obj->IsSymbol());
   2583 
   2584   CHECK(sym1->Equals(env.local(), sym1).FromJust());
   2585   CHECK(sym2->Equals(env.local(), sym2).FromJust());
   2586   CHECK(!sym1->Equals(env.local(), sym2).FromJust());
   2587   CHECK(!sym2->Equals(env.local(), sym1).FromJust());
   2588   CHECK(sym1->StrictEquals(sym1));
   2589   CHECK(sym2->StrictEquals(sym2));
   2590   CHECK(!sym1->StrictEquals(sym2));
   2591   CHECK(!sym2->StrictEquals(sym1));
   2592 
   2593   CHECK(sym2->Name()->Equals(env.local(), v8_str("my-symbol")).FromJust());
   2594 
   2595   v8::Local<v8::Value> sym_val = sym2;
   2596   CHECK(sym_val->IsSymbol());
   2597   CHECK(sym_val->Equals(env.local(), sym2).FromJust());
   2598   CHECK(sym_val->StrictEquals(sym2));
   2599   CHECK(v8::Symbol::Cast(*sym_val)->Equals(env.local(), sym2).FromJust());
   2600 
   2601   v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
   2602   CHECK(sym_obj->IsSymbolObject());
   2603   CHECK(!sym2->IsSymbolObject());
   2604   CHECK(!obj->IsSymbolObject());
   2605   CHECK(sym_obj->Equals(env.local(), sym2).FromJust());
   2606   CHECK(!sym_obj->StrictEquals(sym2));
   2607   CHECK(v8::SymbolObject::Cast(*sym_obj)
   2608             ->Equals(env.local(), sym_obj)
   2609             .FromJust());
   2610   CHECK(v8::SymbolObject::Cast(*sym_obj)
   2611             ->ValueOf()
   2612             ->Equals(env.local(), sym2)
   2613             .FromJust());
   2614 
   2615   // Make sure delete of a non-existent symbol property works.
   2616   CHECK(obj->Delete(env.local(), sym1).FromJust());
   2617   CHECK(!obj->Has(env.local(), sym1).FromJust());
   2618 
   2619   CHECK(
   2620       obj->Set(env.local(), sym1, v8::Integer::New(isolate, 1503)).FromJust());
   2621   CHECK(obj->Has(env.local(), sym1).FromJust());
   2622   CHECK_EQ(1503, obj->Get(env.local(), sym1)
   2623                      .ToLocalChecked()
   2624                      ->Int32Value(env.local())
   2625                      .FromJust());
   2626   CHECK(
   2627       obj->Set(env.local(), sym1, v8::Integer::New(isolate, 2002)).FromJust());
   2628   CHECK(obj->Has(env.local(), sym1).FromJust());
   2629   CHECK_EQ(2002, obj->Get(env.local(), sym1)
   2630                      .ToLocalChecked()
   2631                      ->Int32Value(env.local())
   2632                      .FromJust());
   2633   CHECK_EQ(v8::None, obj->GetPropertyAttributes(env.local(), sym1).FromJust());
   2634 
   2635   CHECK_EQ(0u,
   2636            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   2637   unsigned num_props =
   2638       obj->GetPropertyNames(env.local()).ToLocalChecked()->Length();
   2639   CHECK(obj->Set(env.local(), v8_str("bla"), v8::Integer::New(isolate, 20))
   2640             .FromJust());
   2641   CHECK_EQ(1u,
   2642            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   2643   CHECK_EQ(num_props + 1,
   2644            obj->GetPropertyNames(env.local()).ToLocalChecked()->Length());
   2645 
   2646   CcTest::heap()->CollectAllGarbage();
   2647 
   2648   CHECK(obj->SetAccessor(env.local(), sym3, SymbolAccessorGetter,
   2649                          SymbolAccessorSetter)
   2650             .FromJust());
   2651   CHECK(obj->Get(env.local(), sym3).ToLocalChecked()->IsUndefined());
   2652   CHECK(obj->Set(env.local(), sym3, v8::Integer::New(isolate, 42)).FromJust());
   2653   CHECK(obj->Get(env.local(), sym3)
   2654             .ToLocalChecked()
   2655             ->Equals(env.local(), v8::Integer::New(isolate, 42))
   2656             .FromJust());
   2657   CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
   2658             .ToLocalChecked()
   2659             ->Equals(env.local(), v8::Integer::New(isolate, 42))
   2660             .FromJust());
   2661 
   2662   // Add another property and delete it afterwards to force the object in
   2663   // slow case.
   2664   CHECK(
   2665       obj->Set(env.local(), sym2, v8::Integer::New(isolate, 2008)).FromJust());
   2666   CHECK_EQ(2002, obj->Get(env.local(), sym1)
   2667                      .ToLocalChecked()
   2668                      ->Int32Value(env.local())
   2669                      .FromJust());
   2670   CHECK_EQ(2008, obj->Get(env.local(), sym2)
   2671                      .ToLocalChecked()
   2672                      ->Int32Value(env.local())
   2673                      .FromJust());
   2674   CHECK_EQ(2002, obj->Get(env.local(), sym1)
   2675                      .ToLocalChecked()
   2676                      ->Int32Value(env.local())
   2677                      .FromJust());
   2678   CHECK_EQ(2u,
   2679            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   2680 
   2681   CHECK(obj->Has(env.local(), sym1).FromJust());
   2682   CHECK(obj->Has(env.local(), sym2).FromJust());
   2683   CHECK(obj->Has(env.local(), sym3).FromJust());
   2684   CHECK(obj->Has(env.local(), v8_str("accessor_sym3")).FromJust());
   2685   CHECK(obj->Delete(env.local(), sym2).FromJust());
   2686   CHECK(obj->Has(env.local(), sym1).FromJust());
   2687   CHECK(!obj->Has(env.local(), sym2).FromJust());
   2688   CHECK(obj->Has(env.local(), sym3).FromJust());
   2689   CHECK(obj->Has(env.local(), v8_str("accessor_sym3")).FromJust());
   2690   CHECK_EQ(2002, obj->Get(env.local(), sym1)
   2691                      .ToLocalChecked()
   2692                      ->Int32Value(env.local())
   2693                      .FromJust());
   2694   CHECK(obj->Get(env.local(), sym3)
   2695             .ToLocalChecked()
   2696             ->Equals(env.local(), v8::Integer::New(isolate, 42))
   2697             .FromJust());
   2698   CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
   2699             .ToLocalChecked()
   2700             ->Equals(env.local(), v8::Integer::New(isolate, 42))
   2701             .FromJust());
   2702   CHECK_EQ(2u,
   2703            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   2704 
   2705   // Symbol properties are inherited.
   2706   v8::Local<v8::Object> child = v8::Object::New(isolate);
   2707   CHECK(child->SetPrototype(env.local(), obj).FromJust());
   2708   CHECK(child->Has(env.local(), sym1).FromJust());
   2709   CHECK_EQ(2002, child->Get(env.local(), sym1)
   2710                      .ToLocalChecked()
   2711                      ->Int32Value(env.local())
   2712                      .FromJust());
   2713   CHECK(obj->Get(env.local(), sym3)
   2714             .ToLocalChecked()
   2715             ->Equals(env.local(), v8::Integer::New(isolate, 42))
   2716             .FromJust());
   2717   CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
   2718             .ToLocalChecked()
   2719             ->Equals(env.local(), v8::Integer::New(isolate, 42))
   2720             .FromJust());
   2721   CHECK_EQ(0u,
   2722            child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   2723 }
   2724 
   2725 
   2726 THREADED_TEST(SymbolTemplateProperties) {
   2727   LocalContext env;
   2728   v8::Isolate* isolate = env->GetIsolate();
   2729   v8::HandleScope scope(isolate);
   2730   v8::Local<v8::FunctionTemplate> foo = v8::FunctionTemplate::New(isolate);
   2731   v8::Local<v8::Name> name = v8::Symbol::New(isolate);
   2732   CHECK(!name.IsEmpty());
   2733   foo->PrototypeTemplate()->Set(name, v8::FunctionTemplate::New(isolate));
   2734   v8::Local<v8::Object> new_instance =
   2735       foo->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
   2736   CHECK(!new_instance.IsEmpty());
   2737   CHECK(new_instance->Has(env.local(), name).FromJust());
   2738 }
   2739 
   2740 
   2741 THREADED_TEST(PrivatePropertiesOnProxies) {
   2742   i::FLAG_harmony_proxies = true;
   2743   LocalContext env;
   2744   v8::Isolate* isolate = env->GetIsolate();
   2745   v8::HandleScope scope(isolate);
   2746 
   2747   v8::Local<v8::Object> target = CompileRun("({})").As<v8::Object>();
   2748   v8::Local<v8::Object> handler = CompileRun("({})").As<v8::Object>();
   2749 
   2750   v8::Local<v8::Proxy> proxy =
   2751       v8::Proxy::New(env.local(), target, handler).ToLocalChecked();
   2752 
   2753   v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
   2754   v8::Local<v8::Private> priv2 =
   2755       v8::Private::New(isolate, v8_str("my-private"));
   2756 
   2757   CcTest::heap()->CollectAllGarbage();
   2758 
   2759   CHECK(priv2->Name()
   2760             ->Equals(env.local(),
   2761                      v8::String::NewFromUtf8(isolate, "my-private",
   2762                                              v8::NewStringType::kNormal)
   2763                          .ToLocalChecked())
   2764             .FromJust());
   2765 
   2766   // Make sure delete of a non-existent private symbol property works.
   2767   proxy->DeletePrivate(env.local(), priv1).FromJust();
   2768   CHECK(!proxy->HasPrivate(env.local(), priv1).FromJust());
   2769 
   2770   CHECK(proxy->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 1503))
   2771             .FromJust());
   2772   CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
   2773   CHECK_EQ(1503, proxy->GetPrivate(env.local(), priv1)
   2774                      .ToLocalChecked()
   2775                      ->Int32Value(env.local())
   2776                      .FromJust());
   2777   CHECK(proxy->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 2002))
   2778             .FromJust());
   2779   CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
   2780   CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
   2781                      .ToLocalChecked()
   2782                      ->Int32Value(env.local())
   2783                      .FromJust());
   2784 
   2785   CHECK_EQ(0u,
   2786            proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   2787   unsigned num_props =
   2788       proxy->GetPropertyNames(env.local()).ToLocalChecked()->Length();
   2789   CHECK(proxy->Set(env.local(), v8::String::NewFromUtf8(
   2790                                     isolate, "bla", v8::NewStringType::kNormal)
   2791                                     .ToLocalChecked(),
   2792                    v8::Integer::New(isolate, 20))
   2793             .FromJust());
   2794   CHECK_EQ(1u,
   2795            proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   2796   CHECK_EQ(num_props + 1,
   2797            proxy->GetPropertyNames(env.local()).ToLocalChecked()->Length());
   2798 
   2799   CcTest::heap()->CollectAllGarbage();
   2800 
   2801   // Add another property and delete it afterwards to force the object in
   2802   // slow case.
   2803   CHECK(proxy->SetPrivate(env.local(), priv2, v8::Integer::New(isolate, 2008))
   2804             .FromJust());
   2805   CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
   2806                      .ToLocalChecked()
   2807                      ->Int32Value(env.local())
   2808                      .FromJust());
   2809   CHECK_EQ(2008, proxy->GetPrivate(env.local(), priv2)
   2810                      .ToLocalChecked()
   2811                      ->Int32Value(env.local())
   2812                      .FromJust());
   2813   CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
   2814                      .ToLocalChecked()
   2815                      ->Int32Value(env.local())
   2816                      .FromJust());
   2817   CHECK_EQ(1u,
   2818            proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   2819 
   2820   CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
   2821   CHECK(proxy->HasPrivate(env.local(), priv2).FromJust());
   2822   CHECK(proxy->DeletePrivate(env.local(), priv2).FromJust());
   2823   CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
   2824   CHECK(!proxy->HasPrivate(env.local(), priv2).FromJust());
   2825   CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
   2826                      .ToLocalChecked()
   2827                      ->Int32Value(env.local())
   2828                      .FromJust());
   2829   CHECK_EQ(1u,
   2830            proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   2831 
   2832   // Private properties are not inherited (for the time being).
   2833   v8::Local<v8::Object> child = v8::Object::New(isolate);
   2834   CHECK(child->SetPrototype(env.local(), proxy).FromJust());
   2835   CHECK(!child->HasPrivate(env.local(), priv1).FromJust());
   2836   CHECK_EQ(0u,
   2837            child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   2838 }
   2839 
   2840 
   2841 THREADED_TEST(PrivateProperties) {
   2842   LocalContext env;
   2843   v8::Isolate* isolate = env->GetIsolate();
   2844   v8::HandleScope scope(isolate);
   2845 
   2846   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   2847   v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
   2848   v8::Local<v8::Private> priv2 =
   2849       v8::Private::New(isolate, v8_str("my-private"));
   2850 
   2851   CcTest::heap()->CollectAllGarbage();
   2852 
   2853   CHECK(priv2->Name()
   2854             ->Equals(env.local(),
   2855                      v8::String::NewFromUtf8(isolate, "my-private",
   2856                                              v8::NewStringType::kNormal)
   2857                          .ToLocalChecked())
   2858             .FromJust());
   2859 
   2860   // Make sure delete of a non-existent private symbol property works.
   2861   obj->DeletePrivate(env.local(), priv1).FromJust();
   2862   CHECK(!obj->HasPrivate(env.local(), priv1).FromJust());
   2863 
   2864   CHECK(obj->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 1503))
   2865             .FromJust());
   2866   CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
   2867   CHECK_EQ(1503, obj->GetPrivate(env.local(), priv1)
   2868                      .ToLocalChecked()
   2869                      ->Int32Value(env.local())
   2870                      .FromJust());
   2871   CHECK(obj->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 2002))
   2872             .FromJust());
   2873   CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
   2874   CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
   2875                      .ToLocalChecked()
   2876                      ->Int32Value(env.local())
   2877                      .FromJust());
   2878 
   2879   CHECK_EQ(0u,
   2880            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   2881   unsigned num_props =
   2882       obj->GetPropertyNames(env.local()).ToLocalChecked()->Length();
   2883   CHECK(obj->Set(env.local(), v8::String::NewFromUtf8(
   2884                                   isolate, "bla", v8::NewStringType::kNormal)
   2885                                   .ToLocalChecked(),
   2886                  v8::Integer::New(isolate, 20))
   2887             .FromJust());
   2888   CHECK_EQ(1u,
   2889            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   2890   CHECK_EQ(num_props + 1,
   2891            obj->GetPropertyNames(env.local()).ToLocalChecked()->Length());
   2892 
   2893   CcTest::heap()->CollectAllGarbage();
   2894 
   2895   // Add another property and delete it afterwards to force the object in
   2896   // slow case.
   2897   CHECK(obj->SetPrivate(env.local(), priv2, v8::Integer::New(isolate, 2008))
   2898             .FromJust());
   2899   CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
   2900                      .ToLocalChecked()
   2901                      ->Int32Value(env.local())
   2902                      .FromJust());
   2903   CHECK_EQ(2008, obj->GetPrivate(env.local(), priv2)
   2904                      .ToLocalChecked()
   2905                      ->Int32Value(env.local())
   2906                      .FromJust());
   2907   CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
   2908                      .ToLocalChecked()
   2909                      ->Int32Value(env.local())
   2910                      .FromJust());
   2911   CHECK_EQ(1u,
   2912            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   2913 
   2914   CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
   2915   CHECK(obj->HasPrivate(env.local(), priv2).FromJust());
   2916   CHECK(obj->DeletePrivate(env.local(), priv2).FromJust());
   2917   CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
   2918   CHECK(!obj->HasPrivate(env.local(), priv2).FromJust());
   2919   CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
   2920                      .ToLocalChecked()
   2921                      ->Int32Value(env.local())
   2922                      .FromJust());
   2923   CHECK_EQ(1u,
   2924            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   2925 
   2926   // Private properties are not inherited (for the time being).
   2927   v8::Local<v8::Object> child = v8::Object::New(isolate);
   2928   CHECK(child->SetPrototype(env.local(), obj).FromJust());
   2929   CHECK(!child->HasPrivate(env.local(), priv1).FromJust());
   2930   CHECK_EQ(0u,
   2931            child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
   2932 }
   2933 
   2934 
   2935 THREADED_TEST(GlobalSymbols) {
   2936   LocalContext env;
   2937   v8::Isolate* isolate = env->GetIsolate();
   2938   v8::HandleScope scope(isolate);
   2939 
   2940   v8::Local<String> name = v8_str("my-symbol");
   2941   v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name);
   2942   v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name);
   2943   CHECK(glob2->SameValue(glob));
   2944 
   2945   v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name);
   2946   v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name);
   2947   CHECK(glob_api2->SameValue(glob_api));
   2948   CHECK(!glob_api->SameValue(glob));
   2949 
   2950   v8::Local<v8::Symbol> sym = v8::Symbol::New(isolate, name);
   2951   CHECK(!sym->SameValue(glob));
   2952 
   2953   CompileRun("var sym2 = Symbol.for('my-symbol')");
   2954   v8::Local<Value> sym2 =
   2955       env->Global()->Get(env.local(), v8_str("sym2")).ToLocalChecked();
   2956   CHECK(sym2->SameValue(glob));
   2957   CHECK(!sym2->SameValue(glob_api));
   2958 }
   2959 
   2960 
   2961 static void CheckWellKnownSymbol(v8::Local<v8::Symbol>(*getter)(v8::Isolate*),
   2962                                  const char* name) {
   2963   LocalContext env;
   2964   v8::Isolate* isolate = env->GetIsolate();
   2965   v8::HandleScope scope(isolate);
   2966 
   2967   v8::Local<v8::Symbol> symbol = getter(isolate);
   2968   std::string script = std::string("var sym = ") + name;
   2969   CompileRun(script.c_str());
   2970   v8::Local<Value> value =
   2971       env->Global()->Get(env.local(), v8_str("sym")).ToLocalChecked();
   2972 
   2973   CHECK(!value.IsEmpty());
   2974   CHECK(!symbol.IsEmpty());
   2975   CHECK(value->SameValue(symbol));
   2976 }
   2977 
   2978 
   2979 THREADED_TEST(WellKnownSymbols) {
   2980   CheckWellKnownSymbol(v8::Symbol::GetIterator, "Symbol.iterator");
   2981   CheckWellKnownSymbol(v8::Symbol::GetUnscopables, "Symbol.unscopables");
   2982 }
   2983 
   2984 
   2985 THREADED_TEST(GlobalPrivates) {
   2986   i::FLAG_allow_natives_syntax = true;
   2987   LocalContext env;
   2988   v8::Isolate* isolate = env->GetIsolate();
   2989   v8::HandleScope scope(isolate);
   2990 
   2991   v8::Local<String> name = v8_str("my-private");
   2992   v8::Local<v8::Private> glob = v8::Private::ForApi(isolate, name);
   2993   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   2994   CHECK(obj->SetPrivate(env.local(), glob, v8::Integer::New(isolate, 3))
   2995             .FromJust());
   2996 
   2997   v8::Local<v8::Private> glob2 = v8::Private::ForApi(isolate, name);
   2998   CHECK(obj->HasPrivate(env.local(), glob2).FromJust());
   2999 
   3000   v8::Local<v8::Private> priv = v8::Private::New(isolate, name);
   3001   CHECK(!obj->HasPrivate(env.local(), priv).FromJust());
   3002 
   3003   CompileRun("var intern = %CreatePrivateSymbol('my-private')");
   3004   v8::Local<Value> intern =
   3005       env->Global()->Get(env.local(), v8_str("intern")).ToLocalChecked();
   3006   CHECK(!obj->Has(env.local(), intern).FromJust());
   3007 }
   3008 
   3009 
   3010 class ScopedArrayBufferContents {
   3011  public:
   3012   explicit ScopedArrayBufferContents(const v8::ArrayBuffer::Contents& contents)
   3013       : contents_(contents) {}
   3014   ~ScopedArrayBufferContents() { free(contents_.Data()); }
   3015   void* Data() const { return contents_.Data(); }
   3016   size_t ByteLength() const { return contents_.ByteLength(); }
   3017 
   3018  private:
   3019   const v8::ArrayBuffer::Contents contents_;
   3020 };
   3021 
   3022 template <typename T>
   3023 static void CheckInternalFieldsAreZero(v8::Local<T> value) {
   3024   CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
   3025   for (int i = 0; i < value->InternalFieldCount(); i++) {
   3026     CHECK_EQ(0, value->GetInternalField(i)
   3027                     ->Int32Value(CcTest::isolate()->GetCurrentContext())
   3028                     .FromJust());
   3029   }
   3030 }
   3031 
   3032 
   3033 THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
   3034   LocalContext env;
   3035   v8::Isolate* isolate = env->GetIsolate();
   3036   v8::HandleScope handle_scope(isolate);
   3037 
   3038   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 1024);
   3039   CheckInternalFieldsAreZero(ab);
   3040   CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
   3041   CHECK(!ab->IsExternal());
   3042   CcTest::heap()->CollectAllGarbage();
   3043 
   3044   ScopedArrayBufferContents ab_contents(ab->Externalize());
   3045   CHECK(ab->IsExternal());
   3046 
   3047   CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
   3048   uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
   3049   CHECK(data != NULL);
   3050   CHECK(env->Global()->Set(env.local(), v8_str("ab"), ab).FromJust());
   3051 
   3052   v8::Local<v8::Value> result = CompileRun("ab.byteLength");
   3053   CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
   3054 
   3055   result = CompileRun(
   3056       "var u8 = new Uint8Array(ab);"
   3057       "u8[0] = 0xFF;"
   3058       "u8[1] = 0xAA;"
   3059       "u8.length");
   3060   CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
   3061   CHECK_EQ(0xFF, data[0]);
   3062   CHECK_EQ(0xAA, data[1]);
   3063   data[0] = 0xCC;
   3064   data[1] = 0x11;
   3065   result = CompileRun("u8[0] + u8[1]");
   3066   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
   3067 }
   3068 
   3069 
   3070 THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
   3071   LocalContext env;
   3072   v8::Isolate* isolate = env->GetIsolate();
   3073   v8::HandleScope handle_scope(isolate);
   3074 
   3075 
   3076   v8::Local<v8::Value> result = CompileRun(
   3077       "var ab1 = new ArrayBuffer(2);"
   3078       "var u8_a = new Uint8Array(ab1);"
   3079       "u8_a[0] = 0xAA;"
   3080       "u8_a[1] = 0xFF; u8_a.buffer");
   3081   Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
   3082   CheckInternalFieldsAreZero(ab1);
   3083   CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
   3084   CHECK(!ab1->IsExternal());
   3085   ScopedArrayBufferContents ab1_contents(ab1->Externalize());
   3086   CHECK(ab1->IsExternal());
   3087 
   3088   result = CompileRun("ab1.byteLength");
   3089   CHECK_EQ(2, result->Int32Value(env.local()).FromJust());
   3090   result = CompileRun("u8_a[0]");
   3091   CHECK_EQ(0xAA, result->Int32Value(env.local()).FromJust());
   3092   result = CompileRun("u8_a[1]");
   3093   CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
   3094   result = CompileRun(
   3095       "var u8_b = new Uint8Array(ab1);"
   3096       "u8_b[0] = 0xBB;"
   3097       "u8_a[0]");
   3098   CHECK_EQ(0xBB, result->Int32Value(env.local()).FromJust());
   3099   result = CompileRun("u8_b[1]");
   3100   CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
   3101 
   3102   CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
   3103   uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
   3104   CHECK_EQ(0xBB, ab1_data[0]);
   3105   CHECK_EQ(0xFF, ab1_data[1]);
   3106   ab1_data[0] = 0xCC;
   3107   ab1_data[1] = 0x11;
   3108   result = CompileRun("u8_a[0] + u8_a[1]");
   3109   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
   3110 }
   3111 
   3112 
   3113 THREADED_TEST(ArrayBuffer_External) {
   3114   LocalContext env;
   3115   v8::Isolate* isolate = env->GetIsolate();
   3116   v8::HandleScope handle_scope(isolate);
   3117 
   3118   i::ScopedVector<uint8_t> my_data(100);
   3119   memset(my_data.start(), 0, 100);
   3120   Local<v8::ArrayBuffer> ab3 =
   3121       v8::ArrayBuffer::New(isolate, my_data.start(), 100);
   3122   CheckInternalFieldsAreZero(ab3);
   3123   CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
   3124   CHECK(ab3->IsExternal());
   3125 
   3126   CHECK(env->Global()->Set(env.local(), v8_str("ab3"), ab3).FromJust());
   3127 
   3128   v8::Local<v8::Value> result = CompileRun("ab3.byteLength");
   3129   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
   3130 
   3131   result = CompileRun(
   3132       "var u8_b = new Uint8Array(ab3);"
   3133       "u8_b[0] = 0xBB;"
   3134       "u8_b[1] = 0xCC;"
   3135       "u8_b.length");
   3136   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
   3137   CHECK_EQ(0xBB, my_data[0]);
   3138   CHECK_EQ(0xCC, my_data[1]);
   3139   my_data[0] = 0xCC;
   3140   my_data[1] = 0x11;
   3141   result = CompileRun("u8_b[0] + u8_b[1]");
   3142   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
   3143 }
   3144 
   3145 
   3146 THREADED_TEST(ArrayBuffer_DisableNeuter) {
   3147   LocalContext env;
   3148   v8::Isolate* isolate = env->GetIsolate();
   3149   v8::HandleScope handle_scope(isolate);
   3150 
   3151   i::ScopedVector<uint8_t> my_data(100);
   3152   memset(my_data.start(), 0, 100);
   3153   Local<v8::ArrayBuffer> ab =
   3154       v8::ArrayBuffer::New(isolate, my_data.start(), 100);
   3155   CHECK(ab->IsNeuterable());
   3156 
   3157   i::Handle<i::JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
   3158   buf->set_is_neuterable(false);
   3159 
   3160   CHECK(!ab->IsNeuterable());
   3161 }
   3162 
   3163 
   3164 static void CheckDataViewIsNeutered(v8::Local<v8::DataView> dv) {
   3165   CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
   3166   CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
   3167 }
   3168 
   3169 
   3170 static void CheckIsNeutered(v8::Local<v8::TypedArray> ta) {
   3171   CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
   3172   CHECK_EQ(0, static_cast<int>(ta->Length()));
   3173   CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
   3174 }
   3175 
   3176 
   3177 static void CheckIsTypedArrayVarNeutered(const char* name) {
   3178   i::ScopedVector<char> source(1024);
   3179   i::SNPrintF(source,
   3180               "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
   3181               name, name, name);
   3182   CHECK(CompileRun(source.start())->IsTrue());
   3183   v8::Local<v8::TypedArray> ta =
   3184       v8::Local<v8::TypedArray>::Cast(CompileRun(name));
   3185   CheckIsNeutered(ta);
   3186 }
   3187 
   3188 
   3189 template <typename TypedArray, int kElementSize>
   3190 static Local<TypedArray> CreateAndCheck(Local<v8::ArrayBuffer> ab,
   3191                                         int byteOffset, int length) {
   3192   v8::Local<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
   3193   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
   3194   CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
   3195   CHECK_EQ(length, static_cast<int>(ta->Length()));
   3196   CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
   3197   return ta;
   3198 }
   3199 
   3200 
   3201 THREADED_TEST(ArrayBuffer_NeuteringApi) {
   3202   LocalContext env;
   3203   v8::Isolate* isolate = env->GetIsolate();
   3204   v8::HandleScope handle_scope(isolate);
   3205 
   3206   v8::Local<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1024);
   3207 
   3208   v8::Local<v8::Uint8Array> u8a =
   3209       CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
   3210   v8::Local<v8::Uint8ClampedArray> u8c =
   3211       CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
   3212   v8::Local<v8::Int8Array> i8a =
   3213       CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
   3214 
   3215   v8::Local<v8::Uint16Array> u16a =
   3216       CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
   3217   v8::Local<v8::Int16Array> i16a =
   3218       CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
   3219 
   3220   v8::Local<v8::Uint32Array> u32a =
   3221       CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
   3222   v8::Local<v8::Int32Array> i32a =
   3223       CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
   3224 
   3225   v8::Local<v8::Float32Array> f32a =
   3226       CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
   3227   v8::Local<v8::Float64Array> f64a =
   3228       CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
   3229 
   3230   v8::Local<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
   3231   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
   3232   CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
   3233   CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
   3234 
   3235   ScopedArrayBufferContents contents(buffer->Externalize());
   3236   buffer->Neuter();
   3237   CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
   3238   CheckIsNeutered(u8a);
   3239   CheckIsNeutered(u8c);
   3240   CheckIsNeutered(i8a);
   3241   CheckIsNeutered(u16a);
   3242   CheckIsNeutered(i16a);
   3243   CheckIsNeutered(u32a);
   3244   CheckIsNeutered(i32a);
   3245   CheckIsNeutered(f32a);
   3246   CheckIsNeutered(f64a);
   3247   CheckDataViewIsNeutered(dv);
   3248 }
   3249 
   3250 
   3251 THREADED_TEST(ArrayBuffer_NeuteringScript) {
   3252   LocalContext env;
   3253   v8::Isolate* isolate = env->GetIsolate();
   3254   v8::HandleScope handle_scope(isolate);
   3255 
   3256   CompileRun(
   3257       "var ab = new ArrayBuffer(1024);"
   3258       "var u8a = new Uint8Array(ab, 1, 1023);"
   3259       "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
   3260       "var i8a = new Int8Array(ab, 1, 1023);"
   3261       "var u16a = new Uint16Array(ab, 2, 511);"
   3262       "var i16a = new Int16Array(ab, 2, 511);"
   3263       "var u32a = new Uint32Array(ab, 4, 255);"
   3264       "var i32a = new Int32Array(ab, 4, 255);"
   3265       "var f32a = new Float32Array(ab, 4, 255);"
   3266       "var f64a = new Float64Array(ab, 8, 127);"
   3267       "var dv = new DataView(ab, 1, 1023);");
   3268 
   3269   v8::Local<v8::ArrayBuffer> ab =
   3270       Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
   3271 
   3272   v8::Local<v8::DataView> dv = v8::Local<v8::DataView>::Cast(CompileRun("dv"));
   3273 
   3274   ScopedArrayBufferContents contents(ab->Externalize());
   3275   ab->Neuter();
   3276   CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
   3277   CHECK_EQ(0, v8_run_int32value(v8_compile("ab.byteLength")));
   3278 
   3279   CheckIsTypedArrayVarNeutered("u8a");
   3280   CheckIsTypedArrayVarNeutered("u8c");
   3281   CheckIsTypedArrayVarNeutered("i8a");
   3282   CheckIsTypedArrayVarNeutered("u16a");
   3283   CheckIsTypedArrayVarNeutered("i16a");
   3284   CheckIsTypedArrayVarNeutered("u32a");
   3285   CheckIsTypedArrayVarNeutered("i32a");
   3286   CheckIsTypedArrayVarNeutered("f32a");
   3287   CheckIsTypedArrayVarNeutered("f64a");
   3288 
   3289   CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
   3290   CheckDataViewIsNeutered(dv);
   3291 }
   3292 
   3293 
   3294 class ScopedSharedArrayBufferContents {
   3295  public:
   3296   explicit ScopedSharedArrayBufferContents(
   3297       const v8::SharedArrayBuffer::Contents& contents)
   3298       : contents_(contents) {}
   3299   ~ScopedSharedArrayBufferContents() { free(contents_.Data()); }
   3300   void* Data() const { return contents_.Data(); }
   3301   size_t ByteLength() const { return contents_.ByteLength(); }
   3302 
   3303  private:
   3304   const v8::SharedArrayBuffer::Contents contents_;
   3305 };
   3306 
   3307 
   3308 THREADED_TEST(SharedArrayBuffer_ApiInternalToExternal) {
   3309   i::FLAG_harmony_sharedarraybuffer = true;
   3310   LocalContext env;
   3311   v8::Isolate* isolate = env->GetIsolate();
   3312   v8::HandleScope handle_scope(isolate);
   3313 
   3314   Local<v8::SharedArrayBuffer> ab = v8::SharedArrayBuffer::New(isolate, 1024);
   3315   CheckInternalFieldsAreZero(ab);
   3316   CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
   3317   CHECK(!ab->IsExternal());
   3318   CcTest::heap()->CollectAllGarbage();
   3319 
   3320   ScopedSharedArrayBufferContents ab_contents(ab->Externalize());
   3321   CHECK(ab->IsExternal());
   3322 
   3323   CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
   3324   uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
   3325   CHECK(data != NULL);
   3326   CHECK(env->Global()->Set(env.local(), v8_str("ab"), ab).FromJust());
   3327 
   3328   v8::Local<v8::Value> result = CompileRun("ab.byteLength");
   3329   CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
   3330 
   3331   result = CompileRun(
   3332       "var u8 = new Uint8Array(ab);"
   3333       "u8[0] = 0xFF;"
   3334       "u8[1] = 0xAA;"
   3335       "u8.length");
   3336   CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
   3337   CHECK_EQ(0xFF, data[0]);
   3338   CHECK_EQ(0xAA, data[1]);
   3339   data[0] = 0xCC;
   3340   data[1] = 0x11;
   3341   result = CompileRun("u8[0] + u8[1]");
   3342   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
   3343 }
   3344 
   3345 
   3346 THREADED_TEST(SharedArrayBuffer_JSInternalToExternal) {
   3347   i::FLAG_harmony_sharedarraybuffer = true;
   3348   LocalContext env;
   3349   v8::Isolate* isolate = env->GetIsolate();
   3350   v8::HandleScope handle_scope(isolate);
   3351 
   3352 
   3353   v8::Local<v8::Value> result = CompileRun(
   3354       "var ab1 = new SharedArrayBuffer(2);"
   3355       "var u8_a = new Uint8Array(ab1);"
   3356       "u8_a[0] = 0xAA;"
   3357       "u8_a[1] = 0xFF; u8_a.buffer");
   3358   Local<v8::SharedArrayBuffer> ab1 = Local<v8::SharedArrayBuffer>::Cast(result);
   3359   CheckInternalFieldsAreZero(ab1);
   3360   CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
   3361   CHECK(!ab1->IsExternal());
   3362   ScopedSharedArrayBufferContents ab1_contents(ab1->Externalize());
   3363   CHECK(ab1->IsExternal());
   3364 
   3365   result = CompileRun("ab1.byteLength");
   3366   CHECK_EQ(2, result->Int32Value(env.local()).FromJust());
   3367   result = CompileRun("u8_a[0]");
   3368   CHECK_EQ(0xAA, result->Int32Value(env.local()).FromJust());
   3369   result = CompileRun("u8_a[1]");
   3370   CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
   3371   result = CompileRun(
   3372       "var u8_b = new Uint8Array(ab1);"
   3373       "u8_b[0] = 0xBB;"
   3374       "u8_a[0]");
   3375   CHECK_EQ(0xBB, result->Int32Value(env.local()).FromJust());
   3376   result = CompileRun("u8_b[1]");
   3377   CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
   3378 
   3379   CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
   3380   uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
   3381   CHECK_EQ(0xBB, ab1_data[0]);
   3382   CHECK_EQ(0xFF, ab1_data[1]);
   3383   ab1_data[0] = 0xCC;
   3384   ab1_data[1] = 0x11;
   3385   result = CompileRun("u8_a[0] + u8_a[1]");
   3386   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
   3387 }
   3388 
   3389 
   3390 THREADED_TEST(SharedArrayBuffer_External) {
   3391   i::FLAG_harmony_sharedarraybuffer = true;
   3392   LocalContext env;
   3393   v8::Isolate* isolate = env->GetIsolate();
   3394   v8::HandleScope handle_scope(isolate);
   3395 
   3396   i::ScopedVector<uint8_t> my_data(100);
   3397   memset(my_data.start(), 0, 100);
   3398   Local<v8::SharedArrayBuffer> ab3 =
   3399       v8::SharedArrayBuffer::New(isolate, my_data.start(), 100);
   3400   CheckInternalFieldsAreZero(ab3);
   3401   CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
   3402   CHECK(ab3->IsExternal());
   3403 
   3404   CHECK(env->Global()->Set(env.local(), v8_str("ab3"), ab3).FromJust());
   3405 
   3406   v8::Local<v8::Value> result = CompileRun("ab3.byteLength");
   3407   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
   3408 
   3409   result = CompileRun(
   3410       "var u8_b = new Uint8Array(ab3);"
   3411       "u8_b[0] = 0xBB;"
   3412       "u8_b[1] = 0xCC;"
   3413       "u8_b.length");
   3414   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
   3415   CHECK_EQ(0xBB, my_data[0]);
   3416   CHECK_EQ(0xCC, my_data[1]);
   3417   my_data[0] = 0xCC;
   3418   my_data[1] = 0x11;
   3419   result = CompileRun("u8_b[0] + u8_b[1]");
   3420   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
   3421 }
   3422 
   3423 
   3424 THREADED_TEST(HiddenProperties) {
   3425   LocalContext env;
   3426   v8::Isolate* isolate = env->GetIsolate();
   3427   v8::HandleScope scope(isolate);
   3428 
   3429   v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
   3430   v8::Local<v8::Private> key =
   3431       v8::Private::ForApi(isolate, v8_str("api-test::hidden-key"));
   3432   v8::Local<v8::String> empty = v8_str("");
   3433   v8::Local<v8::String> prop_name = v8_str("prop_name");
   3434 
   3435   CcTest::heap()->CollectAllGarbage();
   3436 
   3437   // Make sure delete of a non-existent hidden value works
   3438   obj->DeletePrivate(env.local(), key).FromJust();
   3439 
   3440   CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 1503))
   3441             .FromJust());
   3442   CHECK_EQ(1503, obj->GetPrivate(env.local(), key)
   3443                      .ToLocalChecked()
   3444                      ->Int32Value(env.local())
   3445                      .FromJust());
   3446   CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 2002))
   3447             .FromJust());
   3448   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
   3449                      .ToLocalChecked()
   3450                      ->Int32Value(env.local())
   3451                      .FromJust());
   3452 
   3453   CcTest::heap()->CollectAllGarbage();
   3454 
   3455   // Make sure we do not find the hidden property.
   3456   CHECK(!obj->Has(env.local(), empty).FromJust());
   3457   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
   3458                      .ToLocalChecked()
   3459                      ->Int32Value(env.local())
   3460                      .FromJust());
   3461   CHECK(obj->Get(env.local(), empty).ToLocalChecked()->IsUndefined());
   3462   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
   3463                      .ToLocalChecked()
   3464                      ->Int32Value(env.local())
   3465                      .FromJust());
   3466   CHECK(
   3467       obj->Set(env.local(), empty, v8::Integer::New(isolate, 2003)).FromJust());
   3468   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
   3469                      .ToLocalChecked()
   3470                      ->Int32Value(env.local())
   3471                      .FromJust());
   3472   CHECK_EQ(2003, obj->Get(env.local(), empty)
   3473                      .ToLocalChecked()
   3474                      ->Int32Value(env.local())
   3475                      .FromJust());
   3476 
   3477   CcTest::heap()->CollectAllGarbage();
   3478 
   3479   // Add another property and delete it afterwards to force the object in
   3480   // slow case.
   3481   CHECK(obj->Set(env.local(), prop_name, v8::Integer::New(isolate, 2008))
   3482             .FromJust());
   3483   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
   3484                      .ToLocalChecked()
   3485                      ->Int32Value(env.local())
   3486                      .FromJust());
   3487   CHECK_EQ(2008, obj->Get(env.local(), prop_name)
   3488                      .ToLocalChecked()
   3489                      ->Int32Value(env.local())
   3490                      .FromJust());
   3491   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
   3492                      .ToLocalChecked()
   3493                      ->Int32Value(env.local())
   3494                      .FromJust());
   3495   CHECK(obj->Delete(env.local(), prop_name).FromJust());
   3496   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
   3497                      .ToLocalChecked()
   3498                      ->Int32Value(env.local())
   3499                      .FromJust());
   3500 
   3501   CcTest::heap()->CollectAllGarbage();
   3502 
   3503   CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 2002))
   3504             .FromJust());
   3505   CHECK(obj->DeletePrivate(env.local(), key).FromJust());
   3506   CHECK(!obj->HasPrivate(env.local(), key).FromJust());
   3507 }
   3508 
   3509 
   3510 THREADED_TEST(Regress97784) {
   3511   // Regression test for crbug.com/97784
   3512   // Messing with the Object.prototype should not have effect on
   3513   // hidden properties.
   3514   LocalContext env;
   3515   v8::HandleScope scope(env->GetIsolate());
   3516 
   3517   v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
   3518   v8::Local<v8::Private> key =
   3519       v8::Private::New(env->GetIsolate(), v8_str("hidden"));
   3520 
   3521   CompileRun(
   3522       "set_called = false;"
   3523       "Object.defineProperty("
   3524       "    Object.prototype,"
   3525       "    'hidden',"
   3526       "    {get: function() { return 45; },"
   3527       "     set: function() { set_called = true; }})");
   3528 
   3529   CHECK(!obj->HasPrivate(env.local(), key).FromJust());
   3530   // Make sure that the getter and setter from Object.prototype is not invoked.
   3531   // If it did we would have full access to the hidden properties in
   3532   // the accessor.
   3533   CHECK(
   3534       obj->SetPrivate(env.local(), key, v8::Integer::New(env->GetIsolate(), 42))
   3535           .FromJust());
   3536   ExpectFalse("set_called");
   3537   CHECK_EQ(42, obj->GetPrivate(env.local(), key)
   3538                    .ToLocalChecked()
   3539                    ->Int32Value(env.local())
   3540                    .FromJust());
   3541 }
   3542 
   3543 
   3544 THREADED_TEST(External) {
   3545   v8::HandleScope scope(CcTest::isolate());
   3546   int x = 3;
   3547   Local<v8::External> ext = v8::External::New(CcTest::isolate(), &x);
   3548   LocalContext env;
   3549   CHECK(env->Global()->Set(env.local(), v8_str("ext"), ext).FromJust());
   3550   Local<Value> reext_obj = CompileRun("this.ext");
   3551   v8::Local<v8::External> reext = reext_obj.As<v8::External>();
   3552   int* ptr = static_cast<int*>(reext->Value());
   3553   CHECK_EQ(x, 3);
   3554   *ptr = 10;
   3555   CHECK_EQ(x, 10);
   3556 
   3557   // Make sure unaligned pointers are wrapped properly.
   3558   char* data = i::StrDup("0123456789");
   3559   Local<v8::Value> zero = v8::External::New(CcTest::isolate(), &data[0]);
   3560   Local<v8::Value> one = v8::External::New(CcTest::isolate(), &data[1]);
   3561   Local<v8::Value> two = v8::External::New(CcTest::isolate(), &data[2]);
   3562   Local<v8::Value> three = v8::External::New(CcTest::isolate(), &data[3]);
   3563 
   3564   char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
   3565   CHECK_EQ('0', *char_ptr);
   3566   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
   3567   CHECK_EQ('1', *char_ptr);
   3568   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
   3569   CHECK_EQ('2', *char_ptr);
   3570   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
   3571   CHECK_EQ('3', *char_ptr);
   3572   i::DeleteArray(data);
   3573 }
   3574 
   3575 
   3576 THREADED_TEST(GlobalHandle) {
   3577   v8::Isolate* isolate = CcTest::isolate();
   3578   v8::Persistent<String> global;
   3579   {
   3580     v8::HandleScope scope(isolate);
   3581     global.Reset(isolate, v8_str("str"));
   3582   }
   3583   {
   3584     v8::HandleScope scope(isolate);
   3585     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
   3586   }
   3587   global.Reset();
   3588   {
   3589     v8::HandleScope scope(isolate);
   3590     global.Reset(isolate, v8_str("str"));
   3591   }
   3592   {
   3593     v8::HandleScope scope(isolate);
   3594     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
   3595   }
   3596   global.Reset();
   3597 }
   3598 
   3599 
   3600 THREADED_TEST(ResettingGlobalHandle) {
   3601   v8::Isolate* isolate = CcTest::isolate();
   3602   v8::Persistent<String> global;
   3603   {
   3604     v8::HandleScope scope(isolate);
   3605     global.Reset(isolate, v8_str("str"));
   3606   }
   3607   v8::internal::GlobalHandles* global_handles =
   3608       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
   3609   int initial_handle_count = global_handles->global_handles_count();
   3610   {
   3611     v8::HandleScope scope(isolate);
   3612     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
   3613   }
   3614   {
   3615     v8::HandleScope scope(isolate);
   3616     global.Reset(isolate, v8_str("longer"));
   3617   }
   3618   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
   3619   {
   3620     v8::HandleScope scope(isolate);
   3621     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 6);
   3622   }
   3623   global.Reset();
   3624   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
   3625 }
   3626 
   3627 
   3628 THREADED_TEST(ResettingGlobalHandleToEmpty) {
   3629   v8::Isolate* isolate = CcTest::isolate();
   3630   v8::Persistent<String> global;
   3631   {
   3632     v8::HandleScope scope(isolate);
   3633     global.Reset(isolate, v8_str("str"));
   3634   }
   3635   v8::internal::GlobalHandles* global_handles =
   3636       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
   3637   int initial_handle_count = global_handles->global_handles_count();
   3638   {
   3639     v8::HandleScope scope(isolate);
   3640     CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
   3641   }
   3642   {
   3643     v8::HandleScope scope(isolate);
   3644     Local<String> empty;
   3645     global.Reset(isolate, empty);
   3646   }
   3647   CHECK(global.IsEmpty());
   3648   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
   3649 }
   3650 
   3651 
   3652 template <class T>
   3653 static v8::Global<T> PassUnique(v8::Global<T> unique) {
   3654   return unique.Pass();
   3655 }
   3656 
   3657 
   3658 template <class T>
   3659 static v8::Global<T> ReturnUnique(v8::Isolate* isolate,
   3660                                   const v8::Persistent<T>& global) {
   3661   v8::Global<String> unique(isolate, global);
   3662   return unique.Pass();
   3663 }
   3664 
   3665 
   3666 THREADED_TEST(Global) {
   3667   v8::Isolate* isolate = CcTest::isolate();
   3668   v8::Persistent<String> global;
   3669   {
   3670     v8::HandleScope scope(isolate);
   3671     global.Reset(isolate, v8_str("str"));
   3672   }
   3673   v8::internal::GlobalHandles* global_handles =
   3674       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
   3675   int initial_handle_count = global_handles->global_handles_count();
   3676   {
   3677     v8::Global<String> unique(isolate, global);
   3678     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
   3679     // Test assignment via Pass
   3680     {
   3681       v8::Global<String> copy = unique.Pass();
   3682       CHECK(unique.IsEmpty());
   3683       CHECK(copy == global);
   3684       CHECK_EQ(initial_handle_count + 1,
   3685                global_handles->global_handles_count());
   3686       unique = copy.Pass();
   3687     }
   3688     // Test ctor via Pass
   3689     {
   3690       v8::Global<String> copy(unique.Pass());
   3691       CHECK(unique.IsEmpty());
   3692       CHECK(copy == global);
   3693       CHECK_EQ(initial_handle_count + 1,
   3694                global_handles->global_handles_count());
   3695       unique = copy.Pass();
   3696     }
   3697     // Test pass through function call
   3698     {
   3699       v8::Global<String> copy = PassUnique(unique.Pass());
   3700       CHECK(unique.IsEmpty());
   3701       CHECK(copy == global);
   3702       CHECK_EQ(initial_handle_count + 1,
   3703                global_handles->global_handles_count());
   3704       unique = copy.Pass();
   3705     }
   3706     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
   3707   }
   3708   // Test pass from function call
   3709   {
   3710     v8::Global<String> unique = ReturnUnique(isolate, global);
   3711     CHECK(unique == global);
   3712     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
   3713   }
   3714   CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
   3715   global.Reset();
   3716 }
   3717 
   3718 
   3719 namespace {
   3720 
   3721 class TwoPassCallbackData;
   3722 void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
   3723 void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
   3724 
   3725 
   3726 class TwoPassCallbackData {
   3727  public:
   3728   TwoPassCallbackData(v8::Isolate* isolate, int* instance_counter)
   3729       : first_pass_called_(false),
   3730         second_pass_called_(false),
   3731         trigger_gc_(false),
   3732         instance_counter_(instance_counter) {
   3733     HandleScope scope(isolate);
   3734     i::ScopedVector<char> buffer(40);
   3735     i::SNPrintF(buffer, "%p", static_cast<void*>(this));
   3736     auto string =
   3737         v8::String::NewFromUtf8(isolate, buffer.start(),
   3738                                 v8::NewStringType::kNormal).ToLocalChecked();
   3739     cell_.Reset(isolate, string);
   3740     (*instance_counter_)++;
   3741   }
   3742 
   3743   ~TwoPassCallbackData() {
   3744     CHECK(first_pass_called_);
   3745     CHECK(second_pass_called_);
   3746     CHECK(cell_.IsEmpty());
   3747     (*instance_counter_)--;
   3748   }
   3749 
   3750   void FirstPass() {
   3751     CHECK(!first_pass_called_);
   3752     CHECK(!second_pass_called_);
   3753     CHECK(!cell_.IsEmpty());
   3754     cell_.Reset();
   3755     first_pass_called_ = true;
   3756   }
   3757 
   3758   void SecondPass() {
   3759     CHECK(first_pass_called_);
   3760     CHECK(!second_pass_called_);
   3761     CHECK(cell_.IsEmpty());
   3762     second_pass_called_ = true;
   3763     delete this;
   3764   }
   3765 
   3766   void SetWeak() {
   3767     cell_.SetWeak(this, FirstPassCallback, v8::WeakCallbackType::kParameter);
   3768   }
   3769 
   3770   void MarkTriggerGc() { trigger_gc_ = true; }
   3771   bool trigger_gc() { return trigger_gc_; }
   3772 
   3773   int* instance_counter() { return instance_counter_; }
   3774 
   3775  private:
   3776   bool first_pass_called_;
   3777   bool second_pass_called_;
   3778   bool trigger_gc_;
   3779   v8::Global<v8::String> cell_;
   3780   int* instance_counter_;
   3781 };
   3782 
   3783 
   3784 void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
   3785   ApiTestFuzzer::Fuzz();
   3786   bool trigger_gc = data.GetParameter()->trigger_gc();
   3787   int* instance_counter = data.GetParameter()->instance_counter();
   3788   data.GetParameter()->SecondPass();
   3789   if (!trigger_gc) return;
   3790   auto data_2 = new TwoPassCallbackData(data.GetIsolate(), instance_counter);
   3791   data_2->SetWeak();
   3792   CcTest::heap()->CollectAllGarbage();
   3793 }
   3794 
   3795 
   3796 void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
   3797   data.GetParameter()->FirstPass();
   3798   data.SetSecondPassCallback(SecondPassCallback);
   3799 }
   3800 
   3801 }  // namespace
   3802 
   3803 
   3804 TEST(TwoPassPhantomCallbacks) {
   3805   auto isolate = CcTest::isolate();
   3806   const size_t kLength = 20;
   3807   int instance_counter = 0;
   3808   for (size_t i = 0; i < kLength; ++i) {
   3809     auto data = new TwoPassCallbackData(isolate, &instance_counter);
   3810     data->SetWeak();
   3811   }
   3812   CHECK_EQ(static_cast<int>(kLength), instance_counter);
   3813   CcTest::heap()->CollectAllGarbage();
   3814   EmptyMessageQueues(isolate);
   3815   CHECK_EQ(0, instance_counter);
   3816 }
   3817 
   3818 
   3819 TEST(TwoPassPhantomCallbacksNestedGc) {
   3820   auto isolate = CcTest::isolate();
   3821   const size_t kLength = 20;
   3822   TwoPassCallbackData* array[kLength];
   3823   int instance_counter = 0;
   3824   for (size_t i = 0; i < kLength; ++i) {
   3825     array[i] = new TwoPassCallbackData(isolate, &instance_counter);
   3826     array[i]->SetWeak();
   3827   }
   3828   array[5]->MarkTriggerGc();
   3829   array[10]->MarkTriggerGc();
   3830   array[15]->MarkTriggerGc();
   3831   CHECK_EQ(static_cast<int>(kLength), instance_counter);
   3832   CcTest::heap()->CollectAllGarbage();
   3833   EmptyMessageQueues(isolate);
   3834   CHECK_EQ(0, instance_counter);
   3835 }
   3836 
   3837 
   3838 namespace {
   3839 
   3840 void* IntKeyToVoidPointer(int key) { return reinterpret_cast<void*>(key << 1); }
   3841 
   3842 
   3843 Local<v8::Object> NewObjectForIntKey(
   3844     v8::Isolate* isolate, const v8::Global<v8::ObjectTemplate>& templ,
   3845     int key) {
   3846   auto local = Local<v8::ObjectTemplate>::New(isolate, templ);
   3847   auto obj = local->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
   3848   obj->SetAlignedPointerInInternalField(0, IntKeyToVoidPointer(key));
   3849   return obj;
   3850 }
   3851 
   3852 
   3853 template <typename K, typename V>
   3854 class PhantomStdMapTraits : public v8::StdMapTraits<K, V> {
   3855  public:
   3856   typedef typename v8::GlobalValueMap<K, V, PhantomStdMapTraits<K, V>> MapType;
   3857   static const v8::PersistentContainerCallbackType kCallbackType =
   3858       v8::kWeakWithInternalFields;
   3859   struct WeakCallbackDataType {
   3860     MapType* map;
   3861     K key;
   3862   };
   3863   static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key,
   3864                                                      Local<V> value) {
   3865     WeakCallbackDataType* data = new WeakCallbackDataType;
   3866     data->map = map;
   3867     data->key = key;
   3868     return data;
   3869   }
   3870   static MapType* MapFromWeakCallbackInfo(
   3871       const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
   3872     return data.GetParameter()->map;
   3873   }
   3874   static K KeyFromWeakCallbackInfo(
   3875       const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
   3876     return data.GetParameter()->key;
   3877   }
   3878   static void DisposeCallbackData(WeakCallbackDataType* data) { delete data; }
   3879   static void Dispose(v8::Isolate* isolate, v8::Global<V> value, K key) {
   3880     CHECK_EQ(IntKeyToVoidPointer(key),
   3881              v8::Object::GetAlignedPointerFromInternalField(value, 0));
   3882   }
   3883   static void OnWeakCallback(
   3884       const v8::WeakCallbackInfo<WeakCallbackDataType>&) {}
   3885   static void DisposeWeak(
   3886       const v8::WeakCallbackInfo<WeakCallbackDataType>& info) {
   3887     K key = KeyFromWeakCallbackInfo(info);
   3888     CHECK_EQ(IntKeyToVoidPointer(key), info.GetInternalField(0));
   3889     DisposeCallbackData(info.GetParameter());
   3890   }
   3891 };
   3892 
   3893 
   3894 template <typename Map>
   3895 void TestGlobalValueMap() {
   3896   LocalContext env;
   3897   v8::Isolate* isolate = env->GetIsolate();
   3898   v8::Global<ObjectTemplate> templ;
   3899   {
   3900     HandleScope scope(isolate);
   3901     auto t = ObjectTemplate::New(isolate);
   3902     t->SetInternalFieldCount(1);
   3903     templ.Reset(isolate, t);
   3904   }
   3905   Map map(isolate);
   3906   v8::internal::GlobalHandles* global_handles =
   3907       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
   3908   int initial_handle_count = global_handles->global_handles_count();
   3909   CHECK_EQ(0, static_cast<int>(map.Size()));
   3910   {
   3911     HandleScope scope(isolate);
   3912     Local<v8::Object> obj = map.Get(7);
   3913     CHECK(obj.IsEmpty());
   3914     Local<v8::Object> expected = v8::Object::New(isolate);
   3915     map.Set(7, expected);
   3916     CHECK_EQ(1, static_cast<int>(map.Size()));
   3917     obj = map.Get(7);
   3918     CHECK(expected->Equals(env.local(), obj).FromJust());
   3919     {
   3920       typename Map::PersistentValueReference ref = map.GetReference(7);
   3921       CHECK(expected->Equals(env.local(), ref.NewLocal(isolate)).FromJust());
   3922     }
   3923     v8::Global<v8::Object> removed = map.Remove(7);
   3924     CHECK_EQ(0, static_cast<int>(map.Size()));
   3925     CHECK(expected == removed);
   3926     removed = map.Remove(7);
   3927     CHECK(removed.IsEmpty());
   3928     map.Set(8, expected);
   3929     CHECK_EQ(1, static_cast<int>(map.Size()));
   3930     map.Set(8, expected);
   3931     CHECK_EQ(1, static_cast<int>(map.Size()));
   3932     {
   3933       typename Map::PersistentValueReference ref;
   3934       Local<v8::Object> expected2 = NewObjectForIntKey(isolate, templ, 8);
   3935       removed = map.Set(8, v8::Global<v8::Object>(isolate, expected2), &ref);
   3936       CHECK_EQ(1, static_cast<int>(map.Size()));
   3937       CHECK(expected == removed);
   3938       CHECK(expected2->Equals(env.local(), ref.NewLocal(isolate)).FromJust());
   3939     }
   3940   }
   3941   CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
   3942   if (map.IsWeak()) {
   3943     CcTest::i_isolate()->heap()->CollectAllGarbage(
   3944         i::Heap::kAbortIncrementalMarkingMask);
   3945   } else {
   3946     map.Clear();
   3947   }
   3948   CHECK_EQ(0, static_cast<int>(map.Size()));
   3949   CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
   3950   {
   3951     HandleScope scope(isolate);
   3952     Local<v8::Object> value = NewObjectForIntKey(isolate, templ, 9);
   3953     map.Set(9, value);
   3954     map.Clear();
   3955   }
   3956   CHECK_EQ(0, static_cast<int>(map.Size()));
   3957   CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
   3958 }
   3959 
   3960 }  // namespace
   3961 
   3962 
   3963 TEST(GlobalValueMap) {
   3964   // Default case, w/o weak callbacks:
   3965   TestGlobalValueMap<v8::StdGlobalValueMap<int, v8::Object>>();
   3966 
   3967   // Custom traits with weak callbacks:
   3968   typedef v8::GlobalValueMap<int, v8::Object,
   3969                              PhantomStdMapTraits<int, v8::Object>> WeakMap;
   3970   TestGlobalValueMap<WeakMap>();
   3971 }
   3972 
   3973 
   3974 TEST(PersistentValueVector) {
   3975   LocalContext env;
   3976   v8::Isolate* isolate = env->GetIsolate();
   3977   v8::internal::GlobalHandles* global_handles =
   3978       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
   3979   int handle_count = global_handles->global_handles_count();
   3980   HandleScope scope(isolate);
   3981 
   3982   v8::PersistentValueVector<v8::Object> vector(isolate);
   3983 
   3984   Local<v8::Object> obj1 = v8::Object::New(isolate);
   3985   Local<v8::Object> obj2 = v8::Object::New(isolate);
   3986   v8::Global<v8::Object> obj3(isolate, v8::Object::New(isolate));
   3987 
   3988   CHECK(vector.IsEmpty());
   3989   CHECK_EQ(0, static_cast<int>(vector.Size()));
   3990 
   3991   vector.ReserveCapacity(3);
   3992   CHECK(vector.IsEmpty());
   3993 
   3994   vector.Append(obj1);
   3995   vector.Append(obj2);
   3996   vector.Append(obj1);
   3997   vector.Append(obj3.Pass());
   3998   vector.Append(obj1);
   3999 
   4000   CHECK(!vector.IsEmpty());
   4001   CHECK_EQ(5, static_cast<int>(vector.Size()));
   4002   CHECK(obj3.IsEmpty());
   4003   CHECK(obj1->Equals(env.local(), vector.Get(0)).FromJust());
   4004   CHECK(obj1->Equals(env.local(), vector.Get(2)).FromJust());
   4005   CHECK(obj1->Equals(env.local(), vector.Get(4)).FromJust());
   4006   CHECK(obj2->Equals(env.local(), vector.Get(1)).FromJust());
   4007 
   4008   CHECK_EQ(5 + handle_count, global_handles->global_handles_count());
   4009 
   4010   vector.Clear();
   4011   CHECK(vector.IsEmpty());
   4012   CHECK_EQ(0, static_cast<int>(vector.Size()));
   4013   CHECK_EQ(handle_count, global_handles->global_handles_count());
   4014 }
   4015 
   4016 
   4017 THREADED_TEST(GlobalHandleUpcast) {
   4018   v8::Isolate* isolate = CcTest::isolate();
   4019   v8::HandleScope scope(isolate);
   4020   v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
   4021   v8::Persistent<String> global_string(isolate, local);
   4022   v8::Persistent<Value>& global_value =
   4023       v8::Persistent<Value>::Cast(global_string);
   4024   CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
   4025   CHECK(global_string == v8::Persistent<String>::Cast(global_value));
   4026   global_string.Reset();
   4027 }
   4028 
   4029 
   4030 THREADED_TEST(HandleEquality) {
   4031   v8::Isolate* isolate = CcTest::isolate();
   4032   v8::Persistent<String> global1;
   4033   v8::Persistent<String> global2;
   4034   {
   4035     v8::HandleScope scope(isolate);
   4036     global1.Reset(isolate, v8_str("str"));
   4037     global2.Reset(isolate, v8_str("str2"));
   4038   }
   4039   CHECK_EQ(global1 == global1, true);
   4040   CHECK_EQ(global1 != global1, false);
   4041   {
   4042     v8::HandleScope scope(isolate);
   4043     Local<String> local1 = Local<String>::New(isolate, global1);
   4044     Local<String> local2 = Local<String>::New(isolate, global2);
   4045 
   4046     CHECK_EQ(global1 == local1, true);
   4047     CHECK_EQ(global1 != local1, false);
   4048     CHECK_EQ(local1 == global1, true);
   4049     CHECK_EQ(local1 != global1, false);
   4050 
   4051     CHECK_EQ(global1 == local2, false);
   4052     CHECK_EQ(global1 != local2, true);
   4053     CHECK_EQ(local2 == global1, false);
   4054     CHECK_EQ(local2 != global1, true);
   4055 
   4056     CHECK_EQ(local1 == local2, false);
   4057     CHECK_EQ(local1 != local2, true);
   4058 
   4059     Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
   4060     CHECK_EQ(local1 == anotherLocal1, true);
   4061     CHECK_EQ(local1 != anotherLocal1, false);
   4062   }
   4063   global1.Reset();
   4064   global2.Reset();
   4065 }
   4066 
   4067 
   4068 THREADED_TEST(LocalHandle) {
   4069   v8::HandleScope scope(CcTest::isolate());
   4070   v8::Local<String> local =
   4071       v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
   4072   CHECK_EQ(local->Length(), 3);
   4073 }
   4074 
   4075 
   4076 class WeakCallCounter {
   4077  public:
   4078   explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) {}
   4079   int id() { return id_; }
   4080   void increment() { number_of_weak_calls_++; }
   4081   int NumberOfWeakCalls() { return number_of_weak_calls_; }
   4082 
   4083  private:
   4084   int id_;
   4085   int number_of_weak_calls_;
   4086 };
   4087 
   4088 
   4089 template <typename T>
   4090 struct WeakCallCounterAndPersistent {
   4091   explicit WeakCallCounterAndPersistent(WeakCallCounter* counter)
   4092       : counter(counter) {}
   4093   WeakCallCounter* counter;
   4094   v8::Persistent<T> handle;
   4095 };
   4096 
   4097 
   4098 template <typename T>
   4099 static void WeakPointerCallback(
   4100     const v8::WeakCallbackInfo<WeakCallCounterAndPersistent<T>>& data) {
   4101   CHECK_EQ(1234, data.GetParameter()->counter->id());
   4102   data.GetParameter()->counter->increment();
   4103   data.GetParameter()->handle.Reset();
   4104 }
   4105 
   4106 
   4107 template <typename T>
   4108 static UniqueId MakeUniqueId(const Persistent<T>& p) {
   4109   return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
   4110 }
   4111 
   4112 
   4113 THREADED_TEST(ApiObjectGroups) {
   4114   LocalContext env;
   4115   v8::Isolate* iso = env->GetIsolate();
   4116   HandleScope scope(iso);
   4117 
   4118   WeakCallCounter counter(1234);
   4119 
   4120   WeakCallCounterAndPersistent<Value> g1s1(&counter);
   4121   WeakCallCounterAndPersistent<Value> g1s2(&counter);
   4122   WeakCallCounterAndPersistent<Value> g1c1(&counter);
   4123   WeakCallCounterAndPersistent<Value> g2s1(&counter);
   4124   WeakCallCounterAndPersistent<Value> g2s2(&counter);
   4125   WeakCallCounterAndPersistent<Value> g2c1(&counter);
   4126 
   4127   {
   4128     HandleScope scope(iso);
   4129     g1s1.handle.Reset(iso, Object::New(iso));
   4130     g1s2.handle.Reset(iso, Object::New(iso));
   4131     g1c1.handle.Reset(iso, Object::New(iso));
   4132     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
   4133                         v8::WeakCallbackType::kParameter);
   4134     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
   4135                         v8::WeakCallbackType::kParameter);
   4136     g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
   4137                         v8::WeakCallbackType::kParameter);
   4138 
   4139     g2s1.handle.Reset(iso, Object::New(iso));
   4140     g2s2.handle.Reset(iso, Object::New(iso));
   4141     g2c1.handle.Reset(iso, Object::New(iso));
   4142     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
   4143                         v8::WeakCallbackType::kParameter);
   4144     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
   4145                         v8::WeakCallbackType::kParameter);
   4146     g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
   4147                         v8::WeakCallbackType::kParameter);
   4148   }
   4149 
   4150   WeakCallCounterAndPersistent<Value> root(&counter);
   4151   root.handle.Reset(iso, g1s1.handle);  // make a root.
   4152 
   4153   // Connect group 1 and 2, make a cycle.
   4154   {
   4155     HandleScope scope(iso);
   4156     CHECK(Local<Object>::New(iso, g1s2.handle.As<Object>())
   4157               ->Set(env.local(), 0, Local<Value>::New(iso, g2s2.handle))
   4158               .FromJust());
   4159     CHECK(Local<Object>::New(iso, g2s1.handle.As<Object>())
   4160               ->Set(env.local(), 0, Local<Value>::New(iso, g1s1.handle))
   4161               .FromJust());
   4162   }
   4163 
   4164   {
   4165     UniqueId id1 = MakeUniqueId(g1s1.handle);
   4166     UniqueId id2 = MakeUniqueId(g2s2.handle);
   4167     iso->SetObjectGroupId(g1s1.handle, id1);
   4168     iso->SetObjectGroupId(g1s2.handle, id1);
   4169     iso->SetReferenceFromGroup(id1, g1c1.handle);
   4170     iso->SetObjectGroupId(g2s1.handle, id2);
   4171     iso->SetObjectGroupId(g2s2.handle, id2);
   4172     iso->SetReferenceFromGroup(id2, g2c1.handle);
   4173   }
   4174   // Do a single full GC, ensure incremental marking is stopped.
   4175   v8::internal::Heap* heap =
   4176       reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
   4177   heap->CollectAllGarbage();
   4178 
   4179   // All object should be alive.
   4180   CHECK_EQ(0, counter.NumberOfWeakCalls());
   4181 
   4182   // Weaken the root.
   4183   root.handle.SetWeak(&root, &WeakPointerCallback,
   4184                       v8::WeakCallbackType::kParameter);
   4185   // But make children strong roots---all the objects (except for children)
   4186   // should be collectable now.
   4187   g1c1.handle.ClearWeak();
   4188   g2c1.handle.ClearWeak();
   4189 
   4190   // Groups are deleted, rebuild groups.
   4191   {
   4192     UniqueId id1 = MakeUniqueId(g1s1.handle);
   4193     UniqueId id2 = MakeUniqueId(g2s2.handle);
   4194     iso->SetObjectGroupId(g1s1.handle, id1);
   4195     iso->SetObjectGroupId(g1s2.handle, id1);
   4196     iso->SetReferenceFromGroup(id1, g1c1.handle);
   4197     iso->SetObjectGroupId(g2s1.handle, id2);
   4198     iso->SetObjectGroupId(g2s2.handle, id2);
   4199     iso->SetReferenceFromGroup(id2, g2c1.handle);
   4200   }
   4201 
   4202   heap->CollectAllGarbage();
   4203 
   4204   // All objects should be gone. 5 global handles in total.
   4205   CHECK_EQ(5, counter.NumberOfWeakCalls());
   4206 
   4207   // And now make children weak again and collect them.
   4208   g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
   4209                       v8::WeakCallbackType::kParameter);
   4210   g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
   4211                       v8::WeakCallbackType::kParameter);
   4212 
   4213   heap->CollectAllGarbage();
   4214   CHECK_EQ(7, counter.NumberOfWeakCalls());
   4215 }
   4216 
   4217 
   4218 THREADED_TEST(ApiObjectGroupsForSubtypes) {
   4219   LocalContext env;
   4220   v8::Isolate* iso = env->GetIsolate();
   4221   HandleScope scope(iso);
   4222 
   4223   WeakCallCounter counter(1234);
   4224 
   4225   WeakCallCounterAndPersistent<Object> g1s1(&counter);
   4226   WeakCallCounterAndPersistent<String> g1s2(&counter);
   4227   WeakCallCounterAndPersistent<String> g1c1(&counter);
   4228   WeakCallCounterAndPersistent<Object> g2s1(&counter);
   4229   WeakCallCounterAndPersistent<String> g2s2(&counter);
   4230   WeakCallCounterAndPersistent<String> g2c1(&counter);
   4231 
   4232   {
   4233     HandleScope scope(iso);
   4234     g1s1.handle.Reset(iso, Object::New(iso));
   4235     g1s2.handle.Reset(iso, v8_str("foo1"));
   4236     g1c1.handle.Reset(iso, v8_str("foo2"));
   4237     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
   4238                         v8::WeakCallbackType::kParameter);
   4239     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
   4240                         v8::WeakCallbackType::kParameter);
   4241     g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
   4242                         v8::WeakCallbackType::kParameter);
   4243 
   4244     g2s1.handle.Reset(iso, Object::New(iso));
   4245     g2s2.handle.Reset(iso, v8_str("foo3"));
   4246     g2c1.handle.Reset(iso, v8_str("foo4"));
   4247     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
   4248                         v8::WeakCallbackType::kParameter);
   4249     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
   4250                         v8::WeakCallbackType::kParameter);
   4251     g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
   4252                         v8::WeakCallbackType::kParameter);
   4253   }
   4254 
   4255   WeakCallCounterAndPersistent<Value> root(&counter);
   4256   root.handle.Reset(iso, g1s1.handle);  // make a root.
   4257 
   4258   // Connect group 1 and 2, make a cycle.
   4259   {
   4260     HandleScope scope(iso);
   4261     CHECK(Local<Object>::New(iso, g1s1.handle)
   4262               ->Set(env.local(), 0, Local<Object>::New(iso, g2s1.handle))
   4263               .FromJust());
   4264     CHECK(Local<Object>::New(iso, g2s1.handle)
   4265               ->Set(env.local(), 0, Local<Object>::New(iso, g1s1.handle))
   4266               .FromJust());
   4267   }
   4268 
   4269   {
   4270     UniqueId id1 = MakeUniqueId(g1s1.handle);
   4271     UniqueId id2 = MakeUniqueId(g2s2.handle);
   4272     iso->SetObjectGroupId(g1s1.handle, id1);
   4273     iso->SetObjectGroupId(g1s2.handle, id1);
   4274     iso->SetReference(g1s1.handle, g1c1.handle);
   4275     iso->SetObjectGroupId(g2s1.handle, id2);
   4276     iso->SetObjectGroupId(g2s2.handle, id2);
   4277     iso->SetReferenceFromGroup(id2, g2c1.handle);
   4278   }
   4279   // Do a single full GC, ensure incremental marking is stopped.
   4280   v8::internal::Heap* heap =
   4281       reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
   4282   heap->CollectAllGarbage();
   4283 
   4284   // All object should be alive.
   4285   CHECK_EQ(0, counter.NumberOfWeakCalls());
   4286 
   4287   // Weaken the root.
   4288   root.handle.SetWeak(&root, &WeakPointerCallback,
   4289                       v8::WeakCallbackType::kParameter);
   4290   // But make children strong roots---all the objects (except for children)
   4291   // should be collectable now.
   4292   g1c1.handle.ClearWeak();
   4293   g2c1.handle.ClearWeak();
   4294 
   4295   // Groups are deleted, rebuild groups.
   4296   {
   4297     UniqueId id1 = MakeUniqueId(g1s1.handle);
   4298     UniqueId id2 = MakeUniqueId(g2s2.handle);
   4299     iso->SetObjectGroupId(g1s1.handle, id1);
   4300     iso->SetObjectGroupId(g1s2.handle, id1);
   4301     iso->SetReference(g1s1.handle, g1c1.handle);
   4302     iso->SetObjectGroupId(g2s1.handle, id2);
   4303     iso->SetObjectGroupId(g2s2.handle, id2);
   4304     iso->SetReferenceFromGroup(id2, g2c1.handle);
   4305   }
   4306 
   4307   heap->CollectAllGarbage();
   4308 
   4309   // All objects should be gone. 5 global handles in total.
   4310   CHECK_EQ(5, counter.NumberOfWeakCalls());
   4311 
   4312   // And now make children weak again and collect them.
   4313   g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
   4314                       v8::WeakCallbackType::kParameter);
   4315   g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
   4316                       v8::WeakCallbackType::kParameter);
   4317 
   4318   heap->CollectAllGarbage();
   4319   CHECK_EQ(7, counter.NumberOfWeakCalls());
   4320 }
   4321 
   4322 
   4323 THREADED_TEST(ApiObjectGroupsCycle) {
   4324   LocalContext env;
   4325   v8::Isolate* iso = env->GetIsolate();
   4326   HandleScope scope(iso);
   4327 
   4328   WeakCallCounter counter(1234);
   4329 
   4330   WeakCallCounterAndPersistent<Value> g1s1(&counter);
   4331   WeakCallCounterAndPersistent<Value> g1s2(&counter);
   4332   WeakCallCounterAndPersistent<Value> g2s1(&counter);
   4333   WeakCallCounterAndPersistent<Value> g2s2(&counter);
   4334   WeakCallCounterAndPersistent<Value> g3s1(&counter);
   4335   WeakCallCounterAndPersistent<Value> g3s2(&counter);
   4336   WeakCallCounterAndPersistent<Value> g4s1(&counter);
   4337   WeakCallCounterAndPersistent<Value> g4s2(&counter);
   4338 
   4339   {
   4340     HandleScope scope(iso);
   4341     g1s1.handle.Reset(iso, Object::New(iso));
   4342     g1s2.handle.Reset(iso, Object::New(iso));
   4343     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
   4344                         v8::WeakCallbackType::kParameter);
   4345     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
   4346                         v8::WeakCallbackType::kParameter);
   4347     CHECK(g1s1.handle.IsWeak());
   4348     CHECK(g1s2.handle.IsWeak());
   4349 
   4350     g2s1.handle.Reset(iso, Object::New(iso));
   4351     g2s2.handle.Reset(iso, Object::New(iso));
   4352     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
   4353                         v8::WeakCallbackType::kParameter);
   4354     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
   4355                         v8::WeakCallbackType::kParameter);
   4356     CHECK(g2s1.handle.IsWeak());
   4357     CHECK(g2s2.handle.IsWeak());
   4358 
   4359     g3s1.handle.Reset(iso, Object::New(iso));
   4360     g3s2.handle.Reset(iso, Object::New(iso));
   4361     g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback,
   4362                         v8::WeakCallbackType::kParameter);
   4363     g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback,
   4364                         v8::WeakCallbackType::kParameter);
   4365     CHECK(g3s1.handle.IsWeak());
   4366     CHECK(g3s2.handle.IsWeak());
   4367 
   4368     g4s1.handle.Reset(iso, Object::New(iso));
   4369     g4s2.handle.Reset(iso, Object::New(iso));
   4370     g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback,
   4371                         v8::WeakCallbackType::kParameter);
   4372     g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback,
   4373                         v8::WeakCallbackType::kParameter);
   4374     CHECK(g4s1.handle.IsWeak());
   4375     CHECK(g4s2.handle.IsWeak());
   4376   }
   4377 
   4378   WeakCallCounterAndPersistent<Value> root(&counter);
   4379   root.handle.Reset(iso, g1s1.handle);  // make a root.
   4380 
   4381   // Connect groups.  We're building the following cycle:
   4382   // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
   4383   // groups.
   4384   {
   4385     UniqueId id1 = MakeUniqueId(g1s1.handle);
   4386     UniqueId id2 = MakeUniqueId(g2s1.handle);
   4387     UniqueId id3 = MakeUniqueId(g3s1.handle);
   4388     UniqueId id4 = MakeUniqueId(g4s1.handle);
   4389     iso->SetObjectGroupId(g1s1.handle, id1);
   4390     iso->SetObjectGroupId(g1s2.handle, id1);
   4391     iso->SetReferenceFromGroup(id1, g2s1.handle);
   4392     iso->SetObjectGroupId(g2s1.handle, id2);
   4393     iso->SetObjectGroupId(g2s2.handle, id2);
   4394     iso->SetReferenceFromGroup(id2, g3s1.handle);
   4395     iso->SetObjectGroupId(g3s1.handle, id3);
   4396     iso->SetObjectGroupId(g3s2.handle, id3);
   4397     iso->SetReferenceFromGroup(id3, g4s1.handle);
   4398     iso->SetObjectGroupId(g4s1.handle, id4);
   4399     iso->SetObjectGroupId(g4s2.handle, id4);
   4400     iso->SetReferenceFromGroup(id4, g1s1.handle);
   4401   }
   4402   // Do a single full GC
   4403   v8::internal::Heap* heap =
   4404       reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
   4405   heap->CollectAllGarbage();
   4406 
   4407   // All object should be alive.
   4408   CHECK_EQ(0, counter.NumberOfWeakCalls());
   4409 
   4410   // Weaken the root.
   4411   root.handle.SetWeak(&root, &WeakPointerCallback,
   4412                       v8::WeakCallbackType::kParameter);
   4413 
   4414   // Groups are deleted, rebuild groups.
   4415   {
   4416     UniqueId id1 = MakeUniqueId(g1s1.handle);
   4417     UniqueId id2 = MakeUniqueId(g2s1.handle);
   4418     UniqueId id3 = MakeUniqueId(g3s1.handle);
   4419     UniqueId id4 = MakeUniqueId(g4s1.handle);
   4420     iso->SetObjectGroupId(g1s1.handle, id1);
   4421     iso->SetObjectGroupId(g1s2.handle, id1);
   4422     iso->SetReferenceFromGroup(id1, g2s1.handle);
   4423     iso->SetObjectGroupId(g2s1.handle, id2);
   4424     iso->SetObjectGroupId(g2s2.handle, id2);
   4425     iso->SetReferenceFromGroup(id2, g3s1.handle);
   4426     iso->SetObjectGroupId(g3s1.handle, id3);
   4427     iso->SetObjectGroupId(g3s2.handle, id3);
   4428     iso->SetReferenceFromGroup(id3, g4s1.handle);
   4429     iso->SetObjectGroupId(g4s1.handle, id4);
   4430     iso->SetObjectGroupId(g4s2.handle, id4);
   4431     iso->SetReferenceFromGroup(id4, g1s1.handle);
   4432   }
   4433 
   4434   heap->CollectAllGarbage();
   4435 
   4436   // All objects should be gone. 9 global handles in total.
   4437   CHECK_EQ(9, counter.NumberOfWeakCalls());
   4438 }
   4439 
   4440 
   4441 // TODO(mstarzinger): This should be a THREADED_TEST but causes failures
   4442 // on the buildbots, so was made non-threaded for the time being.
   4443 TEST(ApiObjectGroupsCycleForScavenger) {
   4444   i::FLAG_stress_compaction = false;
   4445   i::FLAG_gc_global = false;
   4446   LocalContext env;
   4447   v8::Isolate* iso = env->GetIsolate();
   4448   HandleScope scope(iso);
   4449 
   4450   WeakCallCounter counter(1234);
   4451 
   4452   WeakCallCounterAndPersistent<Value> g1s1(&counter);
   4453   WeakCallCounterAndPersistent<Value> g1s2(&counter);
   4454   WeakCallCounterAndPersistent<Value> g2s1(&counter);
   4455   WeakCallCounterAndPersistent<Value> g2s2(&counter);
   4456   WeakCallCounterAndPersistent<Value> g3s1(&counter);
   4457   WeakCallCounterAndPersistent<Value> g3s2(&counter);
   4458 
   4459   {
   4460     HandleScope scope(iso);
   4461     g1s1.handle.Reset(iso, Object::New(iso));
   4462     g1s2.handle.Reset(iso, Object::New(iso));
   4463     g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
   4464                         v8::WeakCallbackType::kParameter);
   4465     g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
   4466                         v8::WeakCallbackType::kParameter);
   4467 
   4468     g2s1.handle.Reset(iso, Object::New(iso));
   4469     g2s2.handle.Reset(iso, Object::New(iso));
   4470     g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
   4471                         v8::WeakCallbackType::kParameter);
   4472     g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
   4473                         v8::WeakCallbackType::kParameter);
   4474 
   4475     g3s1.handle.Reset(iso, Object::New(iso));
   4476     g3s2.handle.Reset(iso, Object::New(iso));
   4477     g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback,
   4478                         v8::WeakCallbackType::kParameter);
   4479     g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback,
   4480                         v8::WeakCallbackType::kParameter);
   4481   }
   4482 
   4483   // Make a root.
   4484   WeakCallCounterAndPersistent<Value> root(&counter);
   4485   root.handle.Reset(iso, g1s1.handle);
   4486   root.handle.MarkPartiallyDependent();
   4487 
   4488   // Connect groups.  We're building the following cycle:
   4489   // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
   4490   // groups.
   4491   {
   4492     HandleScope handle_scope(iso);
   4493     g1s1.handle.MarkPartiallyDependent();
   4494     g1s2.handle.MarkPartiallyDependent();
   4495     g2s1.handle.MarkPartiallyDependent();
   4496     g2s2.handle.MarkPartiallyDependent();
   4497     g3s1.handle.MarkPartiallyDependent();
   4498     g3s2.handle.MarkPartiallyDependent();
   4499     iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
   4500     iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
   4501     Local<Object>::New(iso, g1s1.handle.As<Object>())
   4502         ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g2s1.handle))
   4503         .FromJust();
   4504     iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
   4505     iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
   4506     Local<Object>::New(iso, g2s1.handle.As<Object>())
   4507         ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g3s1.handle))
   4508         .FromJust();
   4509     iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
   4510     iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
   4511     Local<Object>::New(iso, g3s1.handle.As<Object>())
   4512         ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g1s1.handle))
   4513         .FromJust();
   4514   }
   4515 
   4516   v8::internal::Heap* heap =
   4517       reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
   4518   heap->CollectAllGarbage();
   4519 
   4520   // All objects should be alive.
   4521   CHECK_EQ(0, counter.NumberOfWeakCalls());
   4522 
   4523   // Weaken the root.
   4524   root.handle.SetWeak(&root, &WeakPointerCallback,
   4525                       v8::WeakCallbackType::kParameter);
   4526   root.handle.MarkPartiallyDependent();
   4527 
   4528   // Groups are deleted, rebuild groups.
   4529   {
   4530     HandleScope handle_scope(iso);
   4531     g1s1.handle.MarkPartiallyDependent();
   4532     g1s2.handle.MarkPartiallyDependent();
   4533     g2s1.handle.MarkPartiallyDependent();
   4534     g2s2.handle.MarkPartiallyDependent();
   4535     g3s1.handle.MarkPartiallyDependent();
   4536     g3s2.handle.MarkPartiallyDependent();
   4537     iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
   4538     iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
   4539     Local<Object>::New(iso, g1s1.handle.As<Object>())
   4540         ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g2s1.handle))
   4541         .FromJust();
   4542     iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
   4543     iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
   4544     Local<Object>::New(iso, g2s1.handle.As<Object>())
   4545         ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g3s1.handle))
   4546         .FromJust();
   4547     iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
   4548     iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
   4549     Local<Object>::New(iso, g3s1.handle.As<Object>())
   4550         ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g1s1.handle))
   4551         .FromJust();
   4552   }
   4553 
   4554   heap->CollectAllGarbage();
   4555 
   4556   // All objects should be gone. 7 global handles in total.
   4557   CHECK_EQ(7, counter.NumberOfWeakCalls());
   4558 }
   4559 
   4560 
   4561 THREADED_TEST(ScriptException) {
   4562   LocalContext env;
   4563   v8::HandleScope scope(env->GetIsolate());
   4564   Local<Script> script = v8_compile("throw 'panama!';");
   4565   v8::TryCatch try_catch(env->GetIsolate());
   4566   v8::MaybeLocal<Value> result = script->Run(env.local());
   4567   CHECK(result.IsEmpty());
   4568   CHECK(try_catch.HasCaught());
   4569   String::Utf8Value exception_value(try_catch.Exception());
   4570   CHECK_EQ(0, strcmp(*exception_value, "panama!"));
   4571 }
   4572 
   4573 
   4574 TEST(TryCatchCustomException) {
   4575   LocalContext env;
   4576   v8::Isolate* isolate = env->GetIsolate();
   4577   v8::HandleScope scope(isolate);
   4578   v8::TryCatch try_catch(isolate);
   4579   CompileRun(
   4580       "function CustomError() { this.a = 'b'; }"
   4581       "(function f() { throw new CustomError(); })();");
   4582   CHECK(try_catch.HasCaught());
   4583   CHECK(try_catch.Exception()
   4584             ->ToObject(env.local())
   4585             .ToLocalChecked()
   4586             ->Get(env.local(), v8_str("a"))
   4587             .ToLocalChecked()
   4588             ->Equals(env.local(), v8_str("b"))
   4589             .FromJust());
   4590 }
   4591 
   4592 
   4593 bool message_received;
   4594 
   4595 
   4596 static void check_message_0(v8::Local<v8::Message> message,
   4597                             v8::Local<Value> data) {
   4598   CHECK_EQ(5.76, data->NumberValue(CcTest::isolate()->GetCurrentContext())
   4599                      .FromJust());
   4600   CHECK_EQ(6.75, message->GetScriptOrigin()
   4601                      .ResourceName()
   4602                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
   4603                      .FromJust());
   4604   CHECK(!message->IsSharedCrossOrigin());
   4605   message_received = true;
   4606 }
   4607 
   4608 
   4609 THREADED_TEST(MessageHandler0) {
   4610   message_received = false;
   4611   v8::HandleScope scope(CcTest::isolate());
   4612   CHECK(!message_received);
   4613   LocalContext context;
   4614   CcTest::isolate()->AddMessageListener(check_message_0, v8_num(5.76));
   4615   v8::Local<v8::Script> script = CompileWithOrigin("throw 'error'", "6.75");
   4616   CHECK(script->Run(context.local()).IsEmpty());
   4617   CHECK(message_received);
   4618   // clear out the message listener
   4619   CcTest::isolate()->RemoveMessageListeners(check_message_0);
   4620 }
   4621 
   4622 
   4623 static void check_message_1(v8::Local<v8::Message> message,
   4624                             v8::Local<Value> data) {
   4625   CHECK(data->IsNumber());
   4626   CHECK_EQ(1337,
   4627            data->Int32Value(CcTest::isolate()->GetCurrentContext()).FromJust());
   4628   CHECK(!message->IsSharedCrossOrigin());
   4629   message_received = true;
   4630 }
   4631 
   4632 
   4633 TEST(MessageHandler1) {
   4634   message_received = false;
   4635   v8::HandleScope scope(CcTest::isolate());
   4636   CHECK(!message_received);
   4637   CcTest::isolate()->AddMessageListener(check_message_1);
   4638   LocalContext context;
   4639   CompileRun("throw 1337;");
   4640   CHECK(message_received);
   4641   // clear out the message listener
   4642   CcTest::isolate()->RemoveMessageListeners(check_message_1);
   4643 }
   4644 
   4645 
   4646 static void check_message_2(v8::Local<v8::Message> message,
   4647                             v8::Local<Value> data) {
   4648   LocalContext context;
   4649   CHECK(data->IsObject());
   4650   v8::Local<v8::Value> hidden_property =
   4651       v8::Object::Cast(*data)
   4652           ->GetPrivate(
   4653               context.local(),
   4654               v8::Private::ForApi(CcTest::isolate(), v8_str("hidden key")))
   4655           .ToLocalChecked();
   4656   CHECK(v8_str("hidden value")
   4657             ->Equals(context.local(), hidden_property)
   4658             .FromJust());
   4659   CHECK(!message->IsSharedCrossOrigin());
   4660   message_received = true;
   4661 }
   4662 
   4663 
   4664 TEST(MessageHandler2) {
   4665   message_received = false;
   4666   v8::HandleScope scope(CcTest::isolate());
   4667   CHECK(!message_received);
   4668   CcTest::isolate()->AddMessageListener(check_message_2);
   4669   LocalContext context;
   4670   v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
   4671   v8::Object::Cast(*error)
   4672       ->SetPrivate(context.local(),
   4673                    v8::Private::ForApi(CcTest::isolate(), v8_str("hidden key")),
   4674                    v8_str("hidden value"))
   4675       .FromJust();
   4676   CHECK(context->Global()
   4677             ->Set(context.local(), v8_str("error"), error)
   4678             .FromJust());
   4679   CompileRun("throw error;");
   4680   CHECK(message_received);
   4681   // clear out the message listener
   4682   CcTest::isolate()->RemoveMessageListeners(check_message_2);
   4683 }
   4684 
   4685 
   4686 static void check_message_3(v8::Local<v8::Message> message,
   4687                             v8::Local<Value> data) {
   4688   CHECK(message->IsSharedCrossOrigin());
   4689   CHECK(message->GetScriptOrigin().Options().IsSharedCrossOrigin());
   4690   CHECK(message->GetScriptOrigin().Options().IsEmbedderDebugScript());
   4691   CHECK(message->GetScriptOrigin().Options().IsOpaque());
   4692   CHECK_EQ(6.75, message->GetScriptOrigin()
   4693                      .ResourceName()
   4694                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
   4695                      .FromJust());
   4696   CHECK_EQ(7.40, message->GetScriptOrigin()
   4697                      .SourceMapUrl()
   4698                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
   4699                      .FromJust());
   4700   message_received = true;
   4701 }
   4702 
   4703 
   4704 TEST(MessageHandler3) {
   4705   message_received = false;
   4706   v8::Isolate* isolate = CcTest::isolate();
   4707   v8::HandleScope scope(isolate);
   4708   CHECK(!message_received);
   4709   isolate->AddMessageListener(check_message_3);
   4710   LocalContext context;
   4711   v8::ScriptOrigin origin = v8::ScriptOrigin(
   4712       v8_str("6.75"), v8::Integer::New(isolate, 1),
   4713       v8::Integer::New(isolate, 2), v8::True(isolate), Local<v8::Integer>(),
   4714       v8::True(isolate), v8_str("7.40"), v8::True(isolate));
   4715   v8::Local<v8::Script> script =
   4716       Script::Compile(context.local(), v8_str("throw 'error'"), &origin)
   4717           .ToLocalChecked();
   4718   CHECK(script->Run(context.local()).IsEmpty());
   4719   CHECK(message_received);
   4720   // clear out the message listener
   4721   isolate->RemoveMessageListeners(check_message_3);
   4722 }
   4723 
   4724 
   4725 static void check_message_4(v8::Local<v8::Message> message,
   4726                             v8::Local<Value> data) {
   4727   CHECK(!message->IsSharedCrossOrigin());
   4728   CHECK_EQ(6.75, message->GetScriptOrigin()
   4729                      .ResourceName()
   4730                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
   4731                      .FromJust());
   4732   message_received = true;
   4733 }
   4734 
   4735 
   4736 TEST(MessageHandler4) {
   4737   message_received = false;
   4738   v8::Isolate* isolate = CcTest::isolate();
   4739   v8::HandleScope scope(isolate);
   4740   CHECK(!message_received);
   4741   isolate->AddMessageListener(check_message_4);
   4742   LocalContext context;
   4743   v8::ScriptOrigin origin =
   4744       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
   4745                        v8::Integer::New(isolate, 2), v8::False(isolate));
   4746   v8::Local<v8::Script> script =
   4747       Script::Compile(context.local(), v8_str("throw 'error'"), &origin)
   4748           .ToLocalChecked();
   4749   CHECK(script->Run(context.local()).IsEmpty());
   4750   CHECK(message_received);
   4751   // clear out the message listener
   4752   isolate->RemoveMessageListeners(check_message_4);
   4753 }
   4754 
   4755 
   4756 static void check_message_5a(v8::Local<v8::Message> message,
   4757                              v8::Local<Value> data) {
   4758   CHECK(message->IsSharedCrossOrigin());
   4759   CHECK_EQ(6.75, message->GetScriptOrigin()
   4760                      .ResourceName()
   4761                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
   4762                      .FromJust());
   4763   message_received = true;
   4764 }
   4765 
   4766 
   4767 static void check_message_5b(v8::Local<v8::Message> message,
   4768                              v8::Local<Value> data) {
   4769   CHECK(!message->IsSharedCrossOrigin());
   4770   CHECK_EQ(6.75, message->GetScriptOrigin()
   4771                      .ResourceName()
   4772                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
   4773                      .FromJust());
   4774   message_received = true;
   4775 }
   4776 
   4777 
   4778 TEST(MessageHandler5) {
   4779   message_received = false;
   4780   v8::Isolate* isolate = CcTest::isolate();
   4781   v8::HandleScope scope(isolate);
   4782   CHECK(!message_received);
   4783   isolate->AddMessageListener(check_message_5a);
   4784   LocalContext context;
   4785   v8::ScriptOrigin origin1 =
   4786       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
   4787                        v8::Integer::New(isolate, 2), v8::True(isolate));
   4788   v8::Local<v8::Script> script =
   4789       Script::Compile(context.local(), v8_str("throw 'error'"), &origin1)
   4790           .ToLocalChecked();
   4791   CHECK(script->Run(context.local()).IsEmpty());
   4792   CHECK(message_received);
   4793   // clear out the message listener
   4794   isolate->RemoveMessageListeners(check_message_5a);
   4795 
   4796   message_received = false;
   4797   isolate->AddMessageListener(check_message_5b);
   4798   v8::ScriptOrigin origin2 =
   4799       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
   4800                        v8::Integer::New(isolate, 2), v8::False(isolate));
   4801   script = Script::Compile(context.local(), v8_str("throw 'error'"), &origin2)
   4802                .ToLocalChecked();
   4803   CHECK(script->Run(context.local()).IsEmpty());
   4804   CHECK(message_received);
   4805   // clear out the message listener
   4806   isolate->RemoveMessageListeners(check_message_5b);
   4807 }
   4808 
   4809 
   4810 TEST(NativeWeakMap) {
   4811   v8::Isolate* isolate = CcTest::isolate();
   4812   HandleScope scope(isolate);
   4813   Local<v8::NativeWeakMap> weak_map(v8::NativeWeakMap::New(isolate));
   4814   CHECK(!weak_map.IsEmpty());
   4815 
   4816   LocalContext env;
   4817   Local<Object> value = v8::Object::New(isolate);
   4818 
   4819   Local<Object> local1 = v8::Object::New(isolate);
   4820   CHECK(!weak_map->Has(local1));
   4821   CHECK(weak_map->Get(local1)->IsUndefined());
   4822   weak_map->Set(local1, value);
   4823   CHECK(weak_map->Has(local1));
   4824   CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
   4825 
   4826   WeakCallCounter counter(1234);
   4827   WeakCallCounterAndPersistent<Value> o1(&counter);
   4828   WeakCallCounterAndPersistent<Value> o2(&counter);
   4829   WeakCallCounterAndPersistent<Value> s1(&counter);
   4830   {
   4831     HandleScope scope(isolate);
   4832     Local<v8::Object> obj1 = v8::Object::New(isolate);
   4833     Local<v8::Object> obj2 = v8::Object::New(isolate);
   4834     Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
   4835 
   4836     weak_map->Set(obj1, value);
   4837     weak_map->Set(obj2, value);
   4838     weak_map->Set(sym1, value);
   4839 
   4840     o1.handle.Reset(isolate, obj1);
   4841     o2.handle.Reset(isolate, obj2);
   4842     s1.handle.Reset(isolate, sym1);
   4843 
   4844     CHECK(weak_map->Has(local1));
   4845     CHECK(weak_map->Has(obj1));
   4846     CHECK(weak_map->Has(obj2));
   4847     CHECK(weak_map->Has(sym1));
   4848 
   4849     CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
   4850     CHECK(value->Equals(env.local(), weak_map->Get(obj1)).FromJust());
   4851     CHECK(value->Equals(env.local(), weak_map->Get(obj2)).FromJust());
   4852     CHECK(value->Equals(env.local(), weak_map->Get(sym1)).FromJust());
   4853   }
   4854   CcTest::heap()->CollectAllGarbage();
   4855   {
   4856     HandleScope scope(isolate);
   4857     CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
   4858     CHECK(value->Equals(env.local(),
   4859                         weak_map->Get(Local<Value>::New(isolate, o1.handle)))
   4860               .FromJust());
   4861     CHECK(value->Equals(env.local(),
   4862                         weak_map->Get(Local<Value>::New(isolate, o2.handle)))
   4863               .FromJust());
   4864     CHECK(value->Equals(env.local(),
   4865                         weak_map->Get(Local<Value>::New(isolate, s1.handle)))
   4866               .FromJust());
   4867   }
   4868 
   4869   o1.handle.SetWeak(&o1, &WeakPointerCallback,
   4870                     v8::WeakCallbackType::kParameter);
   4871   o2.handle.SetWeak(&o2, &WeakPointerCallback,
   4872                     v8::WeakCallbackType::kParameter);
   4873   s1.handle.SetWeak(&s1, &WeakPointerCallback,
   4874                     v8::WeakCallbackType::kParameter);
   4875 
   4876   CcTest::heap()->CollectAllGarbage();
   4877   CHECK_EQ(3, counter.NumberOfWeakCalls());
   4878 
   4879   CHECK(o1.handle.IsEmpty());
   4880   CHECK(o2.handle.IsEmpty());
   4881   CHECK(s1.handle.IsEmpty());
   4882 
   4883   CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
   4884   CHECK(weak_map->Delete(local1));
   4885   CHECK(!weak_map->Has(local1));
   4886   CHECK(weak_map->Get(local1)->IsUndefined());
   4887 }
   4888 
   4889 
   4890 THREADED_TEST(GetSetProperty) {
   4891   LocalContext context;
   4892   v8::Isolate* isolate = context->GetIsolate();
   4893   v8::HandleScope scope(isolate);
   4894   CHECK(context->Global()
   4895             ->Set(context.local(), v8_str("foo"), v8_num(14))
   4896             .FromJust());
   4897   CHECK(context->Global()
   4898             ->Set(context.local(), v8_str("12"), v8_num(92))
   4899             .FromJust());
   4900   CHECK(context->Global()
   4901             ->Set(context.local(), v8::Integer::New(isolate, 16), v8_num(32))
   4902             .FromJust());
   4903   CHECK(context->Global()
   4904             ->Set(context.local(), v8_num(13), v8_num(56))
   4905             .FromJust());
   4906   Local<Value> foo = CompileRun("this.foo");
   4907   CHECK_EQ(14, foo->Int32Value(context.local()).FromJust());
   4908   Local<Value> twelve = CompileRun("this[12]");
   4909   CHECK_EQ(92, twelve->Int32Value(context.local()).FromJust());
   4910   Local<Value> sixteen = CompileRun("this[16]");
   4911   CHECK_EQ(32, sixteen->Int32Value(context.local()).FromJust());
   4912   Local<Value> thirteen = CompileRun("this[13]");
   4913   CHECK_EQ(56, thirteen->Int32Value(context.local()).FromJust());
   4914   CHECK_EQ(92, context->Global()
   4915                    ->Get(context.local(), v8::Integer::New(isolate, 12))
   4916                    .ToLocalChecked()
   4917                    ->Int32Value(context.local())
   4918                    .FromJust());
   4919   CHECK_EQ(92, context->Global()
   4920                    ->Get(context.local(), v8_str("12"))
   4921                    .ToLocalChecked()
   4922                    ->Int32Value(context.local())
   4923                    .FromJust());
   4924   CHECK_EQ(92, context->Global()
   4925                    ->Get(context.local(), v8_num(12))
   4926                    .ToLocalChecked()
   4927                    ->Int32Value(context.local())
   4928                    .FromJust());
   4929   CHECK_EQ(32, context->Global()
   4930                    ->Get(context.local(), v8::Integer::New(isolate, 16))
   4931                    .ToLocalChecked()
   4932                    ->Int32Value(context.local())
   4933                    .FromJust());
   4934   CHECK_EQ(32, context->Global()
   4935                    ->Get(context.local(), v8_str("16"))
   4936                    .ToLocalChecked()
   4937                    ->Int32Value(context.local())
   4938                    .FromJust());
   4939   CHECK_EQ(32, context->Global()
   4940                    ->Get(context.local(), v8_num(16))
   4941                    .ToLocalChecked()
   4942                    ->Int32Value(context.local())
   4943                    .FromJust());
   4944   CHECK_EQ(56, context->Global()
   4945                    ->Get(context.local(), v8::Integer::New(isolate, 13))
   4946                    .ToLocalChecked()
   4947                    ->Int32Value(context.local())
   4948                    .FromJust());
   4949   CHECK_EQ(56, context->Global()
   4950                    ->Get(context.local(), v8_str("13"))
   4951                    .ToLocalChecked()
   4952                    ->Int32Value(context.local())
   4953                    .FromJust());
   4954   CHECK_EQ(56, context->Global()
   4955                    ->Get(context.local(), v8_num(13))
   4956                    .ToLocalChecked()
   4957                    ->Int32Value(context.local())
   4958                    .FromJust());
   4959 }
   4960 
   4961 
   4962 THREADED_TEST(PropertyAttributes) {
   4963   LocalContext context;
   4964   v8::HandleScope scope(context->GetIsolate());
   4965   // none
   4966   Local<String> prop = v8_str("none");
   4967   CHECK(context->Global()->Set(context.local(), prop, v8_num(7)).FromJust());
   4968   CHECK_EQ(v8::None, context->Global()
   4969                          ->GetPropertyAttributes(context.local(), prop)
   4970                          .FromJust());
   4971   // read-only
   4972   prop = v8_str("read_only");
   4973   context->Global()
   4974       ->DefineOwnProperty(context.local(), prop, v8_num(7), v8::ReadOnly)
   4975       .FromJust();
   4976   CHECK_EQ(7, context->Global()
   4977                   ->Get(context.local(), prop)
   4978                   .ToLocalChecked()
   4979                   ->Int32Value(context.local())
   4980                   .FromJust());
   4981   CHECK_EQ(v8::ReadOnly, context->Global()
   4982                              ->GetPropertyAttributes(context.local(), prop)
   4983                              .FromJust());
   4984   CompileRun("read_only = 9");
   4985   CHECK_EQ(7, context->Global()
   4986                   ->Get(context.local(), prop)
   4987                   .ToLocalChecked()
   4988                   ->Int32Value(context.local())
   4989                   .FromJust());
   4990   CHECK(context->Global()->Set(context.local(), prop, v8_num(10)).FromJust());
   4991   CHECK_EQ(7, context->Global()
   4992                   ->Get(context.local(), prop)
   4993                   .ToLocalChecked()
   4994                   ->Int32Value(context.local())
   4995                   .FromJust());
   4996   // dont-delete
   4997   prop = v8_str("dont_delete");
   4998   context->Global()
   4999       ->DefineOwnProperty(context.local(), prop, v8_num(13), v8::DontDelete)
   5000       .FromJust();
   5001   CHECK_EQ(13, context->Global()
   5002                    ->Get(context.local(), prop)
   5003                    .ToLocalChecked()
   5004                    ->Int32Value(context.local())
   5005                    .FromJust());
   5006   CompileRun("delete dont_delete");
   5007   CHECK_EQ(13, context->Global()
   5008                    ->Get(context.local(), prop)
   5009                    .ToLocalChecked()
   5010                    ->Int32Value(context.local())
   5011                    .FromJust());
   5012   CHECK_EQ(v8::DontDelete, context->Global()
   5013                                ->GetPropertyAttributes(context.local(), prop)
   5014                                .FromJust());
   5015   // dont-enum
   5016   prop = v8_str("dont_enum");
   5017   context->Global()
   5018       ->DefineOwnProperty(context.local(), prop, v8_num(28), v8::DontEnum)
   5019       .FromJust();
   5020   CHECK_EQ(v8::DontEnum, context->Global()
   5021                              ->GetPropertyAttributes(context.local(), prop)
   5022                              .FromJust());
   5023   // absent
   5024   prop = v8_str("absent");
   5025   CHECK_EQ(v8::None, context->Global()
   5026                          ->GetPropertyAttributes(context.local(), prop)
   5027                          .FromJust());
   5028   Local<Value> fake_prop = v8_num(1);
   5029   CHECK_EQ(v8::None, context->Global()
   5030                          ->GetPropertyAttributes(context.local(), fake_prop)
   5031                          .FromJust());
   5032   // exception
   5033   TryCatch try_catch(context->GetIsolate());
   5034   Local<Value> exception =
   5035       CompileRun("({ toString: function() { throw 'exception';} })");
   5036   CHECK(context->Global()
   5037             ->GetPropertyAttributes(context.local(), exception)
   5038             .IsNothing());
   5039   CHECK(try_catch.HasCaught());
   5040   String::Utf8Value exception_value(try_catch.Exception());
   5041   CHECK_EQ(0, strcmp("exception", *exception_value));
   5042   try_catch.Reset();
   5043 }
   5044 
   5045 
   5046 THREADED_TEST(Array) {
   5047   LocalContext context;
   5048   v8::HandleScope scope(context->GetIsolate());
   5049   Local<v8::Array> array = v8::Array::New(context->GetIsolate());
   5050   CHECK_EQ(0u, array->Length());
   5051   CHECK(array->Get(context.local(), 0).ToLocalChecked()->IsUndefined());
   5052   CHECK(!array->Has(context.local(), 0).FromJust());
   5053   CHECK(array->Get(context.local(), 100).ToLocalChecked()->IsUndefined());
   5054   CHECK(!array->Has(context.local(), 100).FromJust());
   5055   CHECK(array->Set(context.local(), 2, v8_num(7)).FromJust());
   5056   CHECK_EQ(3u, array->Length());
   5057   CHECK(!array->Has(context.local(), 0).FromJust());
   5058   CHECK(!array->Has(context.local(), 1).FromJust());
   5059   CHECK(array->Has(context.local(), 2).FromJust());
   5060   CHECK_EQ(7, array->Get(context.local(), 2)
   5061                   .ToLocalChecked()
   5062                   ->Int32Value(context.local())
   5063                   .FromJust());
   5064   Local<Value> obj = CompileRun("[1, 2, 3]");
   5065   Local<v8::Array> arr = obj.As<v8::Array>();
   5066   CHECK_EQ(3u, arr->Length());
   5067   CHECK_EQ(1, arr->Get(context.local(), 0)
   5068                   .ToLocalChecked()
   5069                   ->Int32Value(context.local())
   5070                   .FromJust());
   5071   CHECK_EQ(2, arr->Get(context.local(), 1)
   5072                   .ToLocalChecked()
   5073                   ->Int32Value(context.local())
   5074                   .FromJust());
   5075   CHECK_EQ(3, arr->Get(context.local(), 2)
   5076                   .ToLocalChecked()
   5077                   ->Int32Value(context.local())
   5078                   .FromJust());
   5079   array = v8::Array::New(context->GetIsolate(), 27);
   5080   CHECK_EQ(27u, array->Length());
   5081   array = v8::Array::New(context->GetIsolate(), -27);
   5082   CHECK_EQ(0u, array->Length());
   5083 }
   5084 
   5085 
   5086 void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
   5087   v8::EscapableHandleScope scope(args.GetIsolate());
   5088   ApiTestFuzzer::Fuzz();
   5089   Local<v8::Array> result = v8::Array::New(args.GetIsolate(), args.Length());
   5090   for (int i = 0; i < args.Length(); i++) {
   5091     CHECK(result->Set(CcTest::isolate()->GetCurrentContext(), i, args[i])
   5092               .FromJust());
   5093   }
   5094   args.GetReturnValue().Set(scope.Escape(result));
   5095 }
   5096 
   5097 
   5098 THREADED_TEST(Vector) {
   5099   v8::Isolate* isolate = CcTest::isolate();
   5100   v8::HandleScope scope(isolate);
   5101   Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
   5102   global->Set(v8_str("f"), v8::FunctionTemplate::New(isolate, HandleF));
   5103   LocalContext context(0, global);
   5104 
   5105   const char* fun = "f()";
   5106   Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
   5107   CHECK_EQ(0u, a0->Length());
   5108 
   5109   const char* fun2 = "f(11)";
   5110   Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
   5111   CHECK_EQ(1u, a1->Length());
   5112   CHECK_EQ(11, a1->Get(context.local(), 0)
   5113                    .ToLocalChecked()
   5114                    ->Int32Value(context.local())
   5115                    .FromJust());
   5116 
   5117   const char* fun3 = "f(12, 13)";
   5118   Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
   5119   CHECK_EQ(2u, a2->Length());
   5120   CHECK_EQ(12, a2->Get(context.local(), 0)
   5121                    .ToLocalChecked()
   5122                    ->Int32Value(context.local())
   5123                    .FromJust());
   5124   CHECK_EQ(13, a2->Get(context.local(), 1)
   5125                    .ToLocalChecked()
   5126                    ->Int32Value(context.local())
   5127                    .FromJust());
   5128 
   5129   const char* fun4 = "f(14, 15, 16)";
   5130   Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
   5131   CHECK_EQ(3u, a3->Length());
   5132   CHECK_EQ(14, a3->Get(context.local(), 0)
   5133                    .ToLocalChecked()
   5134                    ->Int32Value(context.local())
   5135                    .FromJust());
   5136   CHECK_EQ(15, a3->Get(context.local(), 1)
   5137                    .ToLocalChecked()
   5138                    ->Int32Value(context.local())
   5139                    .FromJust());
   5140   CHECK_EQ(16, a3->Get(context.local(), 2)
   5141                    .ToLocalChecked()
   5142                    ->Int32Value(context.local())
   5143                    .FromJust());
   5144 
   5145   const char* fun5 = "f(17, 18, 19, 20)";
   5146   Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
   5147   CHECK_EQ(4u, a4->Length());
   5148   CHECK_EQ(17, a4->Get(context.local(), 0)
   5149                    .ToLocalChecked()
   5150                    ->Int32Value(context.local())
   5151                    .FromJust());
   5152   CHECK_EQ(18, a4->Get(context.local(), 1)
   5153                    .ToLocalChecked()
   5154                    ->Int32Value(context.local())
   5155                    .FromJust());
   5156   CHECK_EQ(19, a4->Get(context.local(), 2)
   5157                    .ToLocalChecked()
   5158                    ->Int32Value(context.local())
   5159                    .FromJust());
   5160   CHECK_EQ(20, a4->Get(context.local(), 3)
   5161                    .ToLocalChecked()
   5162                    ->Int32Value(context.local())
   5163                    .FromJust());
   5164 }
   5165 
   5166 
   5167 THREADED_TEST(FunctionCall) {
   5168   LocalContext context;
   5169   v8::Isolate* isolate = context->GetIsolate();
   5170   v8::HandleScope scope(isolate);
   5171   CompileRun(
   5172       "function Foo() {"
   5173       "  var result = [];"
   5174       "  for (var i = 0; i < arguments.length; i++) {"
   5175       "    result.push(arguments[i]);"
   5176       "  }"
   5177       "  return result;"
   5178       "}"
   5179       "function ReturnThisSloppy() {"
   5180       "  return this;"
   5181       "}"
   5182       "function ReturnThisStrict() {"
   5183       "  'use strict';"
   5184       "  return this;"
   5185       "}");
   5186   Local<Function> Foo = Local<Function>::Cast(
   5187       context->Global()->Get(context.local(), v8_str("Foo")).ToLocalChecked());
   5188   Local<Function> ReturnThisSloppy = Local<Function>::Cast(
   5189       context->Global()
   5190           ->Get(context.local(), v8_str("ReturnThisSloppy"))
   5191           .ToLocalChecked());
   5192   Local<Function> ReturnThisStrict = Local<Function>::Cast(
   5193       context->Global()
   5194           ->Get(context.local(), v8_str("ReturnThisStrict"))
   5195           .ToLocalChecked());
   5196 
   5197   v8::Local<Value>* args0 = NULL;
   5198   Local<v8::Array> a0 = Local<v8::Array>::Cast(
   5199       Foo->Call(context.local(), Foo, 0, args0).ToLocalChecked());
   5200   CHECK_EQ(0u, a0->Length());
   5201 
   5202   v8::Local<Value> args1[] = {v8_num(1.1)};
   5203   Local<v8::Array> a1 = Local<v8::Array>::Cast(
   5204       Foo->Call(context.local(), Foo, 1, args1).ToLocalChecked());
   5205   CHECK_EQ(1u, a1->Length());
   5206   CHECK_EQ(1.1, a1->Get(context.local(), v8::Integer::New(isolate, 0))
   5207                     .ToLocalChecked()
   5208                     ->NumberValue(context.local())
   5209                     .FromJust());
   5210 
   5211   v8::Local<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
   5212   Local<v8::Array> a2 = Local<v8::Array>::Cast(
   5213       Foo->Call(context.local(), Foo, 2, args2).ToLocalChecked());
   5214   CHECK_EQ(2u, a2->Length());
   5215   CHECK_EQ(2.2, a2->Get(context.local(), v8::Integer::New(isolate, 0))
   5216                     .ToLocalChecked()
   5217                     ->NumberValue(context.local())
   5218                     .FromJust());
   5219   CHECK_EQ(3.3, a2->Get(context.local(), v8::Integer::New(isolate, 1))
   5220                     .ToLocalChecked()
   5221                     ->NumberValue(context.local())
   5222                     .FromJust());
   5223 
   5224   v8::Local<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
   5225   Local<v8::Array> a3 = Local<v8::Array>::Cast(
   5226       Foo->Call(context.local(), Foo, 3, args3).ToLocalChecked());
   5227   CHECK_EQ(3u, a3->Length());
   5228   CHECK_EQ(4.4, a3->Get(context.local(), v8::Integer::New(isolate, 0))
   5229                     .ToLocalChecked()
   5230                     ->NumberValue(context.local())
   5231                     .FromJust());
   5232   CHECK_EQ(5.5, a3->Get(context.local(), v8::Integer::New(isolate, 1))
   5233                     .ToLocalChecked()
   5234                     ->NumberValue(context.local())
   5235                     .FromJust());
   5236   CHECK_EQ(6.6, a3->Get(context.local(), v8::Integer::New(isolate, 2))
   5237                     .ToLocalChecked()
   5238                     ->NumberValue(context.local())
   5239                     .FromJust());
   5240 
   5241   v8::Local<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
   5242                               v8_num(10.11)};
   5243   Local<v8::Array> a4 = Local<v8::Array>::Cast(
   5244       Foo->Call(context.local(), Foo, 4, args4).ToLocalChecked());
   5245   CHECK_EQ(4u, a4->Length());
   5246   CHECK_EQ(7.7, a4->Get(context.local(), v8::Integer::New(isolate, 0))
   5247                     .ToLocalChecked()
   5248                     ->NumberValue(context.local())
   5249                     .FromJust());
   5250   CHECK_EQ(8.8, a4->Get(context.local(), v8::Integer::New(isolate, 1))
   5251                     .ToLocalChecked()
   5252                     ->NumberValue(context.local())
   5253                     .FromJust());
   5254   CHECK_EQ(9.9, a4->Get(context.local(), v8::Integer::New(isolate, 2))
   5255                     .ToLocalChecked()
   5256                     ->NumberValue(context.local())
   5257                     .FromJust());
   5258   CHECK_EQ(10.11, a4->Get(context.local(), v8::Integer::New(isolate, 3))
   5259                       .ToLocalChecked()
   5260                       ->NumberValue(context.local())
   5261                       .FromJust());
   5262 
   5263   Local<v8::Value> r1 =
   5264       ReturnThisSloppy->Call(context.local(), v8::Undefined(isolate), 0, NULL)
   5265           .ToLocalChecked();
   5266   CHECK(r1->StrictEquals(context->Global()));
   5267   Local<v8::Value> r2 =
   5268       ReturnThisSloppy->Call(context.local(), v8::Null(isolate), 0, NULL)
   5269           .ToLocalChecked();
   5270   CHECK(r2->StrictEquals(context->Global()));
   5271   Local<v8::Value> r3 =
   5272       ReturnThisSloppy->Call(context.local(), v8_num(42), 0, NULL)
   5273           .ToLocalChecked();
   5274   CHECK(r3->IsNumberObject());
   5275   CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
   5276   Local<v8::Value> r4 =
   5277       ReturnThisSloppy->Call(context.local(), v8_str("hello"), 0, NULL)
   5278           .ToLocalChecked();
   5279   CHECK(r4->IsStringObject());
   5280   CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
   5281   Local<v8::Value> r5 =
   5282       ReturnThisSloppy->Call(context.local(), v8::True(isolate), 0, NULL)
   5283           .ToLocalChecked();
   5284   CHECK(r5->IsBooleanObject());
   5285   CHECK(r5.As<v8::BooleanObject>()->ValueOf());
   5286 
   5287   Local<v8::Value> r6 =
   5288       ReturnThisStrict->Call(context.local(), v8::Undefined(isolate), 0, NULL)
   5289           .ToLocalChecked();
   5290   CHECK(r6->IsUndefined());
   5291   Local<v8::Value> r7 =
   5292       ReturnThisStrict->Call(context.local(), v8::Null(isolate), 0, NULL)
   5293           .ToLocalChecked();
   5294   CHECK(r7->IsNull());
   5295   Local<v8::Value> r8 =
   5296       ReturnThisStrict->Call(context.local(), v8_num(42), 0, NULL)
   5297           .ToLocalChecked();
   5298   CHECK(r8->StrictEquals(v8_num(42)));
   5299   Local<v8::Value> r9 =
   5300       ReturnThisStrict->Call(context.local(), v8_str("hello"), 0, NULL)
   5301           .ToLocalChecked();
   5302   CHECK(r9->StrictEquals(v8_str("hello")));
   5303   Local<v8::Value> r10 =
   5304       ReturnThisStrict->Call(context.local(), v8::True(isolate), 0, NULL)
   5305           .ToLocalChecked();
   5306   CHECK(r10->StrictEquals(v8::True(isolate)));
   5307 }
   5308 
   5309 
   5310 THREADED_TEST(ConstructCall) {
   5311   LocalContext context;
   5312   v8::Isolate* isolate = context->GetIsolate();
   5313   v8::HandleScope scope(isolate);
   5314   CompileRun(
   5315       "function Foo() {"
   5316       "  var result = [];"
   5317       "  for (var i = 0; i < arguments.length; i++) {"
   5318       "    result.push(arguments[i]);"
   5319       "  }"
   5320       "  return result;"
   5321       "}");
   5322   Local<Function> Foo = Local<Function>::Cast(
   5323       context->Global()->Get(context.local(), v8_str("Foo")).ToLocalChecked());
   5324 
   5325   v8::Local<Value>* args0 = NULL;
   5326   Local<v8::Array> a0 = Local<v8::Array>::Cast(
   5327       Foo->NewInstance(context.local(), 0, args0).ToLocalChecked());
   5328   CHECK_EQ(0u, a0->Length());
   5329 
   5330   v8::Local<Value> args1[] = {v8_num(1.1)};
   5331   Local<v8::Array> a1 = Local<v8::Array>::Cast(
   5332       Foo->NewInstance(context.local(), 1, args1).ToLocalChecked());
   5333   CHECK_EQ(1u, a1->Length());
   5334   CHECK_EQ(1.1, a1->Get(context.local(), v8::Integer::New(isolate, 0))
   5335                     .ToLocalChecked()
   5336                     ->NumberValue(context.local())
   5337                     .FromJust());
   5338 
   5339   v8::Local<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
   5340   Local<v8::Array> a2 = Local<v8::Array>::Cast(
   5341       Foo->NewInstance(context.local(), 2, args2).ToLocalChecked());
   5342   CHECK_EQ(2u, a2->Length());
   5343   CHECK_EQ(2.2, a2->Get(context.local(), v8::Integer::New(isolate, 0))
   5344                     .ToLocalChecked()
   5345                     ->NumberValue(context.local())
   5346                     .FromJust());
   5347   CHECK_EQ(3.3, a2->Get(context.local(), v8::Integer::New(isolate, 1))
   5348                     .ToLocalChecked()
   5349                     ->NumberValue(context.local())
   5350                     .FromJust());
   5351 
   5352   v8::Local<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
   5353   Local<v8::Array> a3 = Local<v8::Array>::Cast(
   5354       Foo->NewInstance(context.local(), 3, args3).ToLocalChecked());
   5355   CHECK_EQ(3u, a3->Length());
   5356   CHECK_EQ(4.4, a3->Get(context.local(), v8::Integer::New(isolate, 0))
   5357                     .ToLocalChecked()
   5358                     ->NumberValue(context.local())
   5359                     .FromJust());
   5360   CHECK_EQ(5.5, a3->Get(context.local(), v8::Integer::New(isolate, 1))
   5361                     .ToLocalChecked()
   5362                     ->NumberValue(context.local())
   5363                     .FromJust());
   5364   CHECK_EQ(6.6, a3->Get(context.local(), v8::Integer::New(isolate, 2))
   5365                     .ToLocalChecked()
   5366                     ->NumberValue(context.local())
   5367                     .FromJust());
   5368 
   5369   v8::Local<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
   5370                               v8_num(10.11)};
   5371   Local<v8::Array> a4 = Local<v8::Array>::Cast(
   5372       Foo->NewInstance(context.local(), 4, args4).ToLocalChecked());
   5373   CHECK_EQ(4u, a4->Length());
   5374   CHECK_EQ(7.7, a4->Get(context.local(), v8::Integer::New(isolate, 0))
   5375                     .ToLocalChecked()
   5376                     ->NumberValue(context.local())
   5377                     .FromJust());
   5378   CHECK_EQ(8.8, a4->Get(context.local(), v8::Integer::New(isolate, 1))
   5379                     .ToLocalChecked()
   5380                     ->NumberValue(context.local())
   5381                     .FromJust());
   5382   CHECK_EQ(9.9, a4->Get(context.local(), v8::Integer::New(isolate, 2))
   5383                     .ToLocalChecked()
   5384                     ->NumberValue(context.local())
   5385                     .FromJust());
   5386   CHECK_EQ(10.11, a4->Get(context.local(), v8::Integer::New(isolate, 3))
   5387                       .ToLocalChecked()
   5388                       ->NumberValue(context.local())
   5389                       .FromJust());
   5390 }
   5391 
   5392 
   5393 THREADED_TEST(ConversionNumber) {
   5394   LocalContext env;
   5395   v8::Isolate* isolate = env->GetIsolate();
   5396   v8::HandleScope scope(isolate);
   5397   // Very large number.
   5398   CompileRun("var obj = Math.pow(2,32) * 1237;");
   5399   Local<Value> obj =
   5400       env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5401   CHECK_EQ(5312874545152.0,
   5402            obj->ToNumber(env.local()).ToLocalChecked()->Value());
   5403   CHECK_EQ(0, obj->ToInt32(env.local()).ToLocalChecked()->Value());
   5404   CHECK(0u ==
   5405         obj->ToUint32(env.local())
   5406             .ToLocalChecked()
   5407             ->Value());  // NOLINT - no CHECK_EQ for unsigned.
   5408   // Large number.
   5409   CompileRun("var obj = -1234567890123;");
   5410   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5411   CHECK_EQ(-1234567890123.0,
   5412            obj->ToNumber(env.local()).ToLocalChecked()->Value());
   5413   CHECK_EQ(-1912276171, obj->ToInt32(env.local()).ToLocalChecked()->Value());
   5414   CHECK(2382691125u ==
   5415         obj->ToUint32(env.local()).ToLocalChecked()->Value());  // NOLINT
   5416   // Small positive integer.
   5417   CompileRun("var obj = 42;");
   5418   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5419   CHECK_EQ(42.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
   5420   CHECK_EQ(42, obj->ToInt32(env.local()).ToLocalChecked()->Value());
   5421   CHECK(42u == obj->ToUint32(env.local()).ToLocalChecked()->Value());  // NOLINT
   5422   // Negative integer.
   5423   CompileRun("var obj = -37;");
   5424   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5425   CHECK_EQ(-37.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
   5426   CHECK_EQ(-37, obj->ToInt32(env.local()).ToLocalChecked()->Value());
   5427   CHECK(4294967259u ==
   5428         obj->ToUint32(env.local()).ToLocalChecked()->Value());  // NOLINT
   5429   // Positive non-int32 integer.
   5430   CompileRun("var obj = 0x81234567;");
   5431   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5432   CHECK_EQ(2166572391.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
   5433   CHECK_EQ(-2128394905, obj->ToInt32(env.local()).ToLocalChecked()->Value());
   5434   CHECK(2166572391u ==
   5435         obj->ToUint32(env.local()).ToLocalChecked()->Value());  // NOLINT
   5436   // Fraction.
   5437   CompileRun("var obj = 42.3;");
   5438   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5439   CHECK_EQ(42.3, obj->ToNumber(env.local()).ToLocalChecked()->Value());
   5440   CHECK_EQ(42, obj->ToInt32(env.local()).ToLocalChecked()->Value());
   5441   CHECK(42u == obj->ToUint32(env.local()).ToLocalChecked()->Value());  // NOLINT
   5442   // Large negative fraction.
   5443   CompileRun("var obj = -5726623061.75;");
   5444   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5445   CHECK_EQ(-5726623061.75,
   5446            obj->ToNumber(env.local()).ToLocalChecked()->Value());
   5447   CHECK_EQ(-1431655765, obj->ToInt32(env.local()).ToLocalChecked()->Value());
   5448   CHECK(2863311531u ==
   5449         obj->ToUint32(env.local()).ToLocalChecked()->Value());  // NOLINT
   5450 }
   5451 
   5452 
   5453 THREADED_TEST(isNumberType) {
   5454   LocalContext env;
   5455   v8::HandleScope scope(env->GetIsolate());
   5456   // Very large number.
   5457   CompileRun("var obj = Math.pow(2,32) * 1237;");
   5458   Local<Value> obj =
   5459       env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5460   CHECK(!obj->IsInt32());
   5461   CHECK(!obj->IsUint32());
   5462   // Large negative number.
   5463   CompileRun("var obj = -1234567890123;");
   5464   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5465   CHECK(!obj->IsInt32());
   5466   CHECK(!obj->IsUint32());
   5467   // Small positive integer.
   5468   CompileRun("var obj = 42;");
   5469   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5470   CHECK(obj->IsInt32());
   5471   CHECK(obj->IsUint32());
   5472   // Negative integer.
   5473   CompileRun("var obj = -37;");
   5474   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5475   CHECK(obj->IsInt32());
   5476   CHECK(!obj->IsUint32());
   5477   // Positive non-int32 integer.
   5478   CompileRun("var obj = 0x81234567;");
   5479   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5480   CHECK(!obj->IsInt32());
   5481   CHECK(obj->IsUint32());
   5482   // Fraction.
   5483   CompileRun("var obj = 42.3;");
   5484   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5485   CHECK(!obj->IsInt32());
   5486   CHECK(!obj->IsUint32());
   5487   // Large negative fraction.
   5488   CompileRun("var obj = -5726623061.75;");
   5489   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5490   CHECK(!obj->IsInt32());
   5491   CHECK(!obj->IsUint32());
   5492   // Positive zero
   5493   CompileRun("var obj = 0.0;");
   5494   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5495   CHECK(obj->IsInt32());
   5496   CHECK(obj->IsUint32());
   5497   // Positive zero
   5498   CompileRun("var obj = -0.0;");
   5499   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5500   CHECK(!obj->IsInt32());
   5501   CHECK(!obj->IsUint32());
   5502 }
   5503 
   5504 
   5505 static void CheckUncle(v8::TryCatch* try_catch) {
   5506   CHECK(try_catch->HasCaught());
   5507   String::Utf8Value str_value(try_catch->Exception());
   5508   CHECK_EQ(0, strcmp(*str_value, "uncle?"));
   5509   try_catch->Reset();
   5510 }
   5511 
   5512 
   5513 THREADED_TEST(ConversionException) {
   5514   LocalContext env;
   5515   v8::Isolate* isolate = env->GetIsolate();
   5516   v8::HandleScope scope(isolate);
   5517   CompileRun(
   5518       "function TestClass() { };"
   5519       "TestClass.prototype.toString = function () { throw 'uncle?'; };"
   5520       "var obj = new TestClass();");
   5521   Local<Value> obj =
   5522       env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
   5523 
   5524   v8::TryCatch try_catch(isolate);
   5525 
   5526   CHECK(obj->ToString(env.local()).IsEmpty());
   5527   CheckUncle(&try_catch);
   5528 
   5529   CHECK(obj->ToNumber(env.local()).IsEmpty());
   5530   CheckUncle(&try_catch);
   5531 
   5532   CHECK(obj->ToInteger(env.local()).IsEmpty());
   5533   CheckUncle(&try_catch);
   5534 
   5535   CHECK(obj->ToUint32(env.local()).IsEmpty());
   5536   CheckUncle(&try_catch);
   5537 
   5538   CHECK(obj->ToInt32(env.local()).IsEmpty());
   5539   CheckUncle(&try_catch);
   5540 
   5541   CHECK(v8::Undefined(isolate)->ToObject(env.local()).IsEmpty());
   5542   CHECK(try_catch.HasCaught());
   5543   try_catch.Reset();
   5544 
   5545   CHECK(obj->Int32Value(env.local()).IsNothing());
   5546   CheckUncle(&try_catch);
   5547 
   5548   CHECK(obj->Uint32Value(env.local()).IsNothing());
   5549   CheckUncle(&try_catch);
   5550 
   5551   CHECK(obj->NumberValue(env.local()).IsNothing());
   5552   CheckUncle(&try_catch);
   5553 
   5554   CHECK(obj->IntegerValue(env.local()).IsNothing());
   5555   CheckUncle(&try_catch);
   5556 }
   5557 
   5558 
   5559 void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
   5560   ApiTestFuzzer::Fuzz();
   5561   args.GetIsolate()->ThrowException(v8_str("konto"));
   5562 }
   5563 
   5564 
   5565 void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
   5566   if (args.Length() < 1) {
   5567     args.GetReturnValue().Set(false);
   5568     return;
   5569   }
   5570   v8::HandleScope scope(args.GetIsolate());
   5571   v8::TryCatch try_catch(args.GetIsolate());
   5572   Local<Value> result =
   5573       CompileRun(args[0]
   5574                      ->ToString(args.GetIsolate()->GetCurrentContext())
   5575                      .ToLocalChecked());
   5576   CHECK(!try_catch.HasCaught() || result.IsEmpty());
   5577   args.GetReturnValue().Set(try_catch.HasCaught());
   5578 }
   5579 
   5580 
   5581 THREADED_TEST(APICatch) {
   5582   v8::Isolate* isolate = CcTest::isolate();
   5583   v8::HandleScope scope(isolate);
   5584   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5585   templ->Set(v8_str("ThrowFromC"),
   5586              v8::FunctionTemplate::New(isolate, ThrowFromC));
   5587   LocalContext context(0, templ);
   5588   CompileRun(
   5589       "var thrown = false;"
   5590       "try {"
   5591       "  ThrowFromC();"
   5592       "} catch (e) {"
   5593       "  thrown = true;"
   5594       "}");
   5595   Local<Value> thrown = context->Global()
   5596                             ->Get(context.local(), v8_str("thrown"))
   5597                             .ToLocalChecked();
   5598   CHECK(thrown->BooleanValue(context.local()).FromJust());
   5599 }
   5600 
   5601 
   5602 THREADED_TEST(APIThrowTryCatch) {
   5603   v8::Isolate* isolate = CcTest::isolate();
   5604   v8::HandleScope scope(isolate);
   5605   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5606   templ->Set(v8_str("ThrowFromC"),
   5607              v8::FunctionTemplate::New(isolate, ThrowFromC));
   5608   LocalContext context(0, templ);
   5609   v8::TryCatch try_catch(isolate);
   5610   CompileRun("ThrowFromC();");
   5611   CHECK(try_catch.HasCaught());
   5612 }
   5613 
   5614 
   5615 // Test that a try-finally block doesn't shadow a try-catch block
   5616 // when setting up an external handler.
   5617 //
   5618 // BUG(271): Some of the exception propagation does not work on the
   5619 // ARM simulator because the simulator separates the C++ stack and the
   5620 // JS stack.  This test therefore fails on the simulator.  The test is
   5621 // not threaded to allow the threading tests to run on the simulator.
   5622 TEST(TryCatchInTryFinally) {
   5623   v8::Isolate* isolate = CcTest::isolate();
   5624   v8::HandleScope scope(isolate);
   5625   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5626   templ->Set(v8_str("CCatcher"), v8::FunctionTemplate::New(isolate, CCatcher));
   5627   LocalContext context(0, templ);
   5628   Local<Value> result = CompileRun(
   5629       "try {"
   5630       "  try {"
   5631       "    CCatcher('throw 7;');"
   5632       "  } finally {"
   5633       "  }"
   5634       "} catch (e) {"
   5635       "}");
   5636   CHECK(result->IsTrue());
   5637 }
   5638 
   5639 
   5640 static void check_custom_error_tostring(v8::Local<v8::Message> message,
   5641                                         v8::Local<v8::Value> data) {
   5642   const char* uncaught_error = "Uncaught MyError toString";
   5643   CHECK(message->Get()
   5644             ->Equals(CcTest::isolate()->GetCurrentContext(),
   5645                      v8_str(uncaught_error))
   5646             .FromJust());
   5647 }
   5648 
   5649 
   5650 TEST(CustomErrorToString) {
   5651   LocalContext context;
   5652   v8::HandleScope scope(context->GetIsolate());
   5653   context->GetIsolate()->AddMessageListener(check_custom_error_tostring);
   5654   CompileRun(
   5655       "function MyError(name, message) {                   "
   5656       "  this.name = name;                                 "
   5657       "  this.message = message;                           "
   5658       "}                                                   "
   5659       "MyError.prototype = Object.create(Error.prototype); "
   5660       "MyError.prototype.toString = function() {           "
   5661       "  return 'MyError toString';                        "
   5662       "};                                                  "
   5663       "throw new MyError('my name', 'my message');         ");
   5664   context->GetIsolate()->RemoveMessageListeners(check_custom_error_tostring);
   5665 }
   5666 
   5667 
   5668 static void check_custom_error_message(v8::Local<v8::Message> message,
   5669                                        v8::Local<v8::Value> data) {
   5670   const char* uncaught_error = "Uncaught MyError: my message";
   5671   printf("%s\n", *v8::String::Utf8Value(message->Get()));
   5672   CHECK(message->Get()
   5673             ->Equals(CcTest::isolate()->GetCurrentContext(),
   5674                      v8_str(uncaught_error))
   5675             .FromJust());
   5676 }
   5677 
   5678 
   5679 TEST(CustomErrorMessage) {
   5680   LocalContext context;
   5681   v8::HandleScope scope(context->GetIsolate());
   5682   context->GetIsolate()->AddMessageListener(check_custom_error_message);
   5683 
   5684   // Handlebars.
   5685   CompileRun(
   5686       "function MyError(msg) {                             "
   5687       "  this.name = 'MyError';                            "
   5688       "  this.message = msg;                               "
   5689       "}                                                   "
   5690       "MyError.prototype = new Error();                    "
   5691       "throw new MyError('my message');                    ");
   5692 
   5693   // Closure.
   5694   CompileRun(
   5695       "function MyError(msg) {                             "
   5696       "  this.name = 'MyError';                            "
   5697       "  this.message = msg;                               "
   5698       "}                                                   "
   5699       "inherits = function(childCtor, parentCtor) {        "
   5700       "    function tempCtor() {};                         "
   5701       "    tempCtor.prototype = parentCtor.prototype;      "
   5702       "    childCtor.superClass_ = parentCtor.prototype;   "
   5703       "    childCtor.prototype = new tempCtor();           "
   5704       "    childCtor.prototype.constructor = childCtor;    "
   5705       "};                                                  "
   5706       "inherits(MyError, Error);                           "
   5707       "throw new MyError('my message');                    ");
   5708 
   5709   // Object.create.
   5710   CompileRun(
   5711       "function MyError(msg) {                             "
   5712       "  this.name = 'MyError';                            "
   5713       "  this.message = msg;                               "
   5714       "}                                                   "
   5715       "MyError.prototype = Object.create(Error.prototype); "
   5716       "throw new MyError('my message');                    ");
   5717 
   5718   context->GetIsolate()->RemoveMessageListeners(check_custom_error_message);
   5719 }
   5720 
   5721 
   5722 static void check_custom_rethrowing_message(v8::Local<v8::Message> message,
   5723                                             v8::Local<v8::Value> data) {
   5724   const char* uncaught_error = "Uncaught exception";
   5725   CHECK(message->Get()
   5726             ->Equals(CcTest::isolate()->GetCurrentContext(),
   5727                      v8_str(uncaught_error))
   5728             .FromJust());
   5729 }
   5730 
   5731 
   5732 TEST(CustomErrorRethrowsOnToString) {
   5733   LocalContext context;
   5734   v8::HandleScope scope(context->GetIsolate());
   5735   context->GetIsolate()->AddMessageListener(check_custom_rethrowing_message);
   5736 
   5737   CompileRun(
   5738       "var e = { toString: function() { throw e; } };"
   5739       "try { throw e; } finally {}");
   5740 
   5741   context->GetIsolate()->RemoveMessageListeners(
   5742       check_custom_rethrowing_message);
   5743 }
   5744 
   5745 
   5746 static void receive_message(v8::Local<v8::Message> message,
   5747                             v8::Local<v8::Value> data) {
   5748   message->Get();
   5749   message_received = true;
   5750 }
   5751 
   5752 
   5753 TEST(APIThrowMessage) {
   5754   message_received = false;
   5755   v8::Isolate* isolate = CcTest::isolate();
   5756   v8::HandleScope scope(isolate);
   5757   isolate->AddMessageListener(receive_message);
   5758   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5759   templ->Set(v8_str("ThrowFromC"),
   5760              v8::FunctionTemplate::New(isolate, ThrowFromC));
   5761   LocalContext context(0, templ);
   5762   CompileRun("ThrowFromC();");
   5763   CHECK(message_received);
   5764   isolate->RemoveMessageListeners(receive_message);
   5765 }
   5766 
   5767 
   5768 TEST(APIThrowMessageAndVerboseTryCatch) {
   5769   message_received = false;
   5770   v8::Isolate* isolate = CcTest::isolate();
   5771   v8::HandleScope scope(isolate);
   5772   isolate->AddMessageListener(receive_message);
   5773   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5774   templ->Set(v8_str("ThrowFromC"),
   5775              v8::FunctionTemplate::New(isolate, ThrowFromC));
   5776   LocalContext context(0, templ);
   5777   v8::TryCatch try_catch(isolate);
   5778   try_catch.SetVerbose(true);
   5779   Local<Value> result = CompileRun("ThrowFromC();");
   5780   CHECK(try_catch.HasCaught());
   5781   CHECK(result.IsEmpty());
   5782   CHECK(message_received);
   5783   isolate->RemoveMessageListeners(receive_message);
   5784 }
   5785 
   5786 
   5787 TEST(APIStackOverflowAndVerboseTryCatch) {
   5788   message_received = false;
   5789   LocalContext context;
   5790   v8::HandleScope scope(context->GetIsolate());
   5791   context->GetIsolate()->AddMessageListener(receive_message);
   5792   v8::TryCatch try_catch(context->GetIsolate());
   5793   try_catch.SetVerbose(true);
   5794   Local<Value> result = CompileRun("function foo() { foo(); } foo();");
   5795   CHECK(try_catch.HasCaught());
   5796   CHECK(result.IsEmpty());
   5797   CHECK(message_received);
   5798   context->GetIsolate()->RemoveMessageListeners(receive_message);
   5799 }
   5800 
   5801 
   5802 THREADED_TEST(ExternalScriptException) {
   5803   v8::Isolate* isolate = CcTest::isolate();
   5804   v8::HandleScope scope(isolate);
   5805   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5806   templ->Set(v8_str("ThrowFromC"),
   5807              v8::FunctionTemplate::New(isolate, ThrowFromC));
   5808   LocalContext context(0, templ);
   5809 
   5810   v8::TryCatch try_catch(isolate);
   5811   Local<Value> result = CompileRun("ThrowFromC(); throw 'panama';");
   5812   CHECK(result.IsEmpty());
   5813   CHECK(try_catch.HasCaught());
   5814   String::Utf8Value exception_value(try_catch.Exception());
   5815   CHECK_EQ(0, strcmp("konto", *exception_value));
   5816 }
   5817 
   5818 
   5819 void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
   5820   ApiTestFuzzer::Fuzz();
   5821   CHECK_EQ(4, args.Length());
   5822   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   5823   int count = args[0]->Int32Value(context).FromJust();
   5824   int cInterval = args[2]->Int32Value(context).FromJust();
   5825   if (count == 0) {
   5826     args.GetIsolate()->ThrowException(v8_str("FromC"));
   5827     return;
   5828   } else {
   5829     Local<v8::Object> global = context->Global();
   5830     Local<Value> fun =
   5831         global->Get(context, v8_str("JSThrowCountDown")).ToLocalChecked();
   5832     v8::Local<Value> argv[] = {v8_num(count - 1), args[1], args[2], args[3]};
   5833     if (count % cInterval == 0) {
   5834       v8::TryCatch try_catch(args.GetIsolate());
   5835       Local<Value> result = fun.As<Function>()
   5836                                 ->Call(context, global, 4, argv)
   5837                                 .FromMaybe(Local<Value>());
   5838       int expected = args[3]->Int32Value(context).FromJust();
   5839       if (try_catch.HasCaught()) {
   5840         CHECK_EQ(expected, count);
   5841         CHECK(result.IsEmpty());
   5842         CHECK(!CcTest::i_isolate()->has_scheduled_exception());
   5843       } else {
   5844         CHECK_NE(expected, count);
   5845       }
   5846       args.GetReturnValue().Set(result);
   5847       return;
   5848     } else {
   5849       args.GetReturnValue().Set(fun.As<Function>()
   5850                                     ->Call(context, global, 4, argv)
   5851                                     .FromMaybe(v8::Local<v8::Value>()));
   5852       return;
   5853     }
   5854   }
   5855 }
   5856 
   5857 
   5858 void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
   5859   ApiTestFuzzer::Fuzz();
   5860   CHECK_EQ(3, args.Length());
   5861   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   5862   bool equality = args[0]->BooleanValue(context).FromJust();
   5863   int count = args[1]->Int32Value(context).FromJust();
   5864   int expected = args[2]->Int32Value(context).FromJust();
   5865   if (equality) {
   5866     CHECK_EQ(count, expected);
   5867   } else {
   5868     CHECK_NE(count, expected);
   5869   }
   5870 }
   5871 
   5872 
   5873 THREADED_TEST(EvalInTryFinally) {
   5874   LocalContext context;
   5875   v8::HandleScope scope(context->GetIsolate());
   5876   v8::TryCatch try_catch(context->GetIsolate());
   5877   CompileRun(
   5878       "(function() {"
   5879       "  try {"
   5880       "    eval('asldkf (*&^&*^');"
   5881       "  } finally {"
   5882       "    return;"
   5883       "  }"
   5884       "})()");
   5885   CHECK(!try_catch.HasCaught());
   5886 }
   5887 
   5888 
   5889 // This test works by making a stack of alternating JavaScript and C
   5890 // activations.  These activations set up exception handlers with regular
   5891 // intervals, one interval for C activations and another for JavaScript
   5892 // activations.  When enough activations have been created an exception is
   5893 // thrown and we check that the right activation catches the exception and that
   5894 // no other activations do.  The right activation is always the topmost one with
   5895 // a handler, regardless of whether it is in JavaScript or C.
   5896 //
   5897 // The notation used to describe a test case looks like this:
   5898 //
   5899 //    *JS[4] *C[3] @JS[2] C[1] JS[0]
   5900 //
   5901 // Each entry is an activation, either JS or C.  The index is the count at that
   5902 // level.  Stars identify activations with exception handlers, the @ identifies
   5903 // the exception handler that should catch the exception.
   5904 //
   5905 // BUG(271): Some of the exception propagation does not work on the
   5906 // ARM simulator because the simulator separates the C++ stack and the
   5907 // JS stack.  This test therefore fails on the simulator.  The test is
   5908 // not threaded to allow the threading tests to run on the simulator.
   5909 TEST(ExceptionOrder) {
   5910   v8::Isolate* isolate = CcTest::isolate();
   5911   v8::HandleScope scope(isolate);
   5912   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5913   templ->Set(v8_str("check"), v8::FunctionTemplate::New(isolate, JSCheck));
   5914   templ->Set(v8_str("CThrowCountDown"),
   5915              v8::FunctionTemplate::New(isolate, CThrowCountDown));
   5916   LocalContext context(0, templ);
   5917   CompileRun(
   5918       "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
   5919       "  if (count == 0) throw 'FromJS';"
   5920       "  if (count % jsInterval == 0) {"
   5921       "    try {"
   5922       "      var value = CThrowCountDown(count - 1,"
   5923       "                                  jsInterval,"
   5924       "                                  cInterval,"
   5925       "                                  expected);"
   5926       "      check(false, count, expected);"
   5927       "      return value;"
   5928       "    } catch (e) {"
   5929       "      check(true, count, expected);"
   5930       "    }"
   5931       "  } else {"
   5932       "    return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
   5933       "  }"
   5934       "}");
   5935   Local<Function> fun = Local<Function>::Cast(
   5936       context->Global()
   5937           ->Get(context.local(), v8_str("JSThrowCountDown"))
   5938           .ToLocalChecked());
   5939 
   5940   const int argc = 4;
   5941   //                             count      jsInterval cInterval  expected
   5942 
   5943   // *JS[4] *C[3] @JS[2] C[1] JS[0]
   5944   v8::Local<Value> a0[argc] = {v8_num(4), v8_num(2), v8_num(3), v8_num(2)};
   5945   fun->Call(context.local(), fun, argc, a0).ToLocalChecked();
   5946 
   5947   // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
   5948   v8::Local<Value> a1[argc] = {v8_num(5), v8_num(6), v8_num(1), v8_num(2)};
   5949   fun->Call(context.local(), fun, argc, a1).ToLocalChecked();
   5950 
   5951   // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
   5952   v8::Local<Value> a2[argc] = {v8_num(6), v8_num(7), v8_num(5), v8_num(5)};
   5953   fun->Call(context.local(), fun, argc, a2).ToLocalChecked();
   5954 
   5955   // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
   5956   v8::Local<Value> a3[argc] = {v8_num(6), v8_num(6), v8_num(7), v8_num(6)};
   5957   fun->Call(context.local(), fun, argc, a3).ToLocalChecked();
   5958 
   5959   // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
   5960   v8::Local<Value> a4[argc] = {v8_num(6), v8_num(4), v8_num(5), v8_num(4)};
   5961   fun->Call(context.local(), fun, argc, a4).ToLocalChecked();
   5962 
   5963   // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
   5964   v8::Local<Value> a5[argc] = {v8_num(6), v8_num(4), v8_num(3), v8_num(3)};
   5965   fun->Call(context.local(), fun, argc, a5).ToLocalChecked();
   5966 }
   5967 
   5968 
   5969 void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
   5970   ApiTestFuzzer::Fuzz();
   5971   CHECK_EQ(1, args.Length());
   5972   args.GetIsolate()->ThrowException(args[0]);
   5973 }
   5974 
   5975 
   5976 THREADED_TEST(ThrowValues) {
   5977   v8::Isolate* isolate = CcTest::isolate();
   5978   v8::HandleScope scope(isolate);
   5979   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   5980   templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(isolate, ThrowValue));
   5981   LocalContext context(0, templ);
   5982   v8::Local<v8::Array> result = v8::Local<v8::Array>::Cast(
   5983       CompileRun("function Run(obj) {"
   5984                  "  try {"
   5985                  "    Throw(obj);"
   5986                  "  } catch (e) {"
   5987                  "    return e;"
   5988                  "  }"
   5989                  "  return 'no exception';"
   5990                  "}"
   5991                  "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
   5992   CHECK_EQ(5u, result->Length());
   5993   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 0))
   5994             .ToLocalChecked()
   5995             ->IsString());
   5996   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 1))
   5997             .ToLocalChecked()
   5998             ->IsNumber());
   5999   CHECK_EQ(1, result->Get(context.local(), v8::Integer::New(isolate, 1))
   6000                   .ToLocalChecked()
   6001                   ->Int32Value(context.local())
   6002                   .FromJust());
   6003   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 2))
   6004             .ToLocalChecked()
   6005             ->IsNumber());
   6006   CHECK_EQ(0, result->Get(context.local(), v8::Integer::New(isolate, 2))
   6007                   .ToLocalChecked()
   6008                   ->Int32Value(context.local())
   6009                   .FromJust());
   6010   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 3))
   6011             .ToLocalChecked()
   6012             ->IsNull());
   6013   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 4))
   6014             .ToLocalChecked()
   6015             ->IsUndefined());
   6016 }
   6017 
   6018 
   6019 THREADED_TEST(CatchZero) {
   6020   LocalContext context;
   6021   v8::HandleScope scope(context->GetIsolate());
   6022   v8::TryCatch try_catch(context->GetIsolate());
   6023   CHECK(!try_catch.HasCaught());
   6024   CompileRun("throw 10");
   6025   CHECK(try_catch.HasCaught());
   6026   CHECK_EQ(10, try_catch.Exception()->Int32Value(context.local()).FromJust());
   6027   try_catch.Reset();
   6028   CHECK(!try_catch.HasCaught());
   6029   CompileRun("throw 0");
   6030   CHECK(try_catch.HasCaught());
   6031   CHECK_EQ(0, try_catch.Exception()->Int32Value(context.local()).FromJust());
   6032 }
   6033 
   6034 
   6035 THREADED_TEST(CatchExceptionFromWith) {
   6036   LocalContext context;
   6037   v8::HandleScope scope(context->GetIsolate());
   6038   v8::TryCatch try_catch(context->GetIsolate());
   6039   CHECK(!try_catch.HasCaught());
   6040   CompileRun("var o = {}; with (o) { throw 42; }");
   6041   CHECK(try_catch.HasCaught());
   6042 }
   6043 
   6044 
   6045 THREADED_TEST(TryCatchAndFinallyHidingException) {
   6046   LocalContext context;
   6047   v8::HandleScope scope(context->GetIsolate());
   6048   v8::TryCatch try_catch(context->GetIsolate());
   6049   CHECK(!try_catch.HasCaught());
   6050   CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
   6051   CompileRun("f({toString: function() { throw 42; }});");
   6052   CHECK(!try_catch.HasCaught());
   6053 }
   6054 
   6055 
   6056 void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
   6057   v8::TryCatch try_catch(args.GetIsolate());
   6058 }
   6059 
   6060 
   6061 THREADED_TEST(TryCatchAndFinally) {
   6062   LocalContext context;
   6063   v8::Isolate* isolate = context->GetIsolate();
   6064   v8::HandleScope scope(isolate);
   6065   CHECK(context->Global()
   6066             ->Set(context.local(), v8_str("native_with_try_catch"),
   6067                   v8::FunctionTemplate::New(isolate, WithTryCatch)
   6068                       ->GetFunction(context.local())
   6069                       .ToLocalChecked())
   6070             .FromJust());
   6071   v8::TryCatch try_catch(isolate);
   6072   CHECK(!try_catch.HasCaught());
   6073   CompileRun(
   6074       "try {\n"
   6075       "  throw new Error('a');\n"
   6076       "} finally {\n"
   6077       "  native_with_try_catch();\n"
   6078       "}\n");
   6079   CHECK(try_catch.HasCaught());
   6080 }
   6081 
   6082 
   6083 static void TryCatchNested1Helper(int depth) {
   6084   if (depth > 0) {
   6085     v8::TryCatch try_catch(CcTest::isolate());
   6086     try_catch.SetVerbose(true);
   6087     TryCatchNested1Helper(depth - 1);
   6088     CHECK(try_catch.HasCaught());
   6089     try_catch.ReThrow();
   6090   } else {
   6091     CcTest::isolate()->ThrowException(v8_str("E1"));
   6092   }
   6093 }
   6094 
   6095 
   6096 static void TryCatchNested2Helper(int depth) {
   6097   if (depth > 0) {
   6098     v8::TryCatch try_catch(CcTest::isolate());
   6099     try_catch.SetVerbose(true);
   6100     TryCatchNested2Helper(depth - 1);
   6101     CHECK(try_catch.HasCaught());
   6102     try_catch.ReThrow();
   6103   } else {
   6104     CompileRun("throw 'E2';");
   6105   }
   6106 }
   6107 
   6108 
   6109 TEST(TryCatchNested) {
   6110   v8::V8::Initialize();
   6111   LocalContext context;
   6112   v8::HandleScope scope(context->GetIsolate());
   6113 
   6114   {
   6115     // Test nested try-catch with a native throw in the end.
   6116     v8::TryCatch try_catch(context->GetIsolate());
   6117     TryCatchNested1Helper(5);
   6118     CHECK(try_catch.HasCaught());
   6119     CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E1"));
   6120   }
   6121 
   6122   {
   6123     // Test nested try-catch with a JavaScript throw in the end.
   6124     v8::TryCatch try_catch(context->GetIsolate());
   6125     TryCatchNested2Helper(5);
   6126     CHECK(try_catch.HasCaught());
   6127     CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E2"));
   6128   }
   6129 }
   6130 
   6131 
   6132 void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
   6133   CHECK(try_catch->HasCaught());
   6134   Local<Message> message = try_catch->Message();
   6135   Local<Value> resource = message->GetScriptOrigin().ResourceName();
   6136   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
   6137   CHECK_EQ(0,
   6138            strcmp(*v8::String::Utf8Value(message->Get()), "Uncaught Error: a"));
   6139   CHECK_EQ(1, message->GetLineNumber(CcTest::isolate()->GetCurrentContext())
   6140                   .FromJust());
   6141   CHECK_EQ(0, message->GetStartColumn(CcTest::isolate()->GetCurrentContext())
   6142                   .FromJust());
   6143 }
   6144 
   6145 
   6146 void TryCatchMixedNestingHelper(
   6147     const v8::FunctionCallbackInfo<v8::Value>& args) {
   6148   ApiTestFuzzer::Fuzz();
   6149   v8::TryCatch try_catch(args.GetIsolate());
   6150   CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
   6151   CHECK(try_catch.HasCaught());
   6152   TryCatchMixedNestingCheck(&try_catch);
   6153   try_catch.ReThrow();
   6154 }
   6155 
   6156 
   6157 // This test ensures that an outer TryCatch in the following situation:
   6158 //   C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
   6159 // does not clobber the Message object generated for the inner TryCatch.
   6160 // This exercises the ability of TryCatch.ReThrow() to restore the
   6161 // inner pending Message before throwing the exception again.
   6162 TEST(TryCatchMixedNesting) {
   6163   v8::Isolate* isolate = CcTest::isolate();
   6164   v8::HandleScope scope(isolate);
   6165   v8::V8::Initialize();
   6166   v8::TryCatch try_catch(isolate);
   6167   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6168   templ->Set(v8_str("TryCatchMixedNestingHelper"),
   6169              v8::FunctionTemplate::New(isolate, TryCatchMixedNestingHelper));
   6170   LocalContext context(0, templ);
   6171   CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
   6172   TryCatchMixedNestingCheck(&try_catch);
   6173 }
   6174 
   6175 
   6176 void TryCatchNativeHelper(const v8::FunctionCallbackInfo<v8::Value>& args) {
   6177   ApiTestFuzzer::Fuzz();
   6178   v8::TryCatch try_catch(args.GetIsolate());
   6179   args.GetIsolate()->ThrowException(v8_str("boom"));
   6180   CHECK(try_catch.HasCaught());
   6181 }
   6182 
   6183 
   6184 TEST(TryCatchNative) {
   6185   v8::Isolate* isolate = CcTest::isolate();
   6186   v8::HandleScope scope(isolate);
   6187   v8::V8::Initialize();
   6188   v8::TryCatch try_catch(isolate);
   6189   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6190   templ->Set(v8_str("TryCatchNativeHelper"),
   6191              v8::FunctionTemplate::New(isolate, TryCatchNativeHelper));
   6192   LocalContext context(0, templ);
   6193   CompileRun("TryCatchNativeHelper();");
   6194   CHECK(!try_catch.HasCaught());
   6195 }
   6196 
   6197 
   6198 void TryCatchNativeResetHelper(
   6199     const v8::FunctionCallbackInfo<v8::Value>& args) {
   6200   ApiTestFuzzer::Fuzz();
   6201   v8::TryCatch try_catch(args.GetIsolate());
   6202   args.GetIsolate()->ThrowException(v8_str("boom"));
   6203   CHECK(try_catch.HasCaught());
   6204   try_catch.Reset();
   6205   CHECK(!try_catch.HasCaught());
   6206 }
   6207 
   6208 
   6209 TEST(TryCatchNativeReset) {
   6210   v8::Isolate* isolate = CcTest::isolate();
   6211   v8::HandleScope scope(isolate);
   6212   v8::V8::Initialize();
   6213   v8::TryCatch try_catch(isolate);
   6214   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6215   templ->Set(v8_str("TryCatchNativeResetHelper"),
   6216              v8::FunctionTemplate::New(isolate, TryCatchNativeResetHelper));
   6217   LocalContext context(0, templ);
   6218   CompileRun("TryCatchNativeResetHelper();");
   6219   CHECK(!try_catch.HasCaught());
   6220 }
   6221 
   6222 
   6223 THREADED_TEST(Equality) {
   6224   LocalContext context;
   6225   v8::Isolate* isolate = context->GetIsolate();
   6226   v8::HandleScope scope(context->GetIsolate());
   6227   // Check that equality works at all before relying on CHECK_EQ
   6228   CHECK(v8_str("a")->Equals(context.local(), v8_str("a")).FromJust());
   6229   CHECK(!v8_str("a")->Equals(context.local(), v8_str("b")).FromJust());
   6230 
   6231   CHECK(v8_str("a")->Equals(context.local(), v8_str("a")).FromJust());
   6232   CHECK(!v8_str("a")->Equals(context.local(), v8_str("b")).FromJust());
   6233   CHECK(v8_num(1)->Equals(context.local(), v8_num(1)).FromJust());
   6234   CHECK(v8_num(1.00)->Equals(context.local(), v8_num(1)).FromJust());
   6235   CHECK(!v8_num(1)->Equals(context.local(), v8_num(2)).FromJust());
   6236 
   6237   // Assume String is not internalized.
   6238   CHECK(v8_str("a")->StrictEquals(v8_str("a")));
   6239   CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
   6240   CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
   6241   CHECK(v8_num(1)->StrictEquals(v8_num(1)));
   6242   CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
   6243   CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
   6244   Local<Value> not_a_number = v8_num(std::numeric_limits<double>::quiet_NaN());
   6245   CHECK(!not_a_number->StrictEquals(not_a_number));
   6246   CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
   6247   CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
   6248 
   6249   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   6250   v8::Persistent<v8::Object> alias(isolate, obj);
   6251   CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
   6252   alias.Reset();
   6253 
   6254   CHECK(v8_str("a")->SameValue(v8_str("a")));
   6255   CHECK(!v8_str("a")->SameValue(v8_str("b")));
   6256   CHECK(!v8_str("5")->SameValue(v8_num(5)));
   6257   CHECK(v8_num(1)->SameValue(v8_num(1)));
   6258   CHECK(!v8_num(1)->SameValue(v8_num(2)));
   6259   CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
   6260   CHECK(not_a_number->SameValue(not_a_number));
   6261   CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
   6262   CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
   6263 }
   6264 
   6265 
   6266 THREADED_TEST(MultiRun) {
   6267   LocalContext context;
   6268   v8::HandleScope scope(context->GetIsolate());
   6269   Local<Script> script = v8_compile("x");
   6270   for (int i = 0; i < 10; i++) {
   6271     script->Run(context.local()).IsEmpty();
   6272   }
   6273 }
   6274 
   6275 
   6276 static void GetXValue(Local<Name> name,
   6277                       const v8::PropertyCallbackInfo<v8::Value>& info) {
   6278   ApiTestFuzzer::Fuzz();
   6279   CHECK(info.Data()
   6280             ->Equals(CcTest::isolate()->GetCurrentContext(), v8_str("donut"))
   6281             .FromJust());
   6282   CHECK(name->Equals(CcTest::isolate()->GetCurrentContext(), v8_str("x"))
   6283             .FromJust());
   6284   info.GetReturnValue().Set(name);
   6285 }
   6286 
   6287 
   6288 THREADED_TEST(SimplePropertyRead) {
   6289   LocalContext context;
   6290   v8::Isolate* isolate = context->GetIsolate();
   6291   v8::HandleScope scope(isolate);
   6292   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6293   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
   6294   CHECK(context->Global()
   6295             ->Set(context.local(), v8_str("obj"),
   6296                   templ->NewInstance(context.local()).ToLocalChecked())
   6297             .FromJust());
   6298   Local<Script> script = v8_compile("obj.x");
   6299   for (int i = 0; i < 10; i++) {
   6300     Local<Value> result = script->Run(context.local()).ToLocalChecked();
   6301     CHECK(result->Equals(context.local(), v8_str("x")).FromJust());
   6302   }
   6303 }
   6304 
   6305 
   6306 THREADED_TEST(DefinePropertyOnAPIAccessor) {
   6307   LocalContext context;
   6308   v8::Isolate* isolate = context->GetIsolate();
   6309   v8::HandleScope scope(isolate);
   6310   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6311   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
   6312   CHECK(context->Global()
   6313             ->Set(context.local(), v8_str("obj"),
   6314                   templ->NewInstance(context.local()).ToLocalChecked())
   6315             .FromJust());
   6316 
   6317   // Uses getOwnPropertyDescriptor to check the configurable status
   6318   Local<Script> script_desc = v8_compile(
   6319       "var prop = Object.getOwnPropertyDescriptor( "
   6320       "obj, 'x');"
   6321       "prop.configurable;");
   6322   Local<Value> result = script_desc->Run(context.local()).ToLocalChecked();
   6323   CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
   6324 
   6325   // Redefine get - but still configurable
   6326   Local<Script> script_define = v8_compile(
   6327       "var desc = { get: function(){return 42; },"
   6328       "            configurable: true };"
   6329       "Object.defineProperty(obj, 'x', desc);"
   6330       "obj.x");
   6331   result = script_define->Run(context.local()).ToLocalChecked();
   6332   CHECK(result->Equals(context.local(), v8_num(42)).FromJust());
   6333 
   6334   // Check that the accessor is still configurable
   6335   result = script_desc->Run(context.local()).ToLocalChecked();
   6336   CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
   6337 
   6338   // Redefine to a non-configurable
   6339   script_define = v8_compile(
   6340       "var desc = { get: function(){return 43; },"
   6341       "             configurable: false };"
   6342       "Object.defineProperty(obj, 'x', desc);"
   6343       "obj.x");
   6344   result = script_define->Run(context.local()).ToLocalChecked();
   6345   CHECK(result->Equals(context.local(), v8_num(43)).FromJust());
   6346   result = script_desc->Run(context.local()).ToLocalChecked();
   6347   CHECK_EQ(result->BooleanValue(context.local()).FromJust(), false);
   6348 
   6349   // Make sure that it is not possible to redefine again
   6350   v8::TryCatch try_catch(isolate);
   6351   CHECK(script_define->Run(context.local()).IsEmpty());
   6352   CHECK(try_catch.HasCaught());
   6353   String::Utf8Value exception_value(try_catch.Exception());
   6354   CHECK_EQ(0,
   6355            strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
   6356 }
   6357 
   6358 
   6359 THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
   6360   v8::Isolate* isolate = CcTest::isolate();
   6361   v8::HandleScope scope(isolate);
   6362   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6363   templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
   6364   LocalContext context;
   6365   CHECK(context->Global()
   6366             ->Set(context.local(), v8_str("obj"),
   6367                   templ->NewInstance(context.local()).ToLocalChecked())
   6368             .FromJust());
   6369 
   6370   Local<Script> script_desc = v8_compile(
   6371       "var prop ="
   6372       "Object.getOwnPropertyDescriptor( "
   6373       "obj, 'x');"
   6374       "prop.configurable;");
   6375   Local<Value> result = script_desc->Run(context.local()).ToLocalChecked();
   6376   CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
   6377 
   6378   Local<Script> script_define = v8_compile(
   6379       "var desc = {get: function(){return 42; },"
   6380       "            configurable: true };"
   6381       "Object.defineProperty(obj, 'x', desc);"
   6382       "obj.x");
   6383   result = script_define->Run(context.local()).ToLocalChecked();
   6384   CHECK(result->Equals(context.local(), v8_num(42)).FromJust());
   6385 
   6386   result = script_desc->Run(context.local()).ToLocalChecked();
   6387   CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
   6388 
   6389   script_define = v8_compile(
   6390       "var desc = {get: function(){return 43; },"
   6391       "            configurable: false };"
   6392       "Object.defineProperty(obj, 'x', desc);"
   6393       "obj.x");
   6394   result = script_define->Run(context.local()).ToLocalChecked();
   6395   CHECK(result->Equals(context.local(), v8_num(43)).FromJust());
   6396 
   6397   result = script_desc->Run(context.local()).ToLocalChecked();
   6398   CHECK_EQ(result->BooleanValue(context.local()).FromJust(), false);
   6399 
   6400   v8::TryCatch try_catch(isolate);
   6401   CHECK(script_define->Run(context.local()).IsEmpty());
   6402   CHECK(try_catch.HasCaught());
   6403   String::Utf8Value exception_value(try_catch.Exception());
   6404   CHECK_EQ(0,
   6405            strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
   6406 }
   6407 
   6408 
   6409 static v8::Local<v8::Object> GetGlobalProperty(LocalContext* context,
   6410                                                char const* name) {
   6411   return v8::Local<v8::Object>::Cast(
   6412       (*context)
   6413           ->Global()
   6414           ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name))
   6415           .ToLocalChecked());
   6416 }
   6417 
   6418 
   6419 THREADED_TEST(DefineAPIAccessorOnObject) {
   6420   v8::Isolate* isolate = CcTest::isolate();
   6421   v8::HandleScope scope(isolate);
   6422   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6423   LocalContext context;
   6424 
   6425   CHECK(context->Global()
   6426             ->Set(context.local(), v8_str("obj1"),
   6427                   templ->NewInstance(context.local()).ToLocalChecked())
   6428             .FromJust());
   6429   CompileRun("var obj2 = {};");
   6430 
   6431   CHECK(CompileRun("obj1.x")->IsUndefined());
   6432   CHECK(CompileRun("obj2.x")->IsUndefined());
   6433 
   6434   CHECK(GetGlobalProperty(&context, "obj1")
   6435             ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
   6436                           v8_str("donut"))
   6437             .FromJust());
   6438 
   6439   ExpectString("obj1.x", "x");
   6440   CHECK(CompileRun("obj2.x")->IsUndefined());
   6441 
   6442   CHECK(GetGlobalProperty(&context, "obj2")
   6443             ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
   6444                           v8_str("donut"))
   6445             .FromJust());
   6446 
   6447   ExpectString("obj1.x", "x");
   6448   ExpectString("obj2.x", "x");
   6449 
   6450   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   6451   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   6452 
   6453   CompileRun(
   6454       "Object.defineProperty(obj1, 'x',"
   6455       "{ get: function() { return 'y'; }, configurable: true })");
   6456 
   6457   ExpectString("obj1.x", "y");
   6458   ExpectString("obj2.x", "x");
   6459 
   6460   CompileRun(
   6461       "Object.defineProperty(obj2, 'x',"
   6462       "{ get: function() { return 'y'; }, configurable: true })");
   6463 
   6464   ExpectString("obj1.x", "y");
   6465   ExpectString("obj2.x", "y");
   6466 
   6467   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   6468   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   6469 
   6470   CHECK(GetGlobalProperty(&context, "obj1")
   6471             ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
   6472                           v8_str("donut"))
   6473             .FromJust());
   6474   CHECK(GetGlobalProperty(&context, "obj2")
   6475             ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
   6476                           v8_str("donut"))
   6477             .FromJust());
   6478 
   6479   ExpectString("obj1.x", "x");
   6480   ExpectString("obj2.x", "x");
   6481 
   6482   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   6483   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   6484 
   6485   // Define getters/setters, but now make them not configurable.
   6486   CompileRun(
   6487       "Object.defineProperty(obj1, 'x',"
   6488       "{ get: function() { return 'z'; }, configurable: false })");
   6489   CompileRun(
   6490       "Object.defineProperty(obj2, 'x',"
   6491       "{ get: function() { return 'z'; }, configurable: false })");
   6492   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   6493   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   6494 
   6495   ExpectString("obj1.x", "z");
   6496   ExpectString("obj2.x", "z");
   6497 
   6498   CHECK(GetGlobalProperty(&context, "obj1")
   6499             ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
   6500                           v8_str("donut"))
   6501             .IsNothing());
   6502   CHECK(GetGlobalProperty(&context, "obj2")
   6503             ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
   6504                           v8_str("donut"))
   6505             .IsNothing());
   6506 
   6507   ExpectString("obj1.x", "z");
   6508   ExpectString("obj2.x", "z");
   6509 }
   6510 
   6511 
   6512 THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
   6513   v8::Isolate* isolate = CcTest::isolate();
   6514   v8::HandleScope scope(isolate);
   6515   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6516   LocalContext context;
   6517 
   6518   CHECK(context->Global()
   6519             ->Set(context.local(), v8_str("obj1"),
   6520                   templ->NewInstance(context.local()).ToLocalChecked())
   6521             .FromJust());
   6522   CompileRun("var obj2 = {};");
   6523 
   6524   CHECK(GetGlobalProperty(&context, "obj1")
   6525             ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
   6526                           v8_str("donut"), v8::DEFAULT, v8::DontDelete)
   6527             .FromJust());
   6528   CHECK(GetGlobalProperty(&context, "obj2")
   6529             ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
   6530                           v8_str("donut"), v8::DEFAULT, v8::DontDelete)
   6531             .FromJust());
   6532 
   6533   ExpectString("obj1.x", "x");
   6534   ExpectString("obj2.x", "x");
   6535 
   6536   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
   6537   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
   6538 
   6539   CHECK(GetGlobalProperty(&context, "obj1")
   6540             ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
   6541                           v8_str("donut"))
   6542             .IsNothing());
   6543   CHECK(GetGlobalProperty(&context, "obj2")
   6544             ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
   6545                           v8_str("donut"))
   6546             .IsNothing());
   6547 
   6548   {
   6549     v8::TryCatch try_catch(isolate);
   6550     CompileRun(
   6551         "Object.defineProperty(obj1, 'x',"
   6552         "{get: function() { return 'func'; }})");
   6553     CHECK(try_catch.HasCaught());
   6554     String::Utf8Value exception_value(try_catch.Exception());
   6555     CHECK_EQ(
   6556         0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
   6557   }
   6558   {
   6559     v8::TryCatch try_catch(isolate);
   6560     CompileRun(
   6561         "Object.defineProperty(obj2, 'x',"
   6562         "{get: function() { return 'func'; }})");
   6563     CHECK(try_catch.HasCaught());
   6564     String::Utf8Value exception_value(try_catch.Exception());
   6565     CHECK_EQ(
   6566         0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
   6567   }
   6568 }
   6569 
   6570 
   6571 static void Get239Value(Local<Name> name,
   6572                         const v8::PropertyCallbackInfo<v8::Value>& info) {
   6573   ApiTestFuzzer::Fuzz();
   6574   CHECK(info.Data()
   6575             ->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("donut"))
   6576             .FromJust());
   6577   CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("239"))
   6578             .FromJust());
   6579   info.GetReturnValue().Set(name);
   6580 }
   6581 
   6582 
   6583 THREADED_TEST(ElementAPIAccessor) {
   6584   v8::Isolate* isolate = CcTest::isolate();
   6585   v8::HandleScope scope(isolate);
   6586   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6587   LocalContext context;
   6588 
   6589   CHECK(context->Global()
   6590             ->Set(context.local(), v8_str("obj1"),
   6591                   templ->NewInstance(context.local()).ToLocalChecked())
   6592             .FromJust());
   6593   CompileRun("var obj2 = {};");
   6594 
   6595   CHECK(GetGlobalProperty(&context, "obj1")
   6596             ->SetAccessor(context.local(), v8_str("239"), Get239Value, NULL,
   6597                           v8_str("donut"))
   6598             .FromJust());
   6599   CHECK(GetGlobalProperty(&context, "obj2")
   6600             ->SetAccessor(context.local(), v8_str("239"), Get239Value, NULL,
   6601                           v8_str("donut"))
   6602             .FromJust());
   6603 
   6604   ExpectString("obj1[239]", "239");
   6605   ExpectString("obj2[239]", "239");
   6606   ExpectString("obj1['239']", "239");
   6607   ExpectString("obj2['239']", "239");
   6608 }
   6609 
   6610 
   6611 v8::Persistent<Value> xValue;
   6612 
   6613 
   6614 static void SetXValue(Local<Name> name, Local<Value> value,
   6615                       const v8::PropertyCallbackInfo<void>& info) {
   6616   Local<Context> context = info.GetIsolate()->GetCurrentContext();
   6617   CHECK(value->Equals(context, v8_num(4)).FromJust());
   6618   CHECK(info.Data()->Equals(context, v8_str("donut")).FromJust());
   6619   CHECK(name->Equals(context, v8_str("x")).FromJust());
   6620   CHECK(xValue.IsEmpty());
   6621   xValue.Reset(info.GetIsolate(), value);
   6622 }
   6623 
   6624 
   6625 THREADED_TEST(SimplePropertyWrite) {
   6626   v8::Isolate* isolate = CcTest::isolate();
   6627   v8::HandleScope scope(isolate);
   6628   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6629   templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
   6630   LocalContext context;
   6631   CHECK(context->Global()
   6632             ->Set(context.local(), v8_str("obj"),
   6633                   templ->NewInstance(context.local()).ToLocalChecked())
   6634             .FromJust());
   6635   Local<Script> script = v8_compile("obj.x = 4");
   6636   for (int i = 0; i < 10; i++) {
   6637     CHECK(xValue.IsEmpty());
   6638     script->Run(context.local()).ToLocalChecked();
   6639     CHECK(v8_num(4)
   6640               ->Equals(context.local(),
   6641                        Local<Value>::New(CcTest::isolate(), xValue))
   6642               .FromJust());
   6643     xValue.Reset();
   6644   }
   6645 }
   6646 
   6647 
   6648 THREADED_TEST(SetterOnly) {
   6649   v8::Isolate* isolate = CcTest::isolate();
   6650   v8::HandleScope scope(isolate);
   6651   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6652   templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
   6653   LocalContext context;
   6654   CHECK(context->Global()
   6655             ->Set(context.local(), v8_str("obj"),
   6656                   templ->NewInstance(context.local()).ToLocalChecked())
   6657             .FromJust());
   6658   Local<Script> script = v8_compile("obj.x = 4; obj.x");
   6659   for (int i = 0; i < 10; i++) {
   6660     CHECK(xValue.IsEmpty());
   6661     script->Run(context.local()).ToLocalChecked();
   6662     CHECK(v8_num(4)
   6663               ->Equals(context.local(),
   6664                        Local<Value>::New(CcTest::isolate(), xValue))
   6665               .FromJust());
   6666     xValue.Reset();
   6667   }
   6668 }
   6669 
   6670 
   6671 THREADED_TEST(NoAccessors) {
   6672   v8::Isolate* isolate = CcTest::isolate();
   6673   v8::HandleScope scope(isolate);
   6674   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6675   templ->SetAccessor(v8_str("x"), static_cast<v8::AccessorGetterCallback>(NULL),
   6676                      NULL, v8_str("donut"));
   6677   LocalContext context;
   6678   CHECK(context->Global()
   6679             ->Set(context.local(), v8_str("obj"),
   6680                   templ->NewInstance(context.local()).ToLocalChecked())
   6681             .FromJust());
   6682   Local<Script> script = v8_compile("obj.x = 4; obj.x");
   6683   for (int i = 0; i < 10; i++) {
   6684     script->Run(context.local()).ToLocalChecked();
   6685   }
   6686 }
   6687 
   6688 
   6689 THREADED_TEST(MultiContexts) {
   6690   v8::Isolate* isolate = CcTest::isolate();
   6691   v8::HandleScope scope(isolate);
   6692   v8::Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6693   templ->Set(v8_str("dummy"),
   6694              v8::FunctionTemplate::New(isolate, DummyCallHandler));
   6695 
   6696   Local<String> password = v8_str("Password");
   6697 
   6698   // Create an environment
   6699   LocalContext context0(0, templ);
   6700   context0->SetSecurityToken(password);
   6701   v8::Local<v8::Object> global0 = context0->Global();
   6702   CHECK(global0->Set(context0.local(), v8_str("custom"), v8_num(1234))
   6703             .FromJust());
   6704   CHECK_EQ(1234, global0->Get(context0.local(), v8_str("custom"))
   6705                      .ToLocalChecked()
   6706                      ->Int32Value(context0.local())
   6707                      .FromJust());
   6708 
   6709   // Create an independent environment
   6710   LocalContext context1(0, templ);
   6711   context1->SetSecurityToken(password);
   6712   v8::Local<v8::Object> global1 = context1->Global();
   6713   CHECK(global1->Set(context1.local(), v8_str("custom"), v8_num(1234))
   6714             .FromJust());
   6715   CHECK(!global0->Equals(context1.local(), global1).FromJust());
   6716   CHECK_EQ(1234, global0->Get(context1.local(), v8_str("custom"))
   6717                      .ToLocalChecked()
   6718                      ->Int32Value(context0.local())
   6719                      .FromJust());
   6720   CHECK_EQ(1234, global1->Get(context1.local(), v8_str("custom"))
   6721                      .ToLocalChecked()
   6722                      ->Int32Value(context1.local())
   6723                      .FromJust());
   6724 
   6725   // Now create a new context with the old global
   6726   LocalContext context2(0, templ, global1);
   6727   context2->SetSecurityToken(password);
   6728   v8::Local<v8::Object> global2 = context2->Global();
   6729   CHECK(global1->Equals(context2.local(), global2).FromJust());
   6730   CHECK_EQ(0, global1->Get(context2.local(), v8_str("custom"))
   6731                   .ToLocalChecked()
   6732                   ->Int32Value(context1.local())
   6733                   .FromJust());
   6734   CHECK_EQ(0, global2->Get(context2.local(), v8_str("custom"))
   6735                   .ToLocalChecked()
   6736                   ->Int32Value(context2.local())
   6737                   .FromJust());
   6738 }
   6739 
   6740 
   6741 THREADED_TEST(FunctionPrototypeAcrossContexts) {
   6742   // Make sure that functions created by cloning boilerplates cannot
   6743   // communicate through their __proto__ field.
   6744 
   6745   v8::HandleScope scope(CcTest::isolate());
   6746 
   6747   LocalContext env0;
   6748   v8::Local<v8::Object> global0 = env0->Global();
   6749   v8::Local<v8::Object> object0 = global0->Get(env0.local(), v8_str("Object"))
   6750                                       .ToLocalChecked()
   6751                                       .As<v8::Object>();
   6752   v8::Local<v8::Object> tostring0 =
   6753       object0->Get(env0.local(), v8_str("toString"))
   6754           .ToLocalChecked()
   6755           .As<v8::Object>();
   6756   v8::Local<v8::Object> proto0 =
   6757       tostring0->Get(env0.local(), v8_str("__proto__"))
   6758           .ToLocalChecked()
   6759           .As<v8::Object>();
   6760   CHECK(proto0->Set(env0.local(), v8_str("custom"), v8_num(1234)).FromJust());
   6761 
   6762   LocalContext env1;
   6763   v8::Local<v8::Object> global1 = env1->Global();
   6764   v8::Local<v8::Object> object1 = global1->Get(env1.local(), v8_str("Object"))
   6765                                       .ToLocalChecked()
   6766                                       .As<v8::Object>();
   6767   v8::Local<v8::Object> tostring1 =
   6768       object1->Get(env1.local(), v8_str("toString"))
   6769           .ToLocalChecked()
   6770           .As<v8::Object>();
   6771   v8::Local<v8::Object> proto1 =
   6772       tostring1->Get(env1.local(), v8_str("__proto__"))
   6773           .ToLocalChecked()
   6774           .As<v8::Object>();
   6775   CHECK(!proto1->Has(env1.local(), v8_str("custom")).FromJust());
   6776 }
   6777 
   6778 
   6779 THREADED_TEST(Regress892105) {
   6780   // Make sure that object and array literals created by cloning
   6781   // boilerplates cannot communicate through their __proto__
   6782   // field. This is rather difficult to check, but we try to add stuff
   6783   // to Object.prototype and Array.prototype and create a new
   6784   // environment. This should succeed.
   6785 
   6786   v8::HandleScope scope(CcTest::isolate());
   6787 
   6788   Local<String> source = v8_str(
   6789       "Object.prototype.obj = 1234;"
   6790       "Array.prototype.arr = 4567;"
   6791       "8901");
   6792 
   6793   LocalContext env0;
   6794   Local<Script> script0 = v8_compile(source);
   6795   CHECK_EQ(8901.0, script0->Run(env0.local())
   6796                        .ToLocalChecked()
   6797                        ->NumberValue(env0.local())
   6798                        .FromJust());
   6799 
   6800   LocalContext env1;
   6801   Local<Script> script1 = v8_compile(source);
   6802   CHECK_EQ(8901.0, script1->Run(env1.local())
   6803                        .ToLocalChecked()
   6804                        ->NumberValue(env1.local())
   6805                        .FromJust());
   6806 }
   6807 
   6808 
   6809 THREADED_TEST(UndetectableObject) {
   6810   LocalContext env;
   6811   v8::HandleScope scope(env->GetIsolate());
   6812 
   6813   Local<v8::FunctionTemplate> desc =
   6814       v8::FunctionTemplate::New(env->GetIsolate());
   6815   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   6816 
   6817   Local<v8::Object> obj = desc->GetFunction(env.local())
   6818                               .ToLocalChecked()
   6819                               ->NewInstance(env.local())
   6820                               .ToLocalChecked();
   6821   CHECK(
   6822       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
   6823 
   6824   ExpectString("undetectable.toString()", "[object Object]");
   6825   ExpectString("typeof undetectable", "undefined");
   6826   ExpectString("typeof(undetectable)", "undefined");
   6827   ExpectBoolean("typeof undetectable == 'undefined'", true);
   6828   ExpectBoolean("typeof undetectable == 'object'", false);
   6829   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
   6830   ExpectBoolean("!undetectable", true);
   6831 
   6832   ExpectObject("true&&undetectable", obj);
   6833   ExpectBoolean("false&&undetectable", false);
   6834   ExpectBoolean("true||undetectable", true);
   6835   ExpectObject("false||undetectable", obj);
   6836 
   6837   ExpectObject("undetectable&&true", obj);
   6838   ExpectObject("undetectable&&false", obj);
   6839   ExpectBoolean("undetectable||true", true);
   6840   ExpectBoolean("undetectable||false", false);
   6841 
   6842   ExpectBoolean("undetectable==null", true);
   6843   ExpectBoolean("null==undetectable", true);
   6844   ExpectBoolean("undetectable==undefined", true);
   6845   ExpectBoolean("undefined==undetectable", true);
   6846   ExpectBoolean("undetectable==undetectable", true);
   6847 
   6848 
   6849   ExpectBoolean("undetectable===null", false);
   6850   ExpectBoolean("null===undetectable", false);
   6851   ExpectBoolean("undetectable===undefined", false);
   6852   ExpectBoolean("undefined===undetectable", false);
   6853   ExpectBoolean("undetectable===undetectable", true);
   6854 }
   6855 
   6856 
   6857 THREADED_TEST(VoidLiteral) {
   6858   LocalContext env;
   6859   v8::Isolate* isolate = env->GetIsolate();
   6860   v8::HandleScope scope(isolate);
   6861 
   6862   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
   6863   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   6864 
   6865   Local<v8::Object> obj = desc->GetFunction(env.local())
   6866                               .ToLocalChecked()
   6867                               ->NewInstance(env.local())
   6868                               .ToLocalChecked();
   6869   CHECK(
   6870       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
   6871 
   6872   ExpectBoolean("undefined == void 0", true);
   6873   ExpectBoolean("undetectable == void 0", true);
   6874   ExpectBoolean("null == void 0", true);
   6875   ExpectBoolean("undefined === void 0", true);
   6876   ExpectBoolean("undetectable === void 0", false);
   6877   ExpectBoolean("null === void 0", false);
   6878 
   6879   ExpectBoolean("void 0 == undefined", true);
   6880   ExpectBoolean("void 0 == undetectable", true);
   6881   ExpectBoolean("void 0 == null", true);
   6882   ExpectBoolean("void 0 === undefined", true);
   6883   ExpectBoolean("void 0 === undetectable", false);
   6884   ExpectBoolean("void 0 === null", false);
   6885 
   6886   ExpectString(
   6887       "(function() {"
   6888       "  try {"
   6889       "    return x === void 0;"
   6890       "  } catch(e) {"
   6891       "    return e.toString();"
   6892       "  }"
   6893       "})()",
   6894       "ReferenceError: x is not defined");
   6895   ExpectString(
   6896       "(function() {"
   6897       "  try {"
   6898       "    return void 0 === x;"
   6899       "  } catch(e) {"
   6900       "    return e.toString();"
   6901       "  }"
   6902       "})()",
   6903       "ReferenceError: x is not defined");
   6904 }
   6905 
   6906 
   6907 THREADED_TEST(ExtensibleOnUndetectable) {
   6908   LocalContext env;
   6909   v8::Isolate* isolate = env->GetIsolate();
   6910   v8::HandleScope scope(isolate);
   6911 
   6912   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
   6913   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   6914 
   6915   Local<v8::Object> obj = desc->GetFunction(env.local())
   6916                               .ToLocalChecked()
   6917                               ->NewInstance(env.local())
   6918                               .ToLocalChecked();
   6919   CHECK(
   6920       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
   6921 
   6922   Local<String> source = v8_str(
   6923       "undetectable.x = 42;"
   6924       "undetectable.x");
   6925 
   6926   Local<Script> script = v8_compile(source);
   6927 
   6928   CHECK(v8::Integer::New(isolate, 42)
   6929             ->Equals(env.local(), script->Run(env.local()).ToLocalChecked())
   6930             .FromJust());
   6931 
   6932   ExpectBoolean("Object.isExtensible(undetectable)", true);
   6933 
   6934   source = v8_str("Object.preventExtensions(undetectable);");
   6935   script = v8_compile(source);
   6936   script->Run(env.local()).ToLocalChecked();
   6937   ExpectBoolean("Object.isExtensible(undetectable)", false);
   6938 
   6939   source = v8_str("undetectable.y = 2000;");
   6940   script = v8_compile(source);
   6941   script->Run(env.local()).ToLocalChecked();
   6942   ExpectBoolean("undetectable.y == undefined", true);
   6943 }
   6944 
   6945 
   6946 // The point of this test is type checking. We run it only so compilers
   6947 // don't complain about an unused function.
   6948 TEST(PersistentHandles) {
   6949   LocalContext env;
   6950   v8::Isolate* isolate = CcTest::isolate();
   6951   v8::HandleScope scope(isolate);
   6952   Local<String> str = v8_str("foo");
   6953   v8::Persistent<String> p_str(isolate, str);
   6954   p_str.Reset();
   6955   Local<Script> scr = v8_compile("");
   6956   v8::Persistent<Script> p_scr(isolate, scr);
   6957   p_scr.Reset();
   6958   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   6959   v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
   6960   p_templ.Reset();
   6961 }
   6962 
   6963 
   6964 static void HandleLogDelegator(
   6965     const v8::FunctionCallbackInfo<v8::Value>& args) {
   6966   ApiTestFuzzer::Fuzz();
   6967 }
   6968 
   6969 
   6970 THREADED_TEST(GlobalObjectTemplate) {
   6971   v8::Isolate* isolate = CcTest::isolate();
   6972   v8::HandleScope handle_scope(isolate);
   6973   Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
   6974   global_template->Set(v8_str("JSNI_Log"),
   6975                        v8::FunctionTemplate::New(isolate, HandleLogDelegator));
   6976   v8::Local<Context> context = Context::New(isolate, 0, global_template);
   6977   Context::Scope context_scope(context);
   6978   CompileRun("JSNI_Log('LOG')");
   6979 }
   6980 
   6981 
   6982 static const char* kSimpleExtensionSource =
   6983     "function Foo() {"
   6984     "  return 4;"
   6985     "}";
   6986 
   6987 
   6988 TEST(SimpleExtensions) {
   6989   v8::HandleScope handle_scope(CcTest::isolate());
   6990   v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
   6991   const char* extension_names[] = {"simpletest"};
   6992   v8::ExtensionConfiguration extensions(1, extension_names);
   6993   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   6994   Context::Scope lock(context);
   6995   v8::Local<Value> result = CompileRun("Foo()");
   6996   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
   6997             .FromJust());
   6998 }
   6999 
   7000 
   7001 static const char* kStackTraceFromExtensionSource =
   7002     "function foo() {"
   7003     "  throw new Error();"
   7004     "}"
   7005     "function bar() {"
   7006     "  foo();"
   7007     "}";
   7008 
   7009 
   7010 TEST(StackTraceInExtension) {
   7011   v8::HandleScope handle_scope(CcTest::isolate());
   7012   v8::RegisterExtension(
   7013       new Extension("stacktracetest", kStackTraceFromExtensionSource));
   7014   const char* extension_names[] = {"stacktracetest"};
   7015   v8::ExtensionConfiguration extensions(1, extension_names);
   7016   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7017   Context::Scope lock(context);
   7018   CompileRun(
   7019       "function user() { bar(); }"
   7020       "var error;"
   7021       "try{ user(); } catch (e) { error = e; }");
   7022   CHECK_EQ(-1, v8_run_int32value(v8_compile("error.stack.indexOf('foo')")));
   7023   CHECK_EQ(-1, v8_run_int32value(v8_compile("error.stack.indexOf('bar')")));
   7024   CHECK_NE(-1, v8_run_int32value(v8_compile("error.stack.indexOf('user')")));
   7025 }
   7026 
   7027 
   7028 TEST(NullExtensions) {
   7029   v8::HandleScope handle_scope(CcTest::isolate());
   7030   v8::RegisterExtension(new Extension("nulltest", NULL));
   7031   const char* extension_names[] = {"nulltest"};
   7032   v8::ExtensionConfiguration extensions(1, extension_names);
   7033   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7034   Context::Scope lock(context);
   7035   v8::Local<Value> result = CompileRun("1+3");
   7036   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
   7037             .FromJust());
   7038 }
   7039 
   7040 
   7041 static const char* kEmbeddedExtensionSource =
   7042     "function Ret54321(){return 54321;}~~@@$"
   7043     "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
   7044 static const int kEmbeddedExtensionSourceValidLen = 34;
   7045 
   7046 
   7047 TEST(ExtensionMissingSourceLength) {
   7048   v8::HandleScope handle_scope(CcTest::isolate());
   7049   v8::RegisterExtension(
   7050       new Extension("srclentest_fail", kEmbeddedExtensionSource));
   7051   const char* extension_names[] = {"srclentest_fail"};
   7052   v8::ExtensionConfiguration extensions(1, extension_names);
   7053   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7054   CHECK(0 == *context);
   7055 }
   7056 
   7057 
   7058 TEST(ExtensionWithSourceLength) {
   7059   for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
   7060        source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
   7061     v8::HandleScope handle_scope(CcTest::isolate());
   7062     i::ScopedVector<char> extension_name(32);
   7063     i::SNPrintF(extension_name, "ext #%d", source_len);
   7064     v8::RegisterExtension(new Extension(
   7065         extension_name.start(), kEmbeddedExtensionSource, 0, 0, source_len));
   7066     const char* extension_names[1] = {extension_name.start()};
   7067     v8::ExtensionConfiguration extensions(1, extension_names);
   7068     v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7069     if (source_len == kEmbeddedExtensionSourceValidLen) {
   7070       Context::Scope lock(context);
   7071       v8::Local<Value> result = CompileRun("Ret54321()");
   7072       CHECK(v8::Integer::New(CcTest::isolate(), 54321)
   7073                 ->Equals(context, result)
   7074                 .FromJust());
   7075     } else {
   7076       // Anything but exactly the right length should fail to compile.
   7077       CHECK(0 == *context);
   7078     }
   7079   }
   7080 }
   7081 
   7082 
   7083 static const char* kEvalExtensionSource1 =
   7084     "function UseEval1() {"
   7085     "  var x = 42;"
   7086     "  return eval('x');"
   7087     "}";
   7088 
   7089 
   7090 static const char* kEvalExtensionSource2 =
   7091     "(function() {"
   7092     "  var x = 42;"
   7093     "  function e() {"
   7094     "    return eval('x');"
   7095     "  }"
   7096     "  this.UseEval2 = e;"
   7097     "})()";
   7098 
   7099 
   7100 TEST(UseEvalFromExtension) {
   7101   v8::HandleScope handle_scope(CcTest::isolate());
   7102   v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
   7103   v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
   7104   const char* extension_names[] = {"evaltest1", "evaltest2"};
   7105   v8::ExtensionConfiguration extensions(2, extension_names);
   7106   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7107   Context::Scope lock(context);
   7108   v8::Local<Value> result = CompileRun("UseEval1()");
   7109   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
   7110             .FromJust());
   7111   result = CompileRun("UseEval2()");
   7112   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
   7113             .FromJust());
   7114 }
   7115 
   7116 
   7117 static const char* kWithExtensionSource1 =
   7118     "function UseWith1() {"
   7119     "  var x = 42;"
   7120     "  with({x:87}) { return x; }"
   7121     "}";
   7122 
   7123 
   7124 static const char* kWithExtensionSource2 =
   7125     "(function() {"
   7126     "  var x = 42;"
   7127     "  function e() {"
   7128     "    with ({x:87}) { return x; }"
   7129     "  }"
   7130     "  this.UseWith2 = e;"
   7131     "})()";
   7132 
   7133 
   7134 TEST(UseWithFromExtension) {
   7135   v8::HandleScope handle_scope(CcTest::isolate());
   7136   v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
   7137   v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
   7138   const char* extension_names[] = {"withtest1", "withtest2"};
   7139   v8::ExtensionConfiguration extensions(2, extension_names);
   7140   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7141   Context::Scope lock(context);
   7142   v8::Local<Value> result = CompileRun("UseWith1()");
   7143   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 87))
   7144             .FromJust());
   7145   result = CompileRun("UseWith2()");
   7146   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 87))
   7147             .FromJust());
   7148 }
   7149 
   7150 
   7151 TEST(AutoExtensions) {
   7152   v8::HandleScope handle_scope(CcTest::isolate());
   7153   Extension* extension = new Extension("autotest", kSimpleExtensionSource);
   7154   extension->set_auto_enable(true);
   7155   v8::RegisterExtension(extension);
   7156   v8::Local<Context> context = Context::New(CcTest::isolate());
   7157   Context::Scope lock(context);
   7158   v8::Local<Value> result = CompileRun("Foo()");
   7159   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
   7160             .FromJust());
   7161 }
   7162 
   7163 
   7164 static const char* kSyntaxErrorInExtensionSource = "[";
   7165 
   7166 
   7167 // Test that a syntax error in an extension does not cause a fatal
   7168 // error but results in an empty context.
   7169 TEST(SyntaxErrorExtensions) {
   7170   v8::HandleScope handle_scope(CcTest::isolate());
   7171   v8::RegisterExtension(
   7172       new Extension("syntaxerror", kSyntaxErrorInExtensionSource));
   7173   const char* extension_names[] = {"syntaxerror"};
   7174   v8::ExtensionConfiguration extensions(1, extension_names);
   7175   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7176   CHECK(context.IsEmpty());
   7177 }
   7178 
   7179 
   7180 static const char* kExceptionInExtensionSource = "throw 42";
   7181 
   7182 
   7183 // Test that an exception when installing an extension does not cause
   7184 // a fatal error but results in an empty context.
   7185 TEST(ExceptionExtensions) {
   7186   v8::HandleScope handle_scope(CcTest::isolate());
   7187   v8::RegisterExtension(
   7188       new Extension("exception", kExceptionInExtensionSource));
   7189   const char* extension_names[] = {"exception"};
   7190   v8::ExtensionConfiguration extensions(1, extension_names);
   7191   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7192   CHECK(context.IsEmpty());
   7193 }
   7194 
   7195 
   7196 static const char* kNativeCallInExtensionSource =
   7197     "function call_runtime_last_index_of(x) {"
   7198     "  return %StringLastIndexOf(x, 'bob', 10);"
   7199     "}";
   7200 
   7201 
   7202 static const char* kNativeCallTest =
   7203     "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
   7204 
   7205 // Test that a native runtime calls are supported in extensions.
   7206 TEST(NativeCallInExtensions) {
   7207   v8::HandleScope handle_scope(CcTest::isolate());
   7208   v8::RegisterExtension(
   7209       new Extension("nativecall", kNativeCallInExtensionSource));
   7210   const char* extension_names[] = {"nativecall"};
   7211   v8::ExtensionConfiguration extensions(1, extension_names);
   7212   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7213   Context::Scope lock(context);
   7214   v8::Local<Value> result = CompileRun(kNativeCallTest);
   7215   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 3))
   7216             .FromJust());
   7217 }
   7218 
   7219 
   7220 class NativeFunctionExtension : public Extension {
   7221  public:
   7222   NativeFunctionExtension(const char* name, const char* source,
   7223                           v8::FunctionCallback fun = &Echo)
   7224       : Extension(name, source), function_(fun) {}
   7225 
   7226   virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
   7227       v8::Isolate* isolate, v8::Local<v8::String> name) {
   7228     return v8::FunctionTemplate::New(isolate, function_);
   7229   }
   7230 
   7231   static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
   7232     if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
   7233   }
   7234 
   7235  private:
   7236   v8::FunctionCallback function_;
   7237 };
   7238 
   7239 
   7240 TEST(NativeFunctionDeclaration) {
   7241   v8::HandleScope handle_scope(CcTest::isolate());
   7242   const char* name = "nativedecl";
   7243   v8::RegisterExtension(
   7244       new NativeFunctionExtension(name, "native function foo();"));
   7245   const char* extension_names[] = {name};
   7246   v8::ExtensionConfiguration extensions(1, extension_names);
   7247   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7248   Context::Scope lock(context);
   7249   v8::Local<Value> result = CompileRun("foo(42);");
   7250   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
   7251             .FromJust());
   7252 }
   7253 
   7254 
   7255 TEST(NativeFunctionDeclarationError) {
   7256   v8::HandleScope handle_scope(CcTest::isolate());
   7257   const char* name = "nativedeclerr";
   7258   // Syntax error in extension code.
   7259   v8::RegisterExtension(
   7260       new NativeFunctionExtension(name, "native\nfunction foo();"));
   7261   const char* extension_names[] = {name};
   7262   v8::ExtensionConfiguration extensions(1, extension_names);
   7263   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7264   CHECK(context.IsEmpty());
   7265 }
   7266 
   7267 
   7268 TEST(NativeFunctionDeclarationErrorEscape) {
   7269   v8::HandleScope handle_scope(CcTest::isolate());
   7270   const char* name = "nativedeclerresc";
   7271   // Syntax error in extension code - escape code in "native" means that
   7272   // it's not treated as a keyword.
   7273   v8::RegisterExtension(
   7274       new NativeFunctionExtension(name, "nativ\\u0065 function foo();"));
   7275   const char* extension_names[] = {name};
   7276   v8::ExtensionConfiguration extensions(1, extension_names);
   7277   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
   7278   CHECK(context.IsEmpty());
   7279 }
   7280 
   7281 
   7282 static void CheckDependencies(const char* name, const char* expected) {
   7283   v8::HandleScope handle_scope(CcTest::isolate());
   7284   v8::ExtensionConfiguration config(1, &name);
   7285   LocalContext context(&config);
   7286   CHECK(
   7287       v8_str(expected)
   7288           ->Equals(context.local(), context->Global()
   7289                                         ->Get(context.local(), v8_str("loaded"))
   7290                                         .ToLocalChecked())
   7291           .FromJust());
   7292 }
   7293 
   7294 
   7295 /*
   7296  * Configuration:
   7297  *
   7298  *     /-- B <--\
   7299  * A <-          -- D <-- E
   7300  *     \-- C <--/
   7301  */
   7302 THREADED_TEST(ExtensionDependency) {
   7303   static const char* kEDeps[] = {"D"};
   7304   v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
   7305   static const char* kDDeps[] = {"B", "C"};
   7306   v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
   7307   static const char* kBCDeps[] = {"A"};
   7308   v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
   7309   v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
   7310   v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
   7311   CheckDependencies("A", "undefinedA");
   7312   CheckDependencies("B", "undefinedAB");
   7313   CheckDependencies("C", "undefinedAC");
   7314   CheckDependencies("D", "undefinedABCD");
   7315   CheckDependencies("E", "undefinedABCDE");
   7316   v8::HandleScope handle_scope(CcTest::isolate());
   7317   static const char* exts[2] = {"C", "E"};
   7318   v8::ExtensionConfiguration config(2, exts);
   7319   LocalContext context(&config);
   7320   CHECK(
   7321       v8_str("undefinedACBDE")
   7322           ->Equals(context.local(), context->Global()
   7323                                         ->Get(context.local(), v8_str("loaded"))
   7324                                         .ToLocalChecked())
   7325           .FromJust());
   7326 }
   7327 
   7328 
   7329 static const char* kExtensionTestScript =
   7330     "native function A();"
   7331     "native function B();"
   7332     "native function C();"
   7333     "function Foo(i) {"
   7334     "  if (i == 0) return A();"
   7335     "  if (i == 1) return B();"
   7336     "  if (i == 2) return C();"
   7337     "}";
   7338 
   7339 
   7340 static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
   7341   ApiTestFuzzer::Fuzz();
   7342   if (args.IsConstructCall()) {
   7343     CHECK(args.This()
   7344               ->Set(args.GetIsolate()->GetCurrentContext(), v8_str("data"),
   7345                     args.Data())
   7346               .FromJust());
   7347     args.GetReturnValue().SetNull();
   7348     return;
   7349   }
   7350   args.GetReturnValue().Set(args.Data());
   7351 }
   7352 
   7353 
   7354 class FunctionExtension : public Extension {
   7355  public:
   7356   FunctionExtension() : Extension("functiontest", kExtensionTestScript) {}
   7357   virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
   7358       v8::Isolate* isolate, v8::Local<String> name);
   7359 };
   7360 
   7361 
   7362 static int lookup_count = 0;
   7363 v8::Local<v8::FunctionTemplate> FunctionExtension::GetNativeFunctionTemplate(
   7364     v8::Isolate* isolate, v8::Local<String> name) {
   7365   lookup_count++;
   7366   if (name->Equals(isolate->GetCurrentContext(), v8_str("A")).FromJust()) {
   7367     return v8::FunctionTemplate::New(isolate, CallFun,
   7368                                      v8::Integer::New(isolate, 8));
   7369   } else if (name->Equals(isolate->GetCurrentContext(), v8_str("B"))
   7370                  .FromJust()) {
   7371     return v8::FunctionTemplate::New(isolate, CallFun,
   7372                                      v8::Integer::New(isolate, 7));
   7373   } else if (name->Equals(isolate->GetCurrentContext(), v8_str("C"))
   7374                  .FromJust()) {
   7375     return v8::FunctionTemplate::New(isolate, CallFun,
   7376                                      v8::Integer::New(isolate, 6));
   7377   } else {
   7378     return v8::Local<v8::FunctionTemplate>();
   7379   }
   7380 }
   7381 
   7382 
   7383 THREADED_TEST(FunctionLookup) {
   7384   v8::RegisterExtension(new FunctionExtension());
   7385   v8::HandleScope handle_scope(CcTest::isolate());
   7386   static const char* exts[1] = {"functiontest"};
   7387   v8::ExtensionConfiguration config(1, exts);
   7388   LocalContext context(&config);
   7389   CHECK_EQ(3, lookup_count);
   7390   CHECK(v8::Integer::New(CcTest::isolate(), 8)
   7391             ->Equals(context.local(), CompileRun("Foo(0)"))
   7392             .FromJust());
   7393   CHECK(v8::Integer::New(CcTest::isolate(), 7)
   7394             ->Equals(context.local(), CompileRun("Foo(1)"))
   7395             .FromJust());
   7396   CHECK(v8::Integer::New(CcTest::isolate(), 6)
   7397             ->Equals(context.local(), CompileRun("Foo(2)"))
   7398             .FromJust());
   7399 }
   7400 
   7401 
   7402 THREADED_TEST(NativeFunctionConstructCall) {
   7403   v8::RegisterExtension(new FunctionExtension());
   7404   v8::HandleScope handle_scope(CcTest::isolate());
   7405   static const char* exts[1] = {"functiontest"};
   7406   v8::ExtensionConfiguration config(1, exts);
   7407   LocalContext context(&config);
   7408   for (int i = 0; i < 10; i++) {
   7409     // Run a few times to ensure that allocation of objects doesn't
   7410     // change behavior of a constructor function.
   7411     CHECK(v8::Integer::New(CcTest::isolate(), 8)
   7412               ->Equals(context.local(), CompileRun("(new A()).data"))
   7413               .FromJust());
   7414     CHECK(v8::Integer::New(CcTest::isolate(), 7)
   7415               ->Equals(context.local(), CompileRun("(new B()).data"))
   7416               .FromJust());
   7417     CHECK(v8::Integer::New(CcTest::isolate(), 6)
   7418               ->Equals(context.local(), CompileRun("(new C()).data"))
   7419               .FromJust());
   7420   }
   7421 }
   7422 
   7423 
   7424 static const char* last_location;
   7425 static const char* last_message;
   7426 void StoringErrorCallback(const char* location, const char* message) {
   7427   if (last_location == NULL) {
   7428     last_location = location;
   7429     last_message = message;
   7430   }
   7431 }
   7432 
   7433 
   7434 // ErrorReporting creates a circular extensions configuration and
   7435 // tests that the fatal error handler gets called.  This renders V8
   7436 // unusable and therefore this test cannot be run in parallel.
   7437 TEST(ErrorReporting) {
   7438   CcTest::isolate()->SetFatalErrorHandler(StoringErrorCallback);
   7439   static const char* aDeps[] = {"B"};
   7440   v8::RegisterExtension(new Extension("A", "", 1, aDeps));
   7441   static const char* bDeps[] = {"A"};
   7442   v8::RegisterExtension(new Extension("B", "", 1, bDeps));
   7443   last_location = NULL;
   7444   v8::ExtensionConfiguration config(1, bDeps);
   7445   v8::Local<Context> context = Context::New(CcTest::isolate(), &config);
   7446   CHECK(context.IsEmpty());
   7447   CHECK(last_location);
   7448 }
   7449 
   7450 
   7451 static void MissingScriptInfoMessageListener(v8::Local<v8::Message> message,
   7452                                              v8::Local<Value> data) {
   7453   v8::Isolate* isolate = CcTest::isolate();
   7454   Local<Context> context = isolate->GetCurrentContext();
   7455   CHECK(message->GetScriptOrigin().ResourceName()->IsUndefined());
   7456   CHECK(v8::Undefined(isolate)
   7457             ->Equals(context, message->GetScriptOrigin().ResourceName())
   7458             .FromJust());
   7459   message->GetLineNumber(context).FromJust();
   7460   message->GetSourceLine(context).ToLocalChecked();
   7461 }
   7462 
   7463 
   7464 THREADED_TEST(ErrorWithMissingScriptInfo) {
   7465   LocalContext context;
   7466   v8::HandleScope scope(context->GetIsolate());
   7467   context->GetIsolate()->AddMessageListener(MissingScriptInfoMessageListener);
   7468   CompileRun("throw Error()");
   7469   context->GetIsolate()->RemoveMessageListeners(
   7470       MissingScriptInfoMessageListener);
   7471 }
   7472 
   7473 
   7474 struct FlagAndPersistent {
   7475   bool flag;
   7476   v8::Global<v8::Object> handle;
   7477 };
   7478 
   7479 
   7480 static void SetFlag(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
   7481   data.GetParameter()->flag = true;
   7482   data.GetParameter()->handle.Reset();
   7483 }
   7484 
   7485 
   7486 static void IndependentWeakHandle(bool global_gc, bool interlinked) {
   7487   v8::Isolate* iso = CcTest::isolate();
   7488   v8::HandleScope scope(iso);
   7489   v8::Local<Context> context = Context::New(iso);
   7490   Context::Scope context_scope(context);
   7491 
   7492   FlagAndPersistent object_a, object_b;
   7493 
   7494   intptr_t big_heap_size;
   7495 
   7496   {
   7497     v8::HandleScope handle_scope(iso);
   7498     Local<Object> a(v8::Object::New(iso));
   7499     Local<Object> b(v8::Object::New(iso));
   7500     object_a.handle.Reset(iso, a);
   7501     object_b.handle.Reset(iso, b);
   7502     if (interlinked) {
   7503       a->Set(context, v8_str("x"), b).FromJust();
   7504       b->Set(context, v8_str("x"), a).FromJust();
   7505     }
   7506     if (global_gc) {
   7507       CcTest::heap()->CollectAllGarbage();
   7508     } else {
   7509       CcTest::heap()->CollectGarbage(i::NEW_SPACE);
   7510     }
   7511     // We are relying on this creating a big flag array and reserving the space
   7512     // up front.
   7513     v8::Local<Value> big_array = CompileRun("new Array(5000)");
   7514     a->Set(context, v8_str("y"), big_array).FromJust();
   7515     big_heap_size = CcTest::heap()->SizeOfObjects();
   7516   }
   7517 
   7518   object_a.flag = false;
   7519   object_b.flag = false;
   7520   object_a.handle.SetWeak(&object_a, &SetFlag,
   7521                           v8::WeakCallbackType::kParameter);
   7522   object_b.handle.SetWeak(&object_b, &SetFlag,
   7523                           v8::WeakCallbackType::kParameter);
   7524   CHECK(!object_b.handle.IsIndependent());
   7525   object_a.handle.MarkIndependent();
   7526   object_b.handle.MarkIndependent();
   7527   CHECK(object_b.handle.IsIndependent());
   7528   if (global_gc) {
   7529     CcTest::heap()->CollectAllGarbage();
   7530   } else {
   7531     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
   7532   }
   7533   // A single GC should be enough to reclaim the memory, since we are using
   7534   // phantom handles.
   7535   CHECK_LT(CcTest::heap()->SizeOfObjects(), big_heap_size - 20000);
   7536   CHECK(object_a.flag);
   7537   CHECK(object_b.flag);
   7538 }
   7539 
   7540 
   7541 TEST(IndependentWeakHandle) {
   7542   IndependentWeakHandle(false, false);
   7543   IndependentWeakHandle(false, true);
   7544   IndependentWeakHandle(true, false);
   7545   IndependentWeakHandle(true, true);
   7546 }
   7547 
   7548 
   7549 class Trivial {
   7550  public:
   7551   explicit Trivial(int x) : x_(x) {}
   7552 
   7553   int x() { return x_; }
   7554   void set_x(int x) { x_ = x; }
   7555 
   7556  private:
   7557   int x_;
   7558 };
   7559 
   7560 
   7561 class Trivial2 {
   7562  public:
   7563   Trivial2(int x, int y) : y_(y), x_(x) {}
   7564 
   7565   int x() { return x_; }
   7566   void set_x(int x) { x_ = x; }
   7567 
   7568   int y() { return y_; }
   7569   void set_y(int y) { y_ = y; }
   7570 
   7571  private:
   7572   int y_;
   7573   int x_;
   7574 };
   7575 
   7576 
   7577 void CheckInternalFields(
   7578     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   7579   v8::Persistent<v8::Object>* handle = data.GetParameter();
   7580   handle->Reset();
   7581   Trivial* t1 = reinterpret_cast<Trivial*>(data.GetInternalField(0));
   7582   Trivial2* t2 = reinterpret_cast<Trivial2*>(data.GetInternalField(1));
   7583   CHECK_EQ(42, t1->x());
   7584   CHECK_EQ(103, t2->x());
   7585   t1->set_x(1729);
   7586   t2->set_x(33550336);
   7587 }
   7588 
   7589 
   7590 void InternalFieldCallback(bool global_gc) {
   7591   LocalContext env;
   7592   v8::Isolate* isolate = env->GetIsolate();
   7593   v8::HandleScope scope(isolate);
   7594 
   7595   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   7596   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
   7597   Trivial* t1;
   7598   Trivial2* t2;
   7599   instance_templ->SetInternalFieldCount(2);
   7600   {
   7601     v8::HandleScope scope(isolate);
   7602     Local<v8::Object> obj = templ->GetFunction(env.local())
   7603                                 .ToLocalChecked()
   7604                                 ->NewInstance(env.local())
   7605                                 .ToLocalChecked();
   7606     v8::Persistent<v8::Object> handle(isolate, obj);
   7607     CHECK_EQ(2, obj->InternalFieldCount());
   7608     CHECK(obj->GetInternalField(0)->IsUndefined());
   7609     t1 = new Trivial(42);
   7610     t2 = new Trivial2(103, 9);
   7611 
   7612     obj->SetAlignedPointerInInternalField(0, t1);
   7613     t1 = reinterpret_cast<Trivial*>(obj->GetAlignedPointerFromInternalField(0));
   7614     CHECK_EQ(42, t1->x());
   7615 
   7616     obj->SetAlignedPointerInInternalField(1, t2);
   7617     t2 =
   7618         reinterpret_cast<Trivial2*>(obj->GetAlignedPointerFromInternalField(1));
   7619     CHECK_EQ(103, t2->x());
   7620 
   7621     handle.SetWeak<v8::Persistent<v8::Object>>(
   7622         &handle, CheckInternalFields, v8::WeakCallbackType::kInternalFields);
   7623     if (!global_gc) {
   7624       handle.MarkIndependent();
   7625     }
   7626   }
   7627   if (global_gc) {
   7628     CcTest::heap()->CollectAllGarbage();
   7629   } else {
   7630     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
   7631   }
   7632 
   7633   CHECK_EQ(1729, t1->x());
   7634   CHECK_EQ(33550336, t2->x());
   7635 
   7636   delete t1;
   7637   delete t2;
   7638 }
   7639 
   7640 
   7641 THREADED_TEST(InternalFieldCallback) {
   7642   InternalFieldCallback(false);
   7643   InternalFieldCallback(true);
   7644 }
   7645 
   7646 
   7647 static void ResetUseValueAndSetFlag(
   7648     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
   7649   // Blink will reset the handle, and then use the other handle, so they
   7650   // can't use the same backing slot.
   7651   data.GetParameter()->handle.Reset();
   7652   data.GetParameter()->flag = true;
   7653 }
   7654 
   7655 
   7656 void v8::internal::HeapTester::ResetWeakHandle(bool global_gc) {
   7657   using v8::Context;
   7658   using v8::Local;
   7659   using v8::Object;
   7660 
   7661   v8::Isolate* iso = CcTest::isolate();
   7662   v8::HandleScope scope(iso);
   7663   v8::Local<Context> context = Context::New(iso);
   7664   Context::Scope context_scope(context);
   7665 
   7666   FlagAndPersistent object_a, object_b;
   7667 
   7668   {
   7669     v8::HandleScope handle_scope(iso);
   7670     Local<Object> a(v8::Object::New(iso));
   7671     Local<Object> b(v8::Object::New(iso));
   7672     object_a.handle.Reset(iso, a);
   7673     object_b.handle.Reset(iso, b);
   7674     if (global_gc) {
   7675       CcTest::heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
   7676     } else {
   7677       CcTest::heap()->CollectGarbage(i::NEW_SPACE);
   7678     }
   7679   }
   7680 
   7681   object_a.flag = false;
   7682   object_b.flag = false;
   7683   object_a.handle.SetWeak(&object_a, &ResetUseValueAndSetFlag,
   7684                           v8::WeakCallbackType::kParameter);
   7685   object_b.handle.SetWeak(&object_b, &ResetUseValueAndSetFlag,
   7686                           v8::WeakCallbackType::kParameter);
   7687   if (!global_gc) {
   7688     object_a.handle.MarkIndependent();
   7689     object_b.handle.MarkIndependent();
   7690     CHECK(object_b.handle.IsIndependent());
   7691   }
   7692   if (global_gc) {
   7693     CcTest::heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
   7694   } else {
   7695     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
   7696   }
   7697   CHECK(object_a.flag);
   7698   CHECK(object_b.flag);
   7699 }
   7700 
   7701 
   7702 THREADED_HEAP_TEST(ResetWeakHandle) {
   7703   v8::internal::HeapTester::ResetWeakHandle(false);
   7704   v8::internal::HeapTester::ResetWeakHandle(true);
   7705 }
   7706 
   7707 
   7708 static void InvokeScavenge() { CcTest::heap()->CollectGarbage(i::NEW_SPACE); }
   7709 
   7710 
   7711 static void InvokeMarkSweep() { CcTest::heap()->CollectAllGarbage(); }
   7712 
   7713 
   7714 static void ForceScavenge2(
   7715     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
   7716   data.GetParameter()->flag = true;
   7717   InvokeScavenge();
   7718 }
   7719 
   7720 static void ForceScavenge1(
   7721     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
   7722   data.GetParameter()->handle.Reset();
   7723   data.SetSecondPassCallback(ForceScavenge2);
   7724 }
   7725 
   7726 
   7727 static void ForceMarkSweep2(
   7728     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
   7729   data.GetParameter()->flag = true;
   7730   InvokeMarkSweep();
   7731 }
   7732 
   7733 static void ForceMarkSweep1(
   7734     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
   7735   data.GetParameter()->handle.Reset();
   7736   data.SetSecondPassCallback(ForceMarkSweep2);
   7737 }
   7738 
   7739 
   7740 THREADED_TEST(GCFromWeakCallbacks) {
   7741   v8::Isolate* isolate = CcTest::isolate();
   7742   v8::Locker locker(CcTest::isolate());
   7743   v8::HandleScope scope(isolate);
   7744   v8::Local<Context> context = Context::New(isolate);
   7745   Context::Scope context_scope(context);
   7746 
   7747   static const int kNumberOfGCTypes = 2;
   7748   typedef v8::WeakCallbackInfo<FlagAndPersistent>::Callback Callback;
   7749   Callback gc_forcing_callback[kNumberOfGCTypes] = {&ForceScavenge1,
   7750                                                     &ForceMarkSweep1};
   7751 
   7752   typedef void (*GCInvoker)();
   7753   GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
   7754 
   7755   for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
   7756     for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
   7757       FlagAndPersistent object;
   7758       {
   7759         v8::HandleScope handle_scope(isolate);
   7760         object.handle.Reset(isolate, v8::Object::New(isolate));
   7761       }
   7762       object.flag = false;
   7763       object.handle.SetWeak(&object, gc_forcing_callback[inner_gc],
   7764                             v8::WeakCallbackType::kParameter);
   7765       object.handle.MarkIndependent();
   7766       invoke_gc[outer_gc]();
   7767       EmptyMessageQueues(isolate);
   7768       CHECK(object.flag);
   7769     }
   7770   }
   7771 }
   7772 
   7773 
   7774 v8::Local<Function> args_fun;
   7775 
   7776 
   7777 static void ArgumentsTestCallback(
   7778     const v8::FunctionCallbackInfo<v8::Value>& args) {
   7779   ApiTestFuzzer::Fuzz();
   7780   v8::Isolate* isolate = args.GetIsolate();
   7781   Local<Context> context = isolate->GetCurrentContext();
   7782   CHECK(args_fun->Equals(context, args.Callee()).FromJust());
   7783   CHECK_EQ(3, args.Length());
   7784   CHECK(v8::Integer::New(isolate, 1)->Equals(context, args[0]).FromJust());
   7785   CHECK(v8::Integer::New(isolate, 2)->Equals(context, args[1]).FromJust());
   7786   CHECK(v8::Integer::New(isolate, 3)->Equals(context, args[2]).FromJust());
   7787   CHECK(v8::Undefined(isolate)->Equals(context, args[3]).FromJust());
   7788   v8::HandleScope scope(args.GetIsolate());
   7789   CcTest::heap()->CollectAllGarbage();
   7790 }
   7791 
   7792 
   7793 THREADED_TEST(Arguments) {
   7794   v8::Isolate* isolate = CcTest::isolate();
   7795   v8::HandleScope scope(isolate);
   7796   v8::Local<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
   7797   global->Set(v8_str("f"),
   7798               v8::FunctionTemplate::New(isolate, ArgumentsTestCallback));
   7799   LocalContext context(NULL, global);
   7800   args_fun = context->Global()
   7801                  ->Get(context.local(), v8_str("f"))
   7802                  .ToLocalChecked()
   7803                  .As<Function>();
   7804   v8_compile("f(1, 2, 3)")->Run(context.local()).ToLocalChecked();
   7805 }
   7806 
   7807 
   7808 static int p_getter_count;
   7809 static int p_getter_count2;
   7810 
   7811 
   7812 static void PGetter(Local<Name> name,
   7813                     const v8::PropertyCallbackInfo<v8::Value>& info) {
   7814   ApiTestFuzzer::Fuzz();
   7815   p_getter_count++;
   7816   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
   7817   v8::Local<v8::Object> global = context->Global();
   7818   CHECK(
   7819       info.Holder()
   7820           ->Equals(context, global->Get(context, v8_str("o1")).ToLocalChecked())
   7821           .FromJust());
   7822   if (name->Equals(context, v8_str("p1")).FromJust()) {
   7823     CHECK(info.This()
   7824               ->Equals(context,
   7825                        global->Get(context, v8_str("o1")).ToLocalChecked())
   7826               .FromJust());
   7827   } else if (name->Equals(context, v8_str("p2")).FromJust()) {
   7828     CHECK(info.This()
   7829               ->Equals(context,
   7830                        global->Get(context, v8_str("o2")).ToLocalChecked())
   7831               .FromJust());
   7832   } else if (name->Equals(context, v8_str("p3")).FromJust()) {
   7833     CHECK(info.This()
   7834               ->Equals(context,
   7835                        global->Get(context, v8_str("o3")).ToLocalChecked())
   7836               .FromJust());
   7837   } else if (name->Equals(context, v8_str("p4")).FromJust()) {
   7838     CHECK(info.This()
   7839               ->Equals(context,
   7840                        global->Get(context, v8_str("o4")).ToLocalChecked())
   7841               .FromJust());
   7842   }
   7843 }
   7844 
   7845 
   7846 static void RunHolderTest(v8::Local<v8::ObjectTemplate> obj) {
   7847   ApiTestFuzzer::Fuzz();
   7848   LocalContext context;
   7849   CHECK(context->Global()
   7850             ->Set(context.local(), v8_str("o1"),
   7851                   obj->NewInstance(context.local()).ToLocalChecked())
   7852             .FromJust());
   7853   CompileRun(
   7854     "o1.__proto__ = { };"
   7855     "var o2 = { __proto__: o1 };"
   7856     "var o3 = { __proto__: o2 };"
   7857     "var o4 = { __proto__: o3 };"
   7858     "for (var i = 0; i < 10; i++) o4.p4;"
   7859     "for (var i = 0; i < 10; i++) o3.p3;"
   7860     "for (var i = 0; i < 10; i++) o2.p2;"
   7861     "for (var i = 0; i < 10; i++) o1.p1;");
   7862 }
   7863 
   7864 
   7865 static void PGetter2(Local<Name> name,
   7866                      const v8::PropertyCallbackInfo<v8::Value>& info) {
   7867   ApiTestFuzzer::Fuzz();
   7868   p_getter_count2++;
   7869   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
   7870   v8::Local<v8::Object> global = context->Global();
   7871   CHECK(
   7872       info.Holder()
   7873           ->Equals(context, global->Get(context, v8_str("o1")).ToLocalChecked())
   7874           .FromJust());
   7875   if (name->Equals(context, v8_str("p1")).FromJust()) {
   7876     CHECK(info.This()
   7877               ->Equals(context,
   7878                        global->Get(context, v8_str("o1")).ToLocalChecked())
   7879               .FromJust());
   7880   } else if (name->Equals(context, v8_str("p2")).FromJust()) {
   7881     CHECK(info.This()
   7882               ->Equals(context,
   7883                        global->Get(context, v8_str("o2")).ToLocalChecked())
   7884               .FromJust());
   7885   } else if (name->Equals(context, v8_str("p3")).FromJust()) {
   7886     CHECK(info.This()
   7887               ->Equals(context,
   7888                        global->Get(context, v8_str("o3")).ToLocalChecked())
   7889               .FromJust());
   7890   } else if (name->Equals(context, v8_str("p4")).FromJust()) {
   7891     CHECK(info.This()
   7892               ->Equals(context,
   7893                        global->Get(context, v8_str("o4")).ToLocalChecked())
   7894               .FromJust());
   7895   }
   7896 }
   7897 
   7898 
   7899 THREADED_TEST(GetterHolders) {
   7900   v8::Isolate* isolate = CcTest::isolate();
   7901   v8::HandleScope scope(isolate);
   7902   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
   7903   obj->SetAccessor(v8_str("p1"), PGetter);
   7904   obj->SetAccessor(v8_str("p2"), PGetter);
   7905   obj->SetAccessor(v8_str("p3"), PGetter);
   7906   obj->SetAccessor(v8_str("p4"), PGetter);
   7907   p_getter_count = 0;
   7908   RunHolderTest(obj);
   7909   CHECK_EQ(40, p_getter_count);
   7910 }
   7911 
   7912 
   7913 THREADED_TEST(PreInterceptorHolders) {
   7914   v8::Isolate* isolate = CcTest::isolate();
   7915   v8::HandleScope scope(isolate);
   7916   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
   7917   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(PGetter2));
   7918   p_getter_count2 = 0;
   7919   RunHolderTest(obj);
   7920   CHECK_EQ(40, p_getter_count2);
   7921 }
   7922 
   7923 
   7924 THREADED_TEST(ObjectInstantiation) {
   7925   v8::Isolate* isolate = CcTest::isolate();
   7926   v8::HandleScope scope(isolate);
   7927   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
   7928   templ->SetAccessor(v8_str("t"), PGetter2);
   7929   LocalContext context;
   7930   CHECK(context->Global()
   7931             ->Set(context.local(), v8_str("o"),
   7932                   templ->NewInstance(context.local()).ToLocalChecked())
   7933             .FromJust());
   7934   for (int i = 0; i < 100; i++) {
   7935     v8::HandleScope inner_scope(CcTest::isolate());
   7936     v8::Local<v8::Object> obj =
   7937         templ->NewInstance(context.local()).ToLocalChecked();
   7938     CHECK(!obj->Equals(context.local(), context->Global()
   7939                                             ->Get(context.local(), v8_str("o"))
   7940                                             .ToLocalChecked())
   7941                .FromJust());
   7942     CHECK(
   7943         context->Global()->Set(context.local(), v8_str("o2"), obj).FromJust());
   7944     v8::Local<Value> value = CompileRun("o.__proto__ === o2.__proto__");
   7945     CHECK(v8::True(isolate)->Equals(context.local(), value).FromJust());
   7946     CHECK(context->Global()->Set(context.local(), v8_str("o"), obj).FromJust());
   7947   }
   7948 }
   7949 
   7950 
   7951 static int StrCmp16(uint16_t* a, uint16_t* b) {
   7952   while (true) {
   7953     if (*a == 0 && *b == 0) return 0;
   7954     if (*a != *b) return 0 + *a - *b;
   7955     a++;
   7956     b++;
   7957   }
   7958 }
   7959 
   7960 
   7961 static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
   7962   while (true) {
   7963     if (n-- == 0) return 0;
   7964     if (*a == 0 && *b == 0) return 0;
   7965     if (*a != *b) return 0 + *a - *b;
   7966     a++;
   7967     b++;
   7968   }
   7969 }
   7970 
   7971 
   7972 int GetUtf8Length(Local<String> str) {
   7973   int len = str->Utf8Length();
   7974   if (len < 0) {
   7975     i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
   7976     i::String::Flatten(istr);
   7977     len = str->Utf8Length();
   7978   }
   7979   return len;
   7980 }
   7981 
   7982 
   7983 THREADED_TEST(StringWrite) {
   7984   LocalContext context;
   7985   v8::HandleScope scope(context->GetIsolate());
   7986   v8::Local<String> str = v8_str("abcde");
   7987   // abc<Icelandic eth><Unicode snowman>.
   7988   v8::Local<String> str2 = v8_str("abc\303\260\342\230\203");
   7989   v8::Local<String> str3 =
   7990       v8::String::NewFromUtf8(context->GetIsolate(), "abc\0def",
   7991                               v8::NewStringType::kNormal, 7)
   7992           .ToLocalChecked();
   7993   // "ab" + lead surrogate + "cd" + trail surrogate + "ef"
   7994   uint16_t orphans[8] = { 0x61, 0x62, 0xd800, 0x63, 0x64, 0xdc00, 0x65, 0x66 };
   7995   v8::Local<String> orphans_str =
   7996       v8::String::NewFromTwoByte(context->GetIsolate(), orphans,
   7997                                  v8::NewStringType::kNormal, 8)
   7998           .ToLocalChecked();
   7999   // single lead surrogate
   8000   uint16_t lead[1] = { 0xd800 };
   8001   v8::Local<String> lead_str =
   8002       v8::String::NewFromTwoByte(context->GetIsolate(), lead,
   8003                                  v8::NewStringType::kNormal, 1)
   8004           .ToLocalChecked();
   8005   // single trail surrogate
   8006   uint16_t trail[1] = { 0xdc00 };
   8007   v8::Local<String> trail_str =
   8008       v8::String::NewFromTwoByte(context->GetIsolate(), trail,
   8009                                  v8::NewStringType::kNormal, 1)
   8010           .ToLocalChecked();
   8011   // surrogate pair
   8012   uint16_t pair[2] = { 0xd800,  0xdc00 };
   8013   v8::Local<String> pair_str =
   8014       v8::String::NewFromTwoByte(context->GetIsolate(), pair,
   8015                                  v8::NewStringType::kNormal, 2)
   8016           .ToLocalChecked();
   8017   const int kStride = 4;  // Must match stride in for loops in JS below.
   8018   CompileRun(
   8019       "var left = '';"
   8020       "for (var i = 0; i < 0xd800; i += 4) {"
   8021       "  left = left + String.fromCharCode(i);"
   8022       "}");
   8023   CompileRun(
   8024       "var right = '';"
   8025       "for (var i = 0; i < 0xd800; i += 4) {"
   8026       "  right = String.fromCharCode(i) + right;"
   8027       "}");
   8028   v8::Local<v8::Object> global = context->Global();
   8029   Local<String> left_tree = global->Get(context.local(), v8_str("left"))
   8030                                 .ToLocalChecked()
   8031                                 .As<String>();
   8032   Local<String> right_tree = global->Get(context.local(), v8_str("right"))
   8033                                  .ToLocalChecked()
   8034                                  .As<String>();
   8035 
   8036   CHECK_EQ(5, str2->Length());
   8037   CHECK_EQ(0xd800 / kStride, left_tree->Length());
   8038   CHECK_EQ(0xd800 / kStride, right_tree->Length());
   8039 
   8040   char buf[100];
   8041   char utf8buf[0xd800 * 3];
   8042   uint16_t wbuf[100];
   8043   int len;
   8044   int charlen;
   8045 
   8046   memset(utf8buf, 0x1, 1000);
   8047   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
   8048   CHECK_EQ(9, len);
   8049   CHECK_EQ(5, charlen);
   8050   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
   8051 
   8052   memset(utf8buf, 0x1, 1000);
   8053   len = str2->WriteUtf8(utf8buf, 8, &charlen);
   8054   CHECK_EQ(8, len);
   8055   CHECK_EQ(5, charlen);
   8056   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
   8057 
   8058   memset(utf8buf, 0x1, 1000);
   8059   len = str2->WriteUtf8(utf8buf, 7, &charlen);
   8060   CHECK_EQ(5, len);
   8061   CHECK_EQ(4, charlen);
   8062   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
   8063 
   8064   memset(utf8buf, 0x1, 1000);
   8065   len = str2->WriteUtf8(utf8buf, 6, &charlen);
   8066   CHECK_EQ(5, len);
   8067   CHECK_EQ(4, charlen);
   8068   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
   8069 
   8070   memset(utf8buf, 0x1, 1000);
   8071   len = str2->WriteUtf8(utf8buf, 5, &charlen);
   8072   CHECK_EQ(5, len);
   8073   CHECK_EQ(4, charlen);
   8074   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
   8075 
   8076   memset(utf8buf, 0x1, 1000);
   8077   len = str2->WriteUtf8(utf8buf, 4, &charlen);
   8078   CHECK_EQ(3, len);
   8079   CHECK_EQ(3, charlen);
   8080   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
   8081 
   8082   memset(utf8buf, 0x1, 1000);
   8083   len = str2->WriteUtf8(utf8buf, 3, &charlen);
   8084   CHECK_EQ(3, len);
   8085   CHECK_EQ(3, charlen);
   8086   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
   8087 
   8088   memset(utf8buf, 0x1, 1000);
   8089   len = str2->WriteUtf8(utf8buf, 2, &charlen);
   8090   CHECK_EQ(2, len);
   8091   CHECK_EQ(2, charlen);
   8092   CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
   8093 
   8094   // allow orphan surrogates by default
   8095   memset(utf8buf, 0x1, 1000);
   8096   len = orphans_str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
   8097   CHECK_EQ(13, len);
   8098   CHECK_EQ(8, charlen);
   8099   CHECK_EQ(0, strcmp(utf8buf, "ab\355\240\200cd\355\260\200ef"));
   8100 
   8101   // replace orphan surrogates with unicode replacement character
   8102   memset(utf8buf, 0x1, 1000);
   8103   len = orphans_str->WriteUtf8(utf8buf,
   8104                                sizeof(utf8buf),
   8105                                &charlen,
   8106                                String::REPLACE_INVALID_UTF8);
   8107   CHECK_EQ(13, len);
   8108   CHECK_EQ(8, charlen);
   8109   CHECK_EQ(0, strcmp(utf8buf, "ab\357\277\275cd\357\277\275ef"));
   8110 
   8111   // replace single lead surrogate with unicode replacement character
   8112   memset(utf8buf, 0x1, 1000);
   8113   len = lead_str->WriteUtf8(utf8buf,
   8114                             sizeof(utf8buf),
   8115                             &charlen,
   8116                             String::REPLACE_INVALID_UTF8);
   8117   CHECK_EQ(4, len);
   8118   CHECK_EQ(1, charlen);
   8119   CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
   8120 
   8121   // replace single trail surrogate with unicode replacement character
   8122   memset(utf8buf, 0x1, 1000);
   8123   len = trail_str->WriteUtf8(utf8buf,
   8124                              sizeof(utf8buf),
   8125                              &charlen,
   8126                              String::REPLACE_INVALID_UTF8);
   8127   CHECK_EQ(4, len);
   8128   CHECK_EQ(1, charlen);
   8129   CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
   8130 
   8131   // do not replace / write anything if surrogate pair does not fit the buffer
   8132   // space
   8133   memset(utf8buf, 0x1, 1000);
   8134   len = pair_str->WriteUtf8(utf8buf,
   8135                              3,
   8136                              &charlen,
   8137                              String::REPLACE_INVALID_UTF8);
   8138   CHECK_EQ(0, len);
   8139   CHECK_EQ(0, charlen);
   8140 
   8141   memset(utf8buf, 0x1, sizeof(utf8buf));
   8142   len = GetUtf8Length(left_tree);
   8143   int utf8_expected =
   8144       (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
   8145   CHECK_EQ(utf8_expected, len);
   8146   len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
   8147   CHECK_EQ(utf8_expected, len);
   8148   CHECK_EQ(0xd800 / kStride, charlen);
   8149   CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
   8150   CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
   8151   CHECK_EQ(0xc0 - kStride,
   8152            static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
   8153   CHECK_EQ(1, utf8buf[utf8_expected]);
   8154 
   8155   memset(utf8buf, 0x1, sizeof(utf8buf));
   8156   len = GetUtf8Length(right_tree);
   8157   CHECK_EQ(utf8_expected, len);
   8158   len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
   8159   CHECK_EQ(utf8_expected, len);
   8160   CHECK_EQ(0xd800 / kStride, charlen);
   8161   CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
   8162   CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
   8163   CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
   8164   CHECK_EQ(1, utf8buf[utf8_expected]);
   8165 
   8166   memset(buf, 0x1, sizeof(buf));
   8167   memset(wbuf, 0x1, sizeof(wbuf));
   8168   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
   8169   CHECK_EQ(5, len);
   8170   len = str->Write(wbuf);
   8171   CHECK_EQ(5, len);
   8172   CHECK_EQ(0, strcmp("abcde", buf));
   8173   uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
   8174   CHECK_EQ(0, StrCmp16(answer1, wbuf));
   8175 
   8176   memset(buf, 0x1, sizeof(buf));
   8177   memset(wbuf, 0x1, sizeof(wbuf));
   8178   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 4);
   8179   CHECK_EQ(4, len);
   8180   len = str->Write(wbuf, 0, 4);
   8181   CHECK_EQ(4, len);
   8182   CHECK_EQ(0, strncmp("abcd\1", buf, 5));
   8183   uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
   8184   CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
   8185 
   8186   memset(buf, 0x1, sizeof(buf));
   8187   memset(wbuf, 0x1, sizeof(wbuf));
   8188   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 5);
   8189   CHECK_EQ(5, len);
   8190   len = str->Write(wbuf, 0, 5);
   8191   CHECK_EQ(5, len);
   8192   CHECK_EQ(0, strncmp("abcde\1", buf, 6));
   8193   uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
   8194   CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
   8195 
   8196   memset(buf, 0x1, sizeof(buf));
   8197   memset(wbuf, 0x1, sizeof(wbuf));
   8198   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 6);
   8199   CHECK_EQ(5, len);
   8200   len = str->Write(wbuf, 0, 6);
   8201   CHECK_EQ(5, len);
   8202   CHECK_EQ(0, strcmp("abcde", buf));
   8203   uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
   8204   CHECK_EQ(0, StrCmp16(answer4, wbuf));
   8205 
   8206   memset(buf, 0x1, sizeof(buf));
   8207   memset(wbuf, 0x1, sizeof(wbuf));
   8208   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, -1);
   8209   CHECK_EQ(1, len);
   8210   len = str->Write(wbuf, 4, -1);
   8211   CHECK_EQ(1, len);
   8212   CHECK_EQ(0, strcmp("e", buf));
   8213   uint16_t answer5[] = {'e', '\0'};
   8214   CHECK_EQ(0, StrCmp16(answer5, wbuf));
   8215 
   8216   memset(buf, 0x1, sizeof(buf));
   8217   memset(wbuf, 0x1, sizeof(wbuf));
   8218   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 6);
   8219   CHECK_EQ(1, len);
   8220   len = str->Write(wbuf, 4, 6);
   8221   CHECK_EQ(1, len);
   8222   CHECK_EQ(0, strcmp("e", buf));
   8223   CHECK_EQ(0, StrCmp16(answer5, wbuf));
   8224 
   8225   memset(buf, 0x1, sizeof(buf));
   8226   memset(wbuf, 0x1, sizeof(wbuf));
   8227   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 1);
   8228   CHECK_EQ(1, len);
   8229   len = str->Write(wbuf, 4, 1);
   8230   CHECK_EQ(1, len);
   8231   CHECK_EQ(0, strncmp("e\1", buf, 2));
   8232   uint16_t answer6[] = {'e', 0x101};
   8233   CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
   8234 
   8235   memset(buf, 0x1, sizeof(buf));
   8236   memset(wbuf, 0x1, sizeof(wbuf));
   8237   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 3, 1);
   8238   CHECK_EQ(1, len);
   8239   len = str->Write(wbuf, 3, 1);
   8240   CHECK_EQ(1, len);
   8241   CHECK_EQ(0, strncmp("d\1", buf, 2));
   8242   uint16_t answer7[] = {'d', 0x101};
   8243   CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
   8244 
   8245   memset(wbuf, 0x1, sizeof(wbuf));
   8246   wbuf[5] = 'X';
   8247   len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
   8248   CHECK_EQ(5, len);
   8249   CHECK_EQ('X', wbuf[5]);
   8250   uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
   8251   uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
   8252   CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
   8253   CHECK_NE(0, StrCmp16(answer8b, wbuf));
   8254   wbuf[5] = '\0';
   8255   CHECK_EQ(0, StrCmp16(answer8b, wbuf));
   8256 
   8257   memset(buf, 0x1, sizeof(buf));
   8258   buf[5] = 'X';
   8259   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
   8260                           0,
   8261                           6,
   8262                           String::NO_NULL_TERMINATION);
   8263   CHECK_EQ(5, len);
   8264   CHECK_EQ('X', buf[5]);
   8265   CHECK_EQ(0, strncmp("abcde", buf, 5));
   8266   CHECK_NE(0, strcmp("abcde", buf));
   8267   buf[5] = '\0';
   8268   CHECK_EQ(0, strcmp("abcde", buf));
   8269 
   8270   memset(utf8buf, 0x1, sizeof(utf8buf));
   8271   utf8buf[8] = 'X';
   8272   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
   8273                         String::NO_NULL_TERMINATION);
   8274   CHECK_EQ(8, len);
   8275   CHECK_EQ('X', utf8buf[8]);
   8276   CHECK_EQ(5, charlen);
   8277   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
   8278   CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
   8279   utf8buf[8] = '\0';
   8280   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
   8281 
   8282   memset(utf8buf, 0x1, sizeof(utf8buf));
   8283   utf8buf[5] = 'X';
   8284   len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
   8285                         String::NO_NULL_TERMINATION);
   8286   CHECK_EQ(5, len);
   8287   CHECK_EQ('X', utf8buf[5]);  // Test that the sixth character is untouched.
   8288   CHECK_EQ(5, charlen);
   8289   utf8buf[5] = '\0';
   8290   CHECK_EQ(0, strcmp(utf8buf, "abcde"));
   8291 
   8292   memset(buf, 0x1, sizeof(buf));
   8293   len = str3->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
   8294   CHECK_EQ(7, len);
   8295   CHECK_EQ(0, strcmp("abc", buf));
   8296   CHECK_EQ(0, buf[3]);
   8297   CHECK_EQ(0, strcmp("def", buf + 4));
   8298 
   8299   CHECK_EQ(0, str->WriteOneByte(NULL, 0, 0, String::NO_NULL_TERMINATION));
   8300   CHECK_EQ(0, str->WriteUtf8(NULL, 0, 0, String::NO_NULL_TERMINATION));
   8301   CHECK_EQ(0, str->Write(NULL, 0, 0, String::NO_NULL_TERMINATION));
   8302 }
   8303 
   8304 
   8305 static void Utf16Helper(
   8306     LocalContext& context,  // NOLINT
   8307     const char* name,
   8308     const char* lengths_name,
   8309     int len) {
   8310   Local<v8::Array> a = Local<v8::Array>::Cast(
   8311       context->Global()->Get(context.local(), v8_str(name)).ToLocalChecked());
   8312   Local<v8::Array> alens =
   8313       Local<v8::Array>::Cast(context->Global()
   8314                                  ->Get(context.local(), v8_str(lengths_name))
   8315                                  .ToLocalChecked());
   8316   for (int i = 0; i < len; i++) {
   8317     Local<v8::String> string =
   8318         Local<v8::String>::Cast(a->Get(context.local(), i).ToLocalChecked());
   8319     Local<v8::Number> expected_len = Local<v8::Number>::Cast(
   8320         alens->Get(context.local(), i).ToLocalChecked());
   8321     int length = GetUtf8Length(string);
   8322     CHECK_EQ(static_cast<int>(expected_len->Value()), length);
   8323   }
   8324 }
   8325 
   8326 
   8327 THREADED_TEST(Utf16) {
   8328   LocalContext context;
   8329   v8::HandleScope scope(context->GetIsolate());
   8330   CompileRun(
   8331       "var pad = '01234567890123456789';"
   8332       "var p = [];"
   8333       "var plens = [20, 3, 3];"
   8334       "p.push('01234567890123456789');"
   8335       "var lead = 0xd800;"
   8336       "var trail = 0xdc00;"
   8337       "p.push(String.fromCharCode(0xd800));"
   8338       "p.push(String.fromCharCode(0xdc00));"
   8339       "var a = [];"
   8340       "var b = [];"
   8341       "var c = [];"
   8342       "var alens = [];"
   8343       "for (var i = 0; i < 3; i++) {"
   8344       "  p[1] = String.fromCharCode(lead++);"
   8345       "  for (var j = 0; j < 3; j++) {"
   8346       "    p[2] = String.fromCharCode(trail++);"
   8347       "    a.push(p[i] + p[j]);"
   8348       "    b.push(p[i] + p[j]);"
   8349       "    c.push(p[i] + p[j]);"
   8350       "    alens.push(plens[i] + plens[j]);"
   8351       "  }"
   8352       "}"
   8353       "alens[5] -= 2;"  // Here the surrogate pairs match up.
   8354       "var a2 = [];"
   8355       "var b2 = [];"
   8356       "var c2 = [];"
   8357       "var a2lens = [];"
   8358       "for (var m = 0; m < 9; m++) {"
   8359       "  for (var n = 0; n < 9; n++) {"
   8360       "    a2.push(a[m] + a[n]);"
   8361       "    b2.push(b[m] + b[n]);"
   8362       "    var newc = 'x' + c[m] + c[n] + 'y';"
   8363       "    c2.push(newc.substring(1, newc.length - 1));"
   8364       "    var utf = alens[m] + alens[n];"  // And here.
   8365            // The 'n's that start with 0xdc.. are 6-8
   8366            // The 'm's that end with 0xd8.. are 1, 4 and 7
   8367       "    if ((m % 3) == 1 && n >= 6) utf -= 2;"
   8368       "    a2lens.push(utf);"
   8369       "  }"
   8370       "}");
   8371   Utf16Helper(context, "a", "alens", 9);
   8372   Utf16Helper(context, "a2", "a2lens", 81);
   8373 }
   8374 
   8375 
   8376 static bool SameSymbol(Local<String> s1, Local<String> s2) {
   8377   i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
   8378   i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
   8379   return *is1 == *is2;
   8380 }
   8381 
   8382 
   8383 THREADED_TEST(Utf16Symbol) {
   8384   LocalContext context;
   8385   v8::HandleScope scope(context->GetIsolate());
   8386 
   8387   Local<String> symbol1 =
   8388       v8::String::NewFromUtf8(context->GetIsolate(), "abc",
   8389                               v8::NewStringType::kInternalized)
   8390           .ToLocalChecked();
   8391   Local<String> symbol2 =
   8392       v8::String::NewFromUtf8(context->GetIsolate(), "abc",
   8393                               v8::NewStringType::kInternalized)
   8394           .ToLocalChecked();
   8395   CHECK(SameSymbol(symbol1, symbol2));
   8396 
   8397   CompileRun(
   8398       "var sym0 = 'benedictus';"
   8399       "var sym0b = 'S\303\270ren';"
   8400       "var sym1 = '\355\240\201\355\260\207';"
   8401       "var sym2 = '\360\220\220\210';"
   8402       "var sym3 = 'x\355\240\201\355\260\207';"
   8403       "var sym4 = 'x\360\220\220\210';"
   8404       "if (sym1.length != 2) throw sym1;"
   8405       "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
   8406       "if (sym2.length != 2) throw sym2;"
   8407       "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
   8408       "if (sym3.length != 3) throw sym3;"
   8409       "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
   8410       "if (sym4.length != 3) throw sym4;"
   8411       "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
   8412   Local<String> sym0 =
   8413       v8::String::NewFromUtf8(context->GetIsolate(), "benedictus",
   8414                               v8::NewStringType::kInternalized)
   8415           .ToLocalChecked();
   8416   Local<String> sym0b =
   8417       v8::String::NewFromUtf8(context->GetIsolate(), "S\303\270ren",
   8418                               v8::NewStringType::kInternalized)
   8419           .ToLocalChecked();
   8420   Local<String> sym1 =
   8421       v8::String::NewFromUtf8(context->GetIsolate(), "\355\240\201\355\260\207",
   8422                               v8::NewStringType::kInternalized)
   8423           .ToLocalChecked();
   8424   Local<String> sym2 =
   8425       v8::String::NewFromUtf8(context->GetIsolate(), "\360\220\220\210",
   8426                               v8::NewStringType::kInternalized)
   8427           .ToLocalChecked();
   8428   Local<String> sym3 = v8::String::NewFromUtf8(context->GetIsolate(),
   8429                                                "x\355\240\201\355\260\207",
   8430                                                v8::NewStringType::kInternalized)
   8431                            .ToLocalChecked();
   8432   Local<String> sym4 =
   8433       v8::String::NewFromUtf8(context->GetIsolate(), "x\360\220\220\210",
   8434                               v8::NewStringType::kInternalized)
   8435           .ToLocalChecked();
   8436   v8::Local<v8::Object> global = context->Global();
   8437   Local<Value> s0 =
   8438       global->Get(context.local(), v8_str("sym0")).ToLocalChecked();
   8439   Local<Value> s0b =
   8440       global->Get(context.local(), v8_str("sym0b")).ToLocalChecked();
   8441   Local<Value> s1 =
   8442       global->Get(context.local(), v8_str("sym1")).ToLocalChecked();
   8443   Local<Value> s2 =
   8444       global->Get(context.local(), v8_str("sym2")).ToLocalChecked();
   8445   Local<Value> s3 =
   8446       global->Get(context.local(), v8_str("sym3")).ToLocalChecked();
   8447   Local<Value> s4 =
   8448       global->Get(context.local(), v8_str("sym4")).ToLocalChecked();
   8449   CHECK(SameSymbol(sym0, Local<String>::Cast(s0)));
   8450   CHECK(SameSymbol(sym0b, Local<String>::Cast(s0b)));
   8451   CHECK(SameSymbol(sym1, Local<String>::Cast(s1)));
   8452   CHECK(SameSymbol(sym2, Local<String>::Cast(s2)));
   8453   CHECK(SameSymbol(sym3, Local<String>::Cast(s3)));
   8454   CHECK(SameSymbol(sym4, Local<String>::Cast(s4)));
   8455 }
   8456 
   8457 
   8458 THREADED_TEST(Utf16MissingTrailing) {
   8459   LocalContext context;
   8460   v8::HandleScope scope(context->GetIsolate());
   8461 
   8462   // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
   8463   int size = 1024 * 64;
   8464   uint8_t* buffer = new uint8_t[size];
   8465   for (int i = 0; i < size; i += 4) {
   8466     buffer[i] = 0xf0;
   8467     buffer[i + 1] = 0x9d;
   8468     buffer[i + 2] = 0x80;
   8469     buffer[i + 3] = 0x9e;
   8470   }
   8471 
   8472   // Now invoke the decoder without last 3 bytes
   8473   v8::Local<v8::String> str =
   8474       v8::String::NewFromUtf8(
   8475           context->GetIsolate(), reinterpret_cast<char*>(buffer),
   8476           v8::NewStringType::kNormal, size - 3).ToLocalChecked();
   8477   USE(str);
   8478   delete[] buffer;
   8479 }
   8480 
   8481 
   8482 THREADED_TEST(Utf16Trailing3Byte) {
   8483   LocalContext context;
   8484   v8::HandleScope scope(context->GetIsolate());
   8485 
   8486   // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
   8487   int size = 1024 * 63;
   8488   uint8_t* buffer = new uint8_t[size];
   8489   for (int i = 0; i < size; i += 3) {
   8490     buffer[i] = 0xe2;
   8491     buffer[i + 1] = 0x80;
   8492     buffer[i + 2] = 0xa6;
   8493   }
   8494 
   8495   // Now invoke the decoder without last 3 bytes
   8496   v8::Local<v8::String> str =
   8497       v8::String::NewFromUtf8(
   8498           context->GetIsolate(), reinterpret_cast<char*>(buffer),
   8499           v8::NewStringType::kNormal, size).ToLocalChecked();
   8500 
   8501   v8::String::Value value(str);
   8502   CHECK_EQ(value.length(), size / 3);
   8503   CHECK_EQ((*value)[value.length() - 1], 0x2026);
   8504 
   8505   delete[] buffer;
   8506 }
   8507 
   8508 
   8509 THREADED_TEST(ToArrayIndex) {
   8510   LocalContext context;
   8511   v8::Isolate* isolate = context->GetIsolate();
   8512   v8::HandleScope scope(isolate);
   8513 
   8514   v8::Local<String> str = v8_str("42");
   8515   v8::MaybeLocal<v8::Uint32> index = str->ToArrayIndex(context.local());
   8516   CHECK(!index.IsEmpty());
   8517   CHECK_EQ(42.0,
   8518            index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
   8519   str = v8_str("42asdf");
   8520   index = str->ToArrayIndex(context.local());
   8521   CHECK(index.IsEmpty());
   8522   str = v8_str("-42");
   8523   index = str->ToArrayIndex(context.local());
   8524   CHECK(index.IsEmpty());
   8525   str = v8_str("4294967294");
   8526   index = str->ToArrayIndex(context.local());
   8527   CHECK(!index.IsEmpty());
   8528   CHECK_EQ(4294967294.0,
   8529            index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
   8530   v8::Local<v8::Number> num = v8::Number::New(isolate, 1);
   8531   index = num->ToArrayIndex(context.local());
   8532   CHECK(!index.IsEmpty());
   8533   CHECK_EQ(1.0,
   8534            index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
   8535   num = v8::Number::New(isolate, -1);
   8536   index = num->ToArrayIndex(context.local());
   8537   CHECK(index.IsEmpty());
   8538   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   8539   index = obj->ToArrayIndex(context.local());
   8540   CHECK(index.IsEmpty());
   8541 }
   8542 
   8543 
   8544 THREADED_TEST(ErrorConstruction) {
   8545   LocalContext context;
   8546   v8::HandleScope scope(context->GetIsolate());
   8547 
   8548   v8::Local<String> foo = v8_str("foo");
   8549   v8::Local<String> message = v8_str("message");
   8550   v8::Local<Value> range_error = v8::Exception::RangeError(foo);
   8551   CHECK(range_error->IsObject());
   8552   CHECK(range_error.As<v8::Object>()
   8553             ->Get(context.local(), message)
   8554             .ToLocalChecked()
   8555             ->Equals(context.local(), foo)
   8556             .FromJust());
   8557   v8::Local<Value> reference_error = v8::Exception::ReferenceError(foo);
   8558   CHECK(reference_error->IsObject());
   8559   CHECK(reference_error.As<v8::Object>()
   8560             ->Get(context.local(), message)
   8561             .ToLocalChecked()
   8562             ->Equals(context.local(), foo)
   8563             .FromJust());
   8564   v8::Local<Value> syntax_error = v8::Exception::SyntaxError(foo);
   8565   CHECK(syntax_error->IsObject());
   8566   CHECK(syntax_error.As<v8::Object>()
   8567             ->Get(context.local(), message)
   8568             .ToLocalChecked()
   8569             ->Equals(context.local(), foo)
   8570             .FromJust());
   8571   v8::Local<Value> type_error = v8::Exception::TypeError(foo);
   8572   CHECK(type_error->IsObject());
   8573   CHECK(type_error.As<v8::Object>()
   8574             ->Get(context.local(), message)
   8575             .ToLocalChecked()
   8576             ->Equals(context.local(), foo)
   8577             .FromJust());
   8578   v8::Local<Value> error = v8::Exception::Error(foo);
   8579   CHECK(error->IsObject());
   8580   CHECK(error.As<v8::Object>()
   8581             ->Get(context.local(), message)
   8582             .ToLocalChecked()
   8583             ->Equals(context.local(), foo)
   8584             .FromJust());
   8585 }
   8586 
   8587 
   8588 static void ThrowV8Exception(const v8::FunctionCallbackInfo<v8::Value>& info) {
   8589   ApiTestFuzzer::Fuzz();
   8590   v8::Local<String> foo = v8_str("foo");
   8591   v8::Local<String> message = v8_str("message");
   8592   v8::Local<Value> error = v8::Exception::Error(foo);
   8593   CHECK(error->IsObject());
   8594   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
   8595   CHECK(error.As<v8::Object>()
   8596             ->Get(context, message)
   8597             .ToLocalChecked()
   8598             ->Equals(context, foo)
   8599             .FromJust());
   8600   info.GetIsolate()->ThrowException(error);
   8601   info.GetReturnValue().SetUndefined();
   8602 }
   8603 
   8604 
   8605 THREADED_TEST(ExceptionCreateMessage) {
   8606   LocalContext context;
   8607   v8::HandleScope scope(context->GetIsolate());
   8608   v8::Local<String> foo_str = v8_str("foo");
   8609   v8::Local<String> message_str = v8_str("message");
   8610 
   8611   context->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(true);
   8612 
   8613   Local<v8::FunctionTemplate> fun =
   8614       v8::FunctionTemplate::New(context->GetIsolate(), ThrowV8Exception);
   8615   v8::Local<v8::Object> global = context->Global();
   8616   CHECK(global->Set(context.local(), v8_str("throwV8Exception"),
   8617                     fun->GetFunction(context.local()).ToLocalChecked())
   8618             .FromJust());
   8619 
   8620   TryCatch try_catch(context->GetIsolate());
   8621   CompileRun(
   8622       "function f1() {\n"
   8623       "  throwV8Exception();\n"
   8624       "};\n"
   8625       "f1();");
   8626   CHECK(try_catch.HasCaught());
   8627 
   8628   v8::Local<v8::Value> error = try_catch.Exception();
   8629   CHECK(error->IsObject());
   8630   CHECK(error.As<v8::Object>()
   8631             ->Get(context.local(), message_str)
   8632             .ToLocalChecked()
   8633             ->Equals(context.local(), foo_str)
   8634             .FromJust());
   8635 
   8636   v8::Local<v8::Message> message =
   8637       v8::Exception::CreateMessage(context->GetIsolate(), error);
   8638   CHECK(!message.IsEmpty());
   8639   CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
   8640   CHECK_EQ(2, message->GetStartColumn(context.local()).FromJust());
   8641 
   8642   v8::Local<v8::StackTrace> stackTrace = message->GetStackTrace();
   8643   CHECK(!stackTrace.IsEmpty());
   8644   CHECK_EQ(2, stackTrace->GetFrameCount());
   8645 
   8646   stackTrace = v8::Exception::GetStackTrace(error);
   8647   CHECK(!stackTrace.IsEmpty());
   8648   CHECK_EQ(2, stackTrace->GetFrameCount());
   8649 
   8650   context->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(false);
   8651 
   8652   // Now check message location when SetCaptureStackTraceForUncaughtExceptions
   8653   // is false.
   8654   try_catch.Reset();
   8655 
   8656   CompileRun(
   8657       "function f2() {\n"
   8658       "  return throwV8Exception();\n"
   8659       "};\n"
   8660       "f2();");
   8661   CHECK(try_catch.HasCaught());
   8662 
   8663   error = try_catch.Exception();
   8664   CHECK(error->IsObject());
   8665   CHECK(error.As<v8::Object>()
   8666             ->Get(context.local(), message_str)
   8667             .ToLocalChecked()
   8668             ->Equals(context.local(), foo_str)
   8669             .FromJust());
   8670 
   8671   message = v8::Exception::CreateMessage(context->GetIsolate(), error);
   8672   CHECK(!message.IsEmpty());
   8673   CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
   8674   CHECK_EQ(9, message->GetStartColumn(context.local()).FromJust());
   8675 
   8676   // Should be empty stack trace.
   8677   stackTrace = message->GetStackTrace();
   8678   CHECK(stackTrace.IsEmpty());
   8679   CHECK(v8::Exception::GetStackTrace(error).IsEmpty());
   8680 }
   8681 
   8682 
   8683 THREADED_TEST(ExceptionCreateMessageLength) {
   8684   LocalContext context;
   8685   v8::HandleScope scope(context->GetIsolate());
   8686 
   8687   // Test that the message is not truncated.
   8688   TryCatch try_catch(context->GetIsolate());
   8689   CompileRun(
   8690       "var message = 'm';"
   8691       "while (message.length < 1000) message += message;"
   8692       "throw message;");
   8693   CHECK(try_catch.HasCaught());
   8694 
   8695   CHECK_LT(1000, try_catch.Message()->Get()->Length());
   8696 }
   8697 
   8698 
   8699 static void YGetter(Local<String> name,
   8700                     const v8::PropertyCallbackInfo<v8::Value>& info) {
   8701   ApiTestFuzzer::Fuzz();
   8702   info.GetReturnValue().Set(v8_num(10));
   8703 }
   8704 
   8705 
   8706 static void YSetter(Local<String> name,
   8707                     Local<Value> value,
   8708                     const v8::PropertyCallbackInfo<void>& info) {
   8709   Local<Object> this_obj = Local<Object>::Cast(info.This());
   8710   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
   8711   if (this_obj->Has(context, name).FromJust())
   8712     this_obj->Delete(context, name).FromJust();
   8713   CHECK(this_obj->Set(context, name, value).FromJust());
   8714 }
   8715 
   8716 
   8717 THREADED_TEST(DeleteAccessor) {
   8718   v8::Isolate* isolate = CcTest::isolate();
   8719   v8::HandleScope scope(isolate);
   8720   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
   8721   obj->SetAccessor(v8_str("y"), YGetter, YSetter);
   8722   LocalContext context;
   8723   v8::Local<v8::Object> holder =
   8724       obj->NewInstance(context.local()).ToLocalChecked();
   8725   CHECK(context->Global()
   8726             ->Set(context.local(), v8_str("holder"), holder)
   8727             .FromJust());
   8728   v8::Local<Value> result =
   8729       CompileRun("holder.y = 11; holder.y = 12; holder.y");
   8730   CHECK_EQ(12u, result->Uint32Value(context.local()).FromJust());
   8731 }
   8732 
   8733 
   8734 static int trouble_nesting = 0;
   8735 static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   8736   ApiTestFuzzer::Fuzz();
   8737   trouble_nesting++;
   8738 
   8739   // Call a JS function that throws an uncaught exception.
   8740   Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   8741   Local<v8::Object> arg_this = context->Global();
   8742   Local<Value> trouble_callee =
   8743       (trouble_nesting == 3)
   8744           ? arg_this->Get(context, v8_str("trouble_callee")).ToLocalChecked()
   8745           : arg_this->Get(context, v8_str("trouble_caller")).ToLocalChecked();
   8746   CHECK(trouble_callee->IsFunction());
   8747   args.GetReturnValue().Set(Function::Cast(*trouble_callee)
   8748                                 ->Call(context, arg_this, 0, NULL)
   8749                                 .FromMaybe(v8::Local<v8::Value>()));
   8750 }
   8751 
   8752 
   8753 static int report_count = 0;
   8754 static void ApiUncaughtExceptionTestListener(v8::Local<v8::Message>,
   8755                                              v8::Local<Value>) {
   8756   report_count++;
   8757 }
   8758 
   8759 
   8760 // Counts uncaught exceptions, but other tests running in parallel
   8761 // also have uncaught exceptions.
   8762 TEST(ApiUncaughtException) {
   8763   report_count = 0;
   8764   LocalContext env;
   8765   v8::Isolate* isolate = env->GetIsolate();
   8766   v8::HandleScope scope(isolate);
   8767   isolate->AddMessageListener(ApiUncaughtExceptionTestListener);
   8768 
   8769   Local<v8::FunctionTemplate> fun =
   8770       v8::FunctionTemplate::New(isolate, TroubleCallback);
   8771   v8::Local<v8::Object> global = env->Global();
   8772   CHECK(global->Set(env.local(), v8_str("trouble"),
   8773                     fun->GetFunction(env.local()).ToLocalChecked())
   8774             .FromJust());
   8775 
   8776   CompileRun(
   8777       "function trouble_callee() {"
   8778       "  var x = null;"
   8779       "  return x.foo;"
   8780       "};"
   8781       "function trouble_caller() {"
   8782       "  trouble();"
   8783       "};");
   8784   Local<Value> trouble =
   8785       global->Get(env.local(), v8_str("trouble")).ToLocalChecked();
   8786   CHECK(trouble->IsFunction());
   8787   Local<Value> trouble_callee =
   8788       global->Get(env.local(), v8_str("trouble_callee")).ToLocalChecked();
   8789   CHECK(trouble_callee->IsFunction());
   8790   Local<Value> trouble_caller =
   8791       global->Get(env.local(), v8_str("trouble_caller")).ToLocalChecked();
   8792   CHECK(trouble_caller->IsFunction());
   8793   Function::Cast(*trouble_caller)
   8794       ->Call(env.local(), global, 0, NULL)
   8795       .FromMaybe(v8::Local<v8::Value>());
   8796   CHECK_EQ(1, report_count);
   8797   isolate->RemoveMessageListeners(ApiUncaughtExceptionTestListener);
   8798 }
   8799 
   8800 
   8801 TEST(ApiUncaughtExceptionInObjectObserve) {
   8802   v8::internal::FLAG_harmony_object_observe = true;
   8803   v8::internal::FLAG_stack_size = 150;
   8804   report_count = 0;
   8805   LocalContext env;
   8806   v8::Isolate* isolate = env->GetIsolate();
   8807   v8::HandleScope scope(isolate);
   8808   isolate->AddMessageListener(ApiUncaughtExceptionTestListener);
   8809   CompileRun(
   8810       "var obj = {};"
   8811       "var observe_count = 0;"
   8812       "function observer1() { ++observe_count; };"
   8813       "function observer2() { ++observe_count; };"
   8814       "function observer_throws() { throw new Error(); };"
   8815       "function stack_overflow() { return (function f(x) { f(x+1); })(0); };"
   8816       "Object.observe(obj, observer_throws.bind());"
   8817       "Object.observe(obj, observer1);"
   8818       "Object.observe(obj, stack_overflow);"
   8819       "Object.observe(obj, observer2);"
   8820       "Object.observe(obj, observer_throws.bind());"
   8821       "obj.foo = 'bar';");
   8822   CHECK_EQ(3, report_count);
   8823   ExpectInt32("observe_count", 2);
   8824   isolate->RemoveMessageListeners(ApiUncaughtExceptionTestListener);
   8825 }
   8826 
   8827 
   8828 static const char* script_resource_name = "ExceptionInNativeScript.js";
   8829 static void ExceptionInNativeScriptTestListener(v8::Local<v8::Message> message,
   8830                                                 v8::Local<Value>) {
   8831   v8::Local<v8::Value> name_val = message->GetScriptOrigin().ResourceName();
   8832   CHECK(!name_val.IsEmpty() && name_val->IsString());
   8833   v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
   8834   CHECK_EQ(0, strcmp(script_resource_name, *name));
   8835   v8::Local<v8::Context> context =
   8836       v8::Isolate::GetCurrent()->GetCurrentContext();
   8837   CHECK_EQ(3, message->GetLineNumber(context).FromJust());
   8838   v8::String::Utf8Value source_line(
   8839       message->GetSourceLine(context).ToLocalChecked());
   8840   CHECK_EQ(0, strcmp("  new o.foo();", *source_line));
   8841 }
   8842 
   8843 
   8844 TEST(ExceptionInNativeScript) {
   8845   LocalContext env;
   8846   v8::Isolate* isolate = env->GetIsolate();
   8847   v8::HandleScope scope(isolate);
   8848   isolate->AddMessageListener(ExceptionInNativeScriptTestListener);
   8849 
   8850   Local<v8::FunctionTemplate> fun =
   8851       v8::FunctionTemplate::New(isolate, TroubleCallback);
   8852   v8::Local<v8::Object> global = env->Global();
   8853   CHECK(global->Set(env.local(), v8_str("trouble"),
   8854                     fun->GetFunction(env.local()).ToLocalChecked())
   8855             .FromJust());
   8856 
   8857   CompileRunWithOrigin(
   8858       "function trouble() {\n"
   8859       "  var o = {};\n"
   8860       "  new o.foo();\n"
   8861       "};",
   8862       script_resource_name);
   8863   Local<Value> trouble =
   8864       global->Get(env.local(), v8_str("trouble")).ToLocalChecked();
   8865   CHECK(trouble->IsFunction());
   8866   CHECK(Function::Cast(*trouble)->Call(env.local(), global, 0, NULL).IsEmpty());
   8867   isolate->RemoveMessageListeners(ExceptionInNativeScriptTestListener);
   8868 }
   8869 
   8870 
   8871 TEST(CompilationErrorUsingTryCatchHandler) {
   8872   LocalContext env;
   8873   v8::HandleScope scope(env->GetIsolate());
   8874   v8::TryCatch try_catch(env->GetIsolate());
   8875   v8_compile("This doesn't &*&@#$&*^ compile.");
   8876   CHECK(*try_catch.Exception());
   8877   CHECK(try_catch.HasCaught());
   8878 }
   8879 
   8880 
   8881 TEST(TryCatchFinallyUsingTryCatchHandler) {
   8882   LocalContext env;
   8883   v8::HandleScope scope(env->GetIsolate());
   8884   v8::TryCatch try_catch(env->GetIsolate());
   8885   CompileRun("try { throw ''; } catch (e) {}");
   8886   CHECK(!try_catch.HasCaught());
   8887   CompileRun("try { throw ''; } finally {}");
   8888   CHECK(try_catch.HasCaught());
   8889   try_catch.Reset();
   8890   CompileRun(
   8891       "(function() {"
   8892       "try { throw ''; } finally { return; }"
   8893       "})()");
   8894   CHECK(!try_catch.HasCaught());
   8895   CompileRun(
   8896       "(function()"
   8897       "  { try { throw ''; } finally { throw 0; }"
   8898       "})()");
   8899   CHECK(try_catch.HasCaught());
   8900 }
   8901 
   8902 
   8903 void CEvaluate(const v8::FunctionCallbackInfo<v8::Value>& args) {
   8904   v8::HandleScope scope(args.GetIsolate());
   8905   CompileRun(args[0]
   8906                  ->ToString(args.GetIsolate()->GetCurrentContext())
   8907                  .ToLocalChecked());
   8908 }
   8909 
   8910 
   8911 TEST(TryCatchFinallyStoresMessageUsingTryCatchHandler) {
   8912   v8::Isolate* isolate = CcTest::isolate();
   8913   v8::HandleScope scope(isolate);
   8914   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   8915   templ->Set(v8_str("CEvaluate"),
   8916              v8::FunctionTemplate::New(isolate, CEvaluate));
   8917   LocalContext context(0, templ);
   8918   v8::TryCatch try_catch(isolate);
   8919   CompileRun("try {"
   8920              "  CEvaluate('throw 1;');"
   8921              "} finally {"
   8922              "}");
   8923   CHECK(try_catch.HasCaught());
   8924   CHECK(!try_catch.Message().IsEmpty());
   8925   String::Utf8Value exception_value(try_catch.Exception());
   8926   CHECK_EQ(0, strcmp(*exception_value, "1"));
   8927   try_catch.Reset();
   8928   CompileRun("try {"
   8929              "  CEvaluate('throw 1;');"
   8930              "} finally {"
   8931              "  throw 2;"
   8932              "}");
   8933   CHECK(try_catch.HasCaught());
   8934   CHECK(!try_catch.Message().IsEmpty());
   8935   String::Utf8Value finally_exception_value(try_catch.Exception());
   8936   CHECK_EQ(0, strcmp(*finally_exception_value, "2"));
   8937 }
   8938 
   8939 
   8940 // For use within the TestSecurityHandler() test.
   8941 static bool g_security_callback_result = false;
   8942 static bool SecurityTestCallback(Local<v8::Context> accessing_context,
   8943                                  Local<v8::Object> accessed_object) {
   8944   printf("a\n");
   8945   return g_security_callback_result;
   8946 }
   8947 
   8948 
   8949 // SecurityHandler can't be run twice
   8950 TEST(SecurityHandler) {
   8951   v8::Isolate* isolate = CcTest::isolate();
   8952   v8::HandleScope scope0(isolate);
   8953   v8::Local<v8::ObjectTemplate> global_template =
   8954       v8::ObjectTemplate::New(isolate);
   8955   global_template->SetAccessCheckCallback(SecurityTestCallback);
   8956   // Create an environment
   8957   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
   8958   context0->Enter();
   8959 
   8960   v8::Local<v8::Object> global0 = context0->Global();
   8961   v8::Local<Script> script0 = v8_compile("foo = 111");
   8962   script0->Run(context0).ToLocalChecked();
   8963   CHECK(global0->Set(context0, v8_str("0"), v8_num(999)).FromJust());
   8964   v8::Local<Value> foo0 =
   8965       global0->Get(context0, v8_str("foo")).ToLocalChecked();
   8966   CHECK_EQ(111, foo0->Int32Value(context0).FromJust());
   8967   v8::Local<Value> z0 = global0->Get(context0, v8_str("0")).ToLocalChecked();
   8968   CHECK_EQ(999, z0->Int32Value(context0).FromJust());
   8969 
   8970   // Create another environment, should fail security checks.
   8971   v8::HandleScope scope1(isolate);
   8972 
   8973   v8::Local<Context> context1 = Context::New(isolate, NULL, global_template);
   8974   context1->Enter();
   8975 
   8976   v8::Local<v8::Object> global1 = context1->Global();
   8977   global1->Set(context1, v8_str("othercontext"), global0).FromJust();
   8978   // This set will fail the security check.
   8979   v8::Local<Script> script1 =
   8980       v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
   8981   CHECK(script1->Run(context1).IsEmpty());
   8982   g_security_callback_result = true;
   8983   // This read will pass the security check.
   8984   v8::Local<Value> foo1 =
   8985       global0->Get(context1, v8_str("foo")).ToLocalChecked();
   8986   CHECK_EQ(111, foo1->Int32Value(context0).FromJust());
   8987   // This read will pass the security check.
   8988   v8::Local<Value> z1 = global0->Get(context1, v8_str("0")).ToLocalChecked();
   8989   CHECK_EQ(999, z1->Int32Value(context1).FromJust());
   8990 
   8991   // Create another environment, should pass security checks.
   8992   {
   8993     v8::HandleScope scope2(isolate);
   8994     LocalContext context2;
   8995     v8::Local<v8::Object> global2 = context2->Global();
   8996     CHECK(global2->Set(context2.local(), v8_str("othercontext"), global0)
   8997               .FromJust());
   8998     v8::Local<Script> script2 =
   8999         v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
   9000     script2->Run(context2.local()).ToLocalChecked();
   9001     v8::Local<Value> foo2 =
   9002         global0->Get(context2.local(), v8_str("foo")).ToLocalChecked();
   9003     CHECK_EQ(333, foo2->Int32Value(context2.local()).FromJust());
   9004     v8::Local<Value> z2 =
   9005         global0->Get(context2.local(), v8_str("0")).ToLocalChecked();
   9006     CHECK_EQ(888, z2->Int32Value(context2.local()).FromJust());
   9007   }
   9008 
   9009   context1->Exit();
   9010   context0->Exit();
   9011 }
   9012 
   9013 
   9014 THREADED_TEST(SecurityChecks) {
   9015   LocalContext env1;
   9016   v8::HandleScope handle_scope(env1->GetIsolate());
   9017   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
   9018 
   9019   Local<Value> foo = v8_str("foo");
   9020   Local<Value> bar = v8_str("bar");
   9021 
   9022   // Set to the same domain.
   9023   env1->SetSecurityToken(foo);
   9024 
   9025   // Create a function in env1.
   9026   CompileRun("spy=function(){return spy;}");
   9027   Local<Value> spy =
   9028       env1->Global()->Get(env1.local(), v8_str("spy")).ToLocalChecked();
   9029   CHECK(spy->IsFunction());
   9030 
   9031   // Create another function accessing global objects.
   9032   CompileRun("spy2=function(){return new this.Array();}");
   9033   Local<Value> spy2 =
   9034       env1->Global()->Get(env1.local(), v8_str("spy2")).ToLocalChecked();
   9035   CHECK(spy2->IsFunction());
   9036 
   9037   // Switch to env2 in the same domain and invoke spy on env2.
   9038   {
   9039     env2->SetSecurityToken(foo);
   9040     // Enter env2
   9041     Context::Scope scope_env2(env2);
   9042     Local<Value> result = Function::Cast(*spy)
   9043                               ->Call(env2, env2->Global(), 0, NULL)
   9044                               .ToLocalChecked();
   9045     CHECK(result->IsFunction());
   9046   }
   9047 
   9048   {
   9049     env2->SetSecurityToken(bar);
   9050     Context::Scope scope_env2(env2);
   9051 
   9052     // Call cross_domain_call, it should throw an exception
   9053     v8::TryCatch try_catch(env1->GetIsolate());
   9054     CHECK(Function::Cast(*spy2)->Call(env2, env2->Global(), 0, NULL).IsEmpty());
   9055     CHECK(try_catch.HasCaught());
   9056   }
   9057 }
   9058 
   9059 
   9060 // Regression test case for issue 1183439.
   9061 THREADED_TEST(SecurityChecksForPrototypeChain) {
   9062   LocalContext current;
   9063   v8::HandleScope scope(current->GetIsolate());
   9064   v8::Local<Context> other = Context::New(current->GetIsolate());
   9065 
   9066   // Change context to be able to get to the Object function in the
   9067   // other context without hitting the security checks.
   9068   v8::Local<Value> other_object;
   9069   { Context::Scope scope(other);
   9070     other_object =
   9071         other->Global()->Get(other, v8_str("Object")).ToLocalChecked();
   9072     CHECK(other->Global()->Set(other, v8_num(42), v8_num(87)).FromJust());
   9073   }
   9074 
   9075   CHECK(current->Global()
   9076             ->Set(current.local(), v8_str("other"), other->Global())
   9077             .FromJust());
   9078   CHECK(v8_compile("other")
   9079             ->Run(current.local())
   9080             .ToLocalChecked()
   9081             ->Equals(current.local(), other->Global())
   9082             .FromJust());
   9083 
   9084   // Make sure the security check fails here and we get an undefined
   9085   // result instead of getting the Object function. Repeat in a loop
   9086   // to make sure to exercise the IC code.
   9087   v8::Local<Script> access_other0 = v8_compile("other.Object");
   9088   v8::Local<Script> access_other1 = v8_compile("other[42]");
   9089   for (int i = 0; i < 5; i++) {
   9090     CHECK(access_other0->Run(current.local()).IsEmpty());
   9091     CHECK(access_other1->Run(current.local()).IsEmpty());
   9092   }
   9093 
   9094   // Create an object that has 'other' in its prototype chain and make
   9095   // sure we cannot access the Object function indirectly through
   9096   // that. Repeat in a loop to make sure to exercise the IC code.
   9097   v8_compile(
   9098       "function F() { };"
   9099       "F.prototype = other;"
   9100       "var f = new F();")
   9101       ->Run(current.local())
   9102       .ToLocalChecked();
   9103   v8::Local<Script> access_f0 = v8_compile("f.Object");
   9104   v8::Local<Script> access_f1 = v8_compile("f[42]");
   9105   for (int j = 0; j < 5; j++) {
   9106     CHECK(access_f0->Run(current.local()).IsEmpty());
   9107     CHECK(access_f1->Run(current.local()).IsEmpty());
   9108   }
   9109 
   9110   // Now it gets hairy: Set the prototype for the other global object
   9111   // to be the current global object. The prototype chain for 'f' now
   9112   // goes through 'other' but ends up in the current global object.
   9113   { Context::Scope scope(other);
   9114     CHECK(other->Global()
   9115               ->Set(other, v8_str("__proto__"), current->Global())
   9116               .FromJust());
   9117   }
   9118   // Set a named and an index property on the current global
   9119   // object. To force the lookup to go through the other global object,
   9120   // the properties must not exist in the other global object.
   9121   CHECK(current->Global()
   9122             ->Set(current.local(), v8_str("foo"), v8_num(100))
   9123             .FromJust());
   9124   CHECK(current->Global()
   9125             ->Set(current.local(), v8_num(99), v8_num(101))
   9126             .FromJust());
   9127   // Try to read the properties from f and make sure that the access
   9128   // gets stopped by the security checks on the other global object.
   9129   Local<Script> access_f2 = v8_compile("f.foo");
   9130   Local<Script> access_f3 = v8_compile("f[99]");
   9131   for (int k = 0; k < 5; k++) {
   9132     CHECK(access_f2->Run(current.local()).IsEmpty());
   9133     CHECK(access_f3->Run(current.local()).IsEmpty());
   9134   }
   9135 }
   9136 
   9137 
   9138 static bool security_check_with_gc_called;
   9139 
   9140 static bool SecurityTestCallbackWithGC(Local<v8::Context> accessing_context,
   9141                                        Local<v8::Object> accessed_object) {
   9142   CcTest::heap()->CollectAllGarbage();
   9143   security_check_with_gc_called = true;
   9144   return true;
   9145 }
   9146 
   9147 
   9148 TEST(SecurityTestGCAllowed) {
   9149   v8::Isolate* isolate = CcTest::isolate();
   9150   v8::HandleScope handle_scope(isolate);
   9151   v8::Local<v8::ObjectTemplate> object_template =
   9152       v8::ObjectTemplate::New(isolate);
   9153   object_template->SetAccessCheckCallback(SecurityTestCallbackWithGC);
   9154 
   9155   v8::Local<Context> context = Context::New(isolate);
   9156   v8::Context::Scope context_scope(context);
   9157 
   9158   CHECK(context->Global()
   9159             ->Set(context, v8_str("obj"),
   9160                   object_template->NewInstance(context).ToLocalChecked())
   9161             .FromJust());
   9162 
   9163   security_check_with_gc_called = false;
   9164   CompileRun("obj[0] = new String(1002);");
   9165   CHECK(security_check_with_gc_called);
   9166 
   9167   security_check_with_gc_called = false;
   9168   CHECK(CompileRun("obj[0]")
   9169             ->ToString(context)
   9170             .ToLocalChecked()
   9171             ->Equals(context, v8_str("1002"))
   9172             .FromJust());
   9173   CHECK(security_check_with_gc_called);
   9174 }
   9175 
   9176 
   9177 THREADED_TEST(CrossDomainDelete) {
   9178   LocalContext env1;
   9179   v8::HandleScope handle_scope(env1->GetIsolate());
   9180   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
   9181 
   9182   Local<Value> foo = v8_str("foo");
   9183   Local<Value> bar = v8_str("bar");
   9184 
   9185   // Set to the same domain.
   9186   env1->SetSecurityToken(foo);
   9187   env2->SetSecurityToken(foo);
   9188 
   9189   CHECK(
   9190       env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
   9191   CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
   9192 
   9193   // Change env2 to a different domain and delete env1.prop.
   9194   env2->SetSecurityToken(bar);
   9195   {
   9196     Context::Scope scope_env2(env2);
   9197     Local<Value> result =
   9198         CompileRun("delete env1.prop");
   9199     CHECK(result.IsEmpty());
   9200   }
   9201 
   9202   // Check that env1.prop still exists.
   9203   Local<Value> v =
   9204       env1->Global()->Get(env1.local(), v8_str("prop")).ToLocalChecked();
   9205   CHECK(v->IsNumber());
   9206   CHECK_EQ(3, v->Int32Value(env1.local()).FromJust());
   9207 }
   9208 
   9209 
   9210 THREADED_TEST(CrossDomainPropertyIsEnumerable) {
   9211   LocalContext env1;
   9212   v8::HandleScope handle_scope(env1->GetIsolate());
   9213   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
   9214 
   9215   Local<Value> foo = v8_str("foo");
   9216   Local<Value> bar = v8_str("bar");
   9217 
   9218   // Set to the same domain.
   9219   env1->SetSecurityToken(foo);
   9220   env2->SetSecurityToken(foo);
   9221 
   9222   CHECK(
   9223       env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
   9224   CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
   9225 
   9226   // env1.prop is enumerable in env2.
   9227   Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
   9228   {
   9229     Context::Scope scope_env2(env2);
   9230     Local<Value> result = CompileRun(test);
   9231     CHECK(result->IsTrue());
   9232   }
   9233 
   9234   // Change env2 to a different domain and test again.
   9235   env2->SetSecurityToken(bar);
   9236   {
   9237     Context::Scope scope_env2(env2);
   9238     Local<Value> result = CompileRun(test);
   9239     CHECK(result.IsEmpty());
   9240   }
   9241 }
   9242 
   9243 
   9244 THREADED_TEST(CrossDomainFor) {
   9245   LocalContext env1;
   9246   v8::HandleScope handle_scope(env1->GetIsolate());
   9247   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
   9248 
   9249   Local<Value> foo = v8_str("foo");
   9250   Local<Value> bar = v8_str("bar");
   9251 
   9252   // Set to the same domain.
   9253   env1->SetSecurityToken(foo);
   9254   env2->SetSecurityToken(foo);
   9255 
   9256   CHECK(
   9257       env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
   9258   CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
   9259 
   9260   // Change env2 to a different domain and set env1's global object
   9261   // as the __proto__ of an object in env2 and enumerate properties
   9262   // in for-in. It shouldn't enumerate properties on env1's global
   9263   // object. It shouldn't throw either, just silently ignore them.
   9264   env2->SetSecurityToken(bar);
   9265   {
   9266     Context::Scope scope_env2(env2);
   9267     Local<Value> result = CompileRun(
   9268         "(function() {"
   9269         "  try {"
   9270         "    for (var p in env1) {"
   9271         "      if (p == 'prop') return false;"
   9272         "    }"
   9273         "    return true;"
   9274         "  } catch (e) {"
   9275         "    return false;"
   9276         "  }"
   9277         "})()");
   9278     CHECK(result->IsTrue());
   9279   }
   9280 }
   9281 
   9282 
   9283 THREADED_TEST(CrossDomainForInOnPrototype) {
   9284   LocalContext env1;
   9285   v8::HandleScope handle_scope(env1->GetIsolate());
   9286   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
   9287 
   9288   Local<Value> foo = v8_str("foo");
   9289   Local<Value> bar = v8_str("bar");
   9290 
   9291   // Set to the same domain.
   9292   env1->SetSecurityToken(foo);
   9293   env2->SetSecurityToken(foo);
   9294 
   9295   CHECK(
   9296       env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
   9297   CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
   9298 
   9299   // Change env2 to a different domain and set env1's global object
   9300   // as the __proto__ of an object in env2 and enumerate properties
   9301   // in for-in. It shouldn't enumerate properties on env1's global
   9302   // object.
   9303   env2->SetSecurityToken(bar);
   9304   {
   9305     Context::Scope scope_env2(env2);
   9306     Local<Value> result = CompileRun(
   9307         "(function() {"
   9308         "  var obj = { '__proto__': env1 };"
   9309         "  try {"
   9310         "    for (var p in obj) {"
   9311         "      if (p == 'prop') return false;"
   9312         "    }"
   9313         "    return true;"
   9314         "  } catch (e) {"
   9315         "    return false;"
   9316         "  }"
   9317         "})()");
   9318     CHECK(result->IsTrue());
   9319   }
   9320 }
   9321 
   9322 
   9323 TEST(ContextDetachGlobal) {
   9324   LocalContext env1;
   9325   v8::HandleScope handle_scope(env1->GetIsolate());
   9326   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
   9327 
   9328 
   9329   Local<Value> foo = v8_str("foo");
   9330 
   9331   // Set to the same domain.
   9332   env1->SetSecurityToken(foo);
   9333   env2->SetSecurityToken(foo);
   9334 
   9335   // Enter env2
   9336   env2->Enter();
   9337 
   9338   // Create a function in env2 and add a reference to it in env1.
   9339   Local<v8::Object> global2 = env2->Global();
   9340   CHECK(global2->Set(env2, v8_str("prop"),
   9341                      v8::Integer::New(env2->GetIsolate(), 1))
   9342             .FromJust());
   9343   CompileRun("function getProp() {return prop;}");
   9344 
   9345   CHECK(env1->Global()
   9346             ->Set(env1.local(), v8_str("getProp"),
   9347                   global2->Get(env2, v8_str("getProp")).ToLocalChecked())
   9348             .FromJust());
   9349 
   9350   // Detach env2's global, and reuse the global object of env2
   9351   env2->Exit();
   9352   env2->DetachGlobal();
   9353 
   9354   v8::Local<Context> env3 = Context::New(
   9355       env1->GetIsolate(), 0, v8::Local<v8::ObjectTemplate>(), global2);
   9356   env3->SetSecurityToken(v8_str("bar"));
   9357 
   9358   env3->Enter();
   9359   Local<v8::Object> global3 = env3->Global();
   9360   CHECK(global2->Equals(env3, global3).FromJust());
   9361   CHECK(global3->Get(env3, v8_str("prop")).ToLocalChecked()->IsUndefined());
   9362   CHECK(global3->Get(env3, v8_str("getProp")).ToLocalChecked()->IsUndefined());
   9363   CHECK(global3->Set(env3, v8_str("prop"),
   9364                      v8::Integer::New(env3->GetIsolate(), -1))
   9365             .FromJust());
   9366   CHECK(global3->Set(env3, v8_str("prop2"),
   9367                      v8::Integer::New(env3->GetIsolate(), 2))
   9368             .FromJust());
   9369   env3->Exit();
   9370 
   9371   // Call getProp in env1, and it should return the value 1
   9372   {
   9373     Local<v8::Object> global1 = env1->Global();
   9374     Local<Value> get_prop =
   9375         global1->Get(env1.local(), v8_str("getProp")).ToLocalChecked();
   9376     CHECK(get_prop->IsFunction());
   9377     v8::TryCatch try_catch(env1->GetIsolate());
   9378     Local<Value> r = Function::Cast(*get_prop)
   9379                          ->Call(env1.local(), global1, 0, NULL)
   9380                          .ToLocalChecked();
   9381     CHECK(!try_catch.HasCaught());
   9382     CHECK_EQ(1, r->Int32Value(env1.local()).FromJust());
   9383   }
   9384 
   9385   // Check that env3 is not accessible from env1
   9386   {
   9387     v8::MaybeLocal<Value> r = global3->Get(env1.local(), v8_str("prop2"));
   9388     CHECK(r.IsEmpty());
   9389   }
   9390 }
   9391 
   9392 
   9393 TEST(DetachGlobal) {
   9394   LocalContext env1;
   9395   v8::HandleScope scope(env1->GetIsolate());
   9396 
   9397   // Create second environment.
   9398   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
   9399 
   9400   Local<Value> foo = v8_str("foo");
   9401 
   9402   // Set same security token for env1 and env2.
   9403   env1->SetSecurityToken(foo);
   9404   env2->SetSecurityToken(foo);
   9405 
   9406   // Create a property on the global object in env2.
   9407   {
   9408     v8::Context::Scope scope(env2);
   9409     CHECK(env2->Global()
   9410               ->Set(env2, v8_str("p"), v8::Integer::New(env2->GetIsolate(), 42))
   9411               .FromJust());
   9412   }
   9413 
   9414   // Create a reference to env2 global from env1 global.
   9415   CHECK(env1->Global()
   9416             ->Set(env1.local(), v8_str("other"), env2->Global())
   9417             .FromJust());
   9418 
   9419   // Check that we have access to other.p in env2 from env1.
   9420   Local<Value> result = CompileRun("other.p");
   9421   CHECK(result->IsInt32());
   9422   CHECK_EQ(42, result->Int32Value(env1.local()).FromJust());
   9423 
   9424   // Hold on to global from env2 and detach global from env2.
   9425   Local<v8::Object> global2 = env2->Global();
   9426   env2->DetachGlobal();
   9427 
   9428   // Check that the global has been detached. No other.p property can
   9429   // be found.
   9430   result = CompileRun("other.p");
   9431   CHECK(result.IsEmpty());
   9432 
   9433   // Reuse global2 for env3.
   9434   v8::Local<Context> env3 = Context::New(
   9435       env1->GetIsolate(), 0, v8::Local<v8::ObjectTemplate>(), global2);
   9436   CHECK(global2->Equals(env1.local(), env3->Global()).FromJust());
   9437 
   9438   // Start by using the same security token for env3 as for env1 and env2.
   9439   env3->SetSecurityToken(foo);
   9440 
   9441   // Create a property on the global object in env3.
   9442   {
   9443     v8::Context::Scope scope(env3);
   9444     CHECK(env3->Global()
   9445               ->Set(env3, v8_str("p"), v8::Integer::New(env3->GetIsolate(), 24))
   9446               .FromJust());
   9447   }
   9448 
   9449   // Check that other.p is now the property in env3 and that we have access.
   9450   result = CompileRun("other.p");
   9451   CHECK(result->IsInt32());
   9452   CHECK_EQ(24, result->Int32Value(env3).FromJust());
   9453 
   9454   // Change security token for env3 to something different from env1 and env2.
   9455   env3->SetSecurityToken(v8_str("bar"));
   9456 
   9457   // Check that we do not have access to other.p in env1. |other| is now
   9458   // the global object for env3 which has a different security token,
   9459   // so access should be blocked.
   9460   result = CompileRun("other.p");
   9461   CHECK(result.IsEmpty());
   9462 }
   9463 
   9464 
   9465 void GetThisX(const v8::FunctionCallbackInfo<v8::Value>& info) {
   9466   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
   9467   info.GetReturnValue().Set(
   9468       context->Global()->Get(context, v8_str("x")).ToLocalChecked());
   9469 }
   9470 
   9471 
   9472 TEST(DetachedAccesses) {
   9473   LocalContext env1;
   9474   v8::HandleScope scope(env1->GetIsolate());
   9475 
   9476   // Create second environment.
   9477   Local<ObjectTemplate> inner_global_template =
   9478       FunctionTemplate::New(env1->GetIsolate())->InstanceTemplate();
   9479   inner_global_template ->SetAccessorProperty(
   9480       v8_str("this_x"), FunctionTemplate::New(env1->GetIsolate(), GetThisX));
   9481   v8::Local<Context> env2 =
   9482       Context::New(env1->GetIsolate(), NULL, inner_global_template);
   9483 
   9484   Local<Value> foo = v8_str("foo");
   9485 
   9486   // Set same security token for env1 and env2.
   9487   env1->SetSecurityToken(foo);
   9488   env2->SetSecurityToken(foo);
   9489 
   9490   CHECK(env1->Global()
   9491             ->Set(env1.local(), v8_str("x"), v8_str("env1_x"))
   9492             .FromJust());
   9493 
   9494   {
   9495     v8::Context::Scope scope(env2);
   9496     CHECK(env2->Global()->Set(env2, v8_str("x"), v8_str("env2_x")).FromJust());
   9497     CompileRun(
   9498         "function bound_x() { return x; }"
   9499         "function get_x()   { return this.x; }"
   9500         "function get_x_w() { return (function() {return this.x;})(); }");
   9501     CHECK(env1->Global()
   9502               ->Set(env1.local(), v8_str("bound_x"), CompileRun("bound_x"))
   9503               .FromJust());
   9504     CHECK(env1->Global()
   9505               ->Set(env1.local(), v8_str("get_x"), CompileRun("get_x"))
   9506               .FromJust());
   9507     CHECK(env1->Global()
   9508               ->Set(env1.local(), v8_str("get_x_w"), CompileRun("get_x_w"))
   9509               .FromJust());
   9510     env1->Global()
   9511         ->Set(env1.local(), v8_str("this_x"),
   9512               CompileRun("Object.getOwnPropertyDescriptor(this, 'this_x').get"))
   9513         .FromJust();
   9514   }
   9515 
   9516   Local<Object> env2_global = env2->Global();
   9517   env2->DetachGlobal();
   9518 
   9519   Local<Value> result;
   9520   result = CompileRun("bound_x()");
   9521   CHECK(v8_str("env2_x")->Equals(env1.local(), result).FromJust());
   9522   result = CompileRun("get_x()");
   9523   CHECK(result.IsEmpty());
   9524   result = CompileRun("get_x_w()");
   9525   CHECK(result.IsEmpty());
   9526   result = CompileRun("this_x()");
   9527   CHECK(v8_str("env2_x")->Equals(env1.local(), result).FromJust());
   9528 
   9529   // Reattach env2's proxy
   9530   env2 = Context::New(env1->GetIsolate(), 0, v8::Local<v8::ObjectTemplate>(),
   9531                       env2_global);
   9532   env2->SetSecurityToken(foo);
   9533   {
   9534     v8::Context::Scope scope(env2);
   9535     CHECK(env2->Global()->Set(env2, v8_str("x"), v8_str("env3_x")).FromJust());
   9536     CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
   9537     result = CompileRun(
   9538         "results = [];"
   9539         "for (var i = 0; i < 4; i++ ) {"
   9540         "  results.push(env1.bound_x());"
   9541         "  results.push(env1.get_x());"
   9542         "  results.push(env1.get_x_w());"
   9543         "  results.push(env1.this_x());"
   9544         "}"
   9545         "results");
   9546     Local<v8::Array> results = Local<v8::Array>::Cast(result);
   9547     CHECK_EQ(16u, results->Length());
   9548     for (int i = 0; i < 16; i += 4) {
   9549       CHECK(v8_str("env2_x")
   9550                 ->Equals(env2, results->Get(env2, i + 0).ToLocalChecked())
   9551                 .FromJust());
   9552       CHECK(v8_str("env1_x")
   9553                 ->Equals(env2, results->Get(env2, i + 1).ToLocalChecked())
   9554                 .FromJust());
   9555       CHECK(v8_str("env3_x")
   9556                 ->Equals(env2, results->Get(env2, i + 2).ToLocalChecked())
   9557                 .FromJust());
   9558       CHECK(v8_str("env2_x")
   9559                 ->Equals(env2, results->Get(env2, i + 3).ToLocalChecked())
   9560                 .FromJust());
   9561     }
   9562   }
   9563 
   9564   result = CompileRun(
   9565       "results = [];"
   9566       "for (var i = 0; i < 4; i++ ) {"
   9567       "  results.push(bound_x());"
   9568       "  results.push(get_x());"
   9569       "  results.push(get_x_w());"
   9570       "  results.push(this_x());"
   9571       "}"
   9572       "results");
   9573   Local<v8::Array> results = Local<v8::Array>::Cast(result);
   9574   CHECK_EQ(16u, results->Length());
   9575   for (int i = 0; i < 16; i += 4) {
   9576     CHECK(v8_str("env2_x")
   9577               ->Equals(env1.local(),
   9578                        results->Get(env1.local(), i + 0).ToLocalChecked())
   9579               .FromJust());
   9580     CHECK(v8_str("env3_x")
   9581               ->Equals(env1.local(),
   9582                        results->Get(env1.local(), i + 1).ToLocalChecked())
   9583               .FromJust());
   9584     CHECK(v8_str("env3_x")
   9585               ->Equals(env1.local(),
   9586                        results->Get(env1.local(), i + 2).ToLocalChecked())
   9587               .FromJust());
   9588     CHECK(v8_str("env2_x")
   9589               ->Equals(env1.local(),
   9590                        results->Get(env1.local(), i + 3).ToLocalChecked())
   9591               .FromJust());
   9592   }
   9593 
   9594   result = CompileRun(
   9595       "results = [];"
   9596       "for (var i = 0; i < 4; i++ ) {"
   9597       "  results.push(this.bound_x());"
   9598       "  results.push(this.get_x());"
   9599       "  results.push(this.get_x_w());"
   9600       "  results.push(this.this_x());"
   9601       "}"
   9602       "results");
   9603   results = Local<v8::Array>::Cast(result);
   9604   CHECK_EQ(16u, results->Length());
   9605   for (int i = 0; i < 16; i += 4) {
   9606     CHECK(v8_str("env2_x")
   9607               ->Equals(env1.local(),
   9608                        results->Get(env1.local(), i + 0).ToLocalChecked())
   9609               .FromJust());
   9610     CHECK(v8_str("env1_x")
   9611               ->Equals(env1.local(),
   9612                        results->Get(env1.local(), i + 1).ToLocalChecked())
   9613               .FromJust());
   9614     CHECK(v8_str("env3_x")
   9615               ->Equals(env1.local(),
   9616                        results->Get(env1.local(), i + 2).ToLocalChecked())
   9617               .FromJust());
   9618     CHECK(v8_str("env2_x")
   9619               ->Equals(env1.local(),
   9620                        results->Get(env1.local(), i + 3).ToLocalChecked())
   9621               .FromJust());
   9622   }
   9623 }
   9624 
   9625 
   9626 static bool allowed_access = false;
   9627 static bool AccessBlocker(Local<v8::Context> accessing_context,
   9628                           Local<v8::Object> accessed_object) {
   9629   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   9630   return context->Global()->Equals(context, accessed_object).FromJust() ||
   9631          allowed_access;
   9632 }
   9633 
   9634 
   9635 static int g_echo_value = -1;
   9636 
   9637 
   9638 static void EchoGetter(
   9639     Local<String> name,
   9640     const v8::PropertyCallbackInfo<v8::Value>& info) {
   9641   info.GetReturnValue().Set(v8_num(g_echo_value));
   9642 }
   9643 
   9644 
   9645 static void EchoSetter(Local<String> name, Local<Value> value,
   9646                        const v8::PropertyCallbackInfo<void>& args) {
   9647   if (value->IsNumber())
   9648     g_echo_value =
   9649         value->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
   9650 }
   9651 
   9652 
   9653 static void UnreachableGetter(
   9654     Local<String> name,
   9655     const v8::PropertyCallbackInfo<v8::Value>& info) {
   9656   CHECK(false);  // This function should not be called..
   9657 }
   9658 
   9659 
   9660 static void UnreachableSetter(Local<String>,
   9661                               Local<Value>,
   9662                               const v8::PropertyCallbackInfo<void>&) {
   9663   CHECK(false);  // This function should nto be called.
   9664 }
   9665 
   9666 
   9667 static void UnreachableFunction(
   9668     const v8::FunctionCallbackInfo<v8::Value>& info) {
   9669   CHECK(false);  // This function should not be called..
   9670 }
   9671 
   9672 
   9673 TEST(AccessControl) {
   9674   v8::Isolate* isolate = CcTest::isolate();
   9675   v8::HandleScope handle_scope(isolate);
   9676   v8::Local<v8::ObjectTemplate> global_template =
   9677       v8::ObjectTemplate::New(isolate);
   9678 
   9679   global_template->SetAccessCheckCallback(AccessBlocker);
   9680 
   9681   // Add an accessor accessible by cross-domain JS code.
   9682   global_template->SetAccessor(
   9683       v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
   9684       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   9685 
   9686 
   9687   // Add an accessor that is not accessible by cross-domain JS code.
   9688   global_template->SetAccessor(v8_str("blocked_prop"), UnreachableGetter,
   9689                                UnreachableSetter, v8::Local<Value>(),
   9690                                v8::DEFAULT);
   9691 
   9692   global_template->SetAccessorProperty(
   9693       v8_str("blocked_js_prop"),
   9694       v8::FunctionTemplate::New(isolate, UnreachableFunction),
   9695       v8::FunctionTemplate::New(isolate, UnreachableFunction),
   9696       v8::None,
   9697       v8::DEFAULT);
   9698 
   9699   // Create an environment
   9700   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
   9701   context0->Enter();
   9702 
   9703   v8::Local<v8::Object> global0 = context0->Global();
   9704 
   9705   // Define a property with JS getter and setter.
   9706   CompileRun(
   9707       "function getter() { return 'getter'; };\n"
   9708       "function setter() { return 'setter'; }\n"
   9709       "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
   9710 
   9711   Local<Value> getter =
   9712       global0->Get(context0, v8_str("getter")).ToLocalChecked();
   9713   Local<Value> setter =
   9714       global0->Get(context0, v8_str("setter")).ToLocalChecked();
   9715 
   9716   // And define normal element.
   9717   CHECK(global0->Set(context0, 239, v8_str("239")).FromJust());
   9718 
   9719   // Define an element with JS getter and setter.
   9720   CompileRun(
   9721       "function el_getter() { return 'el_getter'; };\n"
   9722       "function el_setter() { return 'el_setter'; };\n"
   9723       "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
   9724 
   9725   Local<Value> el_getter =
   9726       global0->Get(context0, v8_str("el_getter")).ToLocalChecked();
   9727   Local<Value> el_setter =
   9728       global0->Get(context0, v8_str("el_setter")).ToLocalChecked();
   9729 
   9730   v8::HandleScope scope1(isolate);
   9731 
   9732   v8::Local<Context> context1 = Context::New(isolate);
   9733   context1->Enter();
   9734 
   9735   v8::Local<v8::Object> global1 = context1->Global();
   9736   CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
   9737 
   9738   // Access blocked property.
   9739   CompileRun("other.blocked_prop = 1");
   9740 
   9741   CHECK(CompileRun("other.blocked_prop").IsEmpty());
   9742   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
   9743             .IsEmpty());
   9744   CHECK(
   9745       CompileRun("propertyIsEnumerable.call(other, 'blocked_prop')").IsEmpty());
   9746 
   9747   // Access blocked element.
   9748   CHECK(CompileRun("other[239] = 1").IsEmpty());
   9749 
   9750   CHECK(CompileRun("other[239]").IsEmpty());
   9751   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239')").IsEmpty());
   9752   CHECK(CompileRun("propertyIsEnumerable.call(other, '239')").IsEmpty());
   9753 
   9754   allowed_access = true;
   9755   // Now we can enumerate the property.
   9756   ExpectTrue("propertyIsEnumerable.call(other, '239')");
   9757   allowed_access = false;
   9758 
   9759   // Access a property with JS accessor.
   9760   CHECK(CompileRun("other.js_accessor_p = 2").IsEmpty());
   9761 
   9762   CHECK(CompileRun("other.js_accessor_p").IsEmpty());
   9763   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'js_accessor_p')")
   9764             .IsEmpty());
   9765 
   9766   allowed_access = true;
   9767 
   9768   ExpectString("other.js_accessor_p", "getter");
   9769   ExpectObject(
   9770       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
   9771   ExpectObject(
   9772       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
   9773   ExpectUndefined(
   9774       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
   9775 
   9776   allowed_access = false;
   9777 
   9778   // Access an element with JS accessor.
   9779   CHECK(CompileRun("other[42] = 2").IsEmpty());
   9780 
   9781   CHECK(CompileRun("other[42]").IsEmpty());
   9782   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '42')").IsEmpty());
   9783 
   9784   allowed_access = true;
   9785 
   9786   ExpectString("other[42]", "el_getter");
   9787   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
   9788   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
   9789   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
   9790 
   9791   allowed_access = false;
   9792 
   9793   v8::Local<Value> value;
   9794 
   9795   // Access accessible property
   9796   value = CompileRun("other.accessible_prop = 3");
   9797   CHECK(value->IsNumber());
   9798   CHECK_EQ(3, value->Int32Value(context1).FromJust());
   9799   CHECK_EQ(3, g_echo_value);
   9800 
   9801   value = CompileRun("other.accessible_prop");
   9802   CHECK(value->IsNumber());
   9803   CHECK_EQ(3, value->Int32Value(context1).FromJust());
   9804 
   9805   value = CompileRun(
   9806       "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
   9807   CHECK(value->IsNumber());
   9808   CHECK_EQ(3, value->Int32Value(context1).FromJust());
   9809 
   9810   value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
   9811   CHECK(value->IsTrue());
   9812 
   9813   // Enumeration doesn't enumerate accessors from inaccessible objects in
   9814   // the prototype chain even if the accessors are in themselves accessible.
   9815   // Enumeration doesn't throw, it silently ignores what it can't access.
   9816   value = CompileRun(
   9817       "(function() {"
   9818       "  var obj = { '__proto__': other };"
   9819       "  try {"
   9820       "    for (var p in obj) {"
   9821       "      if (p == 'accessible_prop' ||"
   9822       "          p == 'blocked_js_prop' ||"
   9823       "          p == 'blocked_js_prop') {"
   9824       "        return false;"
   9825       "      }"
   9826       "    }"
   9827       "    return true;"
   9828       "  } catch (e) {"
   9829       "    return false;"
   9830       "  }"
   9831       "})()");
   9832   CHECK(value->IsTrue());
   9833 
   9834   // Test that preventExtensions fails on a non-accessible object even if that
   9835   // object is already non-extensible.
   9836   CHECK(global1->Set(context1, v8_str("checked_object"),
   9837                      global_template->NewInstance(context1).ToLocalChecked())
   9838             .FromJust());
   9839   allowed_access = true;
   9840   CompileRun("Object.preventExtensions(checked_object)");
   9841   ExpectFalse("Object.isExtensible(checked_object)");
   9842   allowed_access = false;
   9843   CHECK(CompileRun("Object.preventExtensions(checked_object)").IsEmpty());
   9844 
   9845   context1->Exit();
   9846   context0->Exit();
   9847 }
   9848 
   9849 
   9850 TEST(AccessControlES5) {
   9851   v8::Isolate* isolate = CcTest::isolate();
   9852   v8::HandleScope handle_scope(isolate);
   9853   v8::Local<v8::ObjectTemplate> global_template =
   9854       v8::ObjectTemplate::New(isolate);
   9855 
   9856   global_template->SetAccessCheckCallback(AccessBlocker);
   9857 
   9858   // Add accessible accessor.
   9859   global_template->SetAccessor(
   9860       v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
   9861       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   9862 
   9863 
   9864   // Add an accessor that is not accessible by cross-domain JS code.
   9865   global_template->SetAccessor(v8_str("blocked_prop"), UnreachableGetter,
   9866                                UnreachableSetter, v8::Local<Value>(),
   9867                                v8::DEFAULT);
   9868 
   9869   // Create an environment
   9870   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
   9871   context0->Enter();
   9872 
   9873   v8::Local<v8::Object> global0 = context0->Global();
   9874 
   9875   v8::Local<Context> context1 = Context::New(isolate);
   9876   context1->Enter();
   9877   v8::Local<v8::Object> global1 = context1->Global();
   9878   CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
   9879 
   9880   // Regression test for issue 1154.
   9881   CHECK(CompileRun("Object.keys(other).length == 1")
   9882             ->BooleanValue(context1)
   9883             .FromJust());
   9884   CHECK(CompileRun("Object.keys(other)[0] == 'accessible_prop'")
   9885             ->BooleanValue(context1)
   9886             .FromJust());
   9887   CHECK(CompileRun("other.blocked_prop").IsEmpty());
   9888 
   9889   // Regression test for issue 1027.
   9890   CompileRun("Object.defineProperty(\n"
   9891              "  other, 'blocked_prop', {configurable: false})");
   9892   CHECK(CompileRun("other.blocked_prop").IsEmpty());
   9893   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
   9894             .IsEmpty());
   9895 
   9896   // Regression test for issue 1171.
   9897   ExpectTrue("Object.isExtensible(other)");
   9898   CompileRun("Object.preventExtensions(other)");
   9899   ExpectTrue("Object.isExtensible(other)");
   9900 
   9901   // Object.seal and Object.freeze.
   9902   CompileRun("Object.freeze(other)");
   9903   ExpectTrue("Object.isExtensible(other)");
   9904 
   9905   CompileRun("Object.seal(other)");
   9906   ExpectTrue("Object.isExtensible(other)");
   9907 
   9908   // Regression test for issue 1250.
   9909   // Make sure that we can set the accessible accessors value using normal
   9910   // assignment.
   9911   CompileRun("other.accessible_prop = 42");
   9912   CHECK_EQ(42, g_echo_value);
   9913 
   9914   // [[DefineOwnProperty]] always throws for access-checked objects.
   9915   CHECK(
   9916       CompileRun("Object.defineProperty(other, 'accessible_prop', {value: 43})")
   9917           .IsEmpty());
   9918   CHECK(CompileRun("other.accessible_prop == 42")->IsTrue());
   9919   CHECK_EQ(42, g_echo_value);  // Make sure we didn't call the setter.
   9920 }
   9921 
   9922 
   9923 static bool AccessAlwaysBlocked(Local<v8::Context> accessing_context,
   9924                                 Local<v8::Object> global) {
   9925   i::PrintF("Access blocked.\n");
   9926   return false;
   9927 }
   9928 
   9929 
   9930 THREADED_TEST(AccessControlGetOwnPropertyNames) {
   9931   v8::Isolate* isolate = CcTest::isolate();
   9932   v8::HandleScope handle_scope(isolate);
   9933   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   9934 
   9935   obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
   9936   obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   9937 
   9938   // Add an accessor accessible by cross-domain JS code.
   9939   obj_template->SetAccessor(
   9940       v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
   9941       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   9942 
   9943   // Create an environment
   9944   v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
   9945   context0->Enter();
   9946 
   9947   v8::Local<v8::Object> global0 = context0->Global();
   9948 
   9949   v8::HandleScope scope1(CcTest::isolate());
   9950 
   9951   v8::Local<Context> context1 = Context::New(isolate);
   9952   context1->Enter();
   9953 
   9954   v8::Local<v8::Object> global1 = context1->Global();
   9955   CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
   9956   CHECK(global1->Set(context1, v8_str("object"),
   9957                      obj_template->NewInstance(context1).ToLocalChecked())
   9958             .FromJust());
   9959 
   9960   v8::Local<Value> value;
   9961 
   9962   // Attempt to get the property names of the other global object and
   9963   // of an object that requires access checks.  Accessing the other
   9964   // global object should be blocked by access checks on the global
   9965   // proxy object.  Accessing the object that requires access checks
   9966   // is blocked by the access checks on the object itself.
   9967   value = CompileRun(
   9968       "var names = Object.getOwnPropertyNames(other);"
   9969       "names.length == 1 && names[0] == 'accessible_prop';");
   9970   CHECK(value->BooleanValue(context1).FromJust());
   9971 
   9972   value = CompileRun(
   9973       "var names = Object.getOwnPropertyNames(object);"
   9974       "names.length == 1 && names[0] == 'accessible_prop';");
   9975   CHECK(value->BooleanValue(context1).FromJust());
   9976 
   9977   context1->Exit();
   9978   context0->Exit();
   9979 }
   9980 
   9981 
   9982 TEST(Regress470113) {
   9983   v8::Isolate* isolate = CcTest::isolate();
   9984   v8::HandleScope handle_scope(isolate);
   9985   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   9986   obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   9987   LocalContext env;
   9988   CHECK(env->Global()
   9989             ->Set(env.local(), v8_str("prohibited"),
   9990                   obj_template->NewInstance(env.local()).ToLocalChecked())
   9991             .FromJust());
   9992 
   9993   {
   9994     v8::TryCatch try_catch(isolate);
   9995     CompileRun(
   9996         "'use strict';\n"
   9997         "class C extends Object {\n"
   9998         "   m() { super.powned = 'Powned!'; }\n"
   9999         "}\n"
   10000         "let c = new C();\n"
   10001         "c.m.call(prohibited)");
   10002 
   10003     CHECK(try_catch.HasCaught());
   10004   }
   10005 }
   10006 
   10007 
   10008 static void ConstTenGetter(Local<String> name,
   10009                            const v8::PropertyCallbackInfo<v8::Value>& info) {
   10010   info.GetReturnValue().Set(v8_num(10));
   10011 }
   10012 
   10013 
   10014 THREADED_TEST(CrossDomainAccessors) {
   10015   v8::Isolate* isolate = CcTest::isolate();
   10016   v8::HandleScope handle_scope(isolate);
   10017 
   10018   v8::Local<v8::FunctionTemplate> func_template =
   10019       v8::FunctionTemplate::New(isolate);
   10020 
   10021   v8::Local<v8::ObjectTemplate> global_template =
   10022       func_template->InstanceTemplate();
   10023 
   10024   v8::Local<v8::ObjectTemplate> proto_template =
   10025       func_template->PrototypeTemplate();
   10026 
   10027   // Add an accessor to proto that's accessible by cross-domain JS code.
   10028   proto_template->SetAccessor(v8_str("accessible"), ConstTenGetter, 0,
   10029                               v8::Local<Value>(), v8::ALL_CAN_READ);
   10030 
   10031   // Add an accessor that is not accessible by cross-domain JS code.
   10032   global_template->SetAccessor(v8_str("unreachable"), UnreachableGetter, 0,
   10033                                v8::Local<Value>(), v8::DEFAULT);
   10034 
   10035   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
   10036   context0->Enter();
   10037 
   10038   Local<v8::Object> global = context0->Global();
   10039   // Add a normal property that shadows 'accessible'
   10040   CHECK(global->Set(context0, v8_str("accessible"), v8_num(11)).FromJust());
   10041 
   10042   // Enter a new context.
   10043   v8::HandleScope scope1(CcTest::isolate());
   10044   v8::Local<Context> context1 = Context::New(isolate);
   10045   context1->Enter();
   10046 
   10047   v8::Local<v8::Object> global1 = context1->Global();
   10048   CHECK(global1->Set(context1, v8_str("other"), global).FromJust());
   10049 
   10050   // Should return 10, instead of 11
   10051   v8::Local<Value> value =
   10052       v8_compile("other.accessible")->Run(context1).ToLocalChecked();
   10053   CHECK(value->IsNumber());
   10054   CHECK_EQ(10, value->Int32Value(context1).FromJust());
   10055 
   10056   v8::MaybeLocal<v8::Value> maybe_value =
   10057       v8_compile("other.unreachable")->Run(context1);
   10058   CHECK(maybe_value.IsEmpty());
   10059 
   10060   context1->Exit();
   10061   context0->Exit();
   10062 }
   10063 
   10064 
   10065 static int access_count = 0;
   10066 
   10067 static bool AccessCounter(Local<v8::Context> accessing_context,
   10068                           Local<v8::Object> accessed_object) {
   10069   access_count++;
   10070   return true;
   10071 }
   10072 
   10073 
   10074 // This one is too easily disturbed by other tests.
   10075 TEST(AccessControlIC) {
   10076   access_count = 0;
   10077 
   10078   v8::Isolate* isolate = CcTest::isolate();
   10079   v8::HandleScope handle_scope(isolate);
   10080 
   10081   // Create an environment.
   10082   v8::Local<Context> context0 = Context::New(isolate);
   10083   context0->Enter();
   10084 
   10085   // Create an object that requires access-check functions to be
   10086   // called for cross-domain access.
   10087   v8::Local<v8::ObjectTemplate> object_template =
   10088       v8::ObjectTemplate::New(isolate);
   10089   object_template->SetAccessCheckCallback(AccessCounter);
   10090   Local<v8::Object> object =
   10091       object_template->NewInstance(context0).ToLocalChecked();
   10092 
   10093   v8::HandleScope scope1(isolate);
   10094 
   10095   // Create another environment.
   10096   v8::Local<Context> context1 = Context::New(isolate);
   10097   context1->Enter();
   10098 
   10099   // Make easy access to the object from the other environment.
   10100   v8::Local<v8::Object> global1 = context1->Global();
   10101   CHECK(global1->Set(context1, v8_str("obj"), object).FromJust());
   10102 
   10103   v8::Local<Value> value;
   10104 
   10105   // Check that the named access-control function is called every time.
   10106   CompileRun("function testProp(obj) {"
   10107              "  for (var i = 0; i < 10; i++) obj.prop = 1;"
   10108              "  for (var j = 0; j < 10; j++) obj.prop;"
   10109              "  return obj.prop"
   10110              "}");
   10111   value = CompileRun("testProp(obj)");
   10112   CHECK(value->IsNumber());
   10113   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10114   CHECK_EQ(21, access_count);
   10115 
   10116   // Check that the named access-control function is called every time.
   10117   CompileRun("var p = 'prop';"
   10118              "function testKeyed(obj) {"
   10119              "  for (var i = 0; i < 10; i++) obj[p] = 1;"
   10120              "  for (var j = 0; j < 10; j++) obj[p];"
   10121              "  return obj[p];"
   10122              "}");
   10123   // Use obj which requires access checks.  No inline caching is used
   10124   // in that case.
   10125   value = CompileRun("testKeyed(obj)");
   10126   CHECK(value->IsNumber());
   10127   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10128   CHECK_EQ(42, access_count);
   10129   // Force the inline caches into generic state and try again.
   10130   CompileRun("testKeyed({ a: 0 })");
   10131   CompileRun("testKeyed({ b: 0 })");
   10132   value = CompileRun("testKeyed(obj)");
   10133   CHECK(value->IsNumber());
   10134   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10135   CHECK_EQ(63, access_count);
   10136 
   10137   // Check that the indexed access-control function is called every time.
   10138   access_count = 0;
   10139 
   10140   CompileRun("function testIndexed(obj) {"
   10141              "  for (var i = 0; i < 10; i++) obj[0] = 1;"
   10142              "  for (var j = 0; j < 10; j++) obj[0];"
   10143              "  return obj[0]"
   10144              "}");
   10145   value = CompileRun("testIndexed(obj)");
   10146   CHECK(value->IsNumber());
   10147   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10148   CHECK_EQ(21, access_count);
   10149   // Force the inline caches into generic state.
   10150   CompileRun("testIndexed(new Array(1))");
   10151   // Test that the indexed access check is called.
   10152   value = CompileRun("testIndexed(obj)");
   10153   CHECK(value->IsNumber());
   10154   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10155   CHECK_EQ(42, access_count);
   10156 
   10157   access_count = 0;
   10158   // Check that the named access check is called when invoking
   10159   // functions on an object that requires access checks.
   10160   CompileRun("obj.f = function() {}");
   10161   CompileRun("function testCallNormal(obj) {"
   10162              "  for (var i = 0; i < 10; i++) obj.f();"
   10163              "}");
   10164   CompileRun("testCallNormal(obj)");
   10165   printf("%i\n", access_count);
   10166   CHECK_EQ(11, access_count);
   10167 
   10168   // Force obj into slow case.
   10169   value = CompileRun("delete obj.prop");
   10170   CHECK(value->BooleanValue(context1).FromJust());
   10171   // Force inline caches into dictionary probing mode.
   10172   CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
   10173   // Test that the named access check is called.
   10174   value = CompileRun("testProp(obj);");
   10175   CHECK(value->IsNumber());
   10176   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10177   CHECK_EQ(33, access_count);
   10178 
   10179   // Force the call inline cache into dictionary probing mode.
   10180   CompileRun("o.f = function() {}; testCallNormal(o)");
   10181   // Test that the named access check is still called for each
   10182   // invocation of the function.
   10183   value = CompileRun("testCallNormal(obj)");
   10184   CHECK_EQ(43, access_count);
   10185 
   10186   context1->Exit();
   10187   context0->Exit();
   10188 }
   10189 
   10190 
   10191 THREADED_TEST(Version) { v8::V8::GetVersion(); }
   10192 
   10193 
   10194 static void InstanceFunctionCallback(
   10195     const v8::FunctionCallbackInfo<v8::Value>& args) {
   10196   ApiTestFuzzer::Fuzz();
   10197   args.GetReturnValue().Set(v8_num(12));
   10198 }
   10199 
   10200 
   10201 THREADED_TEST(InstanceProperties) {
   10202   LocalContext context;
   10203   v8::Isolate* isolate = context->GetIsolate();
   10204   v8::HandleScope handle_scope(isolate);
   10205 
   10206   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10207   Local<ObjectTemplate> instance = t->InstanceTemplate();
   10208 
   10209   instance->Set(v8_str("x"), v8_num(42));
   10210   instance->Set(v8_str("f"),
   10211                 v8::FunctionTemplate::New(isolate, InstanceFunctionCallback));
   10212 
   10213   Local<Value> o = t->GetFunction(context.local())
   10214                        .ToLocalChecked()
   10215                        ->NewInstance(context.local())
   10216                        .ToLocalChecked();
   10217 
   10218   CHECK(context->Global()->Set(context.local(), v8_str("i"), o).FromJust());
   10219   Local<Value> value = CompileRun("i.x");
   10220   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   10221 
   10222   value = CompileRun("i.f()");
   10223   CHECK_EQ(12, value->Int32Value(context.local()).FromJust());
   10224 }
   10225 
   10226 
   10227 static void GlobalObjectInstancePropertiesGet(
   10228     Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>&) {
   10229   ApiTestFuzzer::Fuzz();
   10230 }
   10231 
   10232 
   10233 THREADED_TEST(GlobalObjectInstanceProperties) {
   10234   v8::Isolate* isolate = CcTest::isolate();
   10235   v8::HandleScope handle_scope(isolate);
   10236 
   10237   Local<Value> global_object;
   10238 
   10239   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10240   t->InstanceTemplate()->SetHandler(
   10241       v8::NamedPropertyHandlerConfiguration(GlobalObjectInstancePropertiesGet));
   10242   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   10243   instance_template->Set(v8_str("x"), v8_num(42));
   10244   instance_template->Set(v8_str("f"),
   10245                          v8::FunctionTemplate::New(isolate,
   10246                                                    InstanceFunctionCallback));
   10247 
   10248   // The script to check how Crankshaft compiles missing global function
   10249   // invocations.  function g is not defined and should throw on call.
   10250   const char* script =
   10251       "function wrapper(call) {"
   10252       "  var x = 0, y = 1;"
   10253       "  for (var i = 0; i < 1000; i++) {"
   10254       "    x += i * 100;"
   10255       "    y += i * 100;"
   10256       "  }"
   10257       "  if (call) g();"
   10258       "}"
   10259       "for (var i = 0; i < 17; i++) wrapper(false);"
   10260       "var thrown = 0;"
   10261       "try { wrapper(true); } catch (e) { thrown = 1; };"
   10262       "thrown";
   10263 
   10264   {
   10265     LocalContext env(NULL, instance_template);
   10266     // Hold on to the global object so it can be used again in another
   10267     // environment initialization.
   10268     global_object = env->Global();
   10269 
   10270     Local<Value> value = CompileRun("x");
   10271     CHECK_EQ(42, value->Int32Value(env.local()).FromJust());
   10272     value = CompileRun("f()");
   10273     CHECK_EQ(12, value->Int32Value(env.local()).FromJust());
   10274     value = CompileRun(script);
   10275     CHECK_EQ(1, value->Int32Value(env.local()).FromJust());
   10276   }
   10277 
   10278   {
   10279     // Create new environment reusing the global object.
   10280     LocalContext env(NULL, instance_template, global_object);
   10281     Local<Value> value = CompileRun("x");
   10282     CHECK_EQ(42, value->Int32Value(env.local()).FromJust());
   10283     value = CompileRun("f()");
   10284     CHECK_EQ(12, value->Int32Value(env.local()).FromJust());
   10285     value = CompileRun(script);
   10286     CHECK_EQ(1, value->Int32Value(env.local()).FromJust());
   10287   }
   10288 }
   10289 
   10290 
   10291 THREADED_TEST(CallKnownGlobalReceiver) {
   10292   v8::Isolate* isolate = CcTest::isolate();
   10293   v8::HandleScope handle_scope(isolate);
   10294 
   10295   Local<Value> global_object;
   10296 
   10297   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10298   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   10299 
   10300   // The script to check that we leave global object not
   10301   // global object proxy on stack when we deoptimize from inside
   10302   // arguments evaluation.
   10303   // To provoke error we need to both force deoptimization
   10304   // from arguments evaluation and to force CallIC to take
   10305   // CallIC_Miss code path that can't cope with global proxy.
   10306   const char* script =
   10307       "function bar(x, y) { try { } finally { } }"
   10308       "function baz(x) { try { } finally { } }"
   10309       "function bom(x) { try { } finally { } }"
   10310       "function foo(x) { bar([x], bom(2)); }"
   10311       "for (var i = 0; i < 10000; i++) foo(1);"
   10312       "foo";
   10313 
   10314   Local<Value> foo;
   10315   {
   10316     LocalContext env(NULL, instance_template);
   10317     // Hold on to the global object so it can be used again in another
   10318     // environment initialization.
   10319     global_object = env->Global();
   10320     foo = CompileRun(script);
   10321   }
   10322 
   10323   {
   10324     // Create new environment reusing the global object.
   10325     LocalContext env(NULL, instance_template, global_object);
   10326     CHECK(env->Global()->Set(env.local(), v8_str("foo"), foo).FromJust());
   10327     CompileRun("foo()");
   10328   }
   10329 }
   10330 
   10331 
   10332 static void ShadowFunctionCallback(
   10333     const v8::FunctionCallbackInfo<v8::Value>& args) {
   10334   ApiTestFuzzer::Fuzz();
   10335   args.GetReturnValue().Set(v8_num(42));
   10336 }
   10337 
   10338 
   10339 static int shadow_y;
   10340 static int shadow_y_setter_call_count;
   10341 static int shadow_y_getter_call_count;
   10342 
   10343 
   10344 static void ShadowYSetter(Local<String>,
   10345                           Local<Value>,
   10346                           const v8::PropertyCallbackInfo<void>&) {
   10347   shadow_y_setter_call_count++;
   10348   shadow_y = 42;
   10349 }
   10350 
   10351 
   10352 static void ShadowYGetter(Local<String> name,
   10353                           const v8::PropertyCallbackInfo<v8::Value>& info) {
   10354   ApiTestFuzzer::Fuzz();
   10355   shadow_y_getter_call_count++;
   10356   info.GetReturnValue().Set(v8_num(shadow_y));
   10357 }
   10358 
   10359 
   10360 static void ShadowIndexedGet(uint32_t index,
   10361                              const v8::PropertyCallbackInfo<v8::Value>&) {
   10362 }
   10363 
   10364 
   10365 static void ShadowNamedGet(Local<Name> key,
   10366                            const v8::PropertyCallbackInfo<v8::Value>&) {}
   10367 
   10368 
   10369 THREADED_TEST(ShadowObject) {
   10370   shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
   10371   v8::Isolate* isolate = CcTest::isolate();
   10372   v8::HandleScope handle_scope(isolate);
   10373 
   10374   Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
   10375   LocalContext context(NULL, global_template);
   10376 
   10377   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10378   t->InstanceTemplate()->SetHandler(
   10379       v8::NamedPropertyHandlerConfiguration(ShadowNamedGet));
   10380   t->InstanceTemplate()->SetHandler(
   10381       v8::IndexedPropertyHandlerConfiguration(ShadowIndexedGet));
   10382   Local<ObjectTemplate> proto = t->PrototypeTemplate();
   10383   Local<ObjectTemplate> instance = t->InstanceTemplate();
   10384 
   10385   proto->Set(v8_str("f"),
   10386              v8::FunctionTemplate::New(isolate,
   10387                                        ShadowFunctionCallback,
   10388                                        Local<Value>()));
   10389   proto->Set(v8_str("x"), v8_num(12));
   10390 
   10391   instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
   10392 
   10393   Local<Value> o = t->GetFunction(context.local())
   10394                        .ToLocalChecked()
   10395                        ->NewInstance(context.local())
   10396                        .ToLocalChecked();
   10397   CHECK(context->Global()
   10398             ->Set(context.local(), v8_str("__proto__"), o)
   10399             .FromJust());
   10400 
   10401   Local<Value> value =
   10402       CompileRun("this.propertyIsEnumerable(0)");
   10403   CHECK(value->IsBoolean());
   10404   CHECK(!value->BooleanValue(context.local()).FromJust());
   10405 
   10406   value = CompileRun("x");
   10407   CHECK_EQ(12, value->Int32Value(context.local()).FromJust());
   10408 
   10409   value = CompileRun("f()");
   10410   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   10411 
   10412   CompileRun("y = 43");
   10413   CHECK_EQ(1, shadow_y_setter_call_count);
   10414   value = CompileRun("y");
   10415   CHECK_EQ(1, shadow_y_getter_call_count);
   10416   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   10417 }
   10418 
   10419 
   10420 THREADED_TEST(HiddenPrototype) {
   10421   LocalContext context;
   10422   v8::Isolate* isolate = context->GetIsolate();
   10423   v8::HandleScope handle_scope(isolate);
   10424 
   10425   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
   10426   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   10427   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   10428   t1->SetHiddenPrototype(true);
   10429   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
   10430   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   10431   t2->SetHiddenPrototype(true);
   10432   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
   10433   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
   10434   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
   10435 
   10436   Local<v8::Object> o0 = t0->GetFunction(context.local())
   10437                              .ToLocalChecked()
   10438                              ->NewInstance(context.local())
   10439                              .ToLocalChecked();
   10440   Local<v8::Object> o1 = t1->GetFunction(context.local())
   10441                              .ToLocalChecked()
   10442                              ->NewInstance(context.local())
   10443                              .ToLocalChecked();
   10444   Local<v8::Object> o2 = t2->GetFunction(context.local())
   10445                              .ToLocalChecked()
   10446                              ->NewInstance(context.local())
   10447                              .ToLocalChecked();
   10448   Local<v8::Object> o3 = t3->GetFunction(context.local())
   10449                              .ToLocalChecked()
   10450                              ->NewInstance(context.local())
   10451                              .ToLocalChecked();
   10452 
   10453   // Setting the prototype on an object skips hidden prototypes.
   10454   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   10455                   .ToLocalChecked()
   10456                   ->Int32Value(context.local())
   10457                   .FromJust());
   10458   CHECK(o0->Set(context.local(), v8_str("__proto__"), o1).FromJust());
   10459   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   10460                   .ToLocalChecked()
   10461                   ->Int32Value(context.local())
   10462                   .FromJust());
   10463   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   10464                   .ToLocalChecked()
   10465                   ->Int32Value(context.local())
   10466                   .FromJust());
   10467   CHECK(o0->Set(context.local(), v8_str("__proto__"), o2).FromJust());
   10468   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   10469                   .ToLocalChecked()
   10470                   ->Int32Value(context.local())
   10471                   .FromJust());
   10472   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   10473                   .ToLocalChecked()
   10474                   ->Int32Value(context.local())
   10475                   .FromJust());
   10476   CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
   10477                   .ToLocalChecked()
   10478                   ->Int32Value(context.local())
   10479                   .FromJust());
   10480   CHECK(o0->Set(context.local(), v8_str("__proto__"), o3).FromJust());
   10481   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   10482                   .ToLocalChecked()
   10483                   ->Int32Value(context.local())
   10484                   .FromJust());
   10485   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   10486                   .ToLocalChecked()
   10487                   ->Int32Value(context.local())
   10488                   .FromJust());
   10489   CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
   10490                   .ToLocalChecked()
   10491                   ->Int32Value(context.local())
   10492                   .FromJust());
   10493   CHECK_EQ(3, o0->Get(context.local(), v8_str("u"))
   10494                   .ToLocalChecked()
   10495                   ->Int32Value(context.local())
   10496                   .FromJust());
   10497 
   10498   // Getting the prototype of o0 should get the first visible one
   10499   // which is o3.  Therefore, z should not be defined on the prototype
   10500   // object.
   10501   Local<Value> proto =
   10502       o0->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   10503   CHECK(proto->IsObject());
   10504   CHECK(proto.As<v8::Object>()
   10505             ->Get(context.local(), v8_str("z"))
   10506             .ToLocalChecked()
   10507             ->IsUndefined());
   10508 }
   10509 
   10510 
   10511 THREADED_TEST(HiddenPrototypeSet) {
   10512   LocalContext context;
   10513   v8::Isolate* isolate = context->GetIsolate();
   10514   v8::HandleScope handle_scope(isolate);
   10515 
   10516   Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New(isolate);
   10517   Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New(isolate);
   10518   ht->SetHiddenPrototype(true);
   10519   Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New(isolate);
   10520   ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   10521 
   10522   Local<v8::Object> o = ot->GetFunction(context.local())
   10523                             .ToLocalChecked()
   10524                             ->NewInstance(context.local())
   10525                             .ToLocalChecked();
   10526   Local<v8::Object> h = ht->GetFunction(context.local())
   10527                             .ToLocalChecked()
   10528                             ->NewInstance(context.local())
   10529                             .ToLocalChecked();
   10530   Local<v8::Object> p = pt->GetFunction(context.local())
   10531                             .ToLocalChecked()
   10532                             ->NewInstance(context.local())
   10533                             .ToLocalChecked();
   10534   CHECK(o->Set(context.local(), v8_str("__proto__"), h).FromJust());
   10535   CHECK(h->Set(context.local(), v8_str("__proto__"), p).FromJust());
   10536 
   10537   // Setting a property that exists on the hidden prototype goes there.
   10538   CHECK(o->Set(context.local(), v8_str("x"), v8_num(7)).FromJust());
   10539   CHECK_EQ(7, o->Get(context.local(), v8_str("x"))
   10540                   .ToLocalChecked()
   10541                   ->Int32Value(context.local())
   10542                   .FromJust());
   10543   CHECK_EQ(7, h->Get(context.local(), v8_str("x"))
   10544                   .ToLocalChecked()
   10545                   ->Int32Value(context.local())
   10546                   .FromJust());
   10547   CHECK(p->Get(context.local(), v8_str("x")).ToLocalChecked()->IsUndefined());
   10548 
   10549   // Setting a new property should not be forwarded to the hidden prototype.
   10550   CHECK(o->Set(context.local(), v8_str("y"), v8_num(6)).FromJust());
   10551   CHECK_EQ(6, o->Get(context.local(), v8_str("y"))
   10552                   .ToLocalChecked()
   10553                   ->Int32Value(context.local())
   10554                   .FromJust());
   10555   CHECK(h->Get(context.local(), v8_str("y")).ToLocalChecked()->IsUndefined());
   10556   CHECK(p->Get(context.local(), v8_str("y")).ToLocalChecked()->IsUndefined());
   10557 
   10558   // Setting a property that only exists on a prototype of the hidden prototype
   10559   // is treated normally again.
   10560   CHECK(p->Set(context.local(), v8_str("z"), v8_num(8)).FromJust());
   10561   CHECK_EQ(8, o->Get(context.local(), v8_str("z"))
   10562                   .ToLocalChecked()
   10563                   ->Int32Value(context.local())
   10564                   .FromJust());
   10565   CHECK_EQ(8, h->Get(context.local(), v8_str("z"))
   10566                   .ToLocalChecked()
   10567                   ->Int32Value(context.local())
   10568                   .FromJust());
   10569   CHECK_EQ(8, p->Get(context.local(), v8_str("z"))
   10570                   .ToLocalChecked()
   10571                   ->Int32Value(context.local())
   10572                   .FromJust());
   10573   CHECK(o->Set(context.local(), v8_str("z"), v8_num(9)).FromJust());
   10574   CHECK_EQ(9, o->Get(context.local(), v8_str("z"))
   10575                   .ToLocalChecked()
   10576                   ->Int32Value(context.local())
   10577                   .FromJust());
   10578   CHECK_EQ(8, h->Get(context.local(), v8_str("z"))
   10579                   .ToLocalChecked()
   10580                   ->Int32Value(context.local())
   10581                   .FromJust());
   10582   CHECK_EQ(8, p->Get(context.local(), v8_str("z"))
   10583                   .ToLocalChecked()
   10584                   ->Int32Value(context.local())
   10585                   .FromJust());
   10586 }
   10587 
   10588 
   10589 // Regression test for issue 2457.
   10590 THREADED_TEST(HiddenPrototypeIdentityHash) {
   10591   LocalContext context;
   10592   v8::HandleScope handle_scope(context->GetIsolate());
   10593 
   10594   Local<FunctionTemplate> t = FunctionTemplate::New(context->GetIsolate());
   10595   t->SetHiddenPrototype(true);
   10596   t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
   10597   Local<Object> p = t->GetFunction(context.local())
   10598                         .ToLocalChecked()
   10599                         ->NewInstance(context.local())
   10600                         .ToLocalChecked();
   10601   Local<Object> o = Object::New(context->GetIsolate());
   10602   CHECK(o->SetPrototype(context.local(), p).FromJust());
   10603 
   10604   int hash = o->GetIdentityHash();
   10605   USE(hash);
   10606   CHECK(o->Set(context.local(), v8_str("foo"), v8_num(42)).FromJust());
   10607   CHECK_EQ(hash, o->GetIdentityHash());
   10608 }
   10609 
   10610 
   10611 THREADED_TEST(SetPrototype) {
   10612   LocalContext context;
   10613   v8::Isolate* isolate = context->GetIsolate();
   10614   v8::HandleScope handle_scope(isolate);
   10615 
   10616   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
   10617   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   10618   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   10619   t1->SetHiddenPrototype(true);
   10620   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
   10621   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   10622   t2->SetHiddenPrototype(true);
   10623   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
   10624   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
   10625   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
   10626 
   10627   Local<v8::Object> o0 = t0->GetFunction(context.local())
   10628                              .ToLocalChecked()
   10629                              ->NewInstance(context.local())
   10630                              .ToLocalChecked();
   10631   Local<v8::Object> o1 = t1->GetFunction(context.local())
   10632                              .ToLocalChecked()
   10633                              ->NewInstance(context.local())
   10634                              .ToLocalChecked();
   10635   Local<v8::Object> o2 = t2->GetFunction(context.local())
   10636                              .ToLocalChecked()
   10637                              ->NewInstance(context.local())
   10638                              .ToLocalChecked();
   10639   Local<v8::Object> o3 = t3->GetFunction(context.local())
   10640                              .ToLocalChecked()
   10641                              ->NewInstance(context.local())
   10642                              .ToLocalChecked();
   10643 
   10644   // Setting the prototype on an object does not skip hidden prototypes.
   10645   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   10646                   .ToLocalChecked()
   10647                   ->Int32Value(context.local())
   10648                   .FromJust());
   10649   CHECK(o0->SetPrototype(context.local(), o1).FromJust());
   10650   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   10651                   .ToLocalChecked()
   10652                   ->Int32Value(context.local())
   10653                   .FromJust());
   10654   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   10655                   .ToLocalChecked()
   10656                   ->Int32Value(context.local())
   10657                   .FromJust());
   10658   CHECK(o1->SetPrototype(context.local(), o2).FromJust());
   10659   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   10660                   .ToLocalChecked()
   10661                   ->Int32Value(context.local())
   10662                   .FromJust());
   10663   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   10664                   .ToLocalChecked()
   10665                   ->Int32Value(context.local())
   10666                   .FromJust());
   10667   CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
   10668                   .ToLocalChecked()
   10669                   ->Int32Value(context.local())
   10670                   .FromJust());
   10671   CHECK(o2->SetPrototype(context.local(), o3).FromJust());
   10672   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   10673                   .ToLocalChecked()
   10674                   ->Int32Value(context.local())
   10675                   .FromJust());
   10676   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   10677                   .ToLocalChecked()
   10678                   ->Int32Value(context.local())
   10679                   .FromJust());
   10680   CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
   10681                   .ToLocalChecked()
   10682                   ->Int32Value(context.local())
   10683                   .FromJust());
   10684   CHECK_EQ(3, o0->Get(context.local(), v8_str("u"))
   10685                   .ToLocalChecked()
   10686                   ->Int32Value(context.local())
   10687                   .FromJust());
   10688 
   10689   // Getting the prototype of o0 should get the first visible one
   10690   // which is o3.  Therefore, z should not be defined on the prototype
   10691   // object.
   10692   Local<Value> proto =
   10693       o0->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   10694   CHECK(proto->IsObject());
   10695   CHECK(proto.As<v8::Object>()->Equals(context.local(), o3).FromJust());
   10696 
   10697   // However, Object::GetPrototype ignores hidden prototype.
   10698   Local<Value> proto0 = o0->GetPrototype();
   10699   CHECK(proto0->IsObject());
   10700   CHECK(proto0.As<v8::Object>()->Equals(context.local(), o1).FromJust());
   10701 
   10702   Local<Value> proto1 = o1->GetPrototype();
   10703   CHECK(proto1->IsObject());
   10704   CHECK(proto1.As<v8::Object>()->Equals(context.local(), o2).FromJust());
   10705 
   10706   Local<Value> proto2 = o2->GetPrototype();
   10707   CHECK(proto2->IsObject());
   10708   CHECK(proto2.As<v8::Object>()->Equals(context.local(), o3).FromJust());
   10709 }
   10710 
   10711 
   10712 // Getting property names of an object with a prototype chain that
   10713 // triggers dictionary elements in GetOwnPropertyNames() shouldn't
   10714 // crash the runtime.
   10715 THREADED_TEST(Regress91517) {
   10716   i::FLAG_allow_natives_syntax = true;
   10717   LocalContext context;
   10718   v8::Isolate* isolate = context->GetIsolate();
   10719   v8::HandleScope handle_scope(isolate);
   10720 
   10721   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   10722   t1->SetHiddenPrototype(true);
   10723   t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
   10724   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   10725   t2->SetHiddenPrototype(true);
   10726   t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
   10727   t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New(isolate));
   10728   t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
   10729   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
   10730   t3->SetHiddenPrototype(true);
   10731   t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
   10732   Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(isolate);
   10733   t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
   10734 
   10735   // Force dictionary-based properties.
   10736   i::ScopedVector<char> name_buf(1024);
   10737   for (int i = 1; i <= 1000; i++) {
   10738     i::SNPrintF(name_buf, "sdf%d", i);
   10739     t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
   10740   }
   10741 
   10742   Local<v8::Object> o1 = t1->GetFunction(context.local())
   10743                              .ToLocalChecked()
   10744                              ->NewInstance(context.local())
   10745                              .ToLocalChecked();
   10746   Local<v8::Object> o2 = t2->GetFunction(context.local())
   10747                              .ToLocalChecked()
   10748                              ->NewInstance(context.local())
   10749                              .ToLocalChecked();
   10750   Local<v8::Object> o3 = t3->GetFunction(context.local())
   10751                              .ToLocalChecked()
   10752                              ->NewInstance(context.local())
   10753                              .ToLocalChecked();
   10754   Local<v8::Object> o4 = t4->GetFunction(context.local())
   10755                              .ToLocalChecked()
   10756                              ->NewInstance(context.local())
   10757                              .ToLocalChecked();
   10758 
   10759   // Create prototype chain of hidden prototypes.
   10760   CHECK(o4->SetPrototype(context.local(), o3).FromJust());
   10761   CHECK(o3->SetPrototype(context.local(), o2).FromJust());
   10762   CHECK(o2->SetPrototype(context.local(), o1).FromJust());
   10763 
   10764   // Call the runtime version of GetOwnPropertyNames() on the natively
   10765   // created object through JavaScript.
   10766   CHECK(context->Global()->Set(context.local(), v8_str("obj"), o4).FromJust());
   10767   // PROPERTY_FILTER_NONE = 0
   10768   CompileRun("var names = %GetOwnPropertyKeys(obj, 0);");
   10769 
   10770   ExpectInt32("names.length", 1006);
   10771   ExpectTrue("names.indexOf(\"baz\") >= 0");
   10772   ExpectTrue("names.indexOf(\"boo\") >= 0");
   10773   ExpectTrue("names.indexOf(\"foo\") >= 0");
   10774   ExpectTrue("names.indexOf(\"fuz1\") >= 0");
   10775   ExpectTrue("names.indexOf(\"fuz2\") >= 0");
   10776   ExpectFalse("names[1005] == undefined");
   10777 }
   10778 
   10779 
   10780 // Getting property names of an object with a hidden and inherited
   10781 // prototype should not duplicate the accessor properties inherited.
   10782 THREADED_TEST(Regress269562) {
   10783   i::FLAG_allow_natives_syntax = true;
   10784   LocalContext context;
   10785   v8::HandleScope handle_scope(context->GetIsolate());
   10786 
   10787   Local<v8::FunctionTemplate> t1 =
   10788       v8::FunctionTemplate::New(context->GetIsolate());
   10789   t1->SetHiddenPrototype(true);
   10790 
   10791   Local<v8::ObjectTemplate> i1 = t1->InstanceTemplate();
   10792   i1->SetAccessor(v8_str("foo"),
   10793                   SimpleAccessorGetter, SimpleAccessorSetter);
   10794   i1->SetAccessor(v8_str("bar"),
   10795                   SimpleAccessorGetter, SimpleAccessorSetter);
   10796   i1->SetAccessor(v8_str("baz"),
   10797                   SimpleAccessorGetter, SimpleAccessorSetter);
   10798   i1->Set(v8_str("n1"), v8_num(1));
   10799   i1->Set(v8_str("n2"), v8_num(2));
   10800 
   10801   Local<v8::Object> o1 = t1->GetFunction(context.local())
   10802                              .ToLocalChecked()
   10803                              ->NewInstance(context.local())
   10804                              .ToLocalChecked();
   10805   Local<v8::FunctionTemplate> t2 =
   10806       v8::FunctionTemplate::New(context->GetIsolate());
   10807   t2->SetHiddenPrototype(true);
   10808 
   10809   // Inherit from t1 and mark prototype as hidden.
   10810   t2->Inherit(t1);
   10811   t2->InstanceTemplate()->Set(v8_str("mine"), v8_num(4));
   10812 
   10813   Local<v8::Object> o2 = t2->GetFunction(context.local())
   10814                              .ToLocalChecked()
   10815                              ->NewInstance(context.local())
   10816                              .ToLocalChecked();
   10817   CHECK(o2->SetPrototype(context.local(), o1).FromJust());
   10818 
   10819   v8::Local<v8::Symbol> sym =
   10820       v8::Symbol::New(context->GetIsolate(), v8_str("s1"));
   10821   CHECK(o1->Set(context.local(), sym, v8_num(3)).FromJust());
   10822   o1->SetPrivate(context.local(),
   10823                  v8::Private::New(context->GetIsolate(), v8_str("h1")),
   10824                  v8::Integer::New(context->GetIsolate(), 2013))
   10825       .FromJust();
   10826 
   10827   // Call the runtime version of GetOwnPropertyNames() on
   10828   // the natively created object through JavaScript.
   10829   CHECK(context->Global()->Set(context.local(), v8_str("obj"), o2).FromJust());
   10830   CHECK(context->Global()->Set(context.local(), v8_str("sym"), sym).FromJust());
   10831   // PROPERTY_FILTER_NONE = 0
   10832   CompileRun("var names = %GetOwnPropertyKeys(obj, 0);");
   10833 
   10834   ExpectInt32("names.length", 7);
   10835   ExpectTrue("names.indexOf(\"foo\") >= 0");
   10836   ExpectTrue("names.indexOf(\"bar\") >= 0");
   10837   ExpectTrue("names.indexOf(\"baz\") >= 0");
   10838   ExpectTrue("names.indexOf(\"n1\") >= 0");
   10839   ExpectTrue("names.indexOf(\"n2\") >= 0");
   10840   ExpectTrue("names.indexOf(sym) >= 0");
   10841   ExpectTrue("names.indexOf(\"mine\") >= 0");
   10842 }
   10843 
   10844 
   10845 THREADED_TEST(FunctionReadOnlyPrototype) {
   10846   LocalContext context;
   10847   v8::Isolate* isolate = context->GetIsolate();
   10848   v8::HandleScope handle_scope(isolate);
   10849 
   10850   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   10851   t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
   10852   t1->ReadOnlyPrototype();
   10853   CHECK(context->Global()
   10854             ->Set(context.local(), v8_str("func1"),
   10855                   t1->GetFunction(context.local()).ToLocalChecked())
   10856             .FromJust());
   10857   // Configured value of ReadOnly flag.
   10858   CHECK(
   10859       CompileRun(
   10860           "(function() {"
   10861           "  descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
   10862           "  return (descriptor['writable'] == false);"
   10863           "})()")
   10864           ->BooleanValue(context.local())
   10865           .FromJust());
   10866   CHECK_EQ(
   10867       42,
   10868       CompileRun("func1.prototype.x")->Int32Value(context.local()).FromJust());
   10869   CHECK_EQ(42, CompileRun("func1.prototype = {}; func1.prototype.x")
   10870                    ->Int32Value(context.local())
   10871                    .FromJust());
   10872 
   10873   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   10874   t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
   10875   CHECK(context->Global()
   10876             ->Set(context.local(), v8_str("func2"),
   10877                   t2->GetFunction(context.local()).ToLocalChecked())
   10878             .FromJust());
   10879   // Default value of ReadOnly flag.
   10880   CHECK(
   10881       CompileRun(
   10882           "(function() {"
   10883           "  descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
   10884           "  return (descriptor['writable'] == true);"
   10885           "})()")
   10886           ->BooleanValue(context.local())
   10887           .FromJust());
   10888   CHECK_EQ(
   10889       42,
   10890       CompileRun("func2.prototype.x")->Int32Value(context.local()).FromJust());
   10891 }
   10892 
   10893 
   10894 THREADED_TEST(SetPrototypeThrows) {
   10895   LocalContext context;
   10896   v8::Isolate* isolate = context->GetIsolate();
   10897   v8::HandleScope handle_scope(isolate);
   10898 
   10899   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10900 
   10901   Local<v8::Object> o0 = t->GetFunction(context.local())
   10902                              .ToLocalChecked()
   10903                              ->NewInstance(context.local())
   10904                              .ToLocalChecked();
   10905   Local<v8::Object> o1 = t->GetFunction(context.local())
   10906                              .ToLocalChecked()
   10907                              ->NewInstance(context.local())
   10908                              .ToLocalChecked();
   10909 
   10910   CHECK(o0->SetPrototype(context.local(), o1).FromJust());
   10911   // If setting the prototype leads to the cycle, SetPrototype should
   10912   // return false and keep VM in sane state.
   10913   v8::TryCatch try_catch(isolate);
   10914   CHECK(o1->SetPrototype(context.local(), o0).IsNothing());
   10915   CHECK(!try_catch.HasCaught());
   10916   CHECK(!CcTest::i_isolate()->has_pending_exception());
   10917 
   10918   CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")
   10919                    ->Int32Value(context.local())
   10920                    .FromJust());
   10921 }
   10922 
   10923 
   10924 THREADED_TEST(FunctionRemovePrototype) {
   10925   LocalContext context;
   10926   v8::Isolate* isolate = context->GetIsolate();
   10927   v8::HandleScope handle_scope(isolate);
   10928 
   10929   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   10930   t1->RemovePrototype();
   10931   Local<v8::Function> fun = t1->GetFunction(context.local()).ToLocalChecked();
   10932   CHECK(context->Global()->Set(context.local(), v8_str("fun"), fun).FromJust());
   10933   CHECK(!CompileRun("'prototype' in fun")
   10934              ->BooleanValue(context.local())
   10935              .FromJust());
   10936 
   10937   v8::TryCatch try_catch(isolate);
   10938   CompileRun("new fun()");
   10939   CHECK(try_catch.HasCaught());
   10940 
   10941   try_catch.Reset();
   10942   CHECK(fun->NewInstance(context.local()).IsEmpty());
   10943   CHECK(try_catch.HasCaught());
   10944 }
   10945 
   10946 
   10947 THREADED_TEST(GetterSetterExceptions) {
   10948   LocalContext context;
   10949   v8::Isolate* isolate = context->GetIsolate();
   10950   v8::HandleScope handle_scope(isolate);
   10951   CompileRun(
   10952       "function Foo() { };"
   10953       "function Throw() { throw 5; };"
   10954       "var x = { };"
   10955       "x.__defineSetter__('set', Throw);"
   10956       "x.__defineGetter__('get', Throw);");
   10957   Local<v8::Object> x = Local<v8::Object>::Cast(
   10958       context->Global()->Get(context.local(), v8_str("x")).ToLocalChecked());
   10959   v8::TryCatch try_catch(isolate);
   10960   CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
   10961             .IsNothing());
   10962   CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
   10963   CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
   10964             .IsNothing());
   10965   CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
   10966   CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
   10967             .IsNothing());
   10968   CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
   10969   CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
   10970             .IsNothing());
   10971   CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
   10972 }
   10973 
   10974 
   10975 THREADED_TEST(Constructor) {
   10976   LocalContext context;
   10977   v8::Isolate* isolate = context->GetIsolate();
   10978   v8::HandleScope handle_scope(isolate);
   10979   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   10980   templ->SetClassName(v8_str("Fun"));
   10981   Local<Function> cons = templ->GetFunction(context.local()).ToLocalChecked();
   10982   CHECK(
   10983       context->Global()->Set(context.local(), v8_str("Fun"), cons).FromJust());
   10984   Local<v8::Object> inst = cons->NewInstance(context.local()).ToLocalChecked();
   10985   i::Handle<i::JSReceiver> obj(v8::Utils::OpenHandle(*inst));
   10986   CHECK(obj->IsJSObject());
   10987   Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
   10988   CHECK(value->BooleanValue(context.local()).FromJust());
   10989 }
   10990 
   10991 
   10992 static void ConstructorCallback(
   10993     const v8::FunctionCallbackInfo<v8::Value>& args) {
   10994   ApiTestFuzzer::Fuzz();
   10995   Local<Object> This;
   10996 
   10997   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   10998   if (args.IsConstructCall()) {
   10999     Local<Object> Holder = args.Holder();
   11000     This = Object::New(args.GetIsolate());
   11001     Local<Value> proto = Holder->GetPrototype();
   11002     if (proto->IsObject()) {
   11003       This->SetPrototype(context, proto).FromJust();
   11004     }
   11005   } else {
   11006     This = args.This();
   11007   }
   11008 
   11009   This->Set(context, v8_str("a"), args[0]).FromJust();
   11010   args.GetReturnValue().Set(This);
   11011 }
   11012 
   11013 
   11014 static void FakeConstructorCallback(
   11015     const v8::FunctionCallbackInfo<v8::Value>& args) {
   11016   ApiTestFuzzer::Fuzz();
   11017   args.GetReturnValue().Set(args[0]);
   11018 }
   11019 
   11020 
   11021 THREADED_TEST(ConstructorForObject) {
   11022   LocalContext context;
   11023   v8::Isolate* isolate = context->GetIsolate();
   11024   v8::HandleScope handle_scope(isolate);
   11025 
   11026   {
   11027     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   11028     instance_template->SetCallAsFunctionHandler(ConstructorCallback);
   11029     Local<Object> instance =
   11030         instance_template->NewInstance(context.local()).ToLocalChecked();
   11031     CHECK(context->Global()
   11032               ->Set(context.local(), v8_str("obj"), instance)
   11033               .FromJust());
   11034     v8::TryCatch try_catch(isolate);
   11035     Local<Value> value;
   11036     CHECK(!try_catch.HasCaught());
   11037 
   11038     // Call the Object's constructor with a 32-bit signed integer.
   11039     value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
   11040     CHECK(!try_catch.HasCaught());
   11041     CHECK(value->IsInt32());
   11042     CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
   11043 
   11044     Local<Value> args1[] = {v8_num(28)};
   11045     Local<Value> value_obj1 =
   11046         instance->CallAsConstructor(context.local(), 1, args1).ToLocalChecked();
   11047     CHECK(value_obj1->IsObject());
   11048     Local<Object> object1 = Local<Object>::Cast(value_obj1);
   11049     value = object1->Get(context.local(), v8_str("a")).ToLocalChecked();
   11050     CHECK(value->IsInt32());
   11051     CHECK(!try_catch.HasCaught());
   11052     CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
   11053 
   11054     // Call the Object's constructor with a String.
   11055     value =
   11056         CompileRun("(function() { var o = new obj('tipli'); return o.a; })()");
   11057     CHECK(!try_catch.HasCaught());
   11058     CHECK(value->IsString());
   11059     String::Utf8Value string_value1(
   11060         value->ToString(context.local()).ToLocalChecked());
   11061     CHECK_EQ(0, strcmp("tipli", *string_value1));
   11062 
   11063     Local<Value> args2[] = {v8_str("tipli")};
   11064     Local<Value> value_obj2 =
   11065         instance->CallAsConstructor(context.local(), 1, args2).ToLocalChecked();
   11066     CHECK(value_obj2->IsObject());
   11067     Local<Object> object2 = Local<Object>::Cast(value_obj2);
   11068     value = object2->Get(context.local(), v8_str("a")).ToLocalChecked();
   11069     CHECK(!try_catch.HasCaught());
   11070     CHECK(value->IsString());
   11071     String::Utf8Value string_value2(
   11072         value->ToString(context.local()).ToLocalChecked());
   11073     CHECK_EQ(0, strcmp("tipli", *string_value2));
   11074 
   11075     // Call the Object's constructor with a Boolean.
   11076     value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
   11077     CHECK(!try_catch.HasCaught());
   11078     CHECK(value->IsBoolean());
   11079     CHECK_EQ(true, value->BooleanValue(context.local()).FromJust());
   11080 
   11081     Local<Value> args3[] = {v8::True(isolate)};
   11082     Local<Value> value_obj3 =
   11083         instance->CallAsConstructor(context.local(), 1, args3).ToLocalChecked();
   11084     CHECK(value_obj3->IsObject());
   11085     Local<Object> object3 = Local<Object>::Cast(value_obj3);
   11086     value = object3->Get(context.local(), v8_str("a")).ToLocalChecked();
   11087     CHECK(!try_catch.HasCaught());
   11088     CHECK(value->IsBoolean());
   11089     CHECK_EQ(true, value->BooleanValue(context.local()).FromJust());
   11090 
   11091     // Call the Object's constructor with undefined.
   11092     Local<Value> args4[] = {v8::Undefined(isolate)};
   11093     Local<Value> value_obj4 =
   11094         instance->CallAsConstructor(context.local(), 1, args4).ToLocalChecked();
   11095     CHECK(value_obj4->IsObject());
   11096     Local<Object> object4 = Local<Object>::Cast(value_obj4);
   11097     value = object4->Get(context.local(), v8_str("a")).ToLocalChecked();
   11098     CHECK(!try_catch.HasCaught());
   11099     CHECK(value->IsUndefined());
   11100 
   11101     // Call the Object's constructor with null.
   11102     Local<Value> args5[] = {v8::Null(isolate)};
   11103     Local<Value> value_obj5 =
   11104         instance->CallAsConstructor(context.local(), 1, args5).ToLocalChecked();
   11105     CHECK(value_obj5->IsObject());
   11106     Local<Object> object5 = Local<Object>::Cast(value_obj5);
   11107     value = object5->Get(context.local(), v8_str("a")).ToLocalChecked();
   11108     CHECK(!try_catch.HasCaught());
   11109     CHECK(value->IsNull());
   11110   }
   11111 
   11112   // Check exception handling when there is no constructor set for the Object.
   11113   {
   11114     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   11115     Local<Object> instance =
   11116         instance_template->NewInstance(context.local()).ToLocalChecked();
   11117     CHECK(context->Global()
   11118               ->Set(context.local(), v8_str("obj2"), instance)
   11119               .FromJust());
   11120     v8::TryCatch try_catch(isolate);
   11121     Local<Value> value;
   11122     CHECK(!try_catch.HasCaught());
   11123 
   11124     value = CompileRun("new obj2(28)");
   11125     CHECK(try_catch.HasCaught());
   11126     String::Utf8Value exception_value1(try_catch.Exception());
   11127     CHECK_EQ(0,
   11128              strcmp("TypeError: obj2 is not a constructor", *exception_value1));
   11129     try_catch.Reset();
   11130 
   11131     Local<Value> args[] = {v8_num(29)};
   11132     CHECK(instance->CallAsConstructor(context.local(), 1, args).IsEmpty());
   11133     CHECK(try_catch.HasCaught());
   11134     String::Utf8Value exception_value2(try_catch.Exception());
   11135     CHECK_EQ(
   11136         0, strcmp("TypeError: object is not a constructor", *exception_value2));
   11137     try_catch.Reset();
   11138   }
   11139 
   11140   // Check the case when constructor throws exception.
   11141   {
   11142     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   11143     instance_template->SetCallAsFunctionHandler(ThrowValue);
   11144     Local<Object> instance =
   11145         instance_template->NewInstance(context.local()).ToLocalChecked();
   11146     CHECK(context->Global()
   11147               ->Set(context.local(), v8_str("obj3"), instance)
   11148               .FromJust());
   11149     v8::TryCatch try_catch(isolate);
   11150     Local<Value> value;
   11151     CHECK(!try_catch.HasCaught());
   11152 
   11153     value = CompileRun("new obj3(22)");
   11154     CHECK(try_catch.HasCaught());
   11155     String::Utf8Value exception_value1(try_catch.Exception());
   11156     CHECK_EQ(0, strcmp("22", *exception_value1));
   11157     try_catch.Reset();
   11158 
   11159     Local<Value> args[] = {v8_num(23)};
   11160     CHECK(instance->CallAsConstructor(context.local(), 1, args).IsEmpty());
   11161     CHECK(try_catch.HasCaught());
   11162     String::Utf8Value exception_value2(try_catch.Exception());
   11163     CHECK_EQ(0, strcmp("23", *exception_value2));
   11164     try_catch.Reset();
   11165   }
   11166 
   11167   // Check whether constructor returns with an object or non-object.
   11168   {
   11169     Local<FunctionTemplate> function_template =
   11170         FunctionTemplate::New(isolate, FakeConstructorCallback);
   11171     Local<Function> function =
   11172         function_template->GetFunction(context.local()).ToLocalChecked();
   11173     Local<Object> instance1 = function;
   11174     CHECK(context->Global()
   11175               ->Set(context.local(), v8_str("obj4"), instance1)
   11176               .FromJust());
   11177     v8::TryCatch try_catch(isolate);
   11178     Local<Value> value;
   11179     CHECK(!try_catch.HasCaught());
   11180 
   11181     CHECK(instance1->IsObject());
   11182     CHECK(instance1->IsFunction());
   11183 
   11184     value = CompileRun("new obj4(28)");
   11185     CHECK(!try_catch.HasCaught());
   11186     CHECK(value->IsObject());
   11187 
   11188     Local<Value> args1[] = {v8_num(28)};
   11189     value = instance1->CallAsConstructor(context.local(), 1, args1)
   11190                 .ToLocalChecked();
   11191     CHECK(!try_catch.HasCaught());
   11192     CHECK(value->IsObject());
   11193 
   11194     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   11195     instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
   11196     Local<Object> instance2 =
   11197         instance_template->NewInstance(context.local()).ToLocalChecked();
   11198     CHECK(context->Global()
   11199               ->Set(context.local(), v8_str("obj5"), instance2)
   11200               .FromJust());
   11201     CHECK(!try_catch.HasCaught());
   11202 
   11203     CHECK(instance2->IsObject());
   11204     CHECK(instance2->IsFunction());
   11205 
   11206     value = CompileRun("new obj5(28)");
   11207     CHECK(!try_catch.HasCaught());
   11208     CHECK(!value->IsObject());
   11209 
   11210     Local<Value> args2[] = {v8_num(28)};
   11211     value = instance2->CallAsConstructor(context.local(), 1, args2)
   11212                 .ToLocalChecked();
   11213     CHECK(!try_catch.HasCaught());
   11214     CHECK(!value->IsObject());
   11215   }
   11216 }
   11217 
   11218 
   11219 THREADED_TEST(FunctionDescriptorException) {
   11220   LocalContext context;
   11221   v8::Isolate* isolate = context->GetIsolate();
   11222   v8::HandleScope handle_scope(isolate);
   11223   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   11224   templ->SetClassName(v8_str("Fun"));
   11225   Local<Function> cons = templ->GetFunction(context.local()).ToLocalChecked();
   11226   CHECK(
   11227       context->Global()->Set(context.local(), v8_str("Fun"), cons).FromJust());
   11228   Local<Value> value = CompileRun(
   11229       "function test() {"
   11230       "  try {"
   11231       "    (new Fun()).blah()"
   11232       "  } catch (e) {"
   11233       "    var str = String(e);"
   11234       // "    if (str.indexOf('TypeError') == -1) return 1;"
   11235       // "    if (str.indexOf('[object Fun]') != -1) return 2;"
   11236       // "    if (str.indexOf('#<Fun>') == -1) return 3;"
   11237       "    return 0;"
   11238       "  }"
   11239       "  return 4;"
   11240       "}"
   11241       "test();");
   11242   CHECK_EQ(0, value->Int32Value(context.local()).FromJust());
   11243 }
   11244 
   11245 
   11246 THREADED_TEST(EvalAliasedDynamic) {
   11247   LocalContext current;
   11248   v8::HandleScope scope(current->GetIsolate());
   11249 
   11250   // Tests where aliased eval can only be resolved dynamically.
   11251   Local<Script> script = v8_compile(
   11252       "function f(x) { "
   11253       "  var foo = 2;"
   11254       "  with (x) { return eval('foo'); }"
   11255       "}"
   11256       "foo = 0;"
   11257       "result1 = f(new Object());"
   11258       "result2 = f(this);"
   11259       "var x = new Object();"
   11260       "x.eval = function(x) { return 1; };"
   11261       "result3 = f(x);");
   11262   script->Run(current.local()).ToLocalChecked();
   11263   CHECK_EQ(2, current->Global()
   11264                   ->Get(current.local(), v8_str("result1"))
   11265                   .ToLocalChecked()
   11266                   ->Int32Value(current.local())
   11267                   .FromJust());
   11268   CHECK_EQ(0, current->Global()
   11269                   ->Get(current.local(), v8_str("result2"))
   11270                   .ToLocalChecked()
   11271                   ->Int32Value(current.local())
   11272                   .FromJust());
   11273   CHECK_EQ(1, current->Global()
   11274                   ->Get(current.local(), v8_str("result3"))
   11275                   .ToLocalChecked()
   11276                   ->Int32Value(current.local())
   11277                   .FromJust());
   11278 
   11279   v8::TryCatch try_catch(current->GetIsolate());
   11280   script = v8_compile(
   11281       "function f(x) { "
   11282       "  var bar = 2;"
   11283       "  with (x) { return eval('bar'); }"
   11284       "}"
   11285       "result4 = f(this)");
   11286   script->Run(current.local()).ToLocalChecked();
   11287   CHECK(!try_catch.HasCaught());
   11288   CHECK_EQ(2, current->Global()
   11289                   ->Get(current.local(), v8_str("result4"))
   11290                   .ToLocalChecked()
   11291                   ->Int32Value(current.local())
   11292                   .FromJust());
   11293 
   11294   try_catch.Reset();
   11295 }
   11296 
   11297 
   11298 THREADED_TEST(CrossEval) {
   11299   v8::HandleScope scope(CcTest::isolate());
   11300   LocalContext other;
   11301   LocalContext current;
   11302 
   11303   Local<String> token = v8_str("<security token>");
   11304   other->SetSecurityToken(token);
   11305   current->SetSecurityToken(token);
   11306 
   11307   // Set up reference from current to other.
   11308   CHECK(current->Global()
   11309             ->Set(current.local(), v8_str("other"), other->Global())
   11310             .FromJust());
   11311 
   11312   // Check that new variables are introduced in other context.
   11313   Local<Script> script = v8_compile("other.eval('var foo = 1234')");
   11314   script->Run(current.local()).ToLocalChecked();
   11315   Local<Value> foo =
   11316       other->Global()->Get(current.local(), v8_str("foo")).ToLocalChecked();
   11317   CHECK_EQ(1234, foo->Int32Value(other.local()).FromJust());
   11318   CHECK(!current->Global()->Has(current.local(), v8_str("foo")).FromJust());
   11319 
   11320   // Check that writing to non-existing properties introduces them in
   11321   // the other context.
   11322   script = v8_compile("other.eval('na = 1234')");
   11323   script->Run(current.local()).ToLocalChecked();
   11324   CHECK_EQ(1234, other->Global()
   11325                      ->Get(current.local(), v8_str("na"))
   11326                      .ToLocalChecked()
   11327                      ->Int32Value(other.local())
   11328                      .FromJust());
   11329   CHECK(!current->Global()->Has(current.local(), v8_str("na")).FromJust());
   11330 
   11331   // Check that global variables in current context are not visible in other
   11332   // context.
   11333   v8::TryCatch try_catch(CcTest::isolate());
   11334   script = v8_compile("var bar = 42; other.eval('bar');");
   11335   CHECK(script->Run(current.local()).IsEmpty());
   11336   CHECK(try_catch.HasCaught());
   11337   try_catch.Reset();
   11338 
   11339   // Check that local variables in current context are not visible in other
   11340   // context.
   11341   script = v8_compile(
   11342       "(function() { "
   11343       "  var baz = 87;"
   11344       "  return other.eval('baz');"
   11345       "})();");
   11346   CHECK(script->Run(current.local()).IsEmpty());
   11347   CHECK(try_catch.HasCaught());
   11348   try_catch.Reset();
   11349 
   11350   // Check that global variables in the other environment are visible
   11351   // when evaluting code.
   11352   CHECK(other->Global()
   11353             ->Set(other.local(), v8_str("bis"), v8_num(1234))
   11354             .FromJust());
   11355   script = v8_compile("other.eval('bis')");
   11356   CHECK_EQ(1234, script->Run(current.local())
   11357                      .ToLocalChecked()
   11358                      ->Int32Value(current.local())
   11359                      .FromJust());
   11360   CHECK(!try_catch.HasCaught());
   11361 
   11362   // Check that the 'this' pointer points to the global object evaluating
   11363   // code.
   11364   CHECK(other->Global()
   11365             ->Set(current.local(), v8_str("t"), other->Global())
   11366             .FromJust());
   11367   script = v8_compile("other.eval('this == t')");
   11368   Local<Value> result = script->Run(current.local()).ToLocalChecked();
   11369   CHECK(result->IsTrue());
   11370   CHECK(!try_catch.HasCaught());
   11371 
   11372   // Check that variables introduced in with-statement are not visible in
   11373   // other context.
   11374   script = v8_compile("with({x:2}){other.eval('x')}");
   11375   CHECK(script->Run(current.local()).IsEmpty());
   11376   CHECK(try_catch.HasCaught());
   11377   try_catch.Reset();
   11378 
   11379   // Check that you cannot use 'eval.call' with another object than the
   11380   // current global object.
   11381   script = v8_compile("other.y = 1; eval.call(other, 'y')");
   11382   CHECK(script->Run(current.local()).IsEmpty());
   11383   CHECK(try_catch.HasCaught());
   11384 }
   11385 
   11386 
   11387 // Test that calling eval in a context which has been detached from
   11388 // its global proxy works.
   11389 THREADED_TEST(EvalInDetachedGlobal) {
   11390   v8::Isolate* isolate = CcTest::isolate();
   11391   v8::HandleScope scope(isolate);
   11392 
   11393   v8::Local<Context> context0 = Context::New(isolate);
   11394   v8::Local<Context> context1 = Context::New(isolate);
   11395 
   11396   // Set up function in context0 that uses eval from context0.
   11397   context0->Enter();
   11398   v8::Local<v8::Value> fun = CompileRun(
   11399       "var x = 42;"
   11400       "(function() {"
   11401       "  var e = eval;"
   11402       "  return function(s) { return e(s); }"
   11403       "})()");
   11404   context0->Exit();
   11405 
   11406   // Put the function into context1 and call it before and after
   11407   // detaching the global.  Before detaching, the call succeeds and
   11408   // after detaching and exception is thrown.
   11409   context1->Enter();
   11410   CHECK(context1->Global()->Set(context1, v8_str("fun"), fun).FromJust());
   11411   v8::Local<v8::Value> x_value = CompileRun("fun('x')");
   11412   CHECK_EQ(42, x_value->Int32Value(context1).FromJust());
   11413   context0->DetachGlobal();
   11414   v8::TryCatch catcher(isolate);
   11415   x_value = CompileRun("fun('x')");
   11416   CHECK_EQ(42, x_value->Int32Value(context1).FromJust());
   11417   context1->Exit();
   11418 }
   11419 
   11420 
   11421 THREADED_TEST(CrossLazyLoad) {
   11422   v8::HandleScope scope(CcTest::isolate());
   11423   LocalContext other;
   11424   LocalContext current;
   11425 
   11426   Local<String> token = v8_str("<security token>");
   11427   other->SetSecurityToken(token);
   11428   current->SetSecurityToken(token);
   11429 
   11430   // Set up reference from current to other.
   11431   CHECK(current->Global()
   11432             ->Set(current.local(), v8_str("other"), other->Global())
   11433             .FromJust());
   11434 
   11435   // Trigger lazy loading in other context.
   11436   Local<Script> script = v8_compile("other.eval('new Date(42)')");
   11437   Local<Value> value = script->Run(current.local()).ToLocalChecked();
   11438   CHECK_EQ(42.0, value->NumberValue(current.local()).FromJust());
   11439 }
   11440 
   11441 
   11442 static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
   11443   ApiTestFuzzer::Fuzz();
   11444   if (args.IsConstructCall()) {
   11445     if (args[0]->IsInt32()) {
   11446       args.GetReturnValue().Set(
   11447           v8_num(-args[0]
   11448                       ->Int32Value(args.GetIsolate()->GetCurrentContext())
   11449                       .FromJust()));
   11450       return;
   11451     }
   11452   }
   11453 
   11454   args.GetReturnValue().Set(args[0]);
   11455 }
   11456 
   11457 
   11458 static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
   11459   args.GetReturnValue().Set(args.This());
   11460 }
   11461 
   11462 
   11463 // Test that a call handler can be set for objects which will allow
   11464 // non-function objects created through the API to be called as
   11465 // functions.
   11466 THREADED_TEST(CallAsFunction) {
   11467   LocalContext context;
   11468   v8::Isolate* isolate = context->GetIsolate();
   11469   v8::HandleScope scope(isolate);
   11470 
   11471   {
   11472     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11473     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   11474     instance_template->SetCallAsFunctionHandler(call_as_function);
   11475     Local<v8::Object> instance = t->GetFunction(context.local())
   11476                                      .ToLocalChecked()
   11477                                      ->NewInstance(context.local())
   11478                                      .ToLocalChecked();
   11479     CHECK(context->Global()
   11480               ->Set(context.local(), v8_str("obj"), instance)
   11481               .FromJust());
   11482     v8::TryCatch try_catch(isolate);
   11483     Local<Value> value;
   11484     CHECK(!try_catch.HasCaught());
   11485 
   11486     value = CompileRun("obj(42)");
   11487     CHECK(!try_catch.HasCaught());
   11488     CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   11489 
   11490     value = CompileRun("(function(o){return o(49)})(obj)");
   11491     CHECK(!try_catch.HasCaught());
   11492     CHECK_EQ(49, value->Int32Value(context.local()).FromJust());
   11493 
   11494     // test special case of call as function
   11495     value = CompileRun("[obj]['0'](45)");
   11496     CHECK(!try_catch.HasCaught());
   11497     CHECK_EQ(45, value->Int32Value(context.local()).FromJust());
   11498 
   11499     value = CompileRun(
   11500         "obj.call = Function.prototype.call;"
   11501         "obj.call(null, 87)");
   11502     CHECK(!try_catch.HasCaught());
   11503     CHECK_EQ(87, value->Int32Value(context.local()).FromJust());
   11504 
   11505     // Regression tests for bug #1116356: Calling call through call/apply
   11506     // must work for non-function receivers.
   11507     const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
   11508     value = CompileRun(apply_99);
   11509     CHECK(!try_catch.HasCaught());
   11510     CHECK_EQ(99, value->Int32Value(context.local()).FromJust());
   11511 
   11512     const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
   11513     value = CompileRun(call_17);
   11514     CHECK(!try_catch.HasCaught());
   11515     CHECK_EQ(17, value->Int32Value(context.local()).FromJust());
   11516 
   11517     // Check that the call-as-function handler can be called through
   11518     // new.
   11519     value = CompileRun("new obj(43)");
   11520     CHECK(!try_catch.HasCaught());
   11521     CHECK_EQ(-43, value->Int32Value(context.local()).FromJust());
   11522 
   11523     // Check that the call-as-function handler can be called through
   11524     // the API.
   11525     v8::Local<Value> args[] = {v8_num(28)};
   11526     value = instance->CallAsFunction(context.local(), instance, 1, args)
   11527                 .ToLocalChecked();
   11528     CHECK(!try_catch.HasCaught());
   11529     CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
   11530   }
   11531 
   11532   {
   11533     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11534     Local<ObjectTemplate> instance_template(t->InstanceTemplate());
   11535     USE(instance_template);
   11536     Local<v8::Object> instance = t->GetFunction(context.local())
   11537                                      .ToLocalChecked()
   11538                                      ->NewInstance(context.local())
   11539                                      .ToLocalChecked();
   11540     CHECK(context->Global()
   11541               ->Set(context.local(), v8_str("obj2"), instance)
   11542               .FromJust());
   11543     v8::TryCatch try_catch(isolate);
   11544     Local<Value> value;
   11545     CHECK(!try_catch.HasCaught());
   11546 
   11547     // Call an object without call-as-function handler through the JS
   11548     value = CompileRun("obj2(28)");
   11549     CHECK(value.IsEmpty());
   11550     CHECK(try_catch.HasCaught());
   11551     String::Utf8Value exception_value1(try_catch.Exception());
   11552     // TODO(verwaest): Better message
   11553     CHECK_EQ(0, strcmp("TypeError: obj2 is not a function", *exception_value1));
   11554     try_catch.Reset();
   11555 
   11556     // Call an object without call-as-function handler through the API
   11557     value = CompileRun("obj2(28)");
   11558     v8::Local<Value> args[] = {v8_num(28)};
   11559     CHECK(
   11560         instance->CallAsFunction(context.local(), instance, 1, args).IsEmpty());
   11561     CHECK(try_catch.HasCaught());
   11562     String::Utf8Value exception_value2(try_catch.Exception());
   11563     CHECK_EQ(0,
   11564              strcmp("TypeError: object is not a function", *exception_value2));
   11565     try_catch.Reset();
   11566   }
   11567 
   11568   {
   11569     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11570     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   11571     instance_template->SetCallAsFunctionHandler(ThrowValue);
   11572     Local<v8::Object> instance = t->GetFunction(context.local())
   11573                                      .ToLocalChecked()
   11574                                      ->NewInstance(context.local())
   11575                                      .ToLocalChecked();
   11576     CHECK(context->Global()
   11577               ->Set(context.local(), v8_str("obj3"), instance)
   11578               .FromJust());
   11579     v8::TryCatch try_catch(isolate);
   11580     Local<Value> value;
   11581     CHECK(!try_catch.HasCaught());
   11582 
   11583     // Catch the exception which is thrown by call-as-function handler
   11584     value = CompileRun("obj3(22)");
   11585     CHECK(try_catch.HasCaught());
   11586     String::Utf8Value exception_value1(try_catch.Exception());
   11587     CHECK_EQ(0, strcmp("22", *exception_value1));
   11588     try_catch.Reset();
   11589 
   11590     v8::Local<Value> args[] = {v8_num(23)};
   11591     CHECK(
   11592         instance->CallAsFunction(context.local(), instance, 1, args).IsEmpty());
   11593     CHECK(try_catch.HasCaught());
   11594     String::Utf8Value exception_value2(try_catch.Exception());
   11595     CHECK_EQ(0, strcmp("23", *exception_value2));
   11596     try_catch.Reset();
   11597   }
   11598 
   11599   {
   11600     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11601     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   11602     instance_template->SetCallAsFunctionHandler(ReturnThis);
   11603     Local<v8::Object> instance = t->GetFunction(context.local())
   11604                                      .ToLocalChecked()
   11605                                      ->NewInstance(context.local())
   11606                                      .ToLocalChecked();
   11607 
   11608     Local<v8::Value> a1 =
   11609         instance->CallAsFunction(context.local(), v8::Undefined(isolate), 0,
   11610                                  NULL)
   11611             .ToLocalChecked();
   11612     CHECK(a1->StrictEquals(instance));
   11613     Local<v8::Value> a2 =
   11614         instance->CallAsFunction(context.local(), v8::Null(isolate), 0, NULL)
   11615             .ToLocalChecked();
   11616     CHECK(a2->StrictEquals(instance));
   11617     Local<v8::Value> a3 =
   11618         instance->CallAsFunction(context.local(), v8_num(42), 0, NULL)
   11619             .ToLocalChecked();
   11620     CHECK(a3->StrictEquals(instance));
   11621     Local<v8::Value> a4 =
   11622         instance->CallAsFunction(context.local(), v8_str("hello"), 0, NULL)
   11623             .ToLocalChecked();
   11624     CHECK(a4->StrictEquals(instance));
   11625     Local<v8::Value> a5 =
   11626         instance->CallAsFunction(context.local(), v8::True(isolate), 0, NULL)
   11627             .ToLocalChecked();
   11628     CHECK(a5->StrictEquals(instance));
   11629   }
   11630 
   11631   {
   11632     CompileRun(
   11633         "function ReturnThisSloppy() {"
   11634         "  return this;"
   11635         "}"
   11636         "function ReturnThisStrict() {"
   11637         "  'use strict';"
   11638         "  return this;"
   11639         "}");
   11640     Local<Function> ReturnThisSloppy = Local<Function>::Cast(
   11641         context->Global()
   11642             ->Get(context.local(), v8_str("ReturnThisSloppy"))
   11643             .ToLocalChecked());
   11644     Local<Function> ReturnThisStrict = Local<Function>::Cast(
   11645         context->Global()
   11646             ->Get(context.local(), v8_str("ReturnThisStrict"))
   11647             .ToLocalChecked());
   11648 
   11649     Local<v8::Value> a1 =
   11650         ReturnThisSloppy->CallAsFunction(context.local(),
   11651                                          v8::Undefined(isolate), 0, NULL)
   11652             .ToLocalChecked();
   11653     CHECK(a1->StrictEquals(context->Global()));
   11654     Local<v8::Value> a2 =
   11655         ReturnThisSloppy->CallAsFunction(context.local(), v8::Null(isolate), 0,
   11656                                          NULL)
   11657             .ToLocalChecked();
   11658     CHECK(a2->StrictEquals(context->Global()));
   11659     Local<v8::Value> a3 =
   11660         ReturnThisSloppy->CallAsFunction(context.local(), v8_num(42), 0, NULL)
   11661             .ToLocalChecked();
   11662     CHECK(a3->IsNumberObject());
   11663     CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
   11664     Local<v8::Value> a4 =
   11665         ReturnThisSloppy->CallAsFunction(context.local(), v8_str("hello"), 0,
   11666                                          NULL)
   11667             .ToLocalChecked();
   11668     CHECK(a4->IsStringObject());
   11669     CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
   11670     Local<v8::Value> a5 =
   11671         ReturnThisSloppy->CallAsFunction(context.local(), v8::True(isolate), 0,
   11672                                          NULL)
   11673             .ToLocalChecked();
   11674     CHECK(a5->IsBooleanObject());
   11675     CHECK(a5.As<v8::BooleanObject>()->ValueOf());
   11676 
   11677     Local<v8::Value> a6 =
   11678         ReturnThisStrict->CallAsFunction(context.local(),
   11679                                          v8::Undefined(isolate), 0, NULL)
   11680             .ToLocalChecked();
   11681     CHECK(a6->IsUndefined());
   11682     Local<v8::Value> a7 =
   11683         ReturnThisStrict->CallAsFunction(context.local(), v8::Null(isolate), 0,
   11684                                          NULL)
   11685             .ToLocalChecked();
   11686     CHECK(a7->IsNull());
   11687     Local<v8::Value> a8 =
   11688         ReturnThisStrict->CallAsFunction(context.local(), v8_num(42), 0, NULL)
   11689             .ToLocalChecked();
   11690     CHECK(a8->StrictEquals(v8_num(42)));
   11691     Local<v8::Value> a9 =
   11692         ReturnThisStrict->CallAsFunction(context.local(), v8_str("hello"), 0,
   11693                                          NULL)
   11694             .ToLocalChecked();
   11695     CHECK(a9->StrictEquals(v8_str("hello")));
   11696     Local<v8::Value> a10 =
   11697         ReturnThisStrict->CallAsFunction(context.local(), v8::True(isolate), 0,
   11698                                          NULL)
   11699             .ToLocalChecked();
   11700     CHECK(a10->StrictEquals(v8::True(isolate)));
   11701   }
   11702 }
   11703 
   11704 
   11705 // Check whether a non-function object is callable.
   11706 THREADED_TEST(CallableObject) {
   11707   LocalContext context;
   11708   v8::Isolate* isolate = context->GetIsolate();
   11709   v8::HandleScope scope(isolate);
   11710 
   11711   {
   11712     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   11713     instance_template->SetCallAsFunctionHandler(call_as_function);
   11714     Local<Object> instance =
   11715         instance_template->NewInstance(context.local()).ToLocalChecked();
   11716     v8::TryCatch try_catch(isolate);
   11717 
   11718     CHECK(instance->IsCallable());
   11719     CHECK(!try_catch.HasCaught());
   11720   }
   11721 
   11722   {
   11723     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   11724     Local<Object> instance =
   11725         instance_template->NewInstance(context.local()).ToLocalChecked();
   11726     v8::TryCatch try_catch(isolate);
   11727 
   11728     CHECK(!instance->IsCallable());
   11729     CHECK(!try_catch.HasCaught());
   11730   }
   11731 
   11732   {
   11733     Local<FunctionTemplate> function_template =
   11734         FunctionTemplate::New(isolate, call_as_function);
   11735     Local<Function> function =
   11736         function_template->GetFunction(context.local()).ToLocalChecked();
   11737     Local<Object> instance = function;
   11738     v8::TryCatch try_catch(isolate);
   11739 
   11740     CHECK(instance->IsCallable());
   11741     CHECK(!try_catch.HasCaught());
   11742   }
   11743 
   11744   {
   11745     Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
   11746     Local<Function> function =
   11747         function_template->GetFunction(context.local()).ToLocalChecked();
   11748     Local<Object> instance = function;
   11749     v8::TryCatch try_catch(isolate);
   11750 
   11751     CHECK(instance->IsCallable());
   11752     CHECK(!try_catch.HasCaught());
   11753   }
   11754 }
   11755 
   11756 
   11757 THREADED_TEST(Regress567998) {
   11758   LocalContext env;
   11759   v8::HandleScope scope(env->GetIsolate());
   11760 
   11761   Local<v8::FunctionTemplate> desc =
   11762       v8::FunctionTemplate::New(env->GetIsolate());
   11763   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   11764   desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis);  // callable
   11765 
   11766   Local<v8::Object> obj = desc->GetFunction(env.local())
   11767                               .ToLocalChecked()
   11768                               ->NewInstance(env.local())
   11769                               .ToLocalChecked();
   11770   CHECK(
   11771       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
   11772 
   11773   ExpectString("undetectable.toString()", "[object Object]");
   11774   ExpectString("typeof undetectable", "undefined");
   11775   ExpectString("typeof(undetectable)", "undefined");
   11776   ExpectBoolean("typeof undetectable == 'undefined'", true);
   11777   ExpectBoolean("typeof undetectable == 'object'", false);
   11778   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
   11779   ExpectBoolean("!undetectable", true);
   11780 
   11781   ExpectObject("true&&undetectable", obj);
   11782   ExpectBoolean("false&&undetectable", false);
   11783   ExpectBoolean("true||undetectable", true);
   11784   ExpectObject("false||undetectable", obj);
   11785 
   11786   ExpectObject("undetectable&&true", obj);
   11787   ExpectObject("undetectable&&false", obj);
   11788   ExpectBoolean("undetectable||true", true);
   11789   ExpectBoolean("undetectable||false", false);
   11790 
   11791   ExpectBoolean("undetectable==null", true);
   11792   ExpectBoolean("null==undetectable", true);
   11793   ExpectBoolean("undetectable==undefined", true);
   11794   ExpectBoolean("undefined==undetectable", true);
   11795   ExpectBoolean("undetectable==undetectable", true);
   11796 
   11797   ExpectBoolean("undetectable===null", false);
   11798   ExpectBoolean("null===undetectable", false);
   11799   ExpectBoolean("undetectable===undefined", false);
   11800   ExpectBoolean("undefined===undetectable", false);
   11801   ExpectBoolean("undetectable===undetectable", true);
   11802 }
   11803 
   11804 
   11805 static int Recurse(v8::Isolate* isolate, int depth, int iterations) {
   11806   v8::HandleScope scope(isolate);
   11807   if (depth == 0) return v8::HandleScope::NumberOfHandles(isolate);
   11808   for (int i = 0; i < iterations; i++) {
   11809     Local<v8::Number> n(v8::Integer::New(isolate, 42));
   11810   }
   11811   return Recurse(isolate, depth - 1, iterations);
   11812 }
   11813 
   11814 
   11815 THREADED_TEST(HandleIteration) {
   11816   static const int kIterations = 500;
   11817   static const int kNesting = 200;
   11818   LocalContext context;
   11819   v8::Isolate* isolate = context->GetIsolate();
   11820   v8::HandleScope scope0(isolate);
   11821   CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
   11822   {
   11823     v8::HandleScope scope1(isolate);
   11824     CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
   11825     for (int i = 0; i < kIterations; i++) {
   11826       Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
   11827       CHECK_EQ(i + 1, v8::HandleScope::NumberOfHandles(isolate));
   11828     }
   11829 
   11830     CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
   11831     {
   11832       v8::HandleScope scope2(CcTest::isolate());
   11833       for (int j = 0; j < kIterations; j++) {
   11834         Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
   11835         CHECK_EQ(j + 1 + kIterations,
   11836                  v8::HandleScope::NumberOfHandles(isolate));
   11837       }
   11838     }
   11839     CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
   11840   }
   11841   CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
   11842   CHECK_EQ(kNesting * kIterations, Recurse(isolate, kNesting, kIterations));
   11843 }
   11844 
   11845 
   11846 static void InterceptorCallICFastApi(
   11847     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   11848   ApiTestFuzzer::Fuzz();
   11849   CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
   11850   int* call_count =
   11851       reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
   11852   ++(*call_count);
   11853   if ((*call_count) % 20 == 0) {
   11854     CcTest::heap()->CollectAllGarbage();
   11855   }
   11856 }
   11857 
   11858 static void FastApiCallback_TrivialSignature(
   11859     const v8::FunctionCallbackInfo<v8::Value>& args) {
   11860   ApiTestFuzzer::Fuzz();
   11861   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
   11862   v8::Isolate* isolate = CcTest::isolate();
   11863   CHECK_EQ(isolate, args.GetIsolate());
   11864   CHECK(args.This()
   11865             ->Equals(isolate->GetCurrentContext(), args.Holder())
   11866             .FromJust());
   11867   CHECK(args.Data()
   11868             ->Equals(isolate->GetCurrentContext(), v8_str("method_data"))
   11869             .FromJust());
   11870   args.GetReturnValue().Set(
   11871       args[0]->Int32Value(isolate->GetCurrentContext()).FromJust() + 1);
   11872 }
   11873 
   11874 static void FastApiCallback_SimpleSignature(
   11875     const v8::FunctionCallbackInfo<v8::Value>& args) {
   11876   ApiTestFuzzer::Fuzz();
   11877   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
   11878   v8::Isolate* isolate = CcTest::isolate();
   11879   CHECK_EQ(isolate, args.GetIsolate());
   11880   CHECK(args.This()
   11881             ->GetPrototype()
   11882             ->Equals(isolate->GetCurrentContext(), args.Holder())
   11883             .FromJust());
   11884   CHECK(args.Data()
   11885             ->Equals(isolate->GetCurrentContext(), v8_str("method_data"))
   11886             .FromJust());
   11887   // Note, we're using HasRealNamedProperty instead of Has to avoid
   11888   // invoking the interceptor again.
   11889   CHECK(args.Holder()
   11890             ->HasRealNamedProperty(isolate->GetCurrentContext(), v8_str("foo"))
   11891             .FromJust());
   11892   args.GetReturnValue().Set(
   11893       args[0]->Int32Value(isolate->GetCurrentContext()).FromJust() + 1);
   11894 }
   11895 
   11896 
   11897 // Helper to maximize the odds of object moving.
   11898 static void GenerateSomeGarbage() {
   11899   CompileRun(
   11900       "var garbage;"
   11901       "for (var i = 0; i < 1000; i++) {"
   11902       "  garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
   11903       "}"
   11904       "garbage = undefined;");
   11905 }
   11906 
   11907 
   11908 void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   11909   static int count = 0;
   11910   if (count++ % 3 == 0) {
   11911     CcTest::heap()->CollectAllGarbage();
   11912         // This should move the stub
   11913     GenerateSomeGarbage();  // This should ensure the old stub memory is flushed
   11914   }
   11915 }
   11916 
   11917 
   11918 THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
   11919   LocalContext context;
   11920   v8::Isolate* isolate = context->GetIsolate();
   11921   v8::HandleScope scope(isolate);
   11922   v8::Local<v8::ObjectTemplate> nativeobject_templ =
   11923       v8::ObjectTemplate::New(isolate);
   11924   nativeobject_templ->Set(isolate, "callback",
   11925                           v8::FunctionTemplate::New(isolate,
   11926                                                     DirectApiCallback));
   11927   v8::Local<v8::Object> nativeobject_obj =
   11928       nativeobject_templ->NewInstance(context.local()).ToLocalChecked();
   11929   CHECK(context->Global()
   11930             ->Set(context.local(), v8_str("nativeobject"), nativeobject_obj)
   11931             .FromJust());
   11932   // call the api function multiple times to ensure direct call stub creation.
   11933   CompileRun(
   11934         "function f() {"
   11935         "  for (var i = 1; i <= 30; i++) {"
   11936         "    nativeobject.callback();"
   11937         "  }"
   11938         "}"
   11939         "f();");
   11940 }
   11941 
   11942 
   11943 void ThrowingDirectApiCallback(
   11944     const v8::FunctionCallbackInfo<v8::Value>& args) {
   11945   args.GetIsolate()->ThrowException(v8_str("g"));
   11946 }
   11947 
   11948 
   11949 THREADED_TEST(CallICFastApi_DirectCall_Throw) {
   11950   LocalContext context;
   11951   v8::Isolate* isolate = context->GetIsolate();
   11952   v8::HandleScope scope(isolate);
   11953   v8::Local<v8::ObjectTemplate> nativeobject_templ =
   11954       v8::ObjectTemplate::New(isolate);
   11955   nativeobject_templ->Set(isolate, "callback",
   11956                           v8::FunctionTemplate::New(isolate,
   11957                                                     ThrowingDirectApiCallback));
   11958   v8::Local<v8::Object> nativeobject_obj =
   11959       nativeobject_templ->NewInstance(context.local()).ToLocalChecked();
   11960   CHECK(context->Global()
   11961             ->Set(context.local(), v8_str("nativeobject"), nativeobject_obj)
   11962             .FromJust());
   11963   // call the api function multiple times to ensure direct call stub creation.
   11964   v8::Local<Value> result = CompileRun(
   11965       "var result = '';"
   11966       "function f() {"
   11967       "  for (var i = 1; i <= 5; i++) {"
   11968       "    try { nativeobject.callback(); } catch (e) { result += e; }"
   11969       "  }"
   11970       "}"
   11971       "f(); result;");
   11972   CHECK(v8_str("ggggg")->Equals(context.local(), result).FromJust());
   11973 }
   11974 
   11975 
   11976 static int p_getter_count_3;
   11977 
   11978 
   11979 static Local<Value> DoDirectGetter() {
   11980   if (++p_getter_count_3 % 3 == 0) {
   11981     CcTest::heap()->CollectAllGarbage();
   11982     GenerateSomeGarbage();
   11983   }
   11984   return v8_str("Direct Getter Result");
   11985 }
   11986 
   11987 
   11988 static void DirectGetterCallback(
   11989     Local<String> name,
   11990     const v8::PropertyCallbackInfo<v8::Value>& info) {
   11991   CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
   11992   info.GetReturnValue().Set(DoDirectGetter());
   11993 }
   11994 
   11995 
   11996 template<typename Accessor>
   11997 static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
   11998   LocalContext context;
   11999   v8::Isolate* isolate = context->GetIsolate();
   12000   v8::HandleScope scope(isolate);
   12001   v8::Local<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
   12002   obj->SetAccessor(v8_str("p1"), accessor);
   12003   CHECK(context->Global()
   12004             ->Set(context.local(), v8_str("o1"),
   12005                   obj->NewInstance(context.local()).ToLocalChecked())
   12006             .FromJust());
   12007   p_getter_count_3 = 0;
   12008   v8::Local<v8::Value> result = CompileRun(
   12009       "function f() {"
   12010       "  for (var i = 0; i < 30; i++) o1.p1;"
   12011       "  return o1.p1"
   12012       "}"
   12013       "f();");
   12014   CHECK(v8_str("Direct Getter Result")
   12015             ->Equals(context.local(), result)
   12016             .FromJust());
   12017   CHECK_EQ(31, p_getter_count_3);
   12018 }
   12019 
   12020 
   12021 THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
   12022   LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
   12023 }
   12024 
   12025 
   12026 void ThrowingDirectGetterCallback(
   12027     Local<String> name,
   12028     const v8::PropertyCallbackInfo<v8::Value>& info) {
   12029   info.GetIsolate()->ThrowException(v8_str("g"));
   12030 }
   12031 
   12032 
   12033 THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
   12034   LocalContext context;
   12035   v8::Isolate* isolate = context->GetIsolate();
   12036   v8::HandleScope scope(isolate);
   12037   v8::Local<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
   12038   obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
   12039   CHECK(context->Global()
   12040             ->Set(context.local(), v8_str("o1"),
   12041                   obj->NewInstance(context.local()).ToLocalChecked())
   12042             .FromJust());
   12043   v8::Local<Value> result = CompileRun(
   12044       "var result = '';"
   12045       "for (var i = 0; i < 5; i++) {"
   12046       "    try { o1.p1; } catch (e) { result += e; }"
   12047       "}"
   12048       "result;");
   12049   CHECK(v8_str("ggggg")->Equals(context.local(), result).FromJust());
   12050 }
   12051 
   12052 
   12053 THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
   12054   int interceptor_call_count = 0;
   12055   v8::Isolate* isolate = CcTest::isolate();
   12056   v8::HandleScope scope(isolate);
   12057   v8::Local<v8::FunctionTemplate> fun_templ =
   12058       v8::FunctionTemplate::New(isolate);
   12059   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12060       isolate, FastApiCallback_TrivialSignature, v8_str("method_data"),
   12061       v8::Local<v8::Signature>());
   12062   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12063   proto_templ->Set(v8_str("method"), method_templ);
   12064   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12065   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12066       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
   12067       v8::External::New(isolate, &interceptor_call_count)));
   12068   LocalContext context;
   12069   v8::Local<v8::Function> fun =
   12070       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12071   GenerateSomeGarbage();
   12072   CHECK(context->Global()
   12073             ->Set(context.local(), v8_str("o"),
   12074                   fun->NewInstance(context.local()).ToLocalChecked())
   12075             .FromJust());
   12076   CompileRun(
   12077       "var result = 0;"
   12078       "for (var i = 0; i < 100; i++) {"
   12079       "  result = o.method(41);"
   12080       "}");
   12081   CHECK_EQ(42, context->Global()
   12082                    ->Get(context.local(), v8_str("result"))
   12083                    .ToLocalChecked()
   12084                    ->Int32Value(context.local())
   12085                    .FromJust());
   12086   CHECK_EQ(100, interceptor_call_count);
   12087 }
   12088 
   12089 
   12090 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
   12091   int interceptor_call_count = 0;
   12092   v8::Isolate* isolate = CcTest::isolate();
   12093   v8::HandleScope scope(isolate);
   12094   v8::Local<v8::FunctionTemplate> fun_templ =
   12095       v8::FunctionTemplate::New(isolate);
   12096   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12097       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12098       v8::Signature::New(isolate, fun_templ));
   12099   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12100   proto_templ->Set(v8_str("method"), method_templ);
   12101   fun_templ->SetHiddenPrototype(true);
   12102   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12103   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12104       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
   12105       v8::External::New(isolate, &interceptor_call_count)));
   12106   LocalContext context;
   12107   v8::Local<v8::Function> fun =
   12108       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12109   GenerateSomeGarbage();
   12110   CHECK(context->Global()
   12111             ->Set(context.local(), v8_str("o"),
   12112                   fun->NewInstance(context.local()).ToLocalChecked())
   12113             .FromJust());
   12114   CompileRun(
   12115       "o.foo = 17;"
   12116       "var receiver = {};"
   12117       "receiver.__proto__ = o;"
   12118       "var result = 0;"
   12119       "for (var i = 0; i < 100; i++) {"
   12120       "  result = receiver.method(41);"
   12121       "}");
   12122   CHECK_EQ(42, context->Global()
   12123                    ->Get(context.local(), v8_str("result"))
   12124                    .ToLocalChecked()
   12125                    ->Int32Value(context.local())
   12126                    .FromJust());
   12127   CHECK_EQ(100, interceptor_call_count);
   12128 }
   12129 
   12130 
   12131 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
   12132   int interceptor_call_count = 0;
   12133   v8::Isolate* isolate = CcTest::isolate();
   12134   v8::HandleScope scope(isolate);
   12135   v8::Local<v8::FunctionTemplate> fun_templ =
   12136       v8::FunctionTemplate::New(isolate);
   12137   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12138       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12139       v8::Signature::New(isolate, fun_templ));
   12140   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12141   proto_templ->Set(v8_str("method"), method_templ);
   12142   fun_templ->SetHiddenPrototype(true);
   12143   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12144   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12145       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
   12146       v8::External::New(isolate, &interceptor_call_count)));
   12147   LocalContext context;
   12148   v8::Local<v8::Function> fun =
   12149       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12150   GenerateSomeGarbage();
   12151   CHECK(context->Global()
   12152             ->Set(context.local(), v8_str("o"),
   12153                   fun->NewInstance(context.local()).ToLocalChecked())
   12154             .FromJust());
   12155   CompileRun(
   12156       "o.foo = 17;"
   12157       "var receiver = {};"
   12158       "receiver.__proto__ = o;"
   12159       "var result = 0;"
   12160       "var saved_result = 0;"
   12161       "for (var i = 0; i < 100; i++) {"
   12162       "  result = receiver.method(41);"
   12163       "  if (i == 50) {"
   12164       "    saved_result = result;"
   12165       "    receiver = {method: function(x) { return x - 1 }};"
   12166       "  }"
   12167       "}");
   12168   CHECK_EQ(40, context->Global()
   12169                    ->Get(context.local(), v8_str("result"))
   12170                    .ToLocalChecked()
   12171                    ->Int32Value(context.local())
   12172                    .FromJust());
   12173   CHECK_EQ(42, context->Global()
   12174                    ->Get(context.local(), v8_str("saved_result"))
   12175                    .ToLocalChecked()
   12176                    ->Int32Value(context.local())
   12177                    .FromJust());
   12178   CHECK_GE(interceptor_call_count, 50);
   12179 }
   12180 
   12181 
   12182 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
   12183   int interceptor_call_count = 0;
   12184   v8::Isolate* isolate = CcTest::isolate();
   12185   v8::HandleScope scope(isolate);
   12186   v8::Local<v8::FunctionTemplate> fun_templ =
   12187       v8::FunctionTemplate::New(isolate);
   12188   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12189       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12190       v8::Signature::New(isolate, fun_templ));
   12191   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12192   proto_templ->Set(v8_str("method"), method_templ);
   12193   fun_templ->SetHiddenPrototype(true);
   12194   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12195   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12196       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
   12197       v8::External::New(isolate, &interceptor_call_count)));
   12198   LocalContext context;
   12199   v8::Local<v8::Function> fun =
   12200       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12201   GenerateSomeGarbage();
   12202   CHECK(context->Global()
   12203             ->Set(context.local(), v8_str("o"),
   12204                   fun->NewInstance(context.local()).ToLocalChecked())
   12205             .FromJust());
   12206   CompileRun(
   12207       "o.foo = 17;"
   12208       "var receiver = {};"
   12209       "receiver.__proto__ = o;"
   12210       "var result = 0;"
   12211       "var saved_result = 0;"
   12212       "for (var i = 0; i < 100; i++) {"
   12213       "  result = receiver.method(41);"
   12214       "  if (i == 50) {"
   12215       "    saved_result = result;"
   12216       "    o.method = function(x) { return x - 1 };"
   12217       "  }"
   12218       "}");
   12219   CHECK_EQ(40, context->Global()
   12220                    ->Get(context.local(), v8_str("result"))
   12221                    .ToLocalChecked()
   12222                    ->Int32Value(context.local())
   12223                    .FromJust());
   12224   CHECK_EQ(42, context->Global()
   12225                    ->Get(context.local(), v8_str("saved_result"))
   12226                    .ToLocalChecked()
   12227                    ->Int32Value(context.local())
   12228                    .FromJust());
   12229   CHECK_GE(interceptor_call_count, 50);
   12230 }
   12231 
   12232 
   12233 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
   12234   int interceptor_call_count = 0;
   12235   v8::Isolate* isolate = CcTest::isolate();
   12236   v8::HandleScope scope(isolate);
   12237   v8::Local<v8::FunctionTemplate> fun_templ =
   12238       v8::FunctionTemplate::New(isolate);
   12239   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12240       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12241       v8::Signature::New(isolate, fun_templ));
   12242   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12243   proto_templ->Set(v8_str("method"), method_templ);
   12244   fun_templ->SetHiddenPrototype(true);
   12245   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12246   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12247       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
   12248       v8::External::New(isolate, &interceptor_call_count)));
   12249   LocalContext context;
   12250   v8::Local<v8::Function> fun =
   12251       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12252   GenerateSomeGarbage();
   12253   CHECK(context->Global()
   12254             ->Set(context.local(), v8_str("o"),
   12255                   fun->NewInstance(context.local()).ToLocalChecked())
   12256             .FromJust());
   12257   v8::TryCatch try_catch(isolate);
   12258   CompileRun(
   12259       "o.foo = 17;"
   12260       "var receiver = {};"
   12261       "receiver.__proto__ = o;"
   12262       "var result = 0;"
   12263       "var saved_result = 0;"
   12264       "for (var i = 0; i < 100; i++) {"
   12265       "  result = receiver.method(41);"
   12266       "  if (i == 50) {"
   12267       "    saved_result = result;"
   12268       "    receiver = 333;"
   12269       "  }"
   12270       "}");
   12271   CHECK(try_catch.HasCaught());
   12272   // TODO(verwaest): Adjust message.
   12273   CHECK(
   12274       v8_str("TypeError: receiver.method is not a function")
   12275           ->Equals(
   12276               context.local(),
   12277               try_catch.Exception()->ToString(context.local()).ToLocalChecked())
   12278           .FromJust());
   12279   CHECK_EQ(42, context->Global()
   12280                    ->Get(context.local(), v8_str("saved_result"))
   12281                    .ToLocalChecked()
   12282                    ->Int32Value(context.local())
   12283                    .FromJust());
   12284   CHECK_GE(interceptor_call_count, 50);
   12285 }
   12286 
   12287 
   12288 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
   12289   int interceptor_call_count = 0;
   12290   v8::Isolate* isolate = CcTest::isolate();
   12291   v8::HandleScope scope(isolate);
   12292   v8::Local<v8::FunctionTemplate> fun_templ =
   12293       v8::FunctionTemplate::New(isolate);
   12294   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12295       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12296       v8::Signature::New(isolate, fun_templ));
   12297   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12298   proto_templ->Set(v8_str("method"), method_templ);
   12299   fun_templ->SetHiddenPrototype(true);
   12300   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12301   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12302       InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
   12303       v8::External::New(isolate, &interceptor_call_count)));
   12304   LocalContext context;
   12305   v8::Local<v8::Function> fun =
   12306       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12307   GenerateSomeGarbage();
   12308   CHECK(context->Global()
   12309             ->Set(context.local(), v8_str("o"),
   12310                   fun->NewInstance(context.local()).ToLocalChecked())
   12311             .FromJust());
   12312   v8::TryCatch try_catch(isolate);
   12313   CompileRun(
   12314       "o.foo = 17;"
   12315       "var receiver = {};"
   12316       "receiver.__proto__ = o;"
   12317       "var result = 0;"
   12318       "var saved_result = 0;"
   12319       "for (var i = 0; i < 100; i++) {"
   12320       "  result = receiver.method(41);"
   12321       "  if (i == 50) {"
   12322       "    saved_result = result;"
   12323       "    receiver = {method: receiver.method};"
   12324       "  }"
   12325       "}");
   12326   CHECK(try_catch.HasCaught());
   12327   CHECK(
   12328       v8_str("TypeError: Illegal invocation")
   12329           ->Equals(
   12330               context.local(),
   12331               try_catch.Exception()->ToString(context.local()).ToLocalChecked())
   12332           .FromJust());
   12333   CHECK_EQ(42, context->Global()
   12334                    ->Get(context.local(), v8_str("saved_result"))
   12335                    .ToLocalChecked()
   12336                    ->Int32Value(context.local())
   12337                    .FromJust());
   12338   CHECK_GE(interceptor_call_count, 50);
   12339 }
   12340 
   12341 
   12342 THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
   12343   v8::Isolate* isolate = CcTest::isolate();
   12344   v8::HandleScope scope(isolate);
   12345   v8::Local<v8::FunctionTemplate> fun_templ =
   12346       v8::FunctionTemplate::New(isolate);
   12347   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12348       isolate, FastApiCallback_TrivialSignature, v8_str("method_data"),
   12349       v8::Local<v8::Signature>());
   12350   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12351   proto_templ->Set(v8_str("method"), method_templ);
   12352   v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12353   USE(templ);
   12354   LocalContext context;
   12355   v8::Local<v8::Function> fun =
   12356       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12357   GenerateSomeGarbage();
   12358   CHECK(context->Global()
   12359             ->Set(context.local(), v8_str("o"),
   12360                   fun->NewInstance(context.local()).ToLocalChecked())
   12361             .FromJust());
   12362   CompileRun(
   12363       "var result = 0;"
   12364       "for (var i = 0; i < 100; i++) {"
   12365       "  result = o.method(41);"
   12366       "}");
   12367 
   12368   CHECK_EQ(42, context->Global()
   12369                    ->Get(context.local(), v8_str("result"))
   12370                    .ToLocalChecked()
   12371                    ->Int32Value(context.local())
   12372                    .FromJust());
   12373 }
   12374 
   12375 
   12376 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
   12377   v8::Isolate* isolate = CcTest::isolate();
   12378   v8::HandleScope scope(isolate);
   12379   v8::Local<v8::FunctionTemplate> fun_templ =
   12380       v8::FunctionTemplate::New(isolate);
   12381   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12382       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12383       v8::Signature::New(isolate, fun_templ));
   12384   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12385   proto_templ->Set(v8_str("method"), method_templ);
   12386   fun_templ->SetHiddenPrototype(true);
   12387   v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12388   CHECK(!templ.IsEmpty());
   12389   LocalContext context;
   12390   v8::Local<v8::Function> fun =
   12391       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12392   GenerateSomeGarbage();
   12393   CHECK(context->Global()
   12394             ->Set(context.local(), v8_str("o"),
   12395                   fun->NewInstance(context.local()).ToLocalChecked())
   12396             .FromJust());
   12397   CompileRun(
   12398       "o.foo = 17;"
   12399       "var receiver = {};"
   12400       "receiver.__proto__ = o;"
   12401       "var result = 0;"
   12402       "for (var i = 0; i < 100; i++) {"
   12403       "  result = receiver.method(41);"
   12404       "}");
   12405 
   12406   CHECK_EQ(42, context->Global()
   12407                    ->Get(context.local(), v8_str("result"))
   12408                    .ToLocalChecked()
   12409                    ->Int32Value(context.local())
   12410                    .FromJust());
   12411 }
   12412 
   12413 
   12414 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
   12415   v8::Isolate* isolate = CcTest::isolate();
   12416   v8::HandleScope scope(isolate);
   12417   v8::Local<v8::FunctionTemplate> fun_templ =
   12418       v8::FunctionTemplate::New(isolate);
   12419   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12420       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12421       v8::Signature::New(isolate, fun_templ));
   12422   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12423   proto_templ->Set(v8_str("method"), method_templ);
   12424   fun_templ->SetHiddenPrototype(true);
   12425   v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12426   CHECK(!templ.IsEmpty());
   12427   LocalContext context;
   12428   v8::Local<v8::Function> fun =
   12429       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12430   GenerateSomeGarbage();
   12431   CHECK(context->Global()
   12432             ->Set(context.local(), v8_str("o"),
   12433                   fun->NewInstance(context.local()).ToLocalChecked())
   12434             .FromJust());
   12435   CompileRun(
   12436       "o.foo = 17;"
   12437       "var receiver = {};"
   12438       "receiver.__proto__ = o;"
   12439       "var result = 0;"
   12440       "var saved_result = 0;"
   12441       "for (var i = 0; i < 100; i++) {"
   12442       "  result = receiver.method(41);"
   12443       "  if (i == 50) {"
   12444       "    saved_result = result;"
   12445       "    receiver = {method: function(x) { return x - 1 }};"
   12446       "  }"
   12447       "}");
   12448   CHECK_EQ(40, context->Global()
   12449                    ->Get(context.local(), v8_str("result"))
   12450                    .ToLocalChecked()
   12451                    ->Int32Value(context.local())
   12452                    .FromJust());
   12453   CHECK_EQ(42, context->Global()
   12454                    ->Get(context.local(), v8_str("saved_result"))
   12455                    .ToLocalChecked()
   12456                    ->Int32Value(context.local())
   12457                    .FromJust());
   12458 }
   12459 
   12460 
   12461 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
   12462   v8::Isolate* isolate = CcTest::isolate();
   12463   v8::HandleScope scope(isolate);
   12464   v8::Local<v8::FunctionTemplate> fun_templ =
   12465       v8::FunctionTemplate::New(isolate);
   12466   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12467       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12468       v8::Signature::New(isolate, fun_templ));
   12469   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12470   proto_templ->Set(v8_str("method"), method_templ);
   12471   fun_templ->SetHiddenPrototype(true);
   12472   v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12473   CHECK(!templ.IsEmpty());
   12474   LocalContext context;
   12475   v8::Local<v8::Function> fun =
   12476       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12477   GenerateSomeGarbage();
   12478   CHECK(context->Global()
   12479             ->Set(context.local(), v8_str("o"),
   12480                   fun->NewInstance(context.local()).ToLocalChecked())
   12481             .FromJust());
   12482   v8::TryCatch try_catch(isolate);
   12483   CompileRun(
   12484       "o.foo = 17;"
   12485       "var receiver = {};"
   12486       "receiver.__proto__ = o;"
   12487       "var result = 0;"
   12488       "var saved_result = 0;"
   12489       "for (var i = 0; i < 100; i++) {"
   12490       "  result = receiver.method(41);"
   12491       "  if (i == 50) {"
   12492       "    saved_result = result;"
   12493       "    receiver = 333;"
   12494       "  }"
   12495       "}");
   12496   CHECK(try_catch.HasCaught());
   12497   // TODO(verwaest): Adjust message.
   12498   CHECK(
   12499       v8_str("TypeError: receiver.method is not a function")
   12500           ->Equals(
   12501               context.local(),
   12502               try_catch.Exception()->ToString(context.local()).ToLocalChecked())
   12503           .FromJust());
   12504   CHECK_EQ(42, context->Global()
   12505                    ->Get(context.local(), v8_str("saved_result"))
   12506                    .ToLocalChecked()
   12507                    ->Int32Value(context.local())
   12508                    .FromJust());
   12509 }
   12510 
   12511 
   12512 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
   12513   v8::Isolate* isolate = CcTest::isolate();
   12514   v8::HandleScope scope(isolate);
   12515   v8::Local<v8::FunctionTemplate> fun_templ =
   12516       v8::FunctionTemplate::New(isolate);
   12517   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12518       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12519       v8::Signature::New(isolate, fun_templ));
   12520   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12521   proto_templ->Set(v8_str("method"), method_templ);
   12522   fun_templ->SetHiddenPrototype(true);
   12523   v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12524   CHECK(!templ.IsEmpty());
   12525   LocalContext context;
   12526   v8::Local<v8::Function> fun =
   12527       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12528   GenerateSomeGarbage();
   12529   CHECK(context->Global()
   12530             ->Set(context.local(), v8_str("o"),
   12531                   fun->NewInstance(context.local()).ToLocalChecked())
   12532             .FromJust());
   12533   v8::TryCatch try_catch(isolate);
   12534   CompileRun(
   12535       "o.foo = 17;"
   12536       "var receiver = {};"
   12537       "receiver.__proto__ = o;"
   12538       "var result = 0;"
   12539       "var saved_result = 0;"
   12540       "for (var i = 0; i < 100; i++) {"
   12541       "  result = receiver.method(41);"
   12542       "  if (i == 50) {"
   12543       "    saved_result = result;"
   12544       "    receiver = Object.create(receiver);"
   12545       "  }"
   12546       "}");
   12547   CHECK(try_catch.HasCaught());
   12548   CHECK(
   12549       v8_str("TypeError: Illegal invocation")
   12550           ->Equals(
   12551               context.local(),
   12552               try_catch.Exception()->ToString(context.local()).ToLocalChecked())
   12553           .FromJust());
   12554   CHECK_EQ(42, context->Global()
   12555                    ->Get(context.local(), v8_str("saved_result"))
   12556                    .ToLocalChecked()
   12557                    ->Int32Value(context.local())
   12558                    .FromJust());
   12559 }
   12560 
   12561 
   12562 static void ThrowingGetter(Local<String> name,
   12563                            const v8::PropertyCallbackInfo<v8::Value>& info) {
   12564   ApiTestFuzzer::Fuzz();
   12565   info.GetIsolate()->ThrowException(Local<Value>());
   12566   info.GetReturnValue().SetUndefined();
   12567 }
   12568 
   12569 
   12570 THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
   12571   LocalContext context;
   12572   HandleScope scope(context->GetIsolate());
   12573 
   12574   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   12575   Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
   12576   instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
   12577 
   12578   Local<Object> instance = templ->GetFunction(context.local())
   12579                                .ToLocalChecked()
   12580                                ->NewInstance(context.local())
   12581                                .ToLocalChecked();
   12582 
   12583   Local<Object> another = Object::New(context->GetIsolate());
   12584   CHECK(another->SetPrototype(context.local(), instance).FromJust());
   12585 
   12586   Local<Object> with_js_getter = CompileRun(
   12587       "o = {};\n"
   12588       "o.__defineGetter__('f', function() { throw undefined; });\n"
   12589       "o\n").As<Object>();
   12590   CHECK(!with_js_getter.IsEmpty());
   12591 
   12592   TryCatch try_catch(context->GetIsolate());
   12593 
   12594   v8::MaybeLocal<Value> result =
   12595       instance->GetRealNamedProperty(context.local(), v8_str("f"));
   12596   CHECK(try_catch.HasCaught());
   12597   try_catch.Reset();
   12598   CHECK(result.IsEmpty());
   12599 
   12600   Maybe<PropertyAttribute> attr =
   12601       instance->GetRealNamedPropertyAttributes(context.local(), v8_str("f"));
   12602   CHECK(!try_catch.HasCaught());
   12603   CHECK(Just(None) == attr);
   12604 
   12605   result = another->GetRealNamedProperty(context.local(), v8_str("f"));
   12606   CHECK(try_catch.HasCaught());
   12607   try_catch.Reset();
   12608   CHECK(result.IsEmpty());
   12609 
   12610   attr = another->GetRealNamedPropertyAttributes(context.local(), v8_str("f"));
   12611   CHECK(!try_catch.HasCaught());
   12612   CHECK(Just(None) == attr);
   12613 
   12614   result = another->GetRealNamedPropertyInPrototypeChain(context.local(),
   12615                                                          v8_str("f"));
   12616   CHECK(try_catch.HasCaught());
   12617   try_catch.Reset();
   12618   CHECK(result.IsEmpty());
   12619 
   12620   attr = another->GetRealNamedPropertyAttributesInPrototypeChain(
   12621       context.local(), v8_str("f"));
   12622   CHECK(!try_catch.HasCaught());
   12623   CHECK(Just(None) == attr);
   12624 
   12625   result = another->Get(context.local(), v8_str("f"));
   12626   CHECK(try_catch.HasCaught());
   12627   try_catch.Reset();
   12628   CHECK(result.IsEmpty());
   12629 
   12630   result = with_js_getter->GetRealNamedProperty(context.local(), v8_str("f"));
   12631   CHECK(try_catch.HasCaught());
   12632   try_catch.Reset();
   12633   CHECK(result.IsEmpty());
   12634 
   12635   attr = with_js_getter->GetRealNamedPropertyAttributes(context.local(),
   12636                                                         v8_str("f"));
   12637   CHECK(!try_catch.HasCaught());
   12638   CHECK(Just(None) == attr);
   12639 
   12640   result = with_js_getter->Get(context.local(), v8_str("f"));
   12641   CHECK(try_catch.HasCaught());
   12642   try_catch.Reset();
   12643   CHECK(result.IsEmpty());
   12644 }
   12645 
   12646 
   12647 static void ThrowingCallbackWithTryCatch(
   12648     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12649   TryCatch try_catch(args.GetIsolate());
   12650   // Verboseness is important: it triggers message delivery which can call into
   12651   // external code.
   12652   try_catch.SetVerbose(true);
   12653   CompileRun("throw 'from JS';");
   12654   CHECK(try_catch.HasCaught());
   12655   CHECK(!CcTest::i_isolate()->has_pending_exception());
   12656   CHECK(!CcTest::i_isolate()->has_scheduled_exception());
   12657 }
   12658 
   12659 
   12660 static int call_depth;
   12661 
   12662 
   12663 static void WithTryCatch(Local<Message> message, Local<Value> data) {
   12664   TryCatch try_catch(CcTest::isolate());
   12665 }
   12666 
   12667 
   12668 static void ThrowFromJS(Local<Message> message, Local<Value> data) {
   12669   if (--call_depth) CompileRun("throw 'ThrowInJS';");
   12670 }
   12671 
   12672 
   12673 static void ThrowViaApi(Local<Message> message, Local<Value> data) {
   12674   if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
   12675 }
   12676 
   12677 
   12678 static void WebKitLike(Local<Message> message, Local<Value> data) {
   12679   Local<String> errorMessageString = message->Get();
   12680   CHECK(!errorMessageString.IsEmpty());
   12681   message->GetStackTrace();
   12682   message->GetScriptOrigin().ResourceName();
   12683 }
   12684 
   12685 
   12686 THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
   12687   LocalContext context;
   12688   v8::Isolate* isolate = context->GetIsolate();
   12689   HandleScope scope(isolate);
   12690 
   12691   Local<Function> func =
   12692       FunctionTemplate::New(isolate, ThrowingCallbackWithTryCatch)
   12693           ->GetFunction(context.local())
   12694           .ToLocalChecked();
   12695   CHECK(
   12696       context->Global()->Set(context.local(), v8_str("func"), func).FromJust());
   12697 
   12698   MessageCallback callbacks[] =
   12699       { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
   12700   for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
   12701     MessageCallback callback = callbacks[i];
   12702     if (callback != NULL) {
   12703       isolate->AddMessageListener(callback);
   12704     }
   12705     // Some small number to control number of times message handler should
   12706     // throw an exception.
   12707     call_depth = 5;
   12708     ExpectFalse(
   12709         "var thrown = false;\n"
   12710         "try { func(); } catch(e) { thrown = true; }\n"
   12711         "thrown\n");
   12712     if (callback != NULL) {
   12713       isolate->RemoveMessageListeners(callback);
   12714     }
   12715   }
   12716 }
   12717 
   12718 
   12719 static void ParentGetter(Local<String> name,
   12720                          const v8::PropertyCallbackInfo<v8::Value>& info) {
   12721   ApiTestFuzzer::Fuzz();
   12722   info.GetReturnValue().Set(v8_num(1));
   12723 }
   12724 
   12725 
   12726 static void ChildGetter(Local<String> name,
   12727                         const v8::PropertyCallbackInfo<v8::Value>& info) {
   12728   ApiTestFuzzer::Fuzz();
   12729   info.GetReturnValue().Set(v8_num(42));
   12730 }
   12731 
   12732 
   12733 THREADED_TEST(Overriding) {
   12734   LocalContext context;
   12735   v8::Isolate* isolate = context->GetIsolate();
   12736   v8::HandleScope scope(isolate);
   12737 
   12738   // Parent template.
   12739   Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
   12740   Local<ObjectTemplate> parent_instance_templ =
   12741       parent_templ->InstanceTemplate();
   12742   parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
   12743 
   12744   // Template that inherits from the parent template.
   12745   Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New(isolate);
   12746   Local<ObjectTemplate> child_instance_templ =
   12747       child_templ->InstanceTemplate();
   12748   child_templ->Inherit(parent_templ);
   12749   // Override 'f'.  The child version of 'f' should get called for child
   12750   // instances.
   12751   child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
   12752   // Add 'g' twice.  The 'g' added last should get called for instances.
   12753   child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
   12754   child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
   12755 
   12756   // Add 'h' as an accessor to the proto template with ReadOnly attributes
   12757   // so 'h' can be shadowed on the instance object.
   12758   Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
   12759   child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
   12760                                  v8::Local<Value>(), v8::DEFAULT, v8::ReadOnly);
   12761 
   12762   // Add 'i' as an accessor to the instance template with ReadOnly attributes
   12763   // but the attribute does not have effect because it is duplicated with
   12764   // NULL setter.
   12765   child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
   12766                                     v8::Local<Value>(), v8::DEFAULT,
   12767                                     v8::ReadOnly);
   12768 
   12769 
   12770   // Instantiate the child template.
   12771   Local<v8::Object> instance = child_templ->GetFunction(context.local())
   12772                                    .ToLocalChecked()
   12773                                    ->NewInstance(context.local())
   12774                                    .ToLocalChecked();
   12775 
   12776   // Check that the child function overrides the parent one.
   12777   CHECK(context->Global()
   12778             ->Set(context.local(), v8_str("o"), instance)
   12779             .FromJust());
   12780   Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
   12781   // Check that the 'g' that was added last is hit.
   12782   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   12783   value = v8_compile("o.g")->Run(context.local()).ToLocalChecked();
   12784   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   12785 
   12786   // Check that 'h' cannot be shadowed.
   12787   value = v8_compile("o.h = 3; o.h")->Run(context.local()).ToLocalChecked();
   12788   CHECK_EQ(1, value->Int32Value(context.local()).FromJust());
   12789 
   12790   // Check that 'i' cannot be shadowed or changed.
   12791   value = v8_compile("o.i = 3; o.i")->Run(context.local()).ToLocalChecked();
   12792   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   12793 }
   12794 
   12795 
   12796 static void IsConstructHandler(
   12797     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12798   ApiTestFuzzer::Fuzz();
   12799   args.GetReturnValue().Set(args.IsConstructCall());
   12800 }
   12801 
   12802 
   12803 THREADED_TEST(IsConstructCall) {
   12804   v8::Isolate* isolate = CcTest::isolate();
   12805   v8::HandleScope scope(isolate);
   12806 
   12807   // Function template with call handler.
   12808   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   12809   templ->SetCallHandler(IsConstructHandler);
   12810 
   12811   LocalContext context;
   12812 
   12813   CHECK(context->Global()
   12814             ->Set(context.local(), v8_str("f"),
   12815                   templ->GetFunction(context.local()).ToLocalChecked())
   12816             .FromJust());
   12817   Local<Value> value = v8_compile("f()")->Run(context.local()).ToLocalChecked();
   12818   CHECK(!value->BooleanValue(context.local()).FromJust());
   12819   value = v8_compile("new f()")->Run(context.local()).ToLocalChecked();
   12820   CHECK(value->BooleanValue(context.local()).FromJust());
   12821 }
   12822 
   12823 
   12824 THREADED_TEST(ObjectProtoToString) {
   12825   v8::Isolate* isolate = CcTest::isolate();
   12826   v8::HandleScope scope(isolate);
   12827   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   12828   templ->SetClassName(v8_str("MyClass"));
   12829 
   12830   LocalContext context;
   12831 
   12832   Local<String> customized_tostring = v8_str("customized toString");
   12833 
   12834   // Replace Object.prototype.toString
   12835   v8_compile(
   12836       "Object.prototype.toString = function() {"
   12837       "  return 'customized toString';"
   12838       "}")
   12839       ->Run(context.local())
   12840       .ToLocalChecked();
   12841 
   12842   // Normal ToString call should call replaced Object.prototype.toString
   12843   Local<v8::Object> instance = templ->GetFunction(context.local())
   12844                                    .ToLocalChecked()
   12845                                    ->NewInstance(context.local())
   12846                                    .ToLocalChecked();
   12847   Local<String> value = instance->ToString(context.local()).ToLocalChecked();
   12848   CHECK(value->IsString() &&
   12849         value->Equals(context.local(), customized_tostring).FromJust());
   12850 
   12851   // ObjectProtoToString should not call replace toString function.
   12852   value = instance->ObjectProtoToString(context.local()).ToLocalChecked();
   12853   CHECK(value->IsString() &&
   12854         value->Equals(context.local(), v8_str("[object MyClass]")).FromJust());
   12855 
   12856   // Check global
   12857   value =
   12858       context->Global()->ObjectProtoToString(context.local()).ToLocalChecked();
   12859   CHECK(value->IsString() &&
   12860         value->Equals(context.local(), v8_str("[object global]")).FromJust());
   12861 
   12862   // Check ordinary object
   12863   Local<Value> object =
   12864       v8_compile("new Object()")->Run(context.local()).ToLocalChecked();
   12865   value = object.As<v8::Object>()
   12866               ->ObjectProtoToString(context.local())
   12867               .ToLocalChecked();
   12868   CHECK(value->IsString() &&
   12869         value->Equals(context.local(), v8_str("[object Object]")).FromJust());
   12870 }
   12871 
   12872 
   12873 TEST(ObjectProtoToStringES6) {
   12874   // TODO(dslomov, caitp): merge into ObjectProtoToString test once shipped.
   12875   i::FLAG_harmony_tostring = true;
   12876   LocalContext context;
   12877   v8::Isolate* isolate = CcTest::isolate();
   12878   v8::HandleScope scope(isolate);
   12879   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   12880   templ->SetClassName(v8_str("MyClass"));
   12881 
   12882   Local<String> customized_tostring = v8_str("customized toString");
   12883 
   12884   // Replace Object.prototype.toString
   12885   CompileRun(
   12886       "Object.prototype.toString = function() {"
   12887       "  return 'customized toString';"
   12888       "}");
   12889 
   12890   // Normal ToString call should call replaced Object.prototype.toString
   12891   Local<v8::Object> instance = templ->GetFunction(context.local())
   12892                                    .ToLocalChecked()
   12893                                    ->NewInstance(context.local())
   12894                                    .ToLocalChecked();
   12895   Local<String> value = instance->ToString(context.local()).ToLocalChecked();
   12896   CHECK(value->IsString() &&
   12897         value->Equals(context.local(), customized_tostring).FromJust());
   12898 
   12899   // ObjectProtoToString should not call replace toString function.
   12900   value = instance->ObjectProtoToString(context.local()).ToLocalChecked();
   12901   CHECK(value->IsString() &&
   12902         value->Equals(context.local(), v8_str("[object MyClass]")).FromJust());
   12903 
   12904   // Check global
   12905   value =
   12906       context->Global()->ObjectProtoToString(context.local()).ToLocalChecked();
   12907   CHECK(value->IsString() &&
   12908         value->Equals(context.local(), v8_str("[object global]")).FromJust());
   12909 
   12910   // Check ordinary object
   12911   Local<Value> object = CompileRun("new Object()");
   12912   value = object.As<v8::Object>()
   12913               ->ObjectProtoToString(context.local())
   12914               .ToLocalChecked();
   12915   CHECK(value->IsString() &&
   12916         value->Equals(context.local(), v8_str("[object Object]")).FromJust());
   12917 
   12918   // Check that ES6 semantics using @@toStringTag work
   12919   Local<v8::Symbol> toStringTag = v8::Symbol::GetToStringTag(isolate);
   12920 
   12921 #define TEST_TOSTRINGTAG(type, tag, expected)                              \
   12922   do {                                                                     \
   12923     object = CompileRun("new " #type "()");                                \
   12924     CHECK(object.As<v8::Object>()                                          \
   12925               ->Set(context.local(), toStringTag, v8_str(#tag))            \
   12926               .FromJust());                                                \
   12927     value = object.As<v8::Object>()                                        \
   12928                 ->ObjectProtoToString(context.local())                     \
   12929                 .ToLocalChecked();                                         \
   12930     CHECK(value->IsString() &&                                             \
   12931           value->Equals(context.local(), v8_str("[object " #expected "]")) \
   12932               .FromJust());                                                \
   12933   } while (0)
   12934 
   12935   TEST_TOSTRINGTAG(Array, Object, Object);
   12936   TEST_TOSTRINGTAG(Object, Arguments, Arguments);
   12937   TEST_TOSTRINGTAG(Object, Array, Array);
   12938   TEST_TOSTRINGTAG(Object, Boolean, Boolean);
   12939   TEST_TOSTRINGTAG(Object, Date, Date);
   12940   TEST_TOSTRINGTAG(Object, Error, Error);
   12941   TEST_TOSTRINGTAG(Object, Function, Function);
   12942   TEST_TOSTRINGTAG(Object, Number, Number);
   12943   TEST_TOSTRINGTAG(Object, RegExp, RegExp);
   12944   TEST_TOSTRINGTAG(Object, String, String);
   12945   TEST_TOSTRINGTAG(Object, Foo, Foo);
   12946 
   12947 #undef TEST_TOSTRINGTAG
   12948 
   12949   Local<v8::RegExp> valueRegExp =
   12950       v8::RegExp::New(context.local(), v8_str("^$"), v8::RegExp::kNone)
   12951           .ToLocalChecked();
   12952   Local<Value> valueNumber = v8_num(123);
   12953   Local<v8::Symbol> valueSymbol = v8_symbol("TestSymbol");
   12954   Local<v8::Function> valueFunction =
   12955       CompileRun("(function fn() {})").As<v8::Function>();
   12956   Local<v8::Object> valueObject = v8::Object::New(v8::Isolate::GetCurrent());
   12957   Local<v8::Primitive> valueNull = v8::Null(v8::Isolate::GetCurrent());
   12958   Local<v8::Primitive> valueUndef = v8::Undefined(v8::Isolate::GetCurrent());
   12959 
   12960 #define TEST_TOSTRINGTAG(type, tagValue, expected)                         \
   12961   do {                                                                     \
   12962     object = CompileRun("new " #type "()");                                \
   12963     CHECK(object.As<v8::Object>()                                          \
   12964               ->Set(context.local(), toStringTag, tagValue)                \
   12965               .FromJust());                                                \
   12966     value = object.As<v8::Object>()                                        \
   12967                 ->ObjectProtoToString(context.local())                     \
   12968                 .ToLocalChecked();                                         \
   12969     CHECK(value->IsString() &&                                             \
   12970           value->Equals(context.local(), v8_str("[object " #expected "]")) \
   12971               .FromJust());                                                \
   12972   } while (0)
   12973 
   12974 #define TEST_TOSTRINGTAG_TYPES(tagValue)                    \
   12975   TEST_TOSTRINGTAG(Array, tagValue, Array);                 \
   12976   TEST_TOSTRINGTAG(Object, tagValue, Object);               \
   12977   TEST_TOSTRINGTAG(Function, tagValue, Function);           \
   12978   TEST_TOSTRINGTAG(Date, tagValue, Date);                   \
   12979   TEST_TOSTRINGTAG(RegExp, tagValue, RegExp);               \
   12980   TEST_TOSTRINGTAG(Error, tagValue, Error);                 \
   12981 
   12982   // Test non-String-valued @@toStringTag
   12983   TEST_TOSTRINGTAG_TYPES(valueRegExp);
   12984   TEST_TOSTRINGTAG_TYPES(valueNumber);
   12985   TEST_TOSTRINGTAG_TYPES(valueSymbol);
   12986   TEST_TOSTRINGTAG_TYPES(valueFunction);
   12987   TEST_TOSTRINGTAG_TYPES(valueObject);
   12988   TEST_TOSTRINGTAG_TYPES(valueNull);
   12989   TEST_TOSTRINGTAG_TYPES(valueUndef);
   12990 
   12991 #undef TEST_TOSTRINGTAG
   12992 #undef TEST_TOSTRINGTAG_TYPES
   12993 
   12994   // @@toStringTag getter throws
   12995   Local<Value> obj = v8::Object::New(isolate);
   12996   obj.As<v8::Object>()
   12997       ->SetAccessor(context.local(), toStringTag, ThrowingSymbolAccessorGetter)
   12998       .FromJust();
   12999   {
   13000     TryCatch try_catch(isolate);
   13001     CHECK(obj.As<v8::Object>()->ObjectProtoToString(context.local()).IsEmpty());
   13002     CHECK(try_catch.HasCaught());
   13003   }
   13004 
   13005   // @@toStringTag getter does not throw
   13006   obj = v8::Object::New(isolate);
   13007   obj.As<v8::Object>()
   13008       ->SetAccessor(context.local(), toStringTag,
   13009                     SymbolAccessorGetterReturnsDefault, 0, v8_str("Test"))
   13010       .FromJust();
   13011   {
   13012     TryCatch try_catch(isolate);
   13013     value = obj.As<v8::Object>()
   13014                 ->ObjectProtoToString(context.local())
   13015                 .ToLocalChecked();
   13016     CHECK(value->IsString() &&
   13017           value->Equals(context.local(), v8_str("[object Test]")).FromJust());
   13018     CHECK(!try_catch.HasCaught());
   13019   }
   13020 
   13021   // JS @@toStringTag value
   13022   obj = CompileRun("obj = {}; obj[Symbol.toStringTag] = 'Test'; obj");
   13023   {
   13024     TryCatch try_catch(isolate);
   13025     value = obj.As<v8::Object>()
   13026                 ->ObjectProtoToString(context.local())
   13027                 .ToLocalChecked();
   13028     CHECK(value->IsString() &&
   13029           value->Equals(context.local(), v8_str("[object Test]")).FromJust());
   13030     CHECK(!try_catch.HasCaught());
   13031   }
   13032 
   13033   // JS @@toStringTag getter throws
   13034   obj = CompileRun(
   13035       "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
   13036       "  get: function() { throw 'Test'; }"
   13037       "}); obj");
   13038   {
   13039     TryCatch try_catch(isolate);
   13040     CHECK(obj.As<v8::Object>()->ObjectProtoToString(context.local()).IsEmpty());
   13041     CHECK(try_catch.HasCaught());
   13042   }
   13043 
   13044   // JS @@toStringTag getter does not throw
   13045   obj = CompileRun(
   13046       "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
   13047       "  get: function() { return 'Test'; }"
   13048       "}); obj");
   13049   {
   13050     TryCatch try_catch(isolate);
   13051     value = obj.As<v8::Object>()
   13052                 ->ObjectProtoToString(context.local())
   13053                 .ToLocalChecked();
   13054     CHECK(value->IsString() &&
   13055           value->Equals(context.local(), v8_str("[object Test]")).FromJust());
   13056     CHECK(!try_catch.HasCaught());
   13057   }
   13058 }
   13059 
   13060 
   13061 THREADED_TEST(ObjectGetConstructorName) {
   13062   v8::Isolate* isolate = CcTest::isolate();
   13063   LocalContext context;
   13064   v8::HandleScope scope(isolate);
   13065   v8_compile(
   13066       "function Parent() {};"
   13067       "function Child() {};"
   13068       "Child.prototype = new Parent();"
   13069       "Child.prototype.constructor = Child;"
   13070       "var outer = { inner: function() { } };"
   13071       "var p = new Parent();"
   13072       "var c = new Child();"
   13073       "var x = new outer.inner();"
   13074       "var proto = Child.prototype;")
   13075       ->Run(context.local())
   13076       .ToLocalChecked();
   13077 
   13078   Local<v8::Value> p =
   13079       context->Global()->Get(context.local(), v8_str("p")).ToLocalChecked();
   13080   CHECK(p->IsObject() &&
   13081         p->ToObject(context.local())
   13082             .ToLocalChecked()
   13083             ->GetConstructorName()
   13084             ->Equals(context.local(), v8_str("Parent"))
   13085             .FromJust());
   13086 
   13087   Local<v8::Value> c =
   13088       context->Global()->Get(context.local(), v8_str("c")).ToLocalChecked();
   13089   CHECK(c->IsObject() &&
   13090         c->ToObject(context.local())
   13091             .ToLocalChecked()
   13092             ->GetConstructorName()
   13093             ->Equals(context.local(), v8_str("Child"))
   13094             .FromJust());
   13095 
   13096   Local<v8::Value> x =
   13097       context->Global()->Get(context.local(), v8_str("x")).ToLocalChecked();
   13098   CHECK(x->IsObject() &&
   13099         x->ToObject(context.local())
   13100             .ToLocalChecked()
   13101             ->GetConstructorName()
   13102             ->Equals(context.local(), v8_str("outer.inner"))
   13103             .FromJust());
   13104 
   13105   Local<v8::Value> child_prototype =
   13106       context->Global()->Get(context.local(), v8_str("proto")).ToLocalChecked();
   13107   CHECK(child_prototype->IsObject() &&
   13108         child_prototype->ToObject(context.local())
   13109             .ToLocalChecked()
   13110             ->GetConstructorName()
   13111             ->Equals(context.local(), v8_str("Parent"))
   13112             .FromJust());
   13113 }
   13114 
   13115 
   13116 THREADED_TEST(SubclassGetConstructorName) {
   13117   v8::Isolate* isolate = CcTest::isolate();
   13118   LocalContext context;
   13119   v8::HandleScope scope(isolate);
   13120   v8_compile(
   13121       "\"use strict\";"
   13122       "class Parent {}"
   13123       "class Child extends Parent {}"
   13124       "var p = new Parent();"
   13125       "var c = new Child();")
   13126       ->Run(context.local())
   13127       .ToLocalChecked();
   13128 
   13129   Local<v8::Value> p =
   13130       context->Global()->Get(context.local(), v8_str("p")).ToLocalChecked();
   13131   CHECK(p->IsObject() &&
   13132         p->ToObject(context.local())
   13133             .ToLocalChecked()
   13134             ->GetConstructorName()
   13135             ->Equals(context.local(), v8_str("Parent"))
   13136             .FromJust());
   13137 
   13138   Local<v8::Value> c =
   13139       context->Global()->Get(context.local(), v8_str("c")).ToLocalChecked();
   13140   CHECK(c->IsObject() &&
   13141         c->ToObject(context.local())
   13142             .ToLocalChecked()
   13143             ->GetConstructorName()
   13144             ->Equals(context.local(), v8_str("Child"))
   13145             .FromJust());
   13146 }
   13147 
   13148 
   13149 bool ApiTestFuzzer::fuzzing_ = false;
   13150 v8::base::Semaphore ApiTestFuzzer::all_tests_done_(0);
   13151 int ApiTestFuzzer::active_tests_;
   13152 int ApiTestFuzzer::tests_being_run_;
   13153 int ApiTestFuzzer::current_;
   13154 
   13155 
   13156 // We are in a callback and want to switch to another thread (if we
   13157 // are currently running the thread fuzzing test).
   13158 void ApiTestFuzzer::Fuzz() {
   13159   if (!fuzzing_) return;
   13160   ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
   13161   test->ContextSwitch();
   13162 }
   13163 
   13164 
   13165 // Let the next thread go.  Since it is also waiting on the V8 lock it may
   13166 // not start immediately.
   13167 bool ApiTestFuzzer::NextThread() {
   13168   int test_position = GetNextTestNumber();
   13169   const char* test_name = RegisterThreadedTest::nth(current_)->name();
   13170   if (test_position == current_) {
   13171     if (kLogThreading)
   13172       printf("Stay with %s\n", test_name);
   13173     return false;
   13174   }
   13175   if (kLogThreading) {
   13176     printf("Switch from %s to %s\n",
   13177            test_name,
   13178            RegisterThreadedTest::nth(test_position)->name());
   13179   }
   13180   current_ = test_position;
   13181   RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
   13182   return true;
   13183 }
   13184 
   13185 
   13186 void ApiTestFuzzer::Run() {
   13187   // When it is our turn...
   13188   gate_.Wait();
   13189   {
   13190     // ... get the V8 lock and start running the test.
   13191     v8::Locker locker(CcTest::isolate());
   13192     CallTest();
   13193   }
   13194   // This test finished.
   13195   active_ = false;
   13196   active_tests_--;
   13197   // If it was the last then signal that fact.
   13198   if (active_tests_ == 0) {
   13199     all_tests_done_.Signal();
   13200   } else {
   13201     // Otherwise select a new test and start that.
   13202     NextThread();
   13203   }
   13204 }
   13205 
   13206 
   13207 static unsigned linear_congruential_generator;
   13208 
   13209 
   13210 void ApiTestFuzzer::SetUp(PartOfTest part) {
   13211   linear_congruential_generator = i::FLAG_testing_prng_seed;
   13212   fuzzing_ = true;
   13213   int count = RegisterThreadedTest::count();
   13214   int start =  count * part / (LAST_PART + 1);
   13215   int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
   13216   active_tests_ = tests_being_run_ = end - start + 1;
   13217   for (int i = 0; i < tests_being_run_; i++) {
   13218     RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
   13219   }
   13220   for (int i = 0; i < active_tests_; i++) {
   13221     RegisterThreadedTest::nth(i)->fuzzer_->Start();
   13222   }
   13223 }
   13224 
   13225 
   13226 static void CallTestNumber(int test_number) {
   13227   (RegisterThreadedTest::nth(test_number)->callback())();
   13228 }
   13229 
   13230 
   13231 void ApiTestFuzzer::RunAllTests() {
   13232   // Set off the first test.
   13233   current_ = -1;
   13234   NextThread();
   13235   // Wait till they are all done.
   13236   all_tests_done_.Wait();
   13237 }
   13238 
   13239 
   13240 int ApiTestFuzzer::GetNextTestNumber() {
   13241   int next_test;
   13242   do {
   13243     next_test = (linear_congruential_generator >> 16) % tests_being_run_;
   13244     linear_congruential_generator *= 1664525u;
   13245     linear_congruential_generator += 1013904223u;
   13246   } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
   13247   return next_test;
   13248 }
   13249 
   13250 
   13251 void ApiTestFuzzer::ContextSwitch() {
   13252   // If the new thread is the same as the current thread there is nothing to do.
   13253   if (NextThread()) {
   13254     // Now it can start.
   13255     v8::Unlocker unlocker(CcTest::isolate());
   13256     // Wait till someone starts us again.
   13257     gate_.Wait();
   13258     // And we're off.
   13259   }
   13260 }
   13261 
   13262 
   13263 void ApiTestFuzzer::TearDown() {
   13264   fuzzing_ = false;
   13265   for (int i = 0; i < RegisterThreadedTest::count(); i++) {
   13266     ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
   13267     if (fuzzer != NULL) fuzzer->Join();
   13268   }
   13269 }
   13270 
   13271 
   13272 // Lets not be needlessly self-referential.
   13273 TEST(Threading1) {
   13274   ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
   13275   ApiTestFuzzer::RunAllTests();
   13276   ApiTestFuzzer::TearDown();
   13277 }
   13278 
   13279 
   13280 TEST(Threading2) {
   13281   ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
   13282   ApiTestFuzzer::RunAllTests();
   13283   ApiTestFuzzer::TearDown();
   13284 }
   13285 
   13286 
   13287 TEST(Threading3) {
   13288   ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
   13289   ApiTestFuzzer::RunAllTests();
   13290   ApiTestFuzzer::TearDown();
   13291 }
   13292 
   13293 
   13294 TEST(Threading4) {
   13295   ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
   13296   ApiTestFuzzer::RunAllTests();
   13297   ApiTestFuzzer::TearDown();
   13298 }
   13299 
   13300 
   13301 void ApiTestFuzzer::CallTest() {
   13302   v8::Isolate::Scope scope(CcTest::isolate());
   13303   if (kLogThreading)
   13304     printf("Start test %d\n", test_number_);
   13305   CallTestNumber(test_number_);
   13306   if (kLogThreading)
   13307     printf("End test %d\n", test_number_);
   13308 }
   13309 
   13310 
   13311 static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13312   v8::Isolate* isolate = args.GetIsolate();
   13313   CHECK(v8::Locker::IsLocked(isolate));
   13314   ApiTestFuzzer::Fuzz();
   13315   v8::Unlocker unlocker(isolate);
   13316   const char* code = "throw 7;";
   13317   {
   13318     v8::Locker nested_locker(isolate);
   13319     v8::HandleScope scope(isolate);
   13320     v8::Local<Value> exception;
   13321     {
   13322       v8::TryCatch try_catch(isolate);
   13323       v8::Local<Value> value = CompileRun(code);
   13324       CHECK(value.IsEmpty());
   13325       CHECK(try_catch.HasCaught());
   13326       // Make sure to wrap the exception in a new handle because
   13327       // the handle returned from the TryCatch is destroyed
   13328       // when the TryCatch is destroyed.
   13329       exception = Local<Value>::New(isolate, try_catch.Exception());
   13330     }
   13331     args.GetIsolate()->ThrowException(exception);
   13332   }
   13333 }
   13334 
   13335 
   13336 static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13337   CHECK(v8::Locker::IsLocked(CcTest::isolate()));
   13338   ApiTestFuzzer::Fuzz();
   13339   v8::Unlocker unlocker(CcTest::isolate());
   13340   const char* code = "throw 7;";
   13341   {
   13342     v8::Locker nested_locker(CcTest::isolate());
   13343     v8::HandleScope scope(args.GetIsolate());
   13344     v8::Local<Value> value = CompileRun(code);
   13345     CHECK(value.IsEmpty());
   13346     args.GetReturnValue().Set(v8_str("foo"));
   13347   }
   13348 }
   13349 
   13350 
   13351 // These are locking tests that don't need to be run again
   13352 // as part of the locking aggregation tests.
   13353 TEST(NestedLockers) {
   13354   v8::Isolate* isolate = CcTest::isolate();
   13355   v8::Locker locker(isolate);
   13356   CHECK(v8::Locker::IsLocked(isolate));
   13357   LocalContext env;
   13358   v8::HandleScope scope(env->GetIsolate());
   13359   Local<v8::FunctionTemplate> fun_templ =
   13360       v8::FunctionTemplate::New(isolate, ThrowInJS);
   13361   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   13362   CHECK(env->Global()->Set(env.local(), v8_str("throw_in_js"), fun).FromJust());
   13363   Local<Script> script = v8_compile("(function () {"
   13364                                     "  try {"
   13365                                     "    throw_in_js();"
   13366                                     "    return 42;"
   13367                                     "  } catch (e) {"
   13368                                     "    return e * 13;"
   13369                                     "  }"
   13370                                     "})();");
   13371   CHECK_EQ(91, script->Run(env.local())
   13372                    .ToLocalChecked()
   13373                    ->Int32Value(env.local())
   13374                    .FromJust());
   13375 }
   13376 
   13377 
   13378 // These are locking tests that don't need to be run again
   13379 // as part of the locking aggregation tests.
   13380 TEST(NestedLockersNoTryCatch) {
   13381   v8::Locker locker(CcTest::isolate());
   13382   LocalContext env;
   13383   v8::HandleScope scope(env->GetIsolate());
   13384   Local<v8::FunctionTemplate> fun_templ =
   13385       v8::FunctionTemplate::New(env->GetIsolate(), ThrowInJSNoCatch);
   13386   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   13387   CHECK(env->Global()->Set(env.local(), v8_str("throw_in_js"), fun).FromJust());
   13388   Local<Script> script = v8_compile("(function () {"
   13389                                     "  try {"
   13390                                     "    throw_in_js();"
   13391                                     "    return 42;"
   13392                                     "  } catch (e) {"
   13393                                     "    return e * 13;"
   13394                                     "  }"
   13395                                     "})();");
   13396   CHECK_EQ(91, script->Run(env.local())
   13397                    .ToLocalChecked()
   13398                    ->Int32Value(env.local())
   13399                    .FromJust());
   13400 }
   13401 
   13402 
   13403 THREADED_TEST(RecursiveLocking) {
   13404   v8::Locker locker(CcTest::isolate());
   13405   {
   13406     v8::Locker locker2(CcTest::isolate());
   13407     CHECK(v8::Locker::IsLocked(CcTest::isolate()));
   13408   }
   13409 }
   13410 
   13411 
   13412 static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13413   ApiTestFuzzer::Fuzz();
   13414   v8::Unlocker unlocker(CcTest::isolate());
   13415 }
   13416 
   13417 
   13418 THREADED_TEST(LockUnlockLock) {
   13419   {
   13420     v8::Locker locker(CcTest::isolate());
   13421     v8::HandleScope scope(CcTest::isolate());
   13422     LocalContext env;
   13423     Local<v8::FunctionTemplate> fun_templ =
   13424         v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
   13425     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   13426     CHECK(env->Global()
   13427               ->Set(env.local(), v8_str("unlock_for_a_moment"), fun)
   13428               .FromJust());
   13429     Local<Script> script = v8_compile("(function () {"
   13430                                       "  unlock_for_a_moment();"
   13431                                       "  return 42;"
   13432                                       "})();");
   13433     CHECK_EQ(42, script->Run(env.local())
   13434                      .ToLocalChecked()
   13435                      ->Int32Value(env.local())
   13436                      .FromJust());
   13437   }
   13438   {
   13439     v8::Locker locker(CcTest::isolate());
   13440     v8::HandleScope scope(CcTest::isolate());
   13441     LocalContext env;
   13442     Local<v8::FunctionTemplate> fun_templ =
   13443         v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
   13444     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   13445     CHECK(env->Global()
   13446               ->Set(env.local(), v8_str("unlock_for_a_moment"), fun)
   13447               .FromJust());
   13448     Local<Script> script = v8_compile("(function () {"
   13449                                       "  unlock_for_a_moment();"
   13450                                       "  return 42;"
   13451                                       "})();");
   13452     CHECK_EQ(42, script->Run(env.local())
   13453                      .ToLocalChecked()
   13454                      ->Int32Value(env.local())
   13455                      .FromJust());
   13456   }
   13457 }
   13458 
   13459 
   13460 static int GetGlobalObjectsCount() {
   13461   int count = 0;
   13462   i::HeapIterator it(CcTest::heap());
   13463   for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
   13464     if (object->IsJSGlobalObject()) {
   13465       i::JSGlobalObject* g = i::JSGlobalObject::cast(object);
   13466       // Skip dummy global object.
   13467       if (i::GlobalDictionary::cast(g->properties())->NumberOfElements() != 0) {
   13468         count++;
   13469       }
   13470     }
   13471   return count;
   13472 }
   13473 
   13474 
   13475 static void CheckSurvivingGlobalObjectsCount(int expected) {
   13476   // We need to collect all garbage twice to be sure that everything
   13477   // has been collected.  This is because inline caches are cleared in
   13478   // the first garbage collection but some of the maps have already
   13479   // been marked at that point.  Therefore some of the maps are not
   13480   // collected until the second garbage collection.
   13481   CcTest::heap()->CollectAllGarbage();
   13482   CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
   13483   int count = GetGlobalObjectsCount();
   13484 #ifdef DEBUG
   13485   if (count != expected) CcTest::heap()->TracePathToGlobal();
   13486 #endif
   13487   CHECK_EQ(expected, count);
   13488 }
   13489 
   13490 
   13491 TEST(DontLeakGlobalObjects) {
   13492   // Regression test for issues 1139850 and 1174891.
   13493 
   13494   i::FLAG_expose_gc = true;
   13495   v8::V8::Initialize();
   13496 
   13497   for (int i = 0; i < 5; i++) {
   13498     { v8::HandleScope scope(CcTest::isolate());
   13499       LocalContext context;
   13500     }
   13501     CcTest::isolate()->ContextDisposedNotification();
   13502     CheckSurvivingGlobalObjectsCount(0);
   13503 
   13504     { v8::HandleScope scope(CcTest::isolate());
   13505       LocalContext context;
   13506       v8_compile("Date")->Run(context.local()).ToLocalChecked();
   13507     }
   13508     CcTest::isolate()->ContextDisposedNotification();
   13509     CheckSurvivingGlobalObjectsCount(0);
   13510 
   13511     { v8::HandleScope scope(CcTest::isolate());
   13512       LocalContext context;
   13513       v8_compile("/aaa/")->Run(context.local()).ToLocalChecked();
   13514     }
   13515     CcTest::isolate()->ContextDisposedNotification();
   13516     CheckSurvivingGlobalObjectsCount(0);
   13517 
   13518     { v8::HandleScope scope(CcTest::isolate());
   13519       const char* extension_list[] = { "v8/gc" };
   13520       v8::ExtensionConfiguration extensions(1, extension_list);
   13521       LocalContext context(&extensions);
   13522       v8_compile("gc();")->Run(context.local()).ToLocalChecked();
   13523     }
   13524     CcTest::isolate()->ContextDisposedNotification();
   13525     CheckSurvivingGlobalObjectsCount(0);
   13526   }
   13527 }
   13528 
   13529 
   13530 TEST(CopyablePersistent) {
   13531   LocalContext context;
   13532   v8::Isolate* isolate = context->GetIsolate();
   13533   i::GlobalHandles* globals =
   13534       reinterpret_cast<i::Isolate*>(isolate)->global_handles();
   13535   int initial_handles = globals->global_handles_count();
   13536   typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
   13537       CopyableObject;
   13538   {
   13539     CopyableObject handle1;
   13540     {
   13541       v8::HandleScope scope(isolate);
   13542       handle1.Reset(isolate, v8::Object::New(isolate));
   13543     }
   13544     CHECK_EQ(initial_handles + 1, globals->global_handles_count());
   13545     CopyableObject  handle2;
   13546     handle2 = handle1;
   13547     CHECK(handle1 == handle2);
   13548     CHECK_EQ(initial_handles + 2, globals->global_handles_count());
   13549     CopyableObject handle3(handle2);
   13550     CHECK(handle1 == handle3);
   13551     CHECK_EQ(initial_handles + 3, globals->global_handles_count());
   13552   }
   13553   // Verify autodispose
   13554   CHECK_EQ(initial_handles, globals->global_handles_count());
   13555 }
   13556 
   13557 
   13558 static void WeakApiCallback(
   13559     const v8::WeakCallbackInfo<Persistent<v8::Object>>& data) {
   13560   data.GetParameter()->Reset();
   13561   delete data.GetParameter();
   13562 }
   13563 
   13564 
   13565 TEST(WeakCallbackApi) {
   13566   LocalContext context;
   13567   v8::Isolate* isolate = context->GetIsolate();
   13568   i::GlobalHandles* globals =
   13569       reinterpret_cast<i::Isolate*>(isolate)->global_handles();
   13570   int initial_handles = globals->global_handles_count();
   13571   {
   13572     v8::HandleScope scope(isolate);
   13573     v8::Local<v8::Object> obj = v8::Object::New(isolate);
   13574     CHECK(
   13575         obj->Set(context.local(), v8_str("key"), v8::Integer::New(isolate, 231))
   13576             .FromJust());
   13577     v8::Persistent<v8::Object>* handle =
   13578         new v8::Persistent<v8::Object>(isolate, obj);
   13579     handle->SetWeak<v8::Persistent<v8::Object>>(
   13580         handle, WeakApiCallback, v8::WeakCallbackType::kParameter);
   13581   }
   13582   reinterpret_cast<i::Isolate*>(isolate)->heap()->CollectAllGarbage(
   13583       i::Heap::kAbortIncrementalMarkingMask);
   13584   // Verify disposed.
   13585   CHECK_EQ(initial_handles, globals->global_handles_count());
   13586 }
   13587 
   13588 
   13589 v8::Persistent<v8::Object> some_object;
   13590 v8::Persistent<v8::Object> bad_handle;
   13591 
   13592 
   13593 void NewPersistentHandleCallback2(
   13594     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   13595   v8::HandleScope scope(data.GetIsolate());
   13596   bad_handle.Reset(data.GetIsolate(), some_object);
   13597 }
   13598 
   13599 
   13600 void NewPersistentHandleCallback1(
   13601     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   13602   data.GetParameter()->Reset();
   13603   data.SetSecondPassCallback(NewPersistentHandleCallback2);
   13604 }
   13605 
   13606 
   13607 THREADED_TEST(NewPersistentHandleFromWeakCallback) {
   13608   LocalContext context;
   13609   v8::Isolate* isolate = context->GetIsolate();
   13610 
   13611   v8::Persistent<v8::Object> handle1, handle2;
   13612   {
   13613     v8::HandleScope scope(isolate);
   13614     some_object.Reset(isolate, v8::Object::New(isolate));
   13615     handle1.Reset(isolate, v8::Object::New(isolate));
   13616     handle2.Reset(isolate, v8::Object::New(isolate));
   13617   }
   13618   // Note: order is implementation dependent alas: currently
   13619   // global handle nodes are processed by PostGarbageCollectionProcessing
   13620   // in reverse allocation order, so if second allocated handle is deleted,
   13621   // weak callback of the first handle would be able to 'reallocate' it.
   13622   handle1.SetWeak(&handle1, NewPersistentHandleCallback1,
   13623                   v8::WeakCallbackType::kParameter);
   13624   handle2.Reset();
   13625   CcTest::heap()->CollectAllGarbage();
   13626 }
   13627 
   13628 
   13629 v8::Persistent<v8::Object> to_be_disposed;
   13630 
   13631 
   13632 void DisposeAndForceGcCallback2(
   13633     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   13634   to_be_disposed.Reset();
   13635   CcTest::heap()->CollectAllGarbage();
   13636 }
   13637 
   13638 
   13639 void DisposeAndForceGcCallback1(
   13640     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   13641   data.GetParameter()->Reset();
   13642   data.SetSecondPassCallback(DisposeAndForceGcCallback2);
   13643 }
   13644 
   13645 
   13646 THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
   13647   LocalContext context;
   13648   v8::Isolate* isolate = context->GetIsolate();
   13649 
   13650   v8::Persistent<v8::Object> handle1, handle2;
   13651   {
   13652     v8::HandleScope scope(isolate);
   13653     handle1.Reset(isolate, v8::Object::New(isolate));
   13654     handle2.Reset(isolate, v8::Object::New(isolate));
   13655   }
   13656   handle1.SetWeak(&handle1, DisposeAndForceGcCallback1,
   13657                   v8::WeakCallbackType::kParameter);
   13658   to_be_disposed.Reset(isolate, handle2);
   13659   CcTest::heap()->CollectAllGarbage();
   13660 }
   13661 
   13662 void DisposingCallback(
   13663     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   13664   data.GetParameter()->Reset();
   13665 }
   13666 
   13667 void HandleCreatingCallback2(
   13668     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   13669   v8::HandleScope scope(data.GetIsolate());
   13670   v8::Global<v8::Object>(data.GetIsolate(), v8::Object::New(data.GetIsolate()));
   13671 }
   13672 
   13673 
   13674 void HandleCreatingCallback1(
   13675     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   13676   data.GetParameter()->Reset();
   13677   data.SetSecondPassCallback(HandleCreatingCallback2);
   13678 }
   13679 
   13680 
   13681 THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
   13682   v8::Locker locker(CcTest::isolate());
   13683   LocalContext context;
   13684   v8::Isolate* isolate = context->GetIsolate();
   13685 
   13686   v8::Persistent<v8::Object> handle1, handle2, handle3;
   13687   {
   13688     v8::HandleScope scope(isolate);
   13689     handle3.Reset(isolate, v8::Object::New(isolate));
   13690     handle2.Reset(isolate, v8::Object::New(isolate));
   13691     handle1.Reset(isolate, v8::Object::New(isolate));
   13692   }
   13693   handle2.SetWeak(&handle2, DisposingCallback,
   13694                   v8::WeakCallbackType::kParameter);
   13695   handle3.SetWeak(&handle3, HandleCreatingCallback1,
   13696                   v8::WeakCallbackType::kParameter);
   13697   CcTest::heap()->CollectAllGarbage();
   13698   EmptyMessageQueues(isolate);
   13699 }
   13700 
   13701 
   13702 THREADED_TEST(CheckForCrossContextObjectLiterals) {
   13703   v8::V8::Initialize();
   13704 
   13705   const int nof = 2;
   13706   const char* sources[nof] = {
   13707     "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
   13708     "Object()"
   13709   };
   13710 
   13711   for (int i = 0; i < nof; i++) {
   13712     const char* source = sources[i];
   13713     { v8::HandleScope scope(CcTest::isolate());
   13714       LocalContext context;
   13715       CompileRun(source);
   13716     }
   13717     { v8::HandleScope scope(CcTest::isolate());
   13718       LocalContext context;
   13719       CompileRun(source);
   13720     }
   13721   }
   13722 }
   13723 
   13724 
   13725 static v8::Local<Value> NestedScope(v8::Local<Context> env) {
   13726   v8::EscapableHandleScope inner(env->GetIsolate());
   13727   env->Enter();
   13728   v8::Local<Value> three = v8_num(3);
   13729   v8::Local<Value> value = inner.Escape(three);
   13730   env->Exit();
   13731   return value;
   13732 }
   13733 
   13734 
   13735 THREADED_TEST(NestedHandleScopeAndContexts) {
   13736   v8::Isolate* isolate = CcTest::isolate();
   13737   v8::HandleScope outer(isolate);
   13738   v8::Local<Context> env = Context::New(isolate);
   13739   env->Enter();
   13740   v8::Local<Value> value = NestedScope(env);
   13741   v8::Local<String> str(value->ToString(env).ToLocalChecked());
   13742   CHECK(!str.IsEmpty());
   13743   env->Exit();
   13744 }
   13745 
   13746 
   13747 static bool MatchPointers(void* key1, void* key2) {
   13748   return key1 == key2;
   13749 }
   13750 
   13751 
   13752 struct SymbolInfo {
   13753   size_t id;
   13754   size_t size;
   13755   std::string name;
   13756 };
   13757 
   13758 
   13759 class SetFunctionEntryHookTest {
   13760  public:
   13761   SetFunctionEntryHookTest() {
   13762     CHECK(instance_ == NULL);
   13763     instance_ = this;
   13764   }
   13765   ~SetFunctionEntryHookTest() {
   13766     CHECK(instance_ == this);
   13767     instance_ = NULL;
   13768   }
   13769   void Reset() {
   13770     symbols_.clear();
   13771     symbol_locations_.clear();
   13772     invocations_.clear();
   13773   }
   13774   void RunTest();
   13775   void OnJitEvent(const v8::JitCodeEvent* event);
   13776   static void JitEvent(const v8::JitCodeEvent* event) {
   13777     CHECK(instance_ != NULL);
   13778     instance_->OnJitEvent(event);
   13779   }
   13780 
   13781   void OnEntryHook(uintptr_t function,
   13782                    uintptr_t return_addr_location);
   13783   static void EntryHook(uintptr_t function,
   13784                         uintptr_t return_addr_location) {
   13785     CHECK(instance_ != NULL);
   13786     instance_->OnEntryHook(function, return_addr_location);
   13787   }
   13788 
   13789   static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13790     CHECK(instance_ != NULL);
   13791     args.GetReturnValue().Set(v8_num(42));
   13792   }
   13793   void RunLoopInNewEnv(v8::Isolate* isolate);
   13794 
   13795   // Records addr as location of symbol.
   13796   void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
   13797 
   13798   // Finds the symbol containing addr
   13799   SymbolInfo* FindSymbolForAddr(i::Address addr);
   13800   // Returns the number of invocations where the caller name contains
   13801   // \p caller_name and the function name contains \p function_name.
   13802   int CountInvocations(const char* caller_name,
   13803                        const char* function_name);
   13804 
   13805   i::Handle<i::JSFunction> foo_func_;
   13806   i::Handle<i::JSFunction> bar_func_;
   13807 
   13808   typedef std::map<size_t, SymbolInfo> SymbolMap;
   13809   typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
   13810   typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
   13811   SymbolMap symbols_;
   13812   SymbolLocationMap symbol_locations_;
   13813   InvocationMap invocations_;
   13814 
   13815   static SetFunctionEntryHookTest* instance_;
   13816 };
   13817 SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
   13818 
   13819 
   13820 // Returns true if addr is in the range [start, start+len).
   13821 static bool Overlaps(i::Address start, size_t len, i::Address addr) {
   13822   if (start <= addr && start + len > addr)
   13823     return true;
   13824 
   13825   return false;
   13826 }
   13827 
   13828 void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
   13829                                               SymbolInfo* symbol) {
   13830   // Insert the symbol at the new location.
   13831   SymbolLocationMap::iterator it =
   13832       symbol_locations_.insert(std::make_pair(addr, symbol)).first;
   13833   // Now erase symbols to the left and right that overlap this one.
   13834   while (it != symbol_locations_.begin()) {
   13835     SymbolLocationMap::iterator left = it;
   13836     --left;
   13837     if (!Overlaps(left->first, left->second->size, addr))
   13838       break;
   13839     symbol_locations_.erase(left);
   13840   }
   13841 
   13842   // Now erase symbols to the left and right that overlap this one.
   13843   while (true) {
   13844     SymbolLocationMap::iterator right = it;
   13845     ++right;
   13846     if (right == symbol_locations_.end())
   13847         break;
   13848     if (!Overlaps(addr, symbol->size, right->first))
   13849       break;
   13850     symbol_locations_.erase(right);
   13851   }
   13852 }
   13853 
   13854 
   13855 void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
   13856   switch (event->type) {
   13857     case v8::JitCodeEvent::CODE_ADDED: {
   13858         CHECK(event->code_start != NULL);
   13859         CHECK_NE(0, static_cast<int>(event->code_len));
   13860         CHECK(event->name.str != NULL);
   13861         size_t symbol_id = symbols_.size();
   13862 
   13863         // Record the new symbol.
   13864         SymbolInfo& info = symbols_[symbol_id];
   13865         info.id = symbol_id;
   13866         info.size = event->code_len;
   13867         info.name.assign(event->name.str, event->name.str + event->name.len);
   13868 
   13869         // And record it's location.
   13870         InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
   13871       }
   13872       break;
   13873 
   13874     case v8::JitCodeEvent::CODE_MOVED: {
   13875         // We would like to never see code move that we haven't seen before,
   13876         // but the code creation event does not happen until the line endings
   13877         // have been calculated (this is so that we can report the line in the
   13878         // script at which the function source is found, see
   13879         // Compiler::RecordFunctionCompilation) and the line endings
   13880         // calculations can cause a GC, which can move the newly created code
   13881         // before its existence can be logged.
   13882         SymbolLocationMap::iterator it(
   13883             symbol_locations_.find(
   13884                 reinterpret_cast<i::Address>(event->code_start)));
   13885         if (it != symbol_locations_.end()) {
   13886           // Found a symbol at this location, move it.
   13887           SymbolInfo* info = it->second;
   13888           symbol_locations_.erase(it);
   13889           InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
   13890                          info);
   13891         }
   13892       }
   13893     default:
   13894       break;
   13895   }
   13896 }
   13897 
   13898 void SetFunctionEntryHookTest::OnEntryHook(
   13899     uintptr_t function, uintptr_t return_addr_location) {
   13900   // Get the function's code object.
   13901   i::Code* function_code = i::Code::GetCodeFromTargetAddress(
   13902       reinterpret_cast<i::Address>(function));
   13903   CHECK(function_code != NULL);
   13904 
   13905   // Then try and look up the caller's code object.
   13906   i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
   13907 
   13908   // Count the invocation.
   13909   SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
   13910   SymbolInfo* function_symbol =
   13911       FindSymbolForAddr(reinterpret_cast<i::Address>(function));
   13912   ++invocations_[std::make_pair(caller_symbol, function_symbol)];
   13913 
   13914   if (!bar_func_.is_null() && function_code == bar_func_->code()) {
   13915     // Check that we have a symbol for the "bar" function at the right location.
   13916     SymbolLocationMap::iterator it(
   13917         symbol_locations_.find(function_code->instruction_start()));
   13918     CHECK(it != symbol_locations_.end());
   13919   }
   13920 
   13921   if (!foo_func_.is_null() && function_code == foo_func_->code()) {
   13922     // Check that we have a symbol for "foo" at the right location.
   13923     SymbolLocationMap::iterator it(
   13924         symbol_locations_.find(function_code->instruction_start()));
   13925     CHECK(it != symbol_locations_.end());
   13926   }
   13927 }
   13928 
   13929 
   13930 SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
   13931   SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
   13932   // Do we have a direct hit on a symbol?
   13933   if (it != symbol_locations_.end()) {
   13934     if (it->first == addr)
   13935       return it->second;
   13936   }
   13937 
   13938   // If not a direct hit, it'll have to be the previous symbol.
   13939   if (it == symbol_locations_.begin())
   13940     return NULL;
   13941 
   13942   --it;
   13943   size_t offs = addr - it->first;
   13944   if (offs < it->second->size)
   13945     return it->second;
   13946 
   13947   return NULL;
   13948 }
   13949 
   13950 
   13951 int SetFunctionEntryHookTest::CountInvocations(
   13952     const char* caller_name, const char* function_name) {
   13953   InvocationMap::iterator it(invocations_.begin());
   13954   int invocations = 0;
   13955   for (; it != invocations_.end(); ++it) {
   13956     SymbolInfo* caller = it->first.first;
   13957     SymbolInfo* function = it->first.second;
   13958 
   13959     // Filter out non-matching functions.
   13960     if (function_name != NULL) {
   13961       if (function->name.find(function_name) == std::string::npos)
   13962         continue;
   13963     }
   13964 
   13965     // Filter out non-matching callers.
   13966     if (caller_name != NULL) {
   13967       if (caller == NULL)
   13968         continue;
   13969       if (caller->name.find(caller_name) == std::string::npos)
   13970         continue;
   13971     }
   13972 
   13973     // It matches add the invocation count to the tally.
   13974     invocations += it->second;
   13975   }
   13976 
   13977   return invocations;
   13978 }
   13979 
   13980 
   13981 void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
   13982   v8::HandleScope outer(isolate);
   13983   v8::Local<Context> env = Context::New(isolate);
   13984   env->Enter();
   13985 
   13986   Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
   13987   t->Set(v8_str("asdf"), v8::FunctionTemplate::New(isolate, RuntimeCallback));
   13988   CHECK(env->Global()
   13989             ->Set(env, v8_str("obj"), t->NewInstance(env).ToLocalChecked())
   13990             .FromJust());
   13991 
   13992   const char* script =
   13993       "function bar() {\n"
   13994       "  var sum = 0;\n"
   13995       "  for (i = 0; i < 100; ++i)\n"
   13996       "    sum = foo(i);\n"
   13997       "  return sum;\n"
   13998       "}\n"
   13999       "function foo(i) { return i * i; }\n"
   14000       "// Invoke on the runtime function.\n"
   14001       "obj.asdf()";
   14002   CompileRun(script);
   14003   bar_func_ = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(
   14004       *env->Global()->Get(env, v8_str("bar")).ToLocalChecked()));
   14005   CHECK(!bar_func_.is_null());
   14006 
   14007   foo_func_ = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(
   14008       *env->Global()->Get(env, v8_str("foo")).ToLocalChecked()));
   14009   CHECK(!foo_func_.is_null());
   14010 
   14011   v8::Local<v8::Value> value = CompileRun("bar();");
   14012   CHECK(value->IsNumber());
   14013   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
   14014 
   14015   // Test the optimized codegen path.
   14016   value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
   14017                      "bar();");
   14018   CHECK(value->IsNumber());
   14019   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
   14020 
   14021   env->Exit();
   14022 }
   14023 
   14024 
   14025 void SetFunctionEntryHookTest::RunTest() {
   14026   // Work in a new isolate throughout.
   14027   v8::Isolate::CreateParams create_params;
   14028   create_params.entry_hook = EntryHook;
   14029   create_params.code_event_handler = JitEvent;
   14030   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   14031   v8::Isolate* isolate = v8::Isolate::New(create_params);
   14032 
   14033   {
   14034     v8::Isolate::Scope scope(isolate);
   14035 
   14036     RunLoopInNewEnv(isolate);
   14037 
   14038     // Check the exepected invocation counts.
   14039     CHECK_EQ(2, CountInvocations(NULL, "bar"));
   14040     CHECK_EQ(200, CountInvocations("bar", "foo"));
   14041     CHECK_EQ(200, CountInvocations(NULL, "foo"));
   14042 
   14043     // Verify that we have an entry hook on some specific stubs.
   14044     CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
   14045     CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
   14046     CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
   14047   }
   14048   isolate->Dispose();
   14049 
   14050   Reset();
   14051 
   14052   // Make sure a second isolate is unaffected by the previous entry hook.
   14053   create_params = v8::Isolate::CreateParams();
   14054   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   14055   isolate = v8::Isolate::New(create_params);
   14056   {
   14057     v8::Isolate::Scope scope(isolate);
   14058 
   14059     // Reset the entry count to zero and set the entry hook.
   14060     RunLoopInNewEnv(isolate);
   14061 
   14062     // We should record no invocations in this isolate.
   14063     CHECK_EQ(0, static_cast<int>(invocations_.size()));
   14064   }
   14065 
   14066   isolate->Dispose();
   14067 }
   14068 
   14069 
   14070 TEST(SetFunctionEntryHook) {
   14071   // FunctionEntryHook does not work well with experimental natives.
   14072   // Experimental natives are compiled during snapshot deserialization.
   14073   // This test breaks because InstallGetter (function from snapshot that
   14074   // only gets called from experimental natives) is compiled with entry hooks.
   14075   i::FLAG_allow_natives_syntax = true;
   14076   i::FLAG_turbo_inlining = false;
   14077   i::FLAG_use_inlining = false;
   14078 
   14079   SetFunctionEntryHookTest test;
   14080   test.RunTest();
   14081 }
   14082 
   14083 
   14084 static i::HashMap* code_map = NULL;
   14085 static i::HashMap* jitcode_line_info = NULL;
   14086 static int saw_bar = 0;
   14087 static int move_events = 0;
   14088 
   14089 
   14090 static bool FunctionNameIs(const char* expected,
   14091                            const v8::JitCodeEvent* event) {
   14092   // Log lines for functions are of the general form:
   14093   // "LazyCompile:<type><function_name>", where the type is one of
   14094   // "*", "~" or "".
   14095   static const char kPreamble[] = "LazyCompile:";
   14096   static size_t kPreambleLen = sizeof(kPreamble) - 1;
   14097 
   14098   if (event->name.len < sizeof(kPreamble) - 1 ||
   14099       strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
   14100     return false;
   14101   }
   14102 
   14103   const char* tail = event->name.str + kPreambleLen;
   14104   size_t tail_len = event->name.len - kPreambleLen;
   14105   size_t expected_len = strlen(expected);
   14106   if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
   14107     --tail_len;
   14108     ++tail;
   14109   }
   14110 
   14111   // Check for tails like 'bar :1'.
   14112   if (tail_len > expected_len + 2 &&
   14113       tail[expected_len] == ' ' &&
   14114       tail[expected_len + 1] == ':' &&
   14115       tail[expected_len + 2] &&
   14116       !strncmp(tail, expected, expected_len)) {
   14117     return true;
   14118   }
   14119 
   14120   if (tail_len != expected_len)
   14121     return false;
   14122 
   14123   return strncmp(tail, expected, expected_len) == 0;
   14124 }
   14125 
   14126 
   14127 static void event_handler(const v8::JitCodeEvent* event) {
   14128   CHECK(event != NULL);
   14129   CHECK(code_map != NULL);
   14130   CHECK(jitcode_line_info != NULL);
   14131 
   14132   class DummyJitCodeLineInfo {
   14133   };
   14134 
   14135   switch (event->type) {
   14136     case v8::JitCodeEvent::CODE_ADDED: {
   14137         CHECK(event->code_start != NULL);
   14138         CHECK_NE(0, static_cast<int>(event->code_len));
   14139         CHECK(event->name.str != NULL);
   14140         i::HashMap::Entry* entry = code_map->LookupOrInsert(
   14141             event->code_start, i::ComputePointerHash(event->code_start));
   14142         entry->value = reinterpret_cast<void*>(event->code_len);
   14143 
   14144         if (FunctionNameIs("bar", event)) {
   14145           ++saw_bar;
   14146         }
   14147       }
   14148       break;
   14149 
   14150     case v8::JitCodeEvent::CODE_MOVED: {
   14151         uint32_t hash = i::ComputePointerHash(event->code_start);
   14152         // We would like to never see code move that we haven't seen before,
   14153         // but the code creation event does not happen until the line endings
   14154         // have been calculated (this is so that we can report the line in the
   14155         // script at which the function source is found, see
   14156         // Compiler::RecordFunctionCompilation) and the line endings
   14157         // calculations can cause a GC, which can move the newly created code
   14158         // before its existence can be logged.
   14159         i::HashMap::Entry* entry = code_map->Lookup(event->code_start, hash);
   14160         if (entry != NULL) {
   14161           ++move_events;
   14162 
   14163           CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
   14164           code_map->Remove(event->code_start, hash);
   14165 
   14166           entry = code_map->LookupOrInsert(
   14167               event->new_code_start,
   14168               i::ComputePointerHash(event->new_code_start));
   14169           entry->value = reinterpret_cast<void*>(event->code_len);
   14170         }
   14171       }
   14172       break;
   14173 
   14174     case v8::JitCodeEvent::CODE_REMOVED:
   14175       // Object/code removal events are currently not dispatched from the GC.
   14176       CHECK(false);
   14177       break;
   14178 
   14179     // For CODE_START_LINE_INFO_RECORDING event, we will create one
   14180     // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
   14181     // record it in jitcode_line_info.
   14182     case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
   14183         DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
   14184         v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
   14185         temp_event->user_data = line_info;
   14186         i::HashMap::Entry* entry = jitcode_line_info->LookupOrInsert(
   14187             line_info, i::ComputePointerHash(line_info));
   14188         entry->value = reinterpret_cast<void*>(line_info);
   14189       }
   14190       break;
   14191     // For these two events, we will check whether the event->user_data
   14192     // data structure is created before during CODE_START_LINE_INFO_RECORDING
   14193     // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
   14194     case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
   14195         CHECK(event->user_data != NULL);
   14196         uint32_t hash = i::ComputePointerHash(event->user_data);
   14197         i::HashMap::Entry* entry =
   14198             jitcode_line_info->Lookup(event->user_data, hash);
   14199         CHECK(entry != NULL);
   14200         delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
   14201       }
   14202       break;
   14203 
   14204     case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
   14205         CHECK(event->user_data != NULL);
   14206         uint32_t hash = i::ComputePointerHash(event->user_data);
   14207         i::HashMap::Entry* entry =
   14208             jitcode_line_info->Lookup(event->user_data, hash);
   14209         CHECK(entry != NULL);
   14210       }
   14211       break;
   14212 
   14213     default:
   14214       // Impossible event.
   14215       CHECK(false);
   14216       break;
   14217   }
   14218 }
   14219 
   14220 
   14221 UNINITIALIZED_TEST(SetJitCodeEventHandler) {
   14222   i::FLAG_stress_compaction = true;
   14223   i::FLAG_incremental_marking = false;
   14224   if (i::FLAG_never_compact) return;
   14225   const char* script =
   14226       "function bar() {"
   14227       "  var sum = 0;"
   14228       "  for (i = 0; i < 10; ++i)"
   14229       "    sum = foo(i);"
   14230       "  return sum;"
   14231       "}"
   14232       "function foo(i) { return i; };"
   14233       "bar();";
   14234 
   14235   // Run this test in a new isolate to make sure we don't
   14236   // have remnants of state from other code.
   14237   v8::Isolate::CreateParams create_params;
   14238   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   14239   v8::Isolate* isolate = v8::Isolate::New(create_params);
   14240   isolate->Enter();
   14241   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   14242   i::Heap* heap = i_isolate->heap();
   14243 
   14244   // Start with a clean slate.
   14245   heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler_Prepare");
   14246 
   14247   {
   14248     v8::HandleScope scope(isolate);
   14249     i::HashMap code(MatchPointers);
   14250     code_map = &code;
   14251 
   14252     i::HashMap lineinfo(MatchPointers);
   14253     jitcode_line_info = &lineinfo;
   14254 
   14255     saw_bar = 0;
   14256     move_events = 0;
   14257 
   14258     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
   14259 
   14260     // Generate new code objects sparsely distributed across several
   14261     // different fragmented code-space pages.
   14262     const int kIterations = 10;
   14263     for (int i = 0; i < kIterations; ++i) {
   14264       LocalContext env(isolate);
   14265       i::AlwaysAllocateScope always_allocate(i_isolate);
   14266       SimulateFullSpace(heap->code_space());
   14267       CompileRun(script);
   14268 
   14269       // Keep a strong reference to the code object in the handle scope.
   14270       i::Handle<i::Code> bar_code(
   14271           i::Handle<i::JSFunction>::cast(
   14272               v8::Utils::OpenHandle(*env->Global()
   14273                                          ->Get(env.local(), v8_str("bar"))
   14274                                          .ToLocalChecked()))
   14275               ->code());
   14276       i::Handle<i::Code> foo_code(
   14277           i::Handle<i::JSFunction>::cast(
   14278               v8::Utils::OpenHandle(*env->Global()
   14279                                          ->Get(env.local(), v8_str("foo"))
   14280                                          .ToLocalChecked()))
   14281               ->code());
   14282 
   14283       // Clear the compilation cache to get more wastage.
   14284       reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
   14285     }
   14286 
   14287     // Force code movement.
   14288     heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler_Move");
   14289 
   14290     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
   14291 
   14292     CHECK_LE(kIterations, saw_bar);
   14293     CHECK_LT(0, move_events);
   14294 
   14295     code_map = NULL;
   14296     jitcode_line_info = NULL;
   14297   }
   14298 
   14299   isolate->Exit();
   14300   isolate->Dispose();
   14301 
   14302   // Do this in a new isolate.
   14303   isolate = v8::Isolate::New(create_params);
   14304   isolate->Enter();
   14305 
   14306   // Verify that we get callbacks for existing code objects when we
   14307   // request enumeration of existing code.
   14308   {
   14309     v8::HandleScope scope(isolate);
   14310     LocalContext env(isolate);
   14311     CompileRun(script);
   14312 
   14313     // Now get code through initial iteration.
   14314     i::HashMap code(MatchPointers);
   14315     code_map = &code;
   14316 
   14317     i::HashMap lineinfo(MatchPointers);
   14318     jitcode_line_info = &lineinfo;
   14319 
   14320     isolate->SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting,
   14321                                     event_handler);
   14322     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
   14323 
   14324     jitcode_line_info = NULL;
   14325     // We expect that we got some events. Note that if we could get code removal
   14326     // notifications, we could compare two collections, one created by listening
   14327     // from the time of creation of an isolate, and the other by subscribing
   14328     // with EnumExisting.
   14329     CHECK_LT(0u, code.occupancy());
   14330 
   14331     code_map = NULL;
   14332   }
   14333 
   14334   isolate->Exit();
   14335   isolate->Dispose();
   14336 }
   14337 
   14338 
   14339 THREADED_TEST(ExternalAllocatedMemory) {
   14340   v8::Isolate* isolate = CcTest::isolate();
   14341   v8::HandleScope outer(isolate);
   14342   v8::Local<Context> env(Context::New(isolate));
   14343   CHECK(!env.IsEmpty());
   14344   const int64_t kSize = 1024*1024;
   14345   int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
   14346   CHECK_EQ(baseline + kSize,
   14347            isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
   14348   CHECK_EQ(baseline,
   14349            isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
   14350   const int64_t kTriggerGCSize =
   14351       v8::internal::Internals::kExternalAllocationLimit + 1;
   14352   CHECK_EQ(baseline + kTriggerGCSize,
   14353            isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize));
   14354   CHECK_EQ(baseline,
   14355            isolate->AdjustAmountOfExternalAllocatedMemory(-kTriggerGCSize));
   14356 }
   14357 
   14358 
   14359 TEST(Regress51719) {
   14360   i::FLAG_incremental_marking = false;
   14361   CcTest::InitializeVM();
   14362 
   14363   const int64_t kTriggerGCSize =
   14364       v8::internal::Internals::kExternalAllocationLimit + 1;
   14365   v8::Isolate* isolate = CcTest::isolate();
   14366   isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize);
   14367 }
   14368 
   14369 
   14370 // Regression test for issue 54, object templates with internal fields
   14371 // but no accessors or interceptors did not get their internal field
   14372 // count set on instances.
   14373 THREADED_TEST(Regress54) {
   14374   LocalContext context;
   14375   v8::Isolate* isolate = context->GetIsolate();
   14376   v8::HandleScope outer(isolate);
   14377   static v8::Persistent<v8::ObjectTemplate> templ;
   14378   if (templ.IsEmpty()) {
   14379     v8::EscapableHandleScope inner(isolate);
   14380     v8::Local<v8::ObjectTemplate> local = v8::ObjectTemplate::New(isolate);
   14381     local->SetInternalFieldCount(1);
   14382     templ.Reset(isolate, inner.Escape(local));
   14383   }
   14384   v8::Local<v8::Object> result =
   14385       v8::Local<v8::ObjectTemplate>::New(isolate, templ)
   14386           ->NewInstance(context.local())
   14387           .ToLocalChecked();
   14388   CHECK_EQ(1, result->InternalFieldCount());
   14389 }
   14390 
   14391 
   14392 // If part of the threaded tests, this test makes ThreadingTest fail
   14393 // on mac.
   14394 TEST(CatchStackOverflow) {
   14395   LocalContext context;
   14396   v8::HandleScope scope(context->GetIsolate());
   14397   v8::TryCatch try_catch(context->GetIsolate());
   14398   v8::Local<v8::Value> result = CompileRun(
   14399       "function f() {"
   14400       "  return f();"
   14401       "}"
   14402       ""
   14403       "f();");
   14404   CHECK(result.IsEmpty());
   14405 }
   14406 
   14407 
   14408 static void CheckTryCatchSourceInfo(v8::Local<v8::Script> script,
   14409                                     const char* resource_name,
   14410                                     int line_offset) {
   14411   v8::HandleScope scope(CcTest::isolate());
   14412   v8::TryCatch try_catch(CcTest::isolate());
   14413   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   14414   CHECK(script->Run(context).IsEmpty());
   14415   CHECK(try_catch.HasCaught());
   14416   v8::Local<v8::Message> message = try_catch.Message();
   14417   CHECK(!message.IsEmpty());
   14418   CHECK_EQ(10 + line_offset, message->GetLineNumber(context).FromJust());
   14419   CHECK_EQ(91, message->GetStartPosition());
   14420   CHECK_EQ(92, message->GetEndPosition());
   14421   CHECK_EQ(2, message->GetStartColumn(context).FromJust());
   14422   CHECK_EQ(3, message->GetEndColumn(context).FromJust());
   14423   v8::String::Utf8Value line(message->GetSourceLine(context).ToLocalChecked());
   14424   CHECK_EQ(0, strcmp("  throw 'nirk';", *line));
   14425   v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
   14426   CHECK_EQ(0, strcmp(resource_name, *name));
   14427 }
   14428 
   14429 
   14430 THREADED_TEST(TryCatchSourceInfo) {
   14431   LocalContext context;
   14432   v8::HandleScope scope(context->GetIsolate());
   14433   v8::Local<v8::String> source = v8_str(
   14434       "function Foo() {\n"
   14435       "  return Bar();\n"
   14436       "}\n"
   14437       "\n"
   14438       "function Bar() {\n"
   14439       "  return Baz();\n"
   14440       "}\n"
   14441       "\n"
   14442       "function Baz() {\n"
   14443       "  throw 'nirk';\n"
   14444       "}\n"
   14445       "\n"
   14446       "Foo();\n");
   14447 
   14448   const char* resource_name;
   14449   v8::Local<v8::Script> script;
   14450   resource_name = "test.js";
   14451   script = CompileWithOrigin(source, resource_name);
   14452   CheckTryCatchSourceInfo(script, resource_name, 0);
   14453 
   14454   resource_name = "test1.js";
   14455   v8::ScriptOrigin origin1(v8_str(resource_name));
   14456   script =
   14457       v8::Script::Compile(context.local(), source, &origin1).ToLocalChecked();
   14458   CheckTryCatchSourceInfo(script, resource_name, 0);
   14459 
   14460   resource_name = "test2.js";
   14461   v8::ScriptOrigin origin2(v8_str(resource_name),
   14462                            v8::Integer::New(context->GetIsolate(), 7));
   14463   script =
   14464       v8::Script::Compile(context.local(), source, &origin2).ToLocalChecked();
   14465   CheckTryCatchSourceInfo(script, resource_name, 7);
   14466 }
   14467 
   14468 
   14469 THREADED_TEST(TryCatchSourceInfoForEOSError) {
   14470   LocalContext context;
   14471   v8::HandleScope scope(context->GetIsolate());
   14472   v8::TryCatch try_catch(context->GetIsolate());
   14473   CHECK(v8::Script::Compile(context.local(), v8_str("!\n")).IsEmpty());
   14474   CHECK(try_catch.HasCaught());
   14475   v8::Local<v8::Message> message = try_catch.Message();
   14476   CHECK_EQ(1, message->GetLineNumber(context.local()).FromJust());
   14477   CHECK_EQ(0, message->GetStartColumn(context.local()).FromJust());
   14478 }
   14479 
   14480 
   14481 THREADED_TEST(CompilationCache) {
   14482   LocalContext context;
   14483   v8::HandleScope scope(context->GetIsolate());
   14484   v8::Local<v8::String> source0 = v8_str("1234");
   14485   v8::Local<v8::String> source1 = v8_str("1234");
   14486   v8::Local<v8::Script> script0 = CompileWithOrigin(source0, "test.js");
   14487   v8::Local<v8::Script> script1 = CompileWithOrigin(source1, "test.js");
   14488   v8::Local<v8::Script> script2 = v8::Script::Compile(context.local(), source0)
   14489                                       .ToLocalChecked();  // different origin
   14490   CHECK_EQ(1234, script0->Run(context.local())
   14491                      .ToLocalChecked()
   14492                      ->Int32Value(context.local())
   14493                      .FromJust());
   14494   CHECK_EQ(1234, script1->Run(context.local())
   14495                      .ToLocalChecked()
   14496                      ->Int32Value(context.local())
   14497                      .FromJust());
   14498   CHECK_EQ(1234, script2->Run(context.local())
   14499                      .ToLocalChecked()
   14500                      ->Int32Value(context.local())
   14501                      .FromJust());
   14502 }
   14503 
   14504 
   14505 static void FunctionNameCallback(
   14506     const v8::FunctionCallbackInfo<v8::Value>& args) {
   14507   ApiTestFuzzer::Fuzz();
   14508   args.GetReturnValue().Set(v8_num(42));
   14509 }
   14510 
   14511 
   14512 THREADED_TEST(CallbackFunctionName) {
   14513   LocalContext context;
   14514   v8::Isolate* isolate = context->GetIsolate();
   14515   v8::HandleScope scope(isolate);
   14516   Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
   14517   t->Set(v8_str("asdf"),
   14518          v8::FunctionTemplate::New(isolate, FunctionNameCallback));
   14519   CHECK(context->Global()
   14520             ->Set(context.local(), v8_str("obj"),
   14521                   t->NewInstance(context.local()).ToLocalChecked())
   14522             .FromJust());
   14523   v8::Local<v8::Value> value = CompileRun("obj.asdf.name");
   14524   CHECK(value->IsString());
   14525   v8::String::Utf8Value name(value);
   14526   CHECK_EQ(0, strcmp("asdf", *name));
   14527 }
   14528 
   14529 
   14530 THREADED_TEST(DateAccess) {
   14531   LocalContext context;
   14532   v8::HandleScope scope(context->GetIsolate());
   14533   v8::Local<v8::Value> date =
   14534       v8::Date::New(context.local(), 1224744689038.0).ToLocalChecked();
   14535   CHECK(date->IsDate());
   14536   CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
   14537 }
   14538 
   14539 
   14540 void CheckProperties(v8::Isolate* isolate, v8::Local<v8::Value> val,
   14541                      unsigned elmc, const char* elmv[]) {
   14542   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   14543   v8::Local<v8::Object> obj = val.As<v8::Object>();
   14544   v8::Local<v8::Array> props = obj->GetPropertyNames(context).ToLocalChecked();
   14545   CHECK_EQ(elmc, props->Length());
   14546   for (unsigned i = 0; i < elmc; i++) {
   14547     v8::String::Utf8Value elm(
   14548         props->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked());
   14549     CHECK_EQ(0, strcmp(elmv[i], *elm));
   14550   }
   14551 }
   14552 
   14553 
   14554 void CheckOwnProperties(v8::Isolate* isolate, v8::Local<v8::Value> val,
   14555                         unsigned elmc, const char* elmv[]) {
   14556   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   14557   v8::Local<v8::Object> obj = val.As<v8::Object>();
   14558   v8::Local<v8::Array> props =
   14559       obj->GetOwnPropertyNames(context).ToLocalChecked();
   14560   CHECK_EQ(elmc, props->Length());
   14561   for (unsigned i = 0; i < elmc; i++) {
   14562     v8::String::Utf8Value elm(
   14563         props->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked());
   14564     CHECK_EQ(0, strcmp(elmv[i], *elm));
   14565   }
   14566 }
   14567 
   14568 
   14569 THREADED_TEST(PropertyEnumeration) {
   14570   LocalContext context;
   14571   v8::Isolate* isolate = context->GetIsolate();
   14572   v8::HandleScope scope(isolate);
   14573   v8::Local<v8::Value> obj = CompileRun(
   14574       "var result = [];"
   14575       "result[0] = {};"
   14576       "result[1] = {a: 1, b: 2};"
   14577       "result[2] = [1, 2, 3];"
   14578       "var proto = {x: 1, y: 2, z: 3};"
   14579       "var x = { __proto__: proto, w: 0, z: 1 };"
   14580       "result[3] = x;"
   14581       "result;");
   14582   v8::Local<v8::Array> elms = obj.As<v8::Array>();
   14583   CHECK_EQ(4u, elms->Length());
   14584   int elmc0 = 0;
   14585   const char** elmv0 = NULL;
   14586   CheckProperties(
   14587       isolate,
   14588       elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
   14589       elmc0, elmv0);
   14590   CheckOwnProperties(
   14591       isolate,
   14592       elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
   14593       elmc0, elmv0);
   14594   int elmc1 = 2;
   14595   const char* elmv1[] = {"a", "b"};
   14596   CheckProperties(
   14597       isolate,
   14598       elms->Get(context.local(), v8::Integer::New(isolate, 1)).ToLocalChecked(),
   14599       elmc1, elmv1);
   14600   CheckOwnProperties(
   14601       isolate,
   14602       elms->Get(context.local(), v8::Integer::New(isolate, 1)).ToLocalChecked(),
   14603       elmc1, elmv1);
   14604   int elmc2 = 3;
   14605   const char* elmv2[] = {"0", "1", "2"};
   14606   CheckProperties(
   14607       isolate,
   14608       elms->Get(context.local(), v8::Integer::New(isolate, 2)).ToLocalChecked(),
   14609       elmc2, elmv2);
   14610   CheckOwnProperties(
   14611       isolate,
   14612       elms->Get(context.local(), v8::Integer::New(isolate, 2)).ToLocalChecked(),
   14613       elmc2, elmv2);
   14614   int elmc3 = 4;
   14615   const char* elmv3[] = {"w", "z", "x", "y"};
   14616   CheckProperties(
   14617       isolate,
   14618       elms->Get(context.local(), v8::Integer::New(isolate, 3)).ToLocalChecked(),
   14619       elmc3, elmv3);
   14620   int elmc4 = 2;
   14621   const char* elmv4[] = {"w", "z"};
   14622   CheckOwnProperties(
   14623       isolate,
   14624       elms->Get(context.local(), v8::Integer::New(isolate, 3)).ToLocalChecked(),
   14625       elmc4, elmv4);
   14626 }
   14627 
   14628 
   14629 THREADED_TEST(PropertyEnumeration2) {
   14630   LocalContext context;
   14631   v8::Isolate* isolate = context->GetIsolate();
   14632   v8::HandleScope scope(isolate);
   14633   v8::Local<v8::Value> obj = CompileRun(
   14634       "var result = [];"
   14635       "result[0] = {};"
   14636       "result[1] = {a: 1, b: 2};"
   14637       "result[2] = [1, 2, 3];"
   14638       "var proto = {x: 1, y: 2, z: 3};"
   14639       "var x = { __proto__: proto, w: 0, z: 1 };"
   14640       "result[3] = x;"
   14641       "result;");
   14642   v8::Local<v8::Array> elms = obj.As<v8::Array>();
   14643   CHECK_EQ(4u, elms->Length());
   14644   int elmc0 = 0;
   14645   const char** elmv0 = NULL;
   14646   CheckProperties(
   14647       isolate,
   14648       elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
   14649       elmc0, elmv0);
   14650 
   14651   v8::Local<v8::Value> val =
   14652       elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked();
   14653   v8::Local<v8::Array> props =
   14654       val.As<v8::Object>()->GetPropertyNames(context.local()).ToLocalChecked();
   14655   CHECK_EQ(0u, props->Length());
   14656   for (uint32_t i = 0; i < props->Length(); i++) {
   14657     printf("p[%u]\n", i);
   14658   }
   14659 }
   14660 
   14661 
   14662 THREADED_TEST(AccessChecksReenabledCorrectly) {
   14663   LocalContext context;
   14664   v8::Isolate* isolate = context->GetIsolate();
   14665   v8::HandleScope scope(isolate);
   14666   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   14667   templ->SetAccessCheckCallback(AccessAlwaysBlocked);
   14668   templ->Set(v8_str("a"), v8_str("a"));
   14669   // Add more than 8 (see kMaxFastProperties) properties
   14670   // so that the constructor will force copying map.
   14671   // Cannot sprintf, gcc complains unsafety.
   14672   char buf[4];
   14673   for (char i = '0'; i <= '9' ; i++) {
   14674     buf[0] = i;
   14675     for (char j = '0'; j <= '9'; j++) {
   14676       buf[1] = j;
   14677       for (char k = '0'; k <= '9'; k++) {
   14678         buf[2] = k;
   14679         buf[3] = 0;
   14680         templ->Set(v8_str(buf), v8::Number::New(isolate, k));
   14681       }
   14682     }
   14683   }
   14684 
   14685   Local<v8::Object> instance_1 =
   14686       templ->NewInstance(context.local()).ToLocalChecked();
   14687   CHECK(context->Global()
   14688             ->Set(context.local(), v8_str("obj_1"), instance_1)
   14689             .FromJust());
   14690 
   14691   Local<Value> value_1 = CompileRun("obj_1.a");
   14692   CHECK(value_1.IsEmpty());
   14693 
   14694   Local<v8::Object> instance_2 =
   14695       templ->NewInstance(context.local()).ToLocalChecked();
   14696   CHECK(context->Global()
   14697             ->Set(context.local(), v8_str("obj_2"), instance_2)
   14698             .FromJust());
   14699 
   14700   Local<Value> value_2 = CompileRun("obj_2.a");
   14701   CHECK(value_2.IsEmpty());
   14702 }
   14703 
   14704 
   14705 // Tests that ScriptData can be serialized and deserialized.
   14706 TEST(PreCompileSerialization) {
   14707   v8::V8::Initialize();
   14708   LocalContext env;
   14709   v8::Isolate* isolate = env->GetIsolate();
   14710   HandleScope handle_scope(isolate);
   14711 
   14712   i::FLAG_min_preparse_length = 0;
   14713   const char* script = "function foo(a) { return a+1; }";
   14714   v8::ScriptCompiler::Source source(v8_str(script));
   14715   v8::ScriptCompiler::Compile(env.local(), &source,
   14716                               v8::ScriptCompiler::kProduceParserCache)
   14717       .ToLocalChecked();
   14718   // Serialize.
   14719   const v8::ScriptCompiler::CachedData* cd = source.GetCachedData();
   14720   i::byte* serialized_data = i::NewArray<i::byte>(cd->length);
   14721   i::MemCopy(serialized_data, cd->data, cd->length);
   14722 
   14723   // Deserialize.
   14724   i::ScriptData* deserialized = new i::ScriptData(serialized_data, cd->length);
   14725 
   14726   // Verify that the original is the same as the deserialized.
   14727   CHECK_EQ(cd->length, deserialized->length());
   14728   CHECK_EQ(0, memcmp(cd->data, deserialized->data(), cd->length));
   14729 
   14730   delete deserialized;
   14731   i::DeleteArray(serialized_data);
   14732 }
   14733 
   14734 
   14735 // This tests that we do not allow dictionary load/call inline caches
   14736 // to use functions that have not yet been compiled.  The potential
   14737 // problem of loading a function that has not yet been compiled can
   14738 // arise because we share code between contexts via the compilation
   14739 // cache.
   14740 THREADED_TEST(DictionaryICLoadedFunction) {
   14741   v8::HandleScope scope(CcTest::isolate());
   14742   // Test LoadIC.
   14743   for (int i = 0; i < 2; i++) {
   14744     LocalContext context;
   14745     CHECK(context->Global()
   14746               ->Set(context.local(), v8_str("tmp"), v8::True(CcTest::isolate()))
   14747               .FromJust());
   14748     context->Global()->Delete(context.local(), v8_str("tmp")).FromJust();
   14749     CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
   14750   }
   14751   // Test CallIC.
   14752   for (int i = 0; i < 2; i++) {
   14753     LocalContext context;
   14754     CHECK(context->Global()
   14755               ->Set(context.local(), v8_str("tmp"), v8::True(CcTest::isolate()))
   14756               .FromJust());
   14757     context->Global()->Delete(context.local(), v8_str("tmp")).FromJust();
   14758     CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
   14759   }
   14760 }
   14761 
   14762 
   14763 // Test that cross-context new calls use the context of the callee to
   14764 // create the new JavaScript object.
   14765 THREADED_TEST(CrossContextNew) {
   14766   v8::Isolate* isolate = CcTest::isolate();
   14767   v8::HandleScope scope(isolate);
   14768   v8::Local<Context> context0 = Context::New(isolate);
   14769   v8::Local<Context> context1 = Context::New(isolate);
   14770 
   14771   // Allow cross-domain access.
   14772   Local<String> token = v8_str("<security token>");
   14773   context0->SetSecurityToken(token);
   14774   context1->SetSecurityToken(token);
   14775 
   14776   // Set an 'x' property on the Object prototype and define a
   14777   // constructor function in context0.
   14778   context0->Enter();
   14779   CompileRun("Object.prototype.x = 42; function C() {};");
   14780   context0->Exit();
   14781 
   14782   // Call the constructor function from context0 and check that the
   14783   // result has the 'x' property.
   14784   context1->Enter();
   14785   CHECK(context1->Global()
   14786             ->Set(context1, v8_str("other"), context0->Global())
   14787             .FromJust());
   14788   Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
   14789   CHECK(value->IsInt32());
   14790   CHECK_EQ(42, value->Int32Value(context1).FromJust());
   14791   context1->Exit();
   14792 }
   14793 
   14794 
   14795 // Verify that we can clone an object
   14796 TEST(ObjectClone) {
   14797   LocalContext env;
   14798   v8::Isolate* isolate = env->GetIsolate();
   14799   v8::HandleScope scope(isolate);
   14800 
   14801   const char* sample =
   14802     "var rv = {};"      \
   14803     "rv.alpha = 'hello';" \
   14804     "rv.beta = 123;"     \
   14805     "rv;";
   14806 
   14807   // Create an object, verify basics.
   14808   Local<Value> val = CompileRun(sample);
   14809   CHECK(val->IsObject());
   14810   Local<v8::Object> obj = val.As<v8::Object>();
   14811   obj->Set(env.local(), v8_str("gamma"), v8_str("cloneme")).FromJust();
   14812 
   14813   CHECK(v8_str("hello")
   14814             ->Equals(env.local(),
   14815                      obj->Get(env.local(), v8_str("alpha")).ToLocalChecked())
   14816             .FromJust());
   14817   CHECK(v8::Integer::New(isolate, 123)
   14818             ->Equals(env.local(),
   14819                      obj->Get(env.local(), v8_str("beta")).ToLocalChecked())
   14820             .FromJust());
   14821   CHECK(v8_str("cloneme")
   14822             ->Equals(env.local(),
   14823                      obj->Get(env.local(), v8_str("gamma")).ToLocalChecked())
   14824             .FromJust());
   14825 
   14826   // Clone it.
   14827   Local<v8::Object> clone = obj->Clone();
   14828   CHECK(v8_str("hello")
   14829             ->Equals(env.local(),
   14830                      clone->Get(env.local(), v8_str("alpha")).ToLocalChecked())
   14831             .FromJust());
   14832   CHECK(v8::Integer::New(isolate, 123)
   14833             ->Equals(env.local(),
   14834                      clone->Get(env.local(), v8_str("beta")).ToLocalChecked())
   14835             .FromJust());
   14836   CHECK(v8_str("cloneme")
   14837             ->Equals(env.local(),
   14838                      clone->Get(env.local(), v8_str("gamma")).ToLocalChecked())
   14839             .FromJust());
   14840 
   14841   // Set a property on the clone, verify each object.
   14842   CHECK(clone->Set(env.local(), v8_str("beta"), v8::Integer::New(isolate, 456))
   14843             .FromJust());
   14844   CHECK(v8::Integer::New(isolate, 123)
   14845             ->Equals(env.local(),
   14846                      obj->Get(env.local(), v8_str("beta")).ToLocalChecked())
   14847             .FromJust());
   14848   CHECK(v8::Integer::New(isolate, 456)
   14849             ->Equals(env.local(),
   14850                      clone->Get(env.local(), v8_str("beta")).ToLocalChecked())
   14851             .FromJust());
   14852 }
   14853 
   14854 
   14855 class OneByteVectorResource : public v8::String::ExternalOneByteStringResource {
   14856  public:
   14857   explicit OneByteVectorResource(i::Vector<const char> vector)
   14858       : data_(vector) {}
   14859   virtual ~OneByteVectorResource() {}
   14860   virtual size_t length() const { return data_.length(); }
   14861   virtual const char* data() const { return data_.start(); }
   14862  private:
   14863   i::Vector<const char> data_;
   14864 };
   14865 
   14866 
   14867 class UC16VectorResource : public v8::String::ExternalStringResource {
   14868  public:
   14869   explicit UC16VectorResource(i::Vector<const i::uc16> vector)
   14870       : data_(vector) {}
   14871   virtual ~UC16VectorResource() {}
   14872   virtual size_t length() const { return data_.length(); }
   14873   virtual const i::uc16* data() const { return data_.start(); }
   14874  private:
   14875   i::Vector<const i::uc16> data_;
   14876 };
   14877 
   14878 
   14879 static void MorphAString(i::String* string,
   14880                          OneByteVectorResource* one_byte_resource,
   14881                          UC16VectorResource* uc16_resource) {
   14882   CHECK(i::StringShape(string).IsExternal());
   14883   if (string->IsOneByteRepresentation()) {
   14884     // Check old map is not internalized or long.
   14885     CHECK(string->map() == CcTest::heap()->external_one_byte_string_map());
   14886     // Morph external string to be TwoByte string.
   14887     string->set_map(CcTest::heap()->external_string_map());
   14888     i::ExternalTwoByteString* morphed =
   14889          i::ExternalTwoByteString::cast(string);
   14890     morphed->set_resource(uc16_resource);
   14891   } else {
   14892     // Check old map is not internalized or long.
   14893     CHECK(string->map() == CcTest::heap()->external_string_map());
   14894     // Morph external string to be one-byte string.
   14895     string->set_map(CcTest::heap()->external_one_byte_string_map());
   14896     i::ExternalOneByteString* morphed = i::ExternalOneByteString::cast(string);
   14897     morphed->set_resource(one_byte_resource);
   14898   }
   14899 }
   14900 
   14901 
   14902 // Test that we can still flatten a string if the components it is built up
   14903 // from have been turned into 16 bit strings in the mean time.
   14904 THREADED_TEST(MorphCompositeStringTest) {
   14905   char utf_buffer[129];
   14906   const char* c_string = "Now is the time for all good men"
   14907                          " to come to the aid of the party";
   14908   uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
   14909   {
   14910     LocalContext env;
   14911     i::Factory* factory = CcTest::i_isolate()->factory();
   14912     v8::HandleScope scope(env->GetIsolate());
   14913     OneByteVectorResource one_byte_resource(
   14914         i::Vector<const char>(c_string, i::StrLength(c_string)));
   14915     UC16VectorResource uc16_resource(
   14916         i::Vector<const uint16_t>(two_byte_string,
   14917                                   i::StrLength(c_string)));
   14918 
   14919     Local<String> lhs(
   14920         v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
   14921                                         &one_byte_resource).ToHandleChecked()));
   14922     Local<String> rhs(
   14923         v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
   14924                                         &one_byte_resource).ToHandleChecked()));
   14925 
   14926     CHECK(env->Global()->Set(env.local(), v8_str("lhs"), lhs).FromJust());
   14927     CHECK(env->Global()->Set(env.local(), v8_str("rhs"), rhs).FromJust());
   14928 
   14929     CompileRun(
   14930         "var cons = lhs + rhs;"
   14931         "var slice = lhs.substring(1, lhs.length - 1);"
   14932         "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
   14933 
   14934     CHECK(lhs->IsOneByte());
   14935     CHECK(rhs->IsOneByte());
   14936 
   14937     MorphAString(*v8::Utils::OpenHandle(*lhs), &one_byte_resource,
   14938                  &uc16_resource);
   14939     MorphAString(*v8::Utils::OpenHandle(*rhs), &one_byte_resource,
   14940                  &uc16_resource);
   14941 
   14942     // This should UTF-8 without flattening, since everything is ASCII.
   14943     Local<String> cons =
   14944         v8_compile("cons")->Run(env.local()).ToLocalChecked().As<String>();
   14945     CHECK_EQ(128, cons->Utf8Length());
   14946     int nchars = -1;
   14947     CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
   14948     CHECK_EQ(128, nchars);
   14949     CHECK_EQ(0, strcmp(
   14950         utf_buffer,
   14951         "Now is the time for all good men to come to the aid of the party"
   14952         "Now is the time for all good men to come to the aid of the party"));
   14953 
   14954     // Now do some stuff to make sure the strings are flattened, etc.
   14955     CompileRun(
   14956         "/[^a-z]/.test(cons);"
   14957         "/[^a-z]/.test(slice);"
   14958         "/[^a-z]/.test(slice_on_cons);");
   14959     const char* expected_cons =
   14960         "Now is the time for all good men to come to the aid of the party"
   14961         "Now is the time for all good men to come to the aid of the party";
   14962     const char* expected_slice =
   14963         "ow is the time for all good men to come to the aid of the part";
   14964     const char* expected_slice_on_cons =
   14965         "ow is the time for all good men to come to the aid of the party"
   14966         "Now is the time for all good men to come to the aid of the part";
   14967     CHECK(v8_str(expected_cons)
   14968               ->Equals(env.local(), env->Global()
   14969                                         ->Get(env.local(), v8_str("cons"))
   14970                                         .ToLocalChecked())
   14971               .FromJust());
   14972     CHECK(v8_str(expected_slice)
   14973               ->Equals(env.local(), env->Global()
   14974                                         ->Get(env.local(), v8_str("slice"))
   14975                                         .ToLocalChecked())
   14976               .FromJust());
   14977     CHECK(v8_str(expected_slice_on_cons)
   14978               ->Equals(env.local(),
   14979                        env->Global()
   14980                            ->Get(env.local(), v8_str("slice_on_cons"))
   14981                            .ToLocalChecked())
   14982               .FromJust());
   14983   }
   14984   i::DeleteArray(two_byte_string);
   14985 }
   14986 
   14987 
   14988 TEST(CompileExternalTwoByteSource) {
   14989   LocalContext context;
   14990   v8::HandleScope scope(context->GetIsolate());
   14991 
   14992   // This is a very short list of sources, which currently is to check for a
   14993   // regression caused by r2703.
   14994   const char* one_byte_sources[] = {
   14995       "0.5",
   14996       "-0.5",   // This mainly testes PushBack in the Scanner.
   14997       "--0.5",  // This mainly testes PushBack in the Scanner.
   14998       NULL};
   14999 
   15000   // Compile the sources as external two byte strings.
   15001   for (int i = 0; one_byte_sources[i] != NULL; i++) {
   15002     uint16_t* two_byte_string = AsciiToTwoByteString(one_byte_sources[i]);
   15003     TestResource* uc16_resource = new TestResource(two_byte_string);
   15004     v8::Local<v8::String> source =
   15005         v8::String::NewExternalTwoByte(context->GetIsolate(), uc16_resource)
   15006             .ToLocalChecked();
   15007     v8::Script::Compile(context.local(), source).FromMaybe(Local<Script>());
   15008   }
   15009 }
   15010 
   15011 
   15012 #ifndef V8_INTERPRETED_REGEXP
   15013 
   15014 struct RegExpInterruptionData {
   15015   v8::base::Atomic32 loop_count;
   15016   UC16VectorResource* string_resource;
   15017   v8::Persistent<v8::String> string;
   15018 } regexp_interruption_data;
   15019 
   15020 
   15021 class RegExpInterruptionThread : public v8::base::Thread {
   15022  public:
   15023   explicit RegExpInterruptionThread(v8::Isolate* isolate)
   15024       : Thread(Options("TimeoutThread")), isolate_(isolate) {}
   15025 
   15026   virtual void Run() {
   15027     for (v8::base::NoBarrier_Store(&regexp_interruption_data.loop_count, 0);
   15028          v8::base::NoBarrier_Load(&regexp_interruption_data.loop_count) < 7;
   15029          v8::base::NoBarrier_AtomicIncrement(
   15030              &regexp_interruption_data.loop_count, 1)) {
   15031       // Wait a bit before requesting GC.
   15032       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
   15033       reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
   15034     }
   15035     // Wait a bit before terminating.
   15036     v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
   15037     isolate_->TerminateExecution();
   15038   }
   15039 
   15040  private:
   15041   v8::Isolate* isolate_;
   15042 };
   15043 
   15044 
   15045 void RunBeforeGC(v8::Isolate* isolate, v8::GCType type,
   15046                  v8::GCCallbackFlags flags) {
   15047   if (v8::base::NoBarrier_Load(&regexp_interruption_data.loop_count) != 2) {
   15048     return;
   15049   }
   15050   v8::HandleScope scope(isolate);
   15051   v8::Local<v8::String> string = v8::Local<v8::String>::New(
   15052       CcTest::isolate(), regexp_interruption_data.string);
   15053   string->MakeExternal(regexp_interruption_data.string_resource);
   15054 }
   15055 
   15056 
   15057 // Test that RegExp execution can be interrupted.  Specifically, we test
   15058 // * interrupting with GC
   15059 // * turn the subject string from one-byte internal to two-byte external string
   15060 // * force termination
   15061 TEST(RegExpInterruption) {
   15062   LocalContext env;
   15063   v8::HandleScope scope(env->GetIsolate());
   15064 
   15065   RegExpInterruptionThread timeout_thread(env->GetIsolate());
   15066 
   15067   env->GetIsolate()->AddGCPrologueCallback(RunBeforeGC);
   15068   static const char* one_byte_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
   15069   i::uc16* uc16_content = AsciiToTwoByteString(one_byte_content);
   15070   v8::Local<v8::String> string = v8_str(one_byte_content);
   15071 
   15072   env->Global()->Set(env.local(), v8_str("a"), string).FromJust();
   15073   regexp_interruption_data.string.Reset(env->GetIsolate(), string);
   15074   regexp_interruption_data.string_resource = new UC16VectorResource(
   15075       i::Vector<const i::uc16>(uc16_content, i::StrLength(one_byte_content)));
   15076 
   15077   v8::TryCatch try_catch(env->GetIsolate());
   15078   timeout_thread.Start();
   15079 
   15080   CompileRun("/((a*)*)*b/.exec(a)");
   15081   CHECK(try_catch.HasTerminated());
   15082 
   15083   timeout_thread.Join();
   15084 
   15085   regexp_interruption_data.string.Reset();
   15086   i::DeleteArray(uc16_content);
   15087 }
   15088 
   15089 #endif  // V8_INTERPRETED_REGEXP
   15090 
   15091 
   15092 // Test that we cannot set a property on the global object if there
   15093 // is a read-only property in the prototype chain.
   15094 TEST(ReadOnlyPropertyInGlobalProto) {
   15095   v8::Isolate* isolate = CcTest::isolate();
   15096   v8::HandleScope scope(isolate);
   15097   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   15098   LocalContext context(0, templ);
   15099   v8::Local<v8::Object> global = context->Global();
   15100   v8::Local<v8::Object> global_proto = v8::Local<v8::Object>::Cast(
   15101       global->Get(context.local(), v8_str("__proto__")).ToLocalChecked());
   15102   global_proto->DefineOwnProperty(context.local(), v8_str("x"),
   15103                                   v8::Integer::New(isolate, 0), v8::ReadOnly)
   15104       .FromJust();
   15105   global_proto->DefineOwnProperty(context.local(), v8_str("y"),
   15106                                   v8::Integer::New(isolate, 0), v8::ReadOnly)
   15107       .FromJust();
   15108   // Check without 'eval' or 'with'.
   15109   v8::Local<v8::Value> res =
   15110       CompileRun("function f() { x = 42; return x; }; f()");
   15111   CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
   15112   // Check with 'eval'.
   15113   res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
   15114   CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
   15115   // Check with 'with'.
   15116   res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
   15117   CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
   15118 }
   15119 
   15120 
   15121 TEST(CreateDataProperty) {
   15122   LocalContext env;
   15123   v8::Isolate* isolate = env->GetIsolate();
   15124   v8::HandleScope handle_scope(isolate);
   15125 
   15126   CompileRun(
   15127       "var a = {};"
   15128       "var b = [];"
   15129       "Object.defineProperty(a, 'foo', {value: 23});"
   15130       "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
   15131 
   15132   v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
   15133       env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
   15134   v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
   15135       env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
   15136   {
   15137     // Can't change a non-configurable properties.
   15138     v8::TryCatch try_catch(isolate);
   15139     CHECK(!obj->CreateDataProperty(env.local(), v8_str("foo"),
   15140                                    v8::Integer::New(isolate, 42)).FromJust());
   15141     CHECK(!try_catch.HasCaught());
   15142     CHECK(obj->CreateDataProperty(env.local(), v8_str("bar"),
   15143                                   v8::Integer::New(isolate, 42)).FromJust());
   15144     CHECK(!try_catch.HasCaught());
   15145     v8::Local<v8::Value> val =
   15146         obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
   15147     CHECK(val->IsNumber());
   15148     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15149   }
   15150 
   15151   {
   15152     // Set a regular property.
   15153     v8::TryCatch try_catch(isolate);
   15154     CHECK(obj->CreateDataProperty(env.local(), v8_str("blub"),
   15155                                   v8::Integer::New(isolate, 42)).FromJust());
   15156     CHECK(!try_catch.HasCaught());
   15157     v8::Local<v8::Value> val =
   15158         obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
   15159     CHECK(val->IsNumber());
   15160     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15161   }
   15162 
   15163   {
   15164     // Set an indexed property.
   15165     v8::TryCatch try_catch(isolate);
   15166     CHECK(obj->CreateDataProperty(env.local(), v8_str("1"),
   15167                                   v8::Integer::New(isolate, 42)).FromJust());
   15168     CHECK(!try_catch.HasCaught());
   15169     v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
   15170     CHECK(val->IsNumber());
   15171     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15172   }
   15173 
   15174   {
   15175     // Special cases for arrays.
   15176     v8::TryCatch try_catch(isolate);
   15177     CHECK(!arr->CreateDataProperty(env.local(), v8_str("length"),
   15178                                    v8::Integer::New(isolate, 1)).FromJust());
   15179     CHECK(!try_catch.HasCaught());
   15180   }
   15181   {
   15182     // Special cases for arrays: index exceeds the array's length
   15183     v8::TryCatch try_catch(isolate);
   15184     CHECK(arr->CreateDataProperty(env.local(), 1, v8::Integer::New(isolate, 23))
   15185               .FromJust());
   15186     CHECK(!try_catch.HasCaught());
   15187     CHECK_EQ(2U, arr->Length());
   15188     v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
   15189     CHECK(val->IsNumber());
   15190     CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
   15191 
   15192     // Set an existing entry.
   15193     CHECK(arr->CreateDataProperty(env.local(), 0, v8::Integer::New(isolate, 42))
   15194               .FromJust());
   15195     CHECK(!try_catch.HasCaught());
   15196     val = arr->Get(env.local(), 0).ToLocalChecked();
   15197     CHECK(val->IsNumber());
   15198     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15199   }
   15200 
   15201   CompileRun("Object.freeze(a);");
   15202   {
   15203     // Can't change non-extensible objects.
   15204     v8::TryCatch try_catch(isolate);
   15205     CHECK(!obj->CreateDataProperty(env.local(), v8_str("baz"),
   15206                                    v8::Integer::New(isolate, 42)).FromJust());
   15207     CHECK(!try_catch.HasCaught());
   15208   }
   15209 
   15210   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   15211   templ->SetAccessCheckCallback(AccessAlwaysBlocked);
   15212   v8::Local<v8::Object> access_checked =
   15213       templ->NewInstance(env.local()).ToLocalChecked();
   15214   {
   15215     v8::TryCatch try_catch(isolate);
   15216     CHECK(access_checked->CreateDataProperty(env.local(), v8_str("foo"),
   15217                                              v8::Integer::New(isolate, 42))
   15218               .IsNothing());
   15219     CHECK(try_catch.HasCaught());
   15220   }
   15221 }
   15222 
   15223 
   15224 TEST(DefineOwnProperty) {
   15225   LocalContext env;
   15226   v8::Isolate* isolate = env->GetIsolate();
   15227   v8::HandleScope handle_scope(isolate);
   15228 
   15229   CompileRun(
   15230       "var a = {};"
   15231       "var b = [];"
   15232       "Object.defineProperty(a, 'foo', {value: 23});"
   15233       "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
   15234 
   15235   v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
   15236       env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
   15237   v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
   15238       env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
   15239   {
   15240     // Can't change a non-configurable properties.
   15241     v8::TryCatch try_catch(isolate);
   15242     CHECK(!obj->DefineOwnProperty(env.local(), v8_str("foo"),
   15243                                   v8::Integer::New(isolate, 42)).FromJust());
   15244     CHECK(!try_catch.HasCaught());
   15245     CHECK(obj->DefineOwnProperty(env.local(), v8_str("bar"),
   15246                                  v8::Integer::New(isolate, 42)).FromJust());
   15247     CHECK(!try_catch.HasCaught());
   15248     v8::Local<v8::Value> val =
   15249         obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
   15250     CHECK(val->IsNumber());
   15251     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15252   }
   15253 
   15254   {
   15255     // Set a regular property.
   15256     v8::TryCatch try_catch(isolate);
   15257     CHECK(obj->DefineOwnProperty(env.local(), v8_str("blub"),
   15258                                  v8::Integer::New(isolate, 42)).FromJust());
   15259     CHECK(!try_catch.HasCaught());
   15260     v8::Local<v8::Value> val =
   15261         obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
   15262     CHECK(val->IsNumber());
   15263     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15264   }
   15265 
   15266   {
   15267     // Set an indexed property.
   15268     v8::TryCatch try_catch(isolate);
   15269     CHECK(obj->DefineOwnProperty(env.local(), v8_str("1"),
   15270                                  v8::Integer::New(isolate, 42)).FromJust());
   15271     CHECK(!try_catch.HasCaught());
   15272     v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
   15273     CHECK(val->IsNumber());
   15274     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15275   }
   15276 
   15277   {
   15278     // Special cases for arrays.
   15279     v8::TryCatch try_catch(isolate);
   15280     CHECK(!arr->DefineOwnProperty(env.local(), v8_str("length"),
   15281                                   v8::Integer::New(isolate, 1)).FromJust());
   15282     CHECK(!try_catch.HasCaught());
   15283   }
   15284   {
   15285     // Special cases for arrays: index exceeds the array's length
   15286     v8::TryCatch try_catch(isolate);
   15287     CHECK(arr->DefineOwnProperty(env.local(), v8_str("1"),
   15288                                  v8::Integer::New(isolate, 23)).FromJust());
   15289     CHECK(!try_catch.HasCaught());
   15290     CHECK_EQ(2U, arr->Length());
   15291     v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
   15292     CHECK(val->IsNumber());
   15293     CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
   15294 
   15295     // Set an existing entry.
   15296     CHECK(arr->DefineOwnProperty(env.local(), v8_str("0"),
   15297                                  v8::Integer::New(isolate, 42)).FromJust());
   15298     CHECK(!try_catch.HasCaught());
   15299     val = arr->Get(env.local(), 0).ToLocalChecked();
   15300     CHECK(val->IsNumber());
   15301     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15302   }
   15303 
   15304   {
   15305     // Set a non-writable property.
   15306     v8::TryCatch try_catch(isolate);
   15307     CHECK(obj->DefineOwnProperty(env.local(), v8_str("lala"),
   15308                                  v8::Integer::New(isolate, 42),
   15309                                  v8::ReadOnly).FromJust());
   15310     CHECK(!try_catch.HasCaught());
   15311     v8::Local<v8::Value> val =
   15312         obj->Get(env.local(), v8_str("lala")).ToLocalChecked();
   15313     CHECK(val->IsNumber());
   15314     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15315     CHECK_EQ(v8::ReadOnly, obj->GetPropertyAttributes(
   15316                                     env.local(), v8_str("lala")).FromJust());
   15317     CHECK(!try_catch.HasCaught());
   15318   }
   15319 
   15320   CompileRun("Object.freeze(a);");
   15321   {
   15322     // Can't change non-extensible objects.
   15323     v8::TryCatch try_catch(isolate);
   15324     CHECK(!obj->DefineOwnProperty(env.local(), v8_str("baz"),
   15325                                   v8::Integer::New(isolate, 42)).FromJust());
   15326     CHECK(!try_catch.HasCaught());
   15327   }
   15328 
   15329   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   15330   templ->SetAccessCheckCallback(AccessAlwaysBlocked);
   15331   v8::Local<v8::Object> access_checked =
   15332       templ->NewInstance(env.local()).ToLocalChecked();
   15333   {
   15334     v8::TryCatch try_catch(isolate);
   15335     CHECK(access_checked->DefineOwnProperty(env.local(), v8_str("foo"),
   15336                                             v8::Integer::New(isolate, 42))
   15337               .IsNothing());
   15338     CHECK(try_catch.HasCaught());
   15339   }
   15340 }
   15341 
   15342 
   15343 THREADED_TEST(GetCurrentContextWhenNotInContext) {
   15344   i::Isolate* isolate = CcTest::i_isolate();
   15345   CHECK(isolate != NULL);
   15346   CHECK(isolate->context() == NULL);
   15347   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
   15348   v8::HandleScope scope(v8_isolate);
   15349   // The following should not crash, but return an empty handle.
   15350   v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
   15351   CHECK(current.IsEmpty());
   15352 }
   15353 
   15354 
   15355 // Check that a variable declaration with no explicit initialization
   15356 // value does shadow an existing property in the prototype chain.
   15357 THREADED_TEST(InitGlobalVarInProtoChain) {
   15358   LocalContext context;
   15359   v8::HandleScope scope(context->GetIsolate());
   15360   // Introduce a variable in the prototype chain.
   15361   CompileRun("__proto__.x = 42");
   15362   v8::Local<v8::Value> result = CompileRun("var x = 43; x");
   15363   CHECK(!result->IsUndefined());
   15364   CHECK_EQ(43, result->Int32Value(context.local()).FromJust());
   15365 }
   15366 
   15367 
   15368 // Regression test for issue 398.
   15369 // If a function is added to an object, creating a constant function
   15370 // field, and the result is cloned, replacing the constant function on the
   15371 // original should not affect the clone.
   15372 // See http://code.google.com/p/v8/issues/detail?id=398
   15373 THREADED_TEST(ReplaceConstantFunction) {
   15374   LocalContext context;
   15375   v8::Isolate* isolate = context->GetIsolate();
   15376   v8::HandleScope scope(isolate);
   15377   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   15378   v8::Local<v8::FunctionTemplate> func_templ =
   15379       v8::FunctionTemplate::New(isolate);
   15380   v8::Local<v8::String> foo_string = v8_str("foo");
   15381   obj->Set(context.local(), foo_string,
   15382            func_templ->GetFunction(context.local()).ToLocalChecked())
   15383       .FromJust();
   15384   v8::Local<v8::Object> obj_clone = obj->Clone();
   15385   obj_clone->Set(context.local(), foo_string, v8_str("Hello")).FromJust();
   15386   CHECK(!obj->Get(context.local(), foo_string).ToLocalChecked()->IsUndefined());
   15387 }
   15388 
   15389 
   15390 static void CheckElementValue(i::Isolate* isolate,
   15391                               int expected,
   15392                               i::Handle<i::Object> obj,
   15393                               int offset) {
   15394   i::Object* element =
   15395       *i::Object::GetElement(isolate, obj, offset).ToHandleChecked();
   15396   CHECK_EQ(expected, i::Smi::cast(element)->value());
   15397 }
   15398 
   15399 
   15400 template <class ExternalArrayClass, class ElementType>
   15401 static void ObjectWithExternalArrayTestHelper(Local<Context> context,
   15402                                               v8::Local<Object> obj,
   15403                                               int element_count,
   15404                                               i::ExternalArrayType array_type,
   15405                                               int64_t low, int64_t high) {
   15406   i::Handle<i::JSReceiver> jsobj = v8::Utils::OpenHandle(*obj);
   15407   i::Isolate* isolate = jsobj->GetIsolate();
   15408   obj->Set(context, v8_str("field"),
   15409            v8::Int32::New(reinterpret_cast<v8::Isolate*>(isolate), 1503))
   15410       .FromJust();
   15411   CHECK(context->Global()->Set(context, v8_str("ext_array"), obj).FromJust());
   15412   v8::Local<v8::Value> result = CompileRun("ext_array.field");
   15413   CHECK_EQ(1503, result->Int32Value(context).FromJust());
   15414   result = CompileRun("ext_array[1]");
   15415   CHECK_EQ(1, result->Int32Value(context).FromJust());
   15416 
   15417   // Check assigned smis
   15418   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15419                       "  ext_array[i] = i;"
   15420                       "}"
   15421                       "var sum = 0;"
   15422                       "for (var i = 0; i < 8; i++) {"
   15423                       "  sum += ext_array[i];"
   15424                       "}"
   15425                       "sum;");
   15426 
   15427   CHECK_EQ(28, result->Int32Value(context).FromJust());
   15428   // Check pass through of assigned smis
   15429   result = CompileRun("var sum = 0;"
   15430                       "for (var i = 0; i < 8; i++) {"
   15431                       "  sum += ext_array[i] = ext_array[i] = -i;"
   15432                       "}"
   15433                       "sum;");
   15434   CHECK_EQ(-28, result->Int32Value(context).FromJust());
   15435 
   15436 
   15437   // Check assigned smis in reverse order
   15438   result = CompileRun("for (var i = 8; --i >= 0; ) {"
   15439                       "  ext_array[i] = i;"
   15440                       "}"
   15441                       "var sum = 0;"
   15442                       "for (var i = 0; i < 8; i++) {"
   15443                       "  sum += ext_array[i];"
   15444                       "}"
   15445                       "sum;");
   15446   CHECK_EQ(28, result->Int32Value(context).FromJust());
   15447 
   15448   // Check pass through of assigned HeapNumbers
   15449   result = CompileRun("var sum = 0;"
   15450                       "for (var i = 0; i < 16; i+=2) {"
   15451                       "  sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
   15452                       "}"
   15453                       "sum;");
   15454   CHECK_EQ(-28, result->Int32Value(context).FromJust());
   15455 
   15456   // Check assigned HeapNumbers
   15457   result = CompileRun("for (var i = 0; i < 16; i+=2) {"
   15458                       "  ext_array[i] = (i * 0.5);"
   15459                       "}"
   15460                       "var sum = 0;"
   15461                       "for (var i = 0; i < 16; i+=2) {"
   15462                       "  sum += ext_array[i];"
   15463                       "}"
   15464                       "sum;");
   15465   CHECK_EQ(28, result->Int32Value(context).FromJust());
   15466 
   15467   // Check assigned HeapNumbers in reverse order
   15468   result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
   15469                       "  ext_array[i] = (i * 0.5);"
   15470                       "}"
   15471                       "var sum = 0;"
   15472                       "for (var i = 0; i < 16; i+=2) {"
   15473                       "  sum += ext_array[i];"
   15474                       "}"
   15475                       "sum;");
   15476   CHECK_EQ(28, result->Int32Value(context).FromJust());
   15477 
   15478   i::ScopedVector<char> test_buf(1024);
   15479 
   15480   // Check legal boundary conditions.
   15481   // The repeated loads and stores ensure the ICs are exercised.
   15482   const char* boundary_program =
   15483       "var res = 0;"
   15484       "for (var i = 0; i < 16; i++) {"
   15485       "  ext_array[i] = %lld;"
   15486       "  if (i > 8) {"
   15487       "    res = ext_array[i];"
   15488       "  }"
   15489       "}"
   15490       "res;";
   15491   i::SNPrintF(test_buf,
   15492               boundary_program,
   15493               low);
   15494   result = CompileRun(test_buf.start());
   15495   CHECK_EQ(low, result->IntegerValue(context).FromJust());
   15496 
   15497   i::SNPrintF(test_buf,
   15498               boundary_program,
   15499               high);
   15500   result = CompileRun(test_buf.start());
   15501   CHECK_EQ(high, result->IntegerValue(context).FromJust());
   15502 
   15503   // Check misprediction of type in IC.
   15504   result = CompileRun("var tmp_array = ext_array;"
   15505                       "var sum = 0;"
   15506                       "for (var i = 0; i < 8; i++) {"
   15507                       "  tmp_array[i] = i;"
   15508                       "  sum += tmp_array[i];"
   15509                       "  if (i == 4) {"
   15510                       "    tmp_array = {};"
   15511                       "  }"
   15512                       "}"
   15513                       "sum;");
   15514   // Force GC to trigger verification.
   15515   CcTest::heap()->CollectAllGarbage();
   15516   CHECK_EQ(28, result->Int32Value(context).FromJust());
   15517 
   15518   // Make sure out-of-range loads do not throw.
   15519   i::SNPrintF(test_buf,
   15520               "var caught_exception = false;"
   15521               "try {"
   15522               "  ext_array[%d];"
   15523               "} catch (e) {"
   15524               "  caught_exception = true;"
   15525               "}"
   15526               "caught_exception;",
   15527               element_count);
   15528   result = CompileRun(test_buf.start());
   15529   CHECK_EQ(false, result->BooleanValue(context).FromJust());
   15530 
   15531   // Make sure out-of-range stores do not throw.
   15532   i::SNPrintF(test_buf,
   15533               "var caught_exception = false;"
   15534               "try {"
   15535               "  ext_array[%d] = 1;"
   15536               "} catch (e) {"
   15537               "  caught_exception = true;"
   15538               "}"
   15539               "caught_exception;",
   15540               element_count);
   15541   result = CompileRun(test_buf.start());
   15542   CHECK_EQ(false, result->BooleanValue(context).FromJust());
   15543 
   15544   // Check other boundary conditions, values and operations.
   15545   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15546                       "  ext_array[7] = undefined;"
   15547                       "}"
   15548                       "ext_array[7];");
   15549   CHECK_EQ(0, result->Int32Value(context).FromJust());
   15550   if (array_type == i::kExternalFloat64Array ||
   15551       array_type == i::kExternalFloat32Array) {
   15552     CHECK(std::isnan(
   15553         i::Object::GetElement(isolate, jsobj, 7).ToHandleChecked()->Number()));
   15554   } else {
   15555     CheckElementValue(isolate, 0, jsobj, 7);
   15556   }
   15557 
   15558   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15559                       "  ext_array[6] = '2.3';"
   15560                       "}"
   15561                       "ext_array[6];");
   15562   CHECK_EQ(2, result->Int32Value(context).FromJust());
   15563   CHECK_EQ(2,
   15564            static_cast<int>(
   15565                i::Object::GetElement(
   15566                    isolate, jsobj, 6).ToHandleChecked()->Number()));
   15567 
   15568   if (array_type != i::kExternalFloat32Array &&
   15569       array_type != i::kExternalFloat64Array) {
   15570     // Though the specification doesn't state it, be explicit about
   15571     // converting NaNs and +/-Infinity to zero.
   15572     result = CompileRun("for (var i = 0; i < 8; i++) {"
   15573                         "  ext_array[i] = 5;"
   15574                         "}"
   15575                         "for (var i = 0; i < 8; i++) {"
   15576                         "  ext_array[i] = NaN;"
   15577                         "}"
   15578                         "ext_array[5];");
   15579     CHECK_EQ(0, result->Int32Value(context).FromJust());
   15580     CheckElementValue(isolate, 0, jsobj, 5);
   15581 
   15582     result = CompileRun("for (var i = 0; i < 8; i++) {"
   15583                         "  ext_array[i] = 5;"
   15584                         "}"
   15585                         "for (var i = 0; i < 8; i++) {"
   15586                         "  ext_array[i] = Infinity;"
   15587                         "}"
   15588                         "ext_array[5];");
   15589     int expected_value =
   15590         (array_type == i::kExternalUint8ClampedArray) ? 255 : 0;
   15591     CHECK_EQ(expected_value, result->Int32Value(context).FromJust());
   15592     CheckElementValue(isolate, expected_value, jsobj, 5);
   15593 
   15594     result = CompileRun("for (var i = 0; i < 8; i++) {"
   15595                         "  ext_array[i] = 5;"
   15596                         "}"
   15597                         "for (var i = 0; i < 8; i++) {"
   15598                         "  ext_array[i] = -Infinity;"
   15599                         "}"
   15600                         "ext_array[5];");
   15601     CHECK_EQ(0, result->Int32Value(context).FromJust());
   15602     CheckElementValue(isolate, 0, jsobj, 5);
   15603 
   15604     // Check truncation behavior of integral arrays.
   15605     const char* unsigned_data =
   15606         "var source_data = [0.6, 10.6];"
   15607         "var expected_results = [0, 10];";
   15608     const char* signed_data =
   15609         "var source_data = [0.6, 10.6, -0.6, -10.6];"
   15610         "var expected_results = [0, 10, 0, -10];";
   15611     const char* pixel_data =
   15612         "var source_data = [0.6, 10.6];"
   15613         "var expected_results = [1, 11];";
   15614     bool is_unsigned = (array_type == i::kExternalUint8Array ||
   15615                         array_type == i::kExternalUint16Array ||
   15616                         array_type == i::kExternalUint32Array);
   15617     bool is_pixel_data = array_type == i::kExternalUint8ClampedArray;
   15618 
   15619     i::SNPrintF(test_buf,
   15620                 "%s"
   15621                 "var all_passed = true;"
   15622                 "for (var i = 0; i < source_data.length; i++) {"
   15623                 "  for (var j = 0; j < 8; j++) {"
   15624                 "    ext_array[j] = source_data[i];"
   15625                 "  }"
   15626                 "  all_passed = all_passed &&"
   15627                 "               (ext_array[5] == expected_results[i]);"
   15628                 "}"
   15629                 "all_passed;",
   15630                 (is_unsigned ?
   15631                      unsigned_data :
   15632                      (is_pixel_data ? pixel_data : signed_data)));
   15633     result = CompileRun(test_buf.start());
   15634     CHECK_EQ(true, result->BooleanValue(context).FromJust());
   15635   }
   15636 
   15637   i::Handle<ExternalArrayClass> array(ExternalArrayClass::cast(
   15638       i::Handle<i::JSObject>::cast(jsobj)->elements()));
   15639   for (int i = 0; i < element_count; i++) {
   15640     array->set(i, static_cast<ElementType>(i));
   15641   }
   15642 
   15643   // Test complex assignments
   15644   result = CompileRun("function ee_op_test_complex_func(sum) {"
   15645                       " for (var i = 0; i < 40; ++i) {"
   15646                       "   sum += (ext_array[i] += 1);"
   15647                       "   sum += (ext_array[i] -= 1);"
   15648                       " } "
   15649                       " return sum;"
   15650                       "}"
   15651                       "sum=0;"
   15652                       "for (var i=0;i<10000;++i) {"
   15653                       "  sum=ee_op_test_complex_func(sum);"
   15654                       "}"
   15655                       "sum;");
   15656   CHECK_EQ(16000000, result->Int32Value(context).FromJust());
   15657 
   15658   // Test count operations
   15659   result = CompileRun("function ee_op_test_count_func(sum) {"
   15660                       " for (var i = 0; i < 40; ++i) {"
   15661                       "   sum += (++ext_array[i]);"
   15662                       "   sum += (--ext_array[i]);"
   15663                       " } "
   15664                       " return sum;"
   15665                       "}"
   15666                       "sum=0;"
   15667                       "for (var i=0;i<10000;++i) {"
   15668                       "  sum=ee_op_test_count_func(sum);"
   15669                       "}"
   15670                       "sum;");
   15671   CHECK_EQ(16000000, result->Int32Value(context).FromJust());
   15672 
   15673   result = CompileRun("ext_array[3] = 33;"
   15674                       "delete ext_array[3];"
   15675                       "ext_array[3];");
   15676   CHECK_EQ(33, result->Int32Value(context).FromJust());
   15677 
   15678   result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
   15679                       "ext_array[2] = 12; ext_array[3] = 13;"
   15680                       "ext_array.__defineGetter__('2',"
   15681                       "function() { return 120; });"
   15682                       "ext_array[2];");
   15683   CHECK_EQ(12, result->Int32Value(context).FromJust());
   15684 
   15685   result = CompileRun("var js_array = new Array(40);"
   15686                       "js_array[0] = 77;"
   15687                       "js_array;");
   15688   CHECK_EQ(77, v8::Object::Cast(*result)
   15689                    ->Get(context, v8_str("0"))
   15690                    .ToLocalChecked()
   15691                    ->Int32Value(context)
   15692                    .FromJust());
   15693 
   15694   result = CompileRun("ext_array[1] = 23;"
   15695                       "ext_array.__proto__ = [];"
   15696                       "js_array.__proto__ = ext_array;"
   15697                       "js_array.concat(ext_array);");
   15698   CHECK_EQ(77, v8::Object::Cast(*result)
   15699                    ->Get(context, v8_str("0"))
   15700                    .ToLocalChecked()
   15701                    ->Int32Value(context)
   15702                    .FromJust());
   15703   CHECK_EQ(23, v8::Object::Cast(*result)
   15704                    ->Get(context, v8_str("1"))
   15705                    .ToLocalChecked()
   15706                    ->Int32Value(context)
   15707                    .FromJust());
   15708 
   15709   result = CompileRun("ext_array[1] = 23;");
   15710   CHECK_EQ(23, result->Int32Value(context).FromJust());
   15711 }
   15712 
   15713 
   15714 template <class FixedTypedArrayClass, i::ElementsKind elements_kind,
   15715           class ElementType>
   15716 static void FixedTypedArrayTestHelper(i::ExternalArrayType array_type,
   15717                                       ElementType low, ElementType high) {
   15718   i::FLAG_allow_natives_syntax = true;
   15719   LocalContext context;
   15720   i::Isolate* isolate = CcTest::i_isolate();
   15721   i::Factory* factory = isolate->factory();
   15722   v8::HandleScope scope(context->GetIsolate());
   15723   const int kElementCount = 260;
   15724   i::Handle<i::JSTypedArray> jsobj =
   15725       factory->NewJSTypedArray(elements_kind, kElementCount);
   15726   i::Handle<FixedTypedArrayClass> fixed_array(
   15727       FixedTypedArrayClass::cast(jsobj->elements()));
   15728   CHECK_EQ(FixedTypedArrayClass::kInstanceType,
   15729            fixed_array->map()->instance_type());
   15730   CHECK_EQ(kElementCount, fixed_array->length());
   15731   CcTest::heap()->CollectAllGarbage();
   15732   for (int i = 0; i < kElementCount; i++) {
   15733     fixed_array->set(i, static_cast<ElementType>(i));
   15734   }
   15735   // Force GC to trigger verification.
   15736   CcTest::heap()->CollectAllGarbage();
   15737   for (int i = 0; i < kElementCount; i++) {
   15738     CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
   15739              static_cast<int64_t>(fixed_array->get_scalar(i)));
   15740   }
   15741   v8::Local<v8::Object> obj = v8::Utils::ToLocal(jsobj);
   15742 
   15743   ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
   15744       context.local(), obj, kElementCount, array_type,
   15745       static_cast<int64_t>(low),
   15746       static_cast<int64_t>(high));
   15747 }
   15748 
   15749 
   15750 THREADED_TEST(FixedUint8Array) {
   15751   FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
   15752       i::kExternalUint8Array, 0x0, 0xFF);
   15753 }
   15754 
   15755 
   15756 THREADED_TEST(FixedUint8ClampedArray) {
   15757   FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
   15758                             i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
   15759       i::kExternalUint8ClampedArray, 0x0, 0xFF);
   15760 }
   15761 
   15762 
   15763 THREADED_TEST(FixedInt8Array) {
   15764   FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
   15765       i::kExternalInt8Array, -0x80, 0x7F);
   15766 }
   15767 
   15768 
   15769 THREADED_TEST(FixedUint16Array) {
   15770   FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
   15771       i::kExternalUint16Array, 0x0, 0xFFFF);
   15772 }
   15773 
   15774 
   15775 THREADED_TEST(FixedInt16Array) {
   15776   FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
   15777       i::kExternalInt16Array, -0x8000, 0x7FFF);
   15778 }
   15779 
   15780 
   15781 THREADED_TEST(FixedUint32Array) {
   15782   FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
   15783       i::kExternalUint32Array, 0x0, UINT_MAX);
   15784 }
   15785 
   15786 
   15787 THREADED_TEST(FixedInt32Array) {
   15788   FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
   15789       i::kExternalInt32Array, INT_MIN, INT_MAX);
   15790 }
   15791 
   15792 
   15793 THREADED_TEST(FixedFloat32Array) {
   15794   FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
   15795       i::kExternalFloat32Array, -500, 500);
   15796 }
   15797 
   15798 
   15799 THREADED_TEST(FixedFloat64Array) {
   15800   FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
   15801       i::kExternalFloat64Array, -500, 500);
   15802 }
   15803 
   15804 
   15805 template <typename ElementType, typename TypedArray, class ExternalArrayClass,
   15806           class ArrayBufferType>
   15807 void TypedArrayTestHelper(i::ExternalArrayType array_type, int64_t low,
   15808                           int64_t high) {
   15809   const int kElementCount = 50;
   15810 
   15811   i::ScopedVector<ElementType> backing_store(kElementCount+2);
   15812 
   15813   LocalContext env;
   15814   v8::Isolate* isolate = env->GetIsolate();
   15815   v8::HandleScope handle_scope(isolate);
   15816 
   15817   Local<ArrayBufferType> ab =
   15818       ArrayBufferType::New(isolate, backing_store.start(),
   15819                            (kElementCount + 2) * sizeof(ElementType));
   15820   Local<TypedArray> ta =
   15821       TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
   15822   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
   15823   CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
   15824   CHECK_EQ(2 * sizeof(ElementType), ta->ByteOffset());
   15825   CHECK_EQ(kElementCount * sizeof(ElementType), ta->ByteLength());
   15826   CHECK(ab->Equals(env.local(), ta->Buffer()).FromJust());
   15827 
   15828   ElementType* data = backing_store.start() + 2;
   15829   for (int i = 0; i < kElementCount; i++) {
   15830     data[i] = static_cast<ElementType>(i);
   15831   }
   15832 
   15833   ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
   15834       env.local(), ta, kElementCount, array_type, low, high);
   15835 }
   15836 
   15837 
   15838 THREADED_TEST(Uint8Array) {
   15839   TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
   15840                        v8::ArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
   15841 }
   15842 
   15843 
   15844 THREADED_TEST(Int8Array) {
   15845   TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
   15846                        v8::ArrayBuffer>(i::kExternalInt8Array, -0x80, 0x7F);
   15847 }
   15848 
   15849 
   15850 THREADED_TEST(Uint16Array) {
   15851   TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
   15852                        v8::ArrayBuffer>(i::kExternalUint16Array, 0, 0xFFFF);
   15853 }
   15854 
   15855 
   15856 THREADED_TEST(Int16Array) {
   15857   TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
   15858                        v8::ArrayBuffer>(i::kExternalInt16Array, -0x8000,
   15859                                         0x7FFF);
   15860 }
   15861 
   15862 
   15863 THREADED_TEST(Uint32Array) {
   15864   TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
   15865                        v8::ArrayBuffer>(i::kExternalUint32Array, 0, UINT_MAX);
   15866 }
   15867 
   15868 
   15869 THREADED_TEST(Int32Array) {
   15870   TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
   15871                        v8::ArrayBuffer>(i::kExternalInt32Array, INT_MIN,
   15872                                         INT_MAX);
   15873 }
   15874 
   15875 
   15876 THREADED_TEST(Float32Array) {
   15877   TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
   15878                        v8::ArrayBuffer>(i::kExternalFloat32Array, -500, 500);
   15879 }
   15880 
   15881 
   15882 THREADED_TEST(Float64Array) {
   15883   TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
   15884                        v8::ArrayBuffer>(i::kExternalFloat64Array, -500, 500);
   15885 }
   15886 
   15887 
   15888 THREADED_TEST(Uint8ClampedArray) {
   15889   TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
   15890                        i::FixedUint8ClampedArray, v8::ArrayBuffer>(
   15891       i::kExternalUint8ClampedArray, 0, 0xFF);
   15892 }
   15893 
   15894 
   15895 THREADED_TEST(DataView) {
   15896   const int kSize = 50;
   15897 
   15898   i::ScopedVector<uint8_t> backing_store(kSize+2);
   15899 
   15900   LocalContext env;
   15901   v8::Isolate* isolate = env->GetIsolate();
   15902   v8::HandleScope handle_scope(isolate);
   15903 
   15904   Local<v8::ArrayBuffer> ab =
   15905       v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
   15906   Local<v8::DataView> dv = v8::DataView::New(ab, 2, kSize);
   15907   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
   15908   CHECK_EQ(2u, dv->ByteOffset());
   15909   CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
   15910   CHECK(ab->Equals(env.local(), dv->Buffer()).FromJust());
   15911 }
   15912 
   15913 
   15914 THREADED_TEST(SkipArrayBufferBackingStoreDuringGC) {
   15915   LocalContext env;
   15916   v8::Isolate* isolate = env->GetIsolate();
   15917   v8::HandleScope handle_scope(isolate);
   15918 
   15919   // Make sure the pointer looks like a heap object
   15920   uint8_t* store_ptr = reinterpret_cast<uint8_t*>(i::kHeapObjectTag);
   15921 
   15922   // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
   15923   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
   15924 
   15925   // Should not crash
   15926   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
   15927   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
   15928   CcTest::heap()->CollectAllGarbage();
   15929   CcTest::heap()->CollectAllGarbage();
   15930 
   15931   // Should not move the pointer
   15932   CHECK_EQ(ab->GetContents().Data(), store_ptr);
   15933 }
   15934 
   15935 
   15936 THREADED_TEST(SkipArrayBufferDuringScavenge) {
   15937   LocalContext env;
   15938   v8::Isolate* isolate = env->GetIsolate();
   15939   v8::HandleScope handle_scope(isolate);
   15940 
   15941   // Make sure the pointer looks like a heap object
   15942   Local<v8::Object> tmp = v8::Object::New(isolate);
   15943   uint8_t* store_ptr =
   15944       reinterpret_cast<uint8_t*>(*reinterpret_cast<uintptr_t*>(*tmp));
   15945 
   15946   // Make `store_ptr` point to from space
   15947   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
   15948 
   15949   // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
   15950   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
   15951 
   15952   // Should not crash,
   15953   // i.e. backing store pointer should not be treated as a heap object pointer
   15954   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
   15955   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
   15956 
   15957   // Use `ab` to silence compiler warning
   15958   CHECK_EQ(ab->GetContents().Data(), store_ptr);
   15959 }
   15960 
   15961 
   15962 THREADED_TEST(SharedUint8Array) {
   15963   i::FLAG_harmony_sharedarraybuffer = true;
   15964   TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
   15965                        v8::SharedArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
   15966 }
   15967 
   15968 
   15969 THREADED_TEST(SharedInt8Array) {
   15970   i::FLAG_harmony_sharedarraybuffer = true;
   15971   TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
   15972                        v8::SharedArrayBuffer>(i::kExternalInt8Array, -0x80,
   15973                                               0x7F);
   15974 }
   15975 
   15976 
   15977 THREADED_TEST(SharedUint16Array) {
   15978   i::FLAG_harmony_sharedarraybuffer = true;
   15979   TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
   15980                        v8::SharedArrayBuffer>(i::kExternalUint16Array, 0,
   15981                                               0xFFFF);
   15982 }
   15983 
   15984 
   15985 THREADED_TEST(SharedInt16Array) {
   15986   i::FLAG_harmony_sharedarraybuffer = true;
   15987   TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
   15988                        v8::SharedArrayBuffer>(i::kExternalInt16Array, -0x8000,
   15989                                               0x7FFF);
   15990 }
   15991 
   15992 
   15993 THREADED_TEST(SharedUint32Array) {
   15994   i::FLAG_harmony_sharedarraybuffer = true;
   15995   TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
   15996                        v8::SharedArrayBuffer>(i::kExternalUint32Array, 0,
   15997                                               UINT_MAX);
   15998 }
   15999 
   16000 
   16001 THREADED_TEST(SharedInt32Array) {
   16002   i::FLAG_harmony_sharedarraybuffer = true;
   16003   TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
   16004                        v8::SharedArrayBuffer>(i::kExternalInt32Array, INT_MIN,
   16005                                               INT_MAX);
   16006 }
   16007 
   16008 
   16009 THREADED_TEST(SharedFloat32Array) {
   16010   i::FLAG_harmony_sharedarraybuffer = true;
   16011   TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
   16012                        v8::SharedArrayBuffer>(i::kExternalFloat32Array, -500,
   16013                                               500);
   16014 }
   16015 
   16016 
   16017 THREADED_TEST(SharedFloat64Array) {
   16018   i::FLAG_harmony_sharedarraybuffer = true;
   16019   TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
   16020                        v8::SharedArrayBuffer>(i::kExternalFloat64Array, -500,
   16021                                               500);
   16022 }
   16023 
   16024 
   16025 THREADED_TEST(SharedUint8ClampedArray) {
   16026   i::FLAG_harmony_sharedarraybuffer = true;
   16027   TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
   16028                        i::FixedUint8ClampedArray, v8::SharedArrayBuffer>(
   16029       i::kExternalUint8ClampedArray, 0, 0xFF);
   16030 }
   16031 
   16032 
   16033 THREADED_TEST(SharedDataView) {
   16034   i::FLAG_harmony_sharedarraybuffer = true;
   16035   const int kSize = 50;
   16036 
   16037   i::ScopedVector<uint8_t> backing_store(kSize + 2);
   16038 
   16039   LocalContext env;
   16040   v8::Isolate* isolate = env->GetIsolate();
   16041   v8::HandleScope handle_scope(isolate);
   16042 
   16043   Local<v8::SharedArrayBuffer> ab =
   16044       v8::SharedArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
   16045   Local<v8::DataView> dv =
   16046       v8::DataView::New(ab, 2, kSize);
   16047   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
   16048   CHECK_EQ(2u, dv->ByteOffset());
   16049   CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
   16050   CHECK(ab->Equals(env.local(), dv->Buffer()).FromJust());
   16051 }
   16052 
   16053 
   16054 #define IS_ARRAY_BUFFER_VIEW_TEST(View)                                     \
   16055   THREADED_TEST(Is##View) {                                                 \
   16056     LocalContext env;                                                       \
   16057     v8::Isolate* isolate = env->GetIsolate();                               \
   16058     v8::HandleScope handle_scope(isolate);                                  \
   16059                                                                             \
   16060     Local<Value> result = CompileRun(                                       \
   16061         "var ab = new ArrayBuffer(128);"                                    \
   16062         "new " #View "(ab)");                                               \
   16063     CHECK(result->IsArrayBufferView());                                     \
   16064     CHECK(result->Is##View());                                              \
   16065     CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>()); \
   16066   }
   16067 
   16068 IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
   16069 IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
   16070 IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
   16071 IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
   16072 IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
   16073 IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
   16074 IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
   16075 IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
   16076 IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
   16077 IS_ARRAY_BUFFER_VIEW_TEST(DataView)
   16078 
   16079 #undef IS_ARRAY_BUFFER_VIEW_TEST
   16080 
   16081 
   16082 
   16083 THREADED_TEST(ScriptContextDependence) {
   16084   LocalContext c1;
   16085   v8::HandleScope scope(c1->GetIsolate());
   16086   const char *source = "foo";
   16087   v8::Local<v8::Script> dep = v8_compile(source);
   16088   v8::ScriptCompiler::Source script_source(
   16089       v8::String::NewFromUtf8(c1->GetIsolate(), source,
   16090                               v8::NewStringType::kNormal)
   16091           .ToLocalChecked());
   16092   v8::Local<v8::UnboundScript> indep =
   16093       v8::ScriptCompiler::CompileUnboundScript(c1->GetIsolate(), &script_source)
   16094           .ToLocalChecked();
   16095   c1->Global()
   16096       ->Set(c1.local(), v8::String::NewFromUtf8(c1->GetIsolate(), "foo",
   16097                                                 v8::NewStringType::kNormal)
   16098                             .ToLocalChecked(),
   16099             v8::Integer::New(c1->GetIsolate(), 100))
   16100       .FromJust();
   16101   CHECK_EQ(
   16102       dep->Run(c1.local()).ToLocalChecked()->Int32Value(c1.local()).FromJust(),
   16103       100);
   16104   CHECK_EQ(indep->BindToCurrentContext()
   16105                ->Run(c1.local())
   16106                .ToLocalChecked()
   16107                ->Int32Value(c1.local())
   16108                .FromJust(),
   16109            100);
   16110   LocalContext c2;
   16111   c2->Global()
   16112       ->Set(c2.local(), v8::String::NewFromUtf8(c2->GetIsolate(), "foo",
   16113                                                 v8::NewStringType::kNormal)
   16114                             .ToLocalChecked(),
   16115             v8::Integer::New(c2->GetIsolate(), 101))
   16116       .FromJust();
   16117   CHECK_EQ(
   16118       dep->Run(c2.local()).ToLocalChecked()->Int32Value(c2.local()).FromJust(),
   16119       100);
   16120   CHECK_EQ(indep->BindToCurrentContext()
   16121                ->Run(c2.local())
   16122                .ToLocalChecked()
   16123                ->Int32Value(c2.local())
   16124                .FromJust(),
   16125            101);
   16126 }
   16127 
   16128 
   16129 THREADED_TEST(StackTrace) {
   16130   LocalContext context;
   16131   v8::HandleScope scope(context->GetIsolate());
   16132   v8::TryCatch try_catch(context->GetIsolate());
   16133   const char *source = "function foo() { FAIL.FAIL; }; foo();";
   16134   v8::Local<v8::String> src = v8_str(source);
   16135   v8::Local<v8::String> origin = v8_str("stack-trace-test");
   16136   v8::ScriptCompiler::Source script_source(src, v8::ScriptOrigin(origin));
   16137   CHECK(v8::ScriptCompiler::CompileUnboundScript(context->GetIsolate(),
   16138                                                  &script_source)
   16139             .ToLocalChecked()
   16140             ->BindToCurrentContext()
   16141             ->Run(context.local())
   16142             .IsEmpty());
   16143   CHECK(try_catch.HasCaught());
   16144   v8::String::Utf8Value stack(
   16145       try_catch.StackTrace(context.local()).ToLocalChecked());
   16146   CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
   16147 }
   16148 
   16149 
   16150 // Checks that a StackFrame has certain expected values.
   16151 void checkStackFrame(const char* expected_script_name,
   16152                      const char* expected_func_name, int expected_line_number,
   16153                      int expected_column, bool is_eval, bool is_constructor,
   16154                      v8::Local<v8::StackFrame> frame) {
   16155   v8::HandleScope scope(CcTest::isolate());
   16156   v8::String::Utf8Value func_name(frame->GetFunctionName());
   16157   v8::String::Utf8Value script_name(frame->GetScriptName());
   16158   if (*script_name == NULL) {
   16159     // The situation where there is no associated script, like for evals.
   16160     CHECK(expected_script_name == NULL);
   16161   } else {
   16162     CHECK(strstr(*script_name, expected_script_name) != NULL);
   16163   }
   16164   CHECK(strstr(*func_name, expected_func_name) != NULL);
   16165   CHECK_EQ(expected_line_number, frame->GetLineNumber());
   16166   CHECK_EQ(expected_column, frame->GetColumn());
   16167   CHECK_EQ(is_eval, frame->IsEval());
   16168   CHECK_EQ(is_constructor, frame->IsConstructor());
   16169 }
   16170 
   16171 
   16172 void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
   16173   v8::HandleScope scope(args.GetIsolate());
   16174   const char* origin = "capture-stack-trace-test";
   16175   const int kOverviewTest = 1;
   16176   const int kDetailedTest = 2;
   16177   const int kFunctionName = 3;
   16178   const int kDisplayName = 4;
   16179   const int kFunctionNameAndDisplayName = 5;
   16180   const int kDisplayNameIsNotString = 6;
   16181   const int kFunctionNameIsNotString = 7;
   16182 
   16183   CHECK(args.Length() == 1);
   16184 
   16185   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   16186   int testGroup = args[0]->Int32Value(context).FromJust();
   16187   if (testGroup == kOverviewTest) {
   16188     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16189         args.GetIsolate(), 10, v8::StackTrace::kOverview);
   16190     CHECK_EQ(4, stackTrace->GetFrameCount());
   16191     checkStackFrame(origin, "bar", 2, 10, false, false,
   16192                     stackTrace->GetFrame(0));
   16193     checkStackFrame(origin, "foo", 6, 3, false, false,
   16194                     stackTrace->GetFrame(1));
   16195     // This is the source string inside the eval which has the call to foo.
   16196     checkStackFrame(NULL, "", 1, 1, false, false, stackTrace->GetFrame(2));
   16197     // The last frame is an anonymous function which has the initial eval call.
   16198     checkStackFrame(origin, "", 8, 7, false, false, stackTrace->GetFrame(3));
   16199 
   16200     CHECK(stackTrace->AsArray()->IsArray());
   16201   } else if (testGroup == kDetailedTest) {
   16202     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16203         args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   16204     CHECK_EQ(4, stackTrace->GetFrameCount());
   16205     checkStackFrame(origin, "bat", 4, 22, false, false,
   16206                     stackTrace->GetFrame(0));
   16207     checkStackFrame(origin, "baz", 8, 3, false, true,
   16208                     stackTrace->GetFrame(1));
   16209     bool is_eval = true;
   16210     // This is the source string inside the eval which has the call to baz.
   16211     checkStackFrame(NULL, "", 1, 1, is_eval, false, stackTrace->GetFrame(2));
   16212     // The last frame is an anonymous function which has the initial eval call.
   16213     checkStackFrame(origin, "", 10, 1, false, false, stackTrace->GetFrame(3));
   16214 
   16215     CHECK(stackTrace->AsArray()->IsArray());
   16216   } else if (testGroup == kFunctionName) {
   16217     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16218         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   16219     CHECK_EQ(3, stackTrace->GetFrameCount());
   16220     checkStackFrame(origin, "function.name", 2, 24, false, false,
   16221                     stackTrace->GetFrame(0));
   16222   } else if (testGroup == kDisplayName) {
   16223     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16224         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   16225     CHECK_EQ(3, stackTrace->GetFrameCount());
   16226     checkStackFrame(origin, "function.displayName", 2, 24, false, false,
   16227                     stackTrace->GetFrame(0));
   16228   } else if (testGroup == kFunctionNameAndDisplayName) {
   16229     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16230         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   16231     CHECK_EQ(3, stackTrace->GetFrameCount());
   16232     checkStackFrame(origin, "function.displayName", 2, 24, false, false,
   16233                     stackTrace->GetFrame(0));
   16234   } else if (testGroup == kDisplayNameIsNotString) {
   16235     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16236         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   16237     CHECK_EQ(3, stackTrace->GetFrameCount());
   16238     checkStackFrame(origin, "function.name", 2, 24, false, false,
   16239                     stackTrace->GetFrame(0));
   16240   } else if (testGroup == kFunctionNameIsNotString) {
   16241     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16242         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   16243     CHECK_EQ(3, stackTrace->GetFrameCount());
   16244     checkStackFrame(origin, "f", 2, 24, false, false, stackTrace->GetFrame(0));
   16245   }
   16246 }
   16247 
   16248 
   16249 // Tests the C++ StackTrace API.
   16250 // TODO(3074796): Reenable this as a THREADED_TEST once it passes.
   16251 // THREADED_TEST(CaptureStackTrace) {
   16252 TEST(CaptureStackTrace) {
   16253   v8::Isolate* isolate = CcTest::isolate();
   16254   v8::HandleScope scope(isolate);
   16255   v8::Local<v8::String> origin = v8_str("capture-stack-trace-test");
   16256   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   16257   templ->Set(v8_str("AnalyzeStackInNativeCode"),
   16258              v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
   16259   LocalContext context(0, templ);
   16260 
   16261   // Test getting OVERVIEW information. Should ignore information that is not
   16262   // script name, function name, line number, and column offset.
   16263   const char *overview_source =
   16264     "function bar() {\n"
   16265     "  var y; AnalyzeStackInNativeCode(1);\n"
   16266     "}\n"
   16267     "function foo() {\n"
   16268     "\n"
   16269     "  bar();\n"
   16270     "}\n"
   16271     "var x;eval('new foo();');";
   16272   v8::Local<v8::String> overview_src = v8_str(overview_source);
   16273   v8::ScriptCompiler::Source script_source(overview_src,
   16274                                            v8::ScriptOrigin(origin));
   16275   v8::Local<Value> overview_result(
   16276       v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source)
   16277           .ToLocalChecked()
   16278           ->BindToCurrentContext()
   16279           ->Run(context.local())
   16280           .ToLocalChecked());
   16281   CHECK(!overview_result.IsEmpty());
   16282   CHECK(overview_result->IsObject());
   16283 
   16284   // Test getting DETAILED information.
   16285   const char *detailed_source =
   16286     "function bat() {AnalyzeStackInNativeCode(2);\n"
   16287     "}\n"
   16288     "\n"
   16289     "function baz() {\n"
   16290     "  bat();\n"
   16291     "}\n"
   16292     "eval('new baz();');";
   16293   v8::Local<v8::String> detailed_src = v8_str(detailed_source);
   16294   // Make the script using a non-zero line and column offset.
   16295   v8::Local<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
   16296   v8::Local<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
   16297   v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
   16298   v8::ScriptCompiler::Source script_source2(detailed_src, detailed_origin);
   16299   v8::Local<v8::UnboundScript> detailed_script(
   16300       v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source2)
   16301           .ToLocalChecked());
   16302   v8::Local<Value> detailed_result(detailed_script->BindToCurrentContext()
   16303                                        ->Run(context.local())
   16304                                        .ToLocalChecked());
   16305   CHECK(!detailed_result.IsEmpty());
   16306   CHECK(detailed_result->IsObject());
   16307 
   16308   // Test using function.name and function.displayName in stack trace
   16309   const char* function_name_source =
   16310       "function bar(function_name, display_name, testGroup) {\n"
   16311       "  var f = function() { AnalyzeStackInNativeCode(testGroup); };\n"
   16312       "  if (function_name) {\n"
   16313       "    Object.defineProperty(f, 'name', { value: function_name });\n"
   16314       "  }\n"
   16315       "  if (display_name) {\n"
   16316       "    f.displayName = display_name;"
   16317       "  }\n"
   16318       "  f()\n"
   16319       "}\n"
   16320       "bar('function.name', undefined, 3);\n"
   16321       "bar(undefined, 'function.displayName', 4);\n"
   16322       "bar('function.name', 'function.displayName', 5);\n"
   16323       "bar('function.name', 239, 6);\n"
   16324       "bar(239, undefined, 7);\n";
   16325   v8::Local<v8::String> function_name_src =
   16326       v8::String::NewFromUtf8(isolate, function_name_source,
   16327                               v8::NewStringType::kNormal)
   16328           .ToLocalChecked();
   16329   v8::ScriptCompiler::Source script_source3(function_name_src,
   16330                                             v8::ScriptOrigin(origin));
   16331   v8::Local<Value> function_name_result(
   16332       v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source3)
   16333           .ToLocalChecked()
   16334           ->BindToCurrentContext()
   16335           ->Run(context.local())
   16336           .ToLocalChecked());
   16337   CHECK(!function_name_result.IsEmpty());
   16338 }
   16339 
   16340 
   16341 static void StackTraceForUncaughtExceptionListener(
   16342     v8::Local<v8::Message> message, v8::Local<Value>) {
   16343   report_count++;
   16344   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   16345   CHECK_EQ(2, stack_trace->GetFrameCount());
   16346   checkStackFrame("origin", "foo", 2, 3, false, false,
   16347                   stack_trace->GetFrame(0));
   16348   checkStackFrame("origin", "bar", 5, 3, false, false,
   16349                   stack_trace->GetFrame(1));
   16350 }
   16351 
   16352 
   16353 TEST(CaptureStackTraceForUncaughtException) {
   16354   report_count = 0;
   16355   LocalContext env;
   16356   v8::Isolate* isolate = env->GetIsolate();
   16357   v8::HandleScope scope(isolate);
   16358   isolate->AddMessageListener(StackTraceForUncaughtExceptionListener);
   16359   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   16360 
   16361   CompileRunWithOrigin(
   16362       "function foo() {\n"
   16363       "  throw 1;\n"
   16364       "};\n"
   16365       "function bar() {\n"
   16366       "  foo();\n"
   16367       "};",
   16368       "origin");
   16369   v8::Local<v8::Object> global = env->Global();
   16370   Local<Value> trouble =
   16371       global->Get(env.local(), v8_str("bar")).ToLocalChecked();
   16372   CHECK(trouble->IsFunction());
   16373   CHECK(Function::Cast(*trouble)->Call(env.local(), global, 0, NULL).IsEmpty());
   16374   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   16375   isolate->RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
   16376   CHECK_EQ(1, report_count);
   16377 }
   16378 
   16379 
   16380 TEST(GetStackTraceForUncaughtExceptionFromSimpleStackTrace) {
   16381   report_count = 0;
   16382   LocalContext env;
   16383   v8::Isolate* isolate = env->GetIsolate();
   16384   v8::HandleScope scope(isolate);
   16385 
   16386   // Create an Error object first.
   16387   CompileRunWithOrigin(
   16388       "function foo() {\n"
   16389       "e=new Error('err');\n"
   16390       "};\n"
   16391       "function bar() {\n"
   16392       "  foo();\n"
   16393       "};\n"
   16394       "var e;",
   16395       "origin");
   16396   v8::Local<v8::Object> global = env->Global();
   16397   Local<Value> trouble =
   16398       global->Get(env.local(), v8_str("bar")).ToLocalChecked();
   16399   CHECK(trouble->IsFunction());
   16400   Function::Cast(*trouble)->Call(env.local(), global, 0, NULL).ToLocalChecked();
   16401 
   16402   // Enable capturing detailed stack trace late, and throw the exception.
   16403   // The detailed stack trace should be extracted from the simple stack.
   16404   isolate->AddMessageListener(StackTraceForUncaughtExceptionListener);
   16405   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   16406   CompileRunWithOrigin("throw e", "origin");
   16407   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   16408   isolate->RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
   16409   CHECK_EQ(1, report_count);
   16410 }
   16411 
   16412 
   16413 TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
   16414   LocalContext env;
   16415   v8::Isolate* isolate = env->GetIsolate();
   16416   v8::HandleScope scope(isolate);
   16417   isolate->SetCaptureStackTraceForUncaughtExceptions(true, 1024,
   16418                                                      v8::StackTrace::kDetailed);
   16419 
   16420   CompileRun(
   16421       "var setters = ['column', 'lineNumber', 'scriptName',\n"
   16422       "    'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
   16423       "    'isConstructor'];\n"
   16424       "for (var i = 0; i < setters.length; i++) {\n"
   16425       "  var prop = setters[i];\n"
   16426       "  Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
   16427       "}\n");
   16428   CompileRun("throw 'exception';");
   16429   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   16430 }
   16431 
   16432 
   16433 static void StackTraceFunctionNameListener(v8::Local<v8::Message> message,
   16434                                            v8::Local<Value>) {
   16435   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   16436   CHECK_EQ(5, stack_trace->GetFrameCount());
   16437   checkStackFrame("origin", "foo:0", 4, 7, false, false,
   16438                   stack_trace->GetFrame(0));
   16439   checkStackFrame("origin", "foo:1", 5, 27, false, false,
   16440                   stack_trace->GetFrame(1));
   16441   checkStackFrame("origin", "foo", 5, 27, false, false,
   16442                   stack_trace->GetFrame(2));
   16443   checkStackFrame("origin", "foo", 5, 27, false, false,
   16444                   stack_trace->GetFrame(3));
   16445   checkStackFrame("origin", "", 1, 14, false, false, stack_trace->GetFrame(4));
   16446 }
   16447 
   16448 
   16449 TEST(GetStackTraceContainsFunctionsWithFunctionName) {
   16450   LocalContext env;
   16451   v8::Isolate* isolate = env->GetIsolate();
   16452   v8::HandleScope scope(isolate);
   16453 
   16454   CompileRunWithOrigin(
   16455       "function gen(name, counter) {\n"
   16456       "  var f = function foo() {\n"
   16457       "    if (counter === 0)\n"
   16458       "      throw 1;\n"
   16459       "    gen(name, counter - 1)();\n"
   16460       "  };\n"
   16461       "  if (counter == 3) {\n"
   16462       "    Object.defineProperty(f, 'name', {get: function(){ throw 239; }});\n"
   16463       "  } else {\n"
   16464       "    Object.defineProperty(f, 'name', {writable:true});\n"
   16465       "    if (counter == 2)\n"
   16466       "      f.name = 42;\n"
   16467       "    else\n"
   16468       "      f.name = name + ':' + counter;\n"
   16469       "  }\n"
   16470       "  return f;\n"
   16471       "};",
   16472       "origin");
   16473 
   16474   isolate->AddMessageListener(StackTraceFunctionNameListener);
   16475   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   16476   CompileRunWithOrigin("gen('foo', 3)();", "origin");
   16477   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   16478   isolate->RemoveMessageListeners(StackTraceFunctionNameListener);
   16479 }
   16480 
   16481 
   16482 static void RethrowStackTraceHandler(v8::Local<v8::Message> message,
   16483                                      v8::Local<v8::Value> data) {
   16484   // Use the frame where JavaScript is called from.
   16485   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   16486   CHECK(!stack_trace.IsEmpty());
   16487   int frame_count = stack_trace->GetFrameCount();
   16488   CHECK_EQ(3, frame_count);
   16489   int line_number[] = {1, 2, 5};
   16490   for (int i = 0; i < frame_count; i++) {
   16491     CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
   16492   }
   16493 }
   16494 
   16495 
   16496 // Test that we only return the stack trace at the site where the exception
   16497 // is first thrown (not where it is rethrown).
   16498 TEST(RethrowStackTrace) {
   16499   LocalContext env;
   16500   v8::Isolate* isolate = env->GetIsolate();
   16501   v8::HandleScope scope(isolate);
   16502   // We make sure that
   16503   // - the stack trace of the ReferenceError in g() is reported.
   16504   // - the stack trace is not overwritten when e1 is rethrown by t().
   16505   // - the stack trace of e2 does not overwrite that of e1.
   16506   const char* source =
   16507       "function g() { error; }          \n"
   16508       "function f() { g(); }            \n"
   16509       "function t(e) { throw e; }       \n"
   16510       "try {                            \n"
   16511       "  f();                           \n"
   16512       "} catch (e1) {                   \n"
   16513       "  try {                          \n"
   16514       "    error;                       \n"
   16515       "  } catch (e2) {                 \n"
   16516       "    t(e1);                       \n"
   16517       "  }                              \n"
   16518       "}                                \n";
   16519   isolate->AddMessageListener(RethrowStackTraceHandler);
   16520   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   16521   CompileRun(source);
   16522   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   16523   isolate->RemoveMessageListeners(RethrowStackTraceHandler);
   16524 }
   16525 
   16526 
   16527 static void RethrowPrimitiveStackTraceHandler(v8::Local<v8::Message> message,
   16528                                               v8::Local<v8::Value> data) {
   16529   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   16530   CHECK(!stack_trace.IsEmpty());
   16531   int frame_count = stack_trace->GetFrameCount();
   16532   CHECK_EQ(2, frame_count);
   16533   int line_number[] = {3, 7};
   16534   for (int i = 0; i < frame_count; i++) {
   16535     CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
   16536   }
   16537 }
   16538 
   16539 
   16540 // Test that we do not recognize identity for primitive exceptions.
   16541 TEST(RethrowPrimitiveStackTrace) {
   16542   LocalContext env;
   16543   v8::Isolate* isolate = env->GetIsolate();
   16544   v8::HandleScope scope(isolate);
   16545   // We do not capture stack trace for non Error objects on creation time.
   16546   // Instead, we capture the stack trace on last throw.
   16547   const char* source =
   16548       "function g() { throw 404; }      \n"
   16549       "function f() { g(); }            \n"
   16550       "function t(e) { throw e; }       \n"
   16551       "try {                            \n"
   16552       "  f();                           \n"
   16553       "} catch (e1) {                   \n"
   16554       "  t(e1)                          \n"
   16555       "}                                \n";
   16556   isolate->AddMessageListener(RethrowPrimitiveStackTraceHandler);
   16557   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   16558   CompileRun(source);
   16559   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   16560   isolate->RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
   16561 }
   16562 
   16563 
   16564 static void RethrowExistingStackTraceHandler(v8::Local<v8::Message> message,
   16565                                              v8::Local<v8::Value> data) {
   16566   // Use the frame where JavaScript is called from.
   16567   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   16568   CHECK(!stack_trace.IsEmpty());
   16569   CHECK_EQ(1, stack_trace->GetFrameCount());
   16570   CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
   16571 }
   16572 
   16573 
   16574 // Test that the stack trace is captured when the error object is created and
   16575 // not where it is thrown.
   16576 TEST(RethrowExistingStackTrace) {
   16577   LocalContext env;
   16578   v8::Isolate* isolate = env->GetIsolate();
   16579   v8::HandleScope scope(isolate);
   16580   const char* source =
   16581       "var e = new Error();           \n"
   16582       "throw e;                       \n";
   16583   isolate->AddMessageListener(RethrowExistingStackTraceHandler);
   16584   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   16585   CompileRun(source);
   16586   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   16587   isolate->RemoveMessageListeners(RethrowExistingStackTraceHandler);
   16588 }
   16589 
   16590 
   16591 static void RethrowBogusErrorStackTraceHandler(v8::Local<v8::Message> message,
   16592                                                v8::Local<v8::Value> data) {
   16593   // Use the frame where JavaScript is called from.
   16594   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   16595   CHECK(!stack_trace.IsEmpty());
   16596   CHECK_EQ(1, stack_trace->GetFrameCount());
   16597   CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
   16598 }
   16599 
   16600 
   16601 // Test that the stack trace is captured where the bogus Error object is thrown.
   16602 TEST(RethrowBogusErrorStackTrace) {
   16603   LocalContext env;
   16604   v8::Isolate* isolate = env->GetIsolate();
   16605   v8::HandleScope scope(isolate);
   16606   const char* source =
   16607       "var e = {__proto__: new Error()} \n"
   16608       "throw e;                         \n";
   16609   isolate->AddMessageListener(RethrowBogusErrorStackTraceHandler);
   16610   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   16611   CompileRun(source);
   16612   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   16613   isolate->RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
   16614 }
   16615 
   16616 
   16617 v8::PromiseRejectEvent reject_event = v8::kPromiseRejectWithNoHandler;
   16618 int promise_reject_counter = 0;
   16619 int promise_revoke_counter = 0;
   16620 int promise_reject_msg_line_number = -1;
   16621 int promise_reject_msg_column_number = -1;
   16622 int promise_reject_line_number = -1;
   16623 int promise_reject_column_number = -1;
   16624 int promise_reject_frame_count = -1;
   16625 
   16626 void PromiseRejectCallback(v8::PromiseRejectMessage reject_message) {
   16627   v8::Local<v8::Object> global = CcTest::global();
   16628   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   16629   if (reject_message.GetEvent() == v8::kPromiseRejectWithNoHandler) {
   16630     promise_reject_counter++;
   16631     global->Set(context, v8_str("rejected"), reject_message.GetPromise())
   16632         .FromJust();
   16633     global->Set(context, v8_str("value"), reject_message.GetValue()).FromJust();
   16634     v8::Local<v8::Message> message = v8::Exception::CreateMessage(
   16635         CcTest::isolate(), reject_message.GetValue());
   16636     v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   16637 
   16638     promise_reject_msg_line_number = message->GetLineNumber(context).FromJust();
   16639     promise_reject_msg_column_number =
   16640         message->GetStartColumn(context).FromJust() + 1;
   16641 
   16642     if (!stack_trace.IsEmpty()) {
   16643       promise_reject_frame_count = stack_trace->GetFrameCount();
   16644       if (promise_reject_frame_count > 0) {
   16645         CHECK(stack_trace->GetFrame(0)
   16646                   ->GetScriptName()
   16647                   ->Equals(context, v8_str("pro"))
   16648                   .FromJust());
   16649         promise_reject_line_number = stack_trace->GetFrame(0)->GetLineNumber();
   16650         promise_reject_column_number = stack_trace->GetFrame(0)->GetColumn();
   16651       } else {
   16652         promise_reject_line_number = -1;
   16653         promise_reject_column_number = -1;
   16654       }
   16655     }
   16656   } else {
   16657     promise_revoke_counter++;
   16658     global->Set(context, v8_str("revoked"), reject_message.GetPromise())
   16659         .FromJust();
   16660     CHECK(reject_message.GetValue().IsEmpty());
   16661   }
   16662 }
   16663 
   16664 
   16665 v8::Local<v8::Promise> GetPromise(const char* name) {
   16666   return v8::Local<v8::Promise>::Cast(
   16667       CcTest::global()
   16668           ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name))
   16669           .ToLocalChecked());
   16670 }
   16671 
   16672 
   16673 v8::Local<v8::Value> RejectValue() {
   16674   return CcTest::global()
   16675       ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
   16676       .ToLocalChecked();
   16677 }
   16678 
   16679 
   16680 void ResetPromiseStates() {
   16681   promise_reject_counter = 0;
   16682   promise_revoke_counter = 0;
   16683   promise_reject_msg_line_number = -1;
   16684   promise_reject_msg_column_number = -1;
   16685   promise_reject_line_number = -1;
   16686   promise_reject_column_number = -1;
   16687   promise_reject_frame_count = -1;
   16688 
   16689   v8::Local<v8::Object> global = CcTest::global();
   16690   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   16691   global->Set(context, v8_str("rejected"), v8_str("")).FromJust();
   16692   global->Set(context, v8_str("value"), v8_str("")).FromJust();
   16693   global->Set(context, v8_str("revoked"), v8_str("")).FromJust();
   16694 }
   16695 
   16696 
   16697 TEST(PromiseRejectCallback) {
   16698   LocalContext env;
   16699   v8::Isolate* isolate = env->GetIsolate();
   16700   v8::HandleScope scope(isolate);
   16701 
   16702   isolate->SetPromiseRejectCallback(PromiseRejectCallback);
   16703 
   16704   ResetPromiseStates();
   16705 
   16706   // Create promise p0.
   16707   CompileRun(
   16708       "var reject;            \n"
   16709       "var p0 = new Promise(  \n"
   16710       "  function(res, rej) { \n"
   16711       "    reject = rej;      \n"
   16712       "  }                    \n"
   16713       ");                     \n");
   16714   CHECK(!GetPromise("p0")->HasHandler());
   16715   CHECK_EQ(0, promise_reject_counter);
   16716   CHECK_EQ(0, promise_revoke_counter);
   16717 
   16718   // Add resolve handler (and default reject handler) to p0.
   16719   CompileRun("var p1 = p0.then(function(){});");
   16720   CHECK(GetPromise("p0")->HasHandler());
   16721   CHECK(!GetPromise("p1")->HasHandler());
   16722   CHECK_EQ(0, promise_reject_counter);
   16723   CHECK_EQ(0, promise_revoke_counter);
   16724 
   16725   // Reject p0.
   16726   CompileRun("reject('ppp');");
   16727   CHECK(GetPromise("p0")->HasHandler());
   16728   CHECK(!GetPromise("p1")->HasHandler());
   16729   CHECK_EQ(1, promise_reject_counter);
   16730   CHECK_EQ(0, promise_revoke_counter);
   16731   CHECK_EQ(v8::kPromiseRejectWithNoHandler, reject_event);
   16732   CHECK(
   16733       GetPromise("rejected")->Equals(env.local(), GetPromise("p1")).FromJust());
   16734   CHECK(RejectValue()->Equals(env.local(), v8_str("ppp")).FromJust());
   16735 
   16736   // Reject p0 again. Callback is not triggered again.
   16737   CompileRun("reject();");
   16738   CHECK(GetPromise("p0")->HasHandler());
   16739   CHECK(!GetPromise("p1")->HasHandler());
   16740   CHECK_EQ(1, promise_reject_counter);
   16741   CHECK_EQ(0, promise_revoke_counter);
   16742 
   16743   // Add resolve handler to p1.
   16744   CompileRun("var p2 = p1.then(function(){});");
   16745   CHECK(GetPromise("p0")->HasHandler());
   16746   CHECK(GetPromise("p1")->HasHandler());
   16747   CHECK(!GetPromise("p2")->HasHandler());
   16748   CHECK_EQ(2, promise_reject_counter);
   16749   CHECK_EQ(1, promise_revoke_counter);
   16750   CHECK(
   16751       GetPromise("rejected")->Equals(env.local(), GetPromise("p2")).FromJust());
   16752   CHECK(RejectValue()->Equals(env.local(), v8_str("ppp")).FromJust());
   16753   CHECK(
   16754       GetPromise("revoked")->Equals(env.local(), GetPromise("p1")).FromJust());
   16755 
   16756   ResetPromiseStates();
   16757 
   16758   // Create promise q0.
   16759   CompileRun(
   16760       "var q0 = new Promise(  \n"
   16761       "  function(res, rej) { \n"
   16762       "    reject = rej;      \n"
   16763       "  }                    \n"
   16764       ");                     \n");
   16765   CHECK(!GetPromise("q0")->HasHandler());
   16766   CHECK_EQ(0, promise_reject_counter);
   16767   CHECK_EQ(0, promise_revoke_counter);
   16768 
   16769   // Add reject handler to q0.
   16770   CompileRun("var q1 = q0.catch(function() {});");
   16771   CHECK(GetPromise("q0")->HasHandler());
   16772   CHECK(!GetPromise("q1")->HasHandler());
   16773   CHECK_EQ(0, promise_reject_counter);
   16774   CHECK_EQ(0, promise_revoke_counter);
   16775 
   16776   // Reject q0.
   16777   CompileRun("reject('qq')");
   16778   CHECK(GetPromise("q0")->HasHandler());
   16779   CHECK(!GetPromise("q1")->HasHandler());
   16780   CHECK_EQ(0, promise_reject_counter);
   16781   CHECK_EQ(0, promise_revoke_counter);
   16782 
   16783   // Add a new reject handler, which rejects by returning Promise.reject().
   16784   // The returned promise q_ triggers a reject callback at first, only to
   16785   // revoke it when returning it causes q2 to be rejected.
   16786   CompileRun(
   16787       "var q_;"
   16788       "var q2 = q0.catch(               \n"
   16789       "   function() {                  \n"
   16790       "     q_ = Promise.reject('qqq'); \n"
   16791       "     return q_;                  \n"
   16792       "   }                             \n"
   16793       ");                               \n");
   16794   CHECK(GetPromise("q0")->HasHandler());
   16795   CHECK(!GetPromise("q1")->HasHandler());
   16796   CHECK(!GetPromise("q2")->HasHandler());
   16797   CHECK(GetPromise("q_")->HasHandler());
   16798   CHECK_EQ(2, promise_reject_counter);
   16799   CHECK_EQ(1, promise_revoke_counter);
   16800   CHECK(
   16801       GetPromise("rejected")->Equals(env.local(), GetPromise("q2")).FromJust());
   16802   CHECK(
   16803       GetPromise("revoked")->Equals(env.local(), GetPromise("q_")).FromJust());
   16804   CHECK(RejectValue()->Equals(env.local(), v8_str("qqq")).FromJust());
   16805 
   16806   // Add a reject handler to the resolved q1, which rejects by throwing.
   16807   CompileRun(
   16808       "var q3 = q1.then(  \n"
   16809       "   function() {    \n"
   16810       "     throw 'qqqq'; \n"
   16811       "   }               \n"
   16812       ");                 \n");
   16813   CHECK(GetPromise("q0")->HasHandler());
   16814   CHECK(GetPromise("q1")->HasHandler());
   16815   CHECK(!GetPromise("q2")->HasHandler());
   16816   CHECK(!GetPromise("q3")->HasHandler());
   16817   CHECK_EQ(3, promise_reject_counter);
   16818   CHECK_EQ(1, promise_revoke_counter);
   16819   CHECK(
   16820       GetPromise("rejected")->Equals(env.local(), GetPromise("q3")).FromJust());
   16821   CHECK(RejectValue()->Equals(env.local(), v8_str("qqqq")).FromJust());
   16822 
   16823   ResetPromiseStates();
   16824 
   16825   // Create promise r0, which has three handlers, two of which handle rejects.
   16826   CompileRun(
   16827       "var r0 = new Promise(             \n"
   16828       "  function(res, rej) {            \n"
   16829       "    reject = rej;                 \n"
   16830       "  }                               \n"
   16831       ");                                \n"
   16832       "var r1 = r0.catch(function() {}); \n"
   16833       "var r2 = r0.then(function() {});  \n"
   16834       "var r3 = r0.then(function() {},   \n"
   16835       "                 function() {});  \n");
   16836   CHECK(GetPromise("r0")->HasHandler());
   16837   CHECK(!GetPromise("r1")->HasHandler());
   16838   CHECK(!GetPromise("r2")->HasHandler());
   16839   CHECK(!GetPromise("r3")->HasHandler());
   16840   CHECK_EQ(0, promise_reject_counter);
   16841   CHECK_EQ(0, promise_revoke_counter);
   16842 
   16843   // Reject r0.
   16844   CompileRun("reject('rrr')");
   16845   CHECK(GetPromise("r0")->HasHandler());
   16846   CHECK(!GetPromise("r1")->HasHandler());
   16847   CHECK(!GetPromise("r2")->HasHandler());
   16848   CHECK(!GetPromise("r3")->HasHandler());
   16849   CHECK_EQ(1, promise_reject_counter);
   16850   CHECK_EQ(0, promise_revoke_counter);
   16851   CHECK(
   16852       GetPromise("rejected")->Equals(env.local(), GetPromise("r2")).FromJust());
   16853   CHECK(RejectValue()->Equals(env.local(), v8_str("rrr")).FromJust());
   16854 
   16855   // Add reject handler to r2.
   16856   CompileRun("var r4 = r2.catch(function() {});");
   16857   CHECK(GetPromise("r0")->HasHandler());
   16858   CHECK(!GetPromise("r1")->HasHandler());
   16859   CHECK(GetPromise("r2")->HasHandler());
   16860   CHECK(!GetPromise("r3")->HasHandler());
   16861   CHECK(!GetPromise("r4")->HasHandler());
   16862   CHECK_EQ(1, promise_reject_counter);
   16863   CHECK_EQ(1, promise_revoke_counter);
   16864   CHECK(
   16865       GetPromise("revoked")->Equals(env.local(), GetPromise("r2")).FromJust());
   16866   CHECK(RejectValue()->Equals(env.local(), v8_str("rrr")).FromJust());
   16867 
   16868   // Add reject handlers to r4.
   16869   CompileRun("var r5 = r4.then(function() {}, function() {});");
   16870   CHECK(GetPromise("r0")->HasHandler());
   16871   CHECK(!GetPromise("r1")->HasHandler());
   16872   CHECK(GetPromise("r2")->HasHandler());
   16873   CHECK(!GetPromise("r3")->HasHandler());
   16874   CHECK(GetPromise("r4")->HasHandler());
   16875   CHECK(!GetPromise("r5")->HasHandler());
   16876   CHECK_EQ(1, promise_reject_counter);
   16877   CHECK_EQ(1, promise_revoke_counter);
   16878 
   16879   ResetPromiseStates();
   16880 
   16881   // Create promise s0, which has three handlers, none of which handle rejects.
   16882   CompileRun(
   16883       "var s0 = new Promise(            \n"
   16884       "  function(res, rej) {           \n"
   16885       "    reject = rej;                \n"
   16886       "  }                              \n"
   16887       ");                               \n"
   16888       "var s1 = s0.then(function() {}); \n"
   16889       "var s2 = s0.then(function() {}); \n"
   16890       "var s3 = s0.then(function() {}); \n");
   16891   CHECK(GetPromise("s0")->HasHandler());
   16892   CHECK(!GetPromise("s1")->HasHandler());
   16893   CHECK(!GetPromise("s2")->HasHandler());
   16894   CHECK(!GetPromise("s3")->HasHandler());
   16895   CHECK_EQ(0, promise_reject_counter);
   16896   CHECK_EQ(0, promise_revoke_counter);
   16897 
   16898   // Reject s0.
   16899   CompileRun("reject('sss')");
   16900   CHECK(GetPromise("s0")->HasHandler());
   16901   CHECK(!GetPromise("s1")->HasHandler());
   16902   CHECK(!GetPromise("s2")->HasHandler());
   16903   CHECK(!GetPromise("s3")->HasHandler());
   16904   CHECK_EQ(3, promise_reject_counter);
   16905   CHECK_EQ(0, promise_revoke_counter);
   16906   CHECK(RejectValue()->Equals(env.local(), v8_str("sss")).FromJust());
   16907 
   16908   // Test stack frames.
   16909   env->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(true);
   16910 
   16911   ResetPromiseStates();
   16912 
   16913   // Create promise t0, which is rejected in the constructor with an error.
   16914   CompileRunWithOrigin(
   16915       "var t0 = new Promise(  \n"
   16916       "  function(res, rej) { \n"
   16917       "    reference_error;   \n"
   16918       "  }                    \n"
   16919       ");                     \n",
   16920       "pro", 0, 0);
   16921   CHECK(!GetPromise("t0")->HasHandler());
   16922   CHECK_EQ(1, promise_reject_counter);
   16923   CHECK_EQ(0, promise_revoke_counter);
   16924   CHECK_EQ(2, promise_reject_frame_count);
   16925   CHECK_EQ(3, promise_reject_line_number);
   16926   CHECK_EQ(5, promise_reject_column_number);
   16927   CHECK_EQ(3, promise_reject_msg_line_number);
   16928   CHECK_EQ(5, promise_reject_msg_column_number);
   16929 
   16930   ResetPromiseStates();
   16931 
   16932   // Create promise u0 and chain u1 to it, which is rejected via throw.
   16933   CompileRunWithOrigin(
   16934       "var u0 = Promise.resolve();        \n"
   16935       "var u1 = u0.then(                  \n"
   16936       "           function() {            \n"
   16937       "             (function() {         \n"
   16938       "                throw new Error(); \n"
   16939       "              })();                \n"
   16940       "           }                       \n"
   16941       "         );                        \n",
   16942       "pro", 0, 0);
   16943   CHECK(GetPromise("u0")->HasHandler());
   16944   CHECK(!GetPromise("u1")->HasHandler());
   16945   CHECK_EQ(1, promise_reject_counter);
   16946   CHECK_EQ(0, promise_revoke_counter);
   16947   CHECK_EQ(2, promise_reject_frame_count);
   16948   CHECK_EQ(5, promise_reject_line_number);
   16949   CHECK_EQ(23, promise_reject_column_number);
   16950   CHECK_EQ(5, promise_reject_msg_line_number);
   16951   CHECK_EQ(23, promise_reject_msg_column_number);
   16952 
   16953   // Throw in u3, which handles u1's rejection.
   16954   CompileRunWithOrigin(
   16955       "function f() {                \n"
   16956       "  return (function() {        \n"
   16957       "    return new Error();       \n"
   16958       "  })();                       \n"
   16959       "}                             \n"
   16960       "var u2 = Promise.reject(f()); \n"
   16961       "var u3 = u1.catch(            \n"
   16962       "           function() {       \n"
   16963       "             return u2;       \n"
   16964       "           }                  \n"
   16965       "         );                   \n",
   16966       "pro", 0, 0);
   16967   CHECK(GetPromise("u0")->HasHandler());
   16968   CHECK(GetPromise("u1")->HasHandler());
   16969   CHECK(GetPromise("u2")->HasHandler());
   16970   CHECK(!GetPromise("u3")->HasHandler());
   16971   CHECK_EQ(3, promise_reject_counter);
   16972   CHECK_EQ(2, promise_revoke_counter);
   16973   CHECK_EQ(3, promise_reject_frame_count);
   16974   CHECK_EQ(3, promise_reject_line_number);
   16975   CHECK_EQ(12, promise_reject_column_number);
   16976   CHECK_EQ(3, promise_reject_msg_line_number);
   16977   CHECK_EQ(12, promise_reject_msg_column_number);
   16978 
   16979   ResetPromiseStates();
   16980 
   16981   // Create promise rejected promise v0, which is incorrectly handled by v1
   16982   // via chaining cycle.
   16983   CompileRunWithOrigin(
   16984       "var v0 = Promise.reject(); \n"
   16985       "var v1 = v0.catch(         \n"
   16986       "           function() {    \n"
   16987       "             return v1;    \n"
   16988       "           }               \n"
   16989       "         );                \n",
   16990       "pro", 0, 0);
   16991   CHECK(GetPromise("v0")->HasHandler());
   16992   CHECK(!GetPromise("v1")->HasHandler());
   16993   CHECK_EQ(2, promise_reject_counter);
   16994   CHECK_EQ(1, promise_revoke_counter);
   16995   CHECK_EQ(0, promise_reject_frame_count);
   16996   CHECK_EQ(-1, promise_reject_line_number);
   16997   CHECK_EQ(-1, promise_reject_column_number);
   16998 
   16999   ResetPromiseStates();
   17000 
   17001   // Create promise t1, which rejects by throwing syntax error from eval.
   17002   CompileRunWithOrigin(
   17003       "var t1 = new Promise(   \n"
   17004       "  function(res, rej) {  \n"
   17005       "    var content = '\\n\\\n"
   17006       "      }';               \n"
   17007       "    eval(content);      \n"
   17008       "  }                     \n"
   17009       ");                      \n",
   17010       "pro", 0, 0);
   17011   CHECK(!GetPromise("t1")->HasHandler());
   17012   CHECK_EQ(1, promise_reject_counter);
   17013   CHECK_EQ(0, promise_revoke_counter);
   17014   CHECK_EQ(2, promise_reject_frame_count);
   17015   CHECK_EQ(5, promise_reject_line_number);
   17016   CHECK_EQ(10, promise_reject_column_number);
   17017   CHECK_EQ(2, promise_reject_msg_line_number);
   17018   CHECK_EQ(7, promise_reject_msg_column_number);
   17019 }
   17020 
   17021 
   17022 void AnalyzeStackOfEvalWithSourceURL(
   17023     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17024   v8::HandleScope scope(args.GetIsolate());
   17025   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17026       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   17027   CHECK_EQ(5, stackTrace->GetFrameCount());
   17028   v8::Local<v8::String> url = v8_str("eval_url");
   17029   for (int i = 0; i < 3; i++) {
   17030     v8::Local<v8::String> name =
   17031         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
   17032     CHECK(!name.IsEmpty());
   17033     CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
   17034   }
   17035 }
   17036 
   17037 
   17038 TEST(SourceURLInStackTrace) {
   17039   v8::Isolate* isolate = CcTest::isolate();
   17040   v8::HandleScope scope(isolate);
   17041   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   17042   templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
   17043              v8::FunctionTemplate::New(isolate,
   17044                                        AnalyzeStackOfEvalWithSourceURL));
   17045   LocalContext context(0, templ);
   17046 
   17047   const char *source =
   17048     "function outer() {\n"
   17049     "function bar() {\n"
   17050     "  AnalyzeStackOfEvalWithSourceURL();\n"
   17051     "}\n"
   17052     "function foo() {\n"
   17053     "\n"
   17054     "  bar();\n"
   17055     "}\n"
   17056     "foo();\n"
   17057     "}\n"
   17058     "eval('(' + outer +')()%s');";
   17059 
   17060   i::ScopedVector<char> code(1024);
   17061   i::SNPrintF(code, source, "//# sourceURL=eval_url");
   17062   CHECK(CompileRun(code.start())->IsUndefined());
   17063   i::SNPrintF(code, source, "//@ sourceURL=eval_url");
   17064   CHECK(CompileRun(code.start())->IsUndefined());
   17065 }
   17066 
   17067 
   17068 static int scriptIdInStack[2];
   17069 
   17070 void AnalyzeScriptIdInStack(
   17071     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17072   v8::HandleScope scope(args.GetIsolate());
   17073   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17074       args.GetIsolate(), 10, v8::StackTrace::kScriptId);
   17075   CHECK_EQ(2, stackTrace->GetFrameCount());
   17076   for (int i = 0; i < 2; i++) {
   17077     scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
   17078   }
   17079 }
   17080 
   17081 
   17082 TEST(ScriptIdInStackTrace) {
   17083   v8::Isolate* isolate = CcTest::isolate();
   17084   v8::HandleScope scope(isolate);
   17085   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   17086   templ->Set(v8_str("AnalyzeScriptIdInStack"),
   17087              v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
   17088   LocalContext context(0, templ);
   17089 
   17090   v8::Local<v8::String> scriptSource = v8_str(
   17091       "function foo() {\n"
   17092       "  AnalyzeScriptIdInStack();"
   17093       "}\n"
   17094       "foo();\n");
   17095   v8::Local<v8::Script> script = CompileWithOrigin(scriptSource, "test");
   17096   script->Run(context.local()).ToLocalChecked();
   17097   for (int i = 0; i < 2; i++) {
   17098     CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
   17099     CHECK_EQ(scriptIdInStack[i], script->GetUnboundScript()->GetId());
   17100   }
   17101 }
   17102 
   17103 
   17104 void AnalyzeStackOfInlineScriptWithSourceURL(
   17105     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17106   v8::HandleScope scope(args.GetIsolate());
   17107   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17108       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   17109   CHECK_EQ(4, stackTrace->GetFrameCount());
   17110   v8::Local<v8::String> url = v8_str("source_url");
   17111   for (int i = 0; i < 3; i++) {
   17112     v8::Local<v8::String> name =
   17113         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
   17114     CHECK(!name.IsEmpty());
   17115     CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
   17116   }
   17117 }
   17118 
   17119 
   17120 TEST(InlineScriptWithSourceURLInStackTrace) {
   17121   v8::Isolate* isolate = CcTest::isolate();
   17122   v8::HandleScope scope(isolate);
   17123   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   17124   templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
   17125              v8::FunctionTemplate::New(
   17126                  CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
   17127   LocalContext context(0, templ);
   17128 
   17129   const char *source =
   17130     "function outer() {\n"
   17131     "function bar() {\n"
   17132     "  AnalyzeStackOfInlineScriptWithSourceURL();\n"
   17133     "}\n"
   17134     "function foo() {\n"
   17135     "\n"
   17136     "  bar();\n"
   17137     "}\n"
   17138     "foo();\n"
   17139     "}\n"
   17140     "outer()\n%s";
   17141 
   17142   i::ScopedVector<char> code(1024);
   17143   i::SNPrintF(code, source, "//# sourceURL=source_url");
   17144   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
   17145   i::SNPrintF(code, source, "//@ sourceURL=source_url");
   17146   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
   17147 }
   17148 
   17149 
   17150 void AnalyzeStackOfDynamicScriptWithSourceURL(
   17151     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17152   v8::HandleScope scope(args.GetIsolate());
   17153   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17154       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   17155   CHECK_EQ(4, stackTrace->GetFrameCount());
   17156   v8::Local<v8::String> url = v8_str("source_url");
   17157   for (int i = 0; i < 3; i++) {
   17158     v8::Local<v8::String> name =
   17159         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
   17160     CHECK(!name.IsEmpty());
   17161     CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
   17162   }
   17163 }
   17164 
   17165 
   17166 TEST(DynamicWithSourceURLInStackTrace) {
   17167   v8::Isolate* isolate = CcTest::isolate();
   17168   v8::HandleScope scope(isolate);
   17169   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   17170   templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
   17171              v8::FunctionTemplate::New(
   17172                  CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
   17173   LocalContext context(0, templ);
   17174 
   17175   const char *source =
   17176     "function outer() {\n"
   17177     "function bar() {\n"
   17178     "  AnalyzeStackOfDynamicScriptWithSourceURL();\n"
   17179     "}\n"
   17180     "function foo() {\n"
   17181     "\n"
   17182     "  bar();\n"
   17183     "}\n"
   17184     "foo();\n"
   17185     "}\n"
   17186     "outer()\n%s";
   17187 
   17188   i::ScopedVector<char> code(1024);
   17189   i::SNPrintF(code, source, "//# sourceURL=source_url");
   17190   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
   17191   i::SNPrintF(code, source, "//@ sourceURL=source_url");
   17192   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
   17193 }
   17194 
   17195 
   17196 TEST(DynamicWithSourceURLInStackTraceString) {
   17197   LocalContext context;
   17198   v8::HandleScope scope(context->GetIsolate());
   17199 
   17200   const char *source =
   17201     "function outer() {\n"
   17202     "  function foo() {\n"
   17203     "    FAIL.FAIL;\n"
   17204     "  }\n"
   17205     "  foo();\n"
   17206     "}\n"
   17207     "outer()\n%s";
   17208 
   17209   i::ScopedVector<char> code(1024);
   17210   i::SNPrintF(code, source, "//# sourceURL=source_url");
   17211   v8::TryCatch try_catch(context->GetIsolate());
   17212   CompileRunWithOrigin(code.start(), "", 0, 0);
   17213   CHECK(try_catch.HasCaught());
   17214   v8::String::Utf8Value stack(
   17215       try_catch.StackTrace(context.local()).ToLocalChecked());
   17216   CHECK(strstr(*stack, "at foo (source_url:3:5)") != NULL);
   17217 }
   17218 
   17219 
   17220 TEST(EvalWithSourceURLInMessageScriptResourceNameOrSourceURL) {
   17221   LocalContext context;
   17222   v8::HandleScope scope(context->GetIsolate());
   17223 
   17224   const char *source =
   17225     "function outer() {\n"
   17226     "  var scriptContents = \"function foo() { FAIL.FAIL; }\\\n"
   17227     "  //# sourceURL=source_url\";\n"
   17228     "  eval(scriptContents);\n"
   17229     "  foo(); }\n"
   17230     "outer();\n"
   17231     "//# sourceURL=outer_url";
   17232 
   17233   v8::TryCatch try_catch(context->GetIsolate());
   17234   CompileRun(source);
   17235   CHECK(try_catch.HasCaught());
   17236 
   17237   Local<v8::Message> message = try_catch.Message();
   17238   Local<Value> sourceURL = message->GetScriptOrigin().ResourceName();
   17239   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(sourceURL), "source_url"));
   17240 }
   17241 
   17242 
   17243 TEST(RecursionWithSourceURLInMessageScriptResourceNameOrSourceURL) {
   17244   LocalContext context;
   17245   v8::HandleScope scope(context->GetIsolate());
   17246 
   17247   const char *source =
   17248     "function outer() {\n"
   17249     "  var scriptContents = \"function boo(){ boo(); }\\\n"
   17250     "  //# sourceURL=source_url\";\n"
   17251     "  eval(scriptContents);\n"
   17252     "  boo(); }\n"
   17253     "outer();\n"
   17254     "//# sourceURL=outer_url";
   17255 
   17256   v8::TryCatch try_catch(context->GetIsolate());
   17257   CompileRun(source);
   17258   CHECK(try_catch.HasCaught());
   17259 
   17260   Local<v8::Message> message = try_catch.Message();
   17261   Local<Value> sourceURL = message->GetScriptOrigin().ResourceName();
   17262   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(sourceURL), "source_url"));
   17263 }
   17264 
   17265 
   17266 static void CreateGarbageInOldSpace() {
   17267   i::Factory* factory = CcTest::i_isolate()->factory();
   17268   v8::HandleScope scope(CcTest::isolate());
   17269   i::AlwaysAllocateScope always_allocate(CcTest::i_isolate());
   17270   for (int i = 0; i < 1000; i++) {
   17271     factory->NewFixedArray(1000, i::TENURED);
   17272   }
   17273 }
   17274 
   17275 
   17276 // Test that idle notification can be handled and eventually collects garbage.
   17277 TEST(TestIdleNotification) {
   17278   if (!i::FLAG_incremental_marking) return;
   17279   const intptr_t MB = 1024 * 1024;
   17280   const double IdlePauseInSeconds = 1.0;
   17281   LocalContext env;
   17282   v8::HandleScope scope(env->GetIsolate());
   17283   intptr_t initial_size = CcTest::heap()->SizeOfObjects();
   17284   CreateGarbageInOldSpace();
   17285   intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
   17286   CHECK_GT(size_with_garbage, initial_size + MB);
   17287   bool finished = false;
   17288   for (int i = 0; i < 200 && !finished; i++) {
   17289     if (i < 10 && CcTest::heap()->incremental_marking()->IsStopped()) {
   17290       CcTest::heap()->StartIdleIncrementalMarking();
   17291     }
   17292     finished = env->GetIsolate()->IdleNotificationDeadline(
   17293         (v8::base::TimeTicks::HighResolutionNow().ToInternalValue() /
   17294          static_cast<double>(v8::base::Time::kMicrosecondsPerSecond)) +
   17295         IdlePauseInSeconds);
   17296     if (CcTest::heap()->mark_compact_collector()->sweeping_in_progress()) {
   17297       CcTest::heap()->mark_compact_collector()->EnsureSweepingCompleted();
   17298     }
   17299   }
   17300   intptr_t final_size = CcTest::heap()->SizeOfObjects();
   17301   CHECK(finished);
   17302   CHECK_LT(final_size, initial_size + 1);
   17303 }
   17304 
   17305 
   17306 TEST(Regress2333) {
   17307   LocalContext env;
   17308   for (int i = 0; i < 3; i++) {
   17309     CcTest::heap()->CollectGarbage(i::NEW_SPACE);
   17310   }
   17311 }
   17312 
   17313 static uint32_t* stack_limit;
   17314 
   17315 static void GetStackLimitCallback(
   17316     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17317   stack_limit = reinterpret_cast<uint32_t*>(
   17318       CcTest::i_isolate()->stack_guard()->real_climit());
   17319 }
   17320 
   17321 
   17322 // Uses the address of a local variable to determine the stack top now.
   17323 // Given a size, returns an address that is that far from the current
   17324 // top of stack.
   17325 static uint32_t* ComputeStackLimit(uint32_t size) {
   17326   uint32_t* answer = &size - (size / sizeof(size));
   17327   // If the size is very large and the stack is very near the bottom of
   17328   // memory then the calculation above may wrap around and give an address
   17329   // that is above the (downwards-growing) stack.  In that case we return
   17330   // a very low address.
   17331   if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
   17332   return answer;
   17333 }
   17334 
   17335 
   17336 // We need at least 165kB for an x64 debug build with clang and ASAN.
   17337 static const int stack_breathing_room = 256 * i::KB;
   17338 
   17339 
   17340 TEST(SetStackLimit) {
   17341   uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
   17342 
   17343   // Set stack limit.
   17344   CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
   17345 
   17346   // Execute a script.
   17347   LocalContext env;
   17348   v8::HandleScope scope(env->GetIsolate());
   17349   Local<v8::FunctionTemplate> fun_templ =
   17350       v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
   17351   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   17352   CHECK(env->Global()
   17353             ->Set(env.local(), v8_str("get_stack_limit"), fun)
   17354             .FromJust());
   17355   CompileRun("get_stack_limit();");
   17356 
   17357   CHECK(stack_limit == set_limit);
   17358 }
   17359 
   17360 
   17361 TEST(SetStackLimitInThread) {
   17362   uint32_t* set_limit;
   17363   {
   17364     v8::Locker locker(CcTest::isolate());
   17365     set_limit = ComputeStackLimit(stack_breathing_room);
   17366 
   17367     // Set stack limit.
   17368     CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
   17369 
   17370     // Execute a script.
   17371     v8::HandleScope scope(CcTest::isolate());
   17372     LocalContext env;
   17373     Local<v8::FunctionTemplate> fun_templ =
   17374         v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
   17375     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   17376     CHECK(env->Global()
   17377               ->Set(env.local(), v8_str("get_stack_limit"), fun)
   17378               .FromJust());
   17379     CompileRun("get_stack_limit();");
   17380 
   17381     CHECK(stack_limit == set_limit);
   17382   }
   17383   {
   17384     v8::Locker locker(CcTest::isolate());
   17385     CHECK(stack_limit == set_limit);
   17386   }
   17387 }
   17388 
   17389 
   17390 THREADED_TEST(GetHeapStatistics) {
   17391   LocalContext c1;
   17392   v8::HandleScope scope(c1->GetIsolate());
   17393   v8::HeapStatistics heap_statistics;
   17394   CHECK_EQ(0u, heap_statistics.total_heap_size());
   17395   CHECK_EQ(0u, heap_statistics.used_heap_size());
   17396   c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
   17397   CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
   17398   CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
   17399 }
   17400 
   17401 
   17402 class VisitorImpl : public v8::ExternalResourceVisitor {
   17403  public:
   17404   explicit VisitorImpl(TestResource** resource) {
   17405     for (int i = 0; i < 4; i++) {
   17406       resource_[i] = resource[i];
   17407       found_resource_[i] = false;
   17408     }
   17409   }
   17410   virtual ~VisitorImpl() {}
   17411   virtual void VisitExternalString(v8::Local<v8::String> string) {
   17412     if (!string->IsExternal()) {
   17413       CHECK(string->IsExternalOneByte());
   17414       return;
   17415     }
   17416     v8::String::ExternalStringResource* resource =
   17417         string->GetExternalStringResource();
   17418     CHECK(resource);
   17419     for (int i = 0; i < 4; i++) {
   17420       if (resource_[i] == resource) {
   17421         CHECK(!found_resource_[i]);
   17422         found_resource_[i] = true;
   17423       }
   17424     }
   17425   }
   17426   void CheckVisitedResources() {
   17427     for (int i = 0; i < 4; i++) {
   17428       CHECK(found_resource_[i]);
   17429     }
   17430   }
   17431 
   17432  private:
   17433   v8::String::ExternalStringResource* resource_[4];
   17434   bool found_resource_[4];
   17435 };
   17436 
   17437 
   17438 TEST(ExternalizeOldSpaceTwoByteCons) {
   17439   v8::Isolate* isolate = CcTest::isolate();
   17440   LocalContext env;
   17441   v8::HandleScope scope(isolate);
   17442   v8::Local<v8::String> cons =
   17443       CompileRun("'Romeo Montague ' + 'Juliet Capulet'")
   17444           ->ToString(env.local())
   17445           .ToLocalChecked();
   17446   CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
   17447   CcTest::heap()->CollectAllAvailableGarbage();
   17448   CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
   17449 
   17450   TestResource* resource = new TestResource(
   17451       AsciiToTwoByteString("Romeo Montague Juliet Capulet"));
   17452   cons->MakeExternal(resource);
   17453 
   17454   CHECK(cons->IsExternal());
   17455   CHECK_EQ(resource, cons->GetExternalStringResource());
   17456   String::Encoding encoding;
   17457   CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
   17458   CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
   17459 }
   17460 
   17461 
   17462 TEST(ExternalizeOldSpaceOneByteCons) {
   17463   v8::Isolate* isolate = CcTest::isolate();
   17464   LocalContext env;
   17465   v8::HandleScope scope(isolate);
   17466   v8::Local<v8::String> cons =
   17467       CompileRun("'Romeo Montague ' + 'Juliet Capulet'")
   17468           ->ToString(env.local())
   17469           .ToLocalChecked();
   17470   CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
   17471   CcTest::heap()->CollectAllAvailableGarbage();
   17472   CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
   17473 
   17474   TestOneByteResource* resource =
   17475       new TestOneByteResource(i::StrDup("Romeo Montague Juliet Capulet"));
   17476   cons->MakeExternal(resource);
   17477 
   17478   CHECK(cons->IsExternalOneByte());
   17479   CHECK_EQ(resource, cons->GetExternalOneByteStringResource());
   17480   String::Encoding encoding;
   17481   CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
   17482   CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
   17483 }
   17484 
   17485 
   17486 TEST(VisitExternalStrings) {
   17487   v8::Isolate* isolate = CcTest::isolate();
   17488   LocalContext env;
   17489   v8::HandleScope scope(isolate);
   17490   const char* string = "Some string";
   17491   uint16_t* two_byte_string = AsciiToTwoByteString(string);
   17492   TestResource* resource[4];
   17493   resource[0] = new TestResource(two_byte_string);
   17494   v8::Local<v8::String> string0 =
   17495       v8::String::NewExternalTwoByte(env->GetIsolate(), resource[0])
   17496           .ToLocalChecked();
   17497   resource[1] = new TestResource(two_byte_string, NULL, false);
   17498   v8::Local<v8::String> string1 =
   17499       v8::String::NewExternalTwoByte(env->GetIsolate(), resource[1])
   17500           .ToLocalChecked();
   17501 
   17502   // Externalized symbol.
   17503   resource[2] = new TestResource(two_byte_string, NULL, false);
   17504   v8::Local<v8::String> string2 =
   17505       v8::String::NewFromUtf8(env->GetIsolate(), string,
   17506                               v8::NewStringType::kInternalized)
   17507           .ToLocalChecked();
   17508   CHECK(string2->MakeExternal(resource[2]));
   17509 
   17510   // Symbolized External.
   17511   resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
   17512   v8::Local<v8::String> string3 =
   17513       v8::String::NewExternalTwoByte(env->GetIsolate(), resource[3])
   17514           .ToLocalChecked();
   17515   CcTest::heap()->CollectAllAvailableGarbage();  // Tenure string.
   17516   // Turn into a symbol.
   17517   i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
   17518   CHECK(!CcTest::i_isolate()->factory()->InternalizeString(
   17519       string3_i).is_null());
   17520   CHECK(string3_i->IsInternalizedString());
   17521 
   17522   // We need to add usages for string* to avoid warnings in GCC 4.7
   17523   CHECK(string0->IsExternal());
   17524   CHECK(string1->IsExternal());
   17525   CHECK(string2->IsExternal());
   17526   CHECK(string3->IsExternal());
   17527 
   17528   VisitorImpl visitor(resource);
   17529   isolate->VisitExternalResources(&visitor);
   17530   visitor.CheckVisitedResources();
   17531 }
   17532 
   17533 
   17534 TEST(ExternalStringCollectedAtTearDown) {
   17535   int destroyed = 0;
   17536   v8::Isolate::CreateParams create_params;
   17537   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   17538   v8::Isolate* isolate = v8::Isolate::New(create_params);
   17539   { v8::Isolate::Scope isolate_scope(isolate);
   17540     v8::HandleScope handle_scope(isolate);
   17541     const char* s = "One string to test them all, one string to find them.";
   17542     TestOneByteResource* inscription =
   17543         new TestOneByteResource(i::StrDup(s), &destroyed);
   17544     v8::Local<v8::String> ring =
   17545         v8::String::NewExternalOneByte(isolate, inscription).ToLocalChecked();
   17546     // Ring is still alive.  Orcs are roaming freely across our lands.
   17547     CHECK_EQ(0, destroyed);
   17548     USE(ring);
   17549   }
   17550 
   17551   isolate->Dispose();
   17552   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
   17553   CHECK_EQ(1, destroyed);
   17554 }
   17555 
   17556 
   17557 TEST(ExternalInternalizedStringCollectedAtTearDown) {
   17558   int destroyed = 0;
   17559   v8::Isolate::CreateParams create_params;
   17560   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   17561   v8::Isolate* isolate = v8::Isolate::New(create_params);
   17562   { v8::Isolate::Scope isolate_scope(isolate);
   17563     LocalContext env(isolate);
   17564     v8::HandleScope handle_scope(isolate);
   17565     CompileRun("var ring = 'One string to test them all';");
   17566     const char* s = "One string to test them all";
   17567     TestOneByteResource* inscription =
   17568         new TestOneByteResource(i::StrDup(s), &destroyed);
   17569     v8::Local<v8::String> ring =
   17570         CompileRun("ring")->ToString(env.local()).ToLocalChecked();
   17571     CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
   17572     ring->MakeExternal(inscription);
   17573     // Ring is still alive.  Orcs are roaming freely across our lands.
   17574     CHECK_EQ(0, destroyed);
   17575     USE(ring);
   17576   }
   17577 
   17578   isolate->Dispose();
   17579   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
   17580   CHECK_EQ(1, destroyed);
   17581 }
   17582 
   17583 
   17584 TEST(ExternalInternalizedStringCollectedAtGC) {
   17585   int destroyed = 0;
   17586   { LocalContext env;
   17587     v8::HandleScope handle_scope(env->GetIsolate());
   17588     CompileRun("var ring = 'One string to test them all';");
   17589     const char* s = "One string to test them all";
   17590     TestOneByteResource* inscription =
   17591         new TestOneByteResource(i::StrDup(s), &destroyed);
   17592     v8::Local<v8::String> ring = CompileRun("ring").As<v8::String>();
   17593     CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
   17594     ring->MakeExternal(inscription);
   17595     // Ring is still alive.  Orcs are roaming freely across our lands.
   17596     CHECK_EQ(0, destroyed);
   17597     USE(ring);
   17598   }
   17599 
   17600   // Garbage collector deals swift blows to evil.
   17601   CcTest::i_isolate()->compilation_cache()->Clear();
   17602   CcTest::heap()->CollectAllAvailableGarbage();
   17603 
   17604   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
   17605   CHECK_EQ(1, destroyed);
   17606 }
   17607 
   17608 
   17609 static double DoubleFromBits(uint64_t value) {
   17610   double target;
   17611   i::MemCopy(&target, &value, sizeof(target));
   17612   return target;
   17613 }
   17614 
   17615 
   17616 static uint64_t DoubleToBits(double value) {
   17617   uint64_t target;
   17618   i::MemCopy(&target, &value, sizeof(target));
   17619   return target;
   17620 }
   17621 
   17622 
   17623 static double DoubleToDateTime(double input) {
   17624   double date_limit = 864e13;
   17625   if (std::isnan(input) || input < -date_limit || input > date_limit) {
   17626     return std::numeric_limits<double>::quiet_NaN();
   17627   }
   17628   return (input < 0) ? -(std::floor(-input)) : std::floor(input);
   17629 }
   17630 
   17631 
   17632 // We don't have a consistent way to write 64-bit constants syntactically, so we
   17633 // split them into two 32-bit constants and combine them programmatically.
   17634 static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
   17635   return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
   17636 }
   17637 
   17638 
   17639 THREADED_TEST(QuietSignalingNaNs) {
   17640   LocalContext context;
   17641   v8::Isolate* isolate = context->GetIsolate();
   17642   v8::HandleScope scope(isolate);
   17643   v8::TryCatch try_catch(isolate);
   17644 
   17645   // Special double values.
   17646   double snan = DoubleFromBits(0x7ff00000, 0x00000001);
   17647   double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
   17648   double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
   17649   double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
   17650   double min_normal = DoubleFromBits(0x00100000, 0x00000000);
   17651   double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
   17652   double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
   17653 
   17654   // Date values are capped at +/-100000000 days (times 864e5 ms per day)
   17655   // on either side of the epoch.
   17656   double date_limit = 864e13;
   17657 
   17658   double test_values[] = {
   17659       snan,
   17660       qnan,
   17661       infinity,
   17662       max_normal,
   17663       date_limit + 1,
   17664       date_limit,
   17665       min_normal,
   17666       max_denormal,
   17667       min_denormal,
   17668       0,
   17669       -0,
   17670       -min_denormal,
   17671       -max_denormal,
   17672       -min_normal,
   17673       -date_limit,
   17674       -date_limit - 1,
   17675       -max_normal,
   17676       -infinity,
   17677       -qnan,
   17678       -snan
   17679   };
   17680   int num_test_values = 20;
   17681 
   17682   for (int i = 0; i < num_test_values; i++) {
   17683     double test_value = test_values[i];
   17684 
   17685     // Check that Number::New preserves non-NaNs and quiets SNaNs.
   17686     v8::Local<v8::Value> number = v8::Number::New(isolate, test_value);
   17687     double stored_number = number->NumberValue(context.local()).FromJust();
   17688     if (!std::isnan(test_value)) {
   17689       CHECK_EQ(test_value, stored_number);
   17690     } else {
   17691       uint64_t stored_bits = DoubleToBits(stored_number);
   17692       // Check if quiet nan (bits 51..62 all set).
   17693 #if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
   17694     !defined(_MIPS_ARCH_MIPS64R6) && !defined(_MIPS_ARCH_MIPS32R6) &&   \
   17695     !defined(USE_SIMULATOR)
   17696       // Most significant fraction bit for quiet nan is set to 0
   17697       // on MIPS architecture. Allowed by IEEE-754.
   17698       CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
   17699 #else
   17700       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
   17701 #endif
   17702     }
   17703 
   17704     // Check that Date::New preserves non-NaNs in the date range and
   17705     // quiets SNaNs.
   17706     v8::Local<v8::Value> date =
   17707         v8::Date::New(context.local(), test_value).ToLocalChecked();
   17708     double expected_stored_date = DoubleToDateTime(test_value);
   17709     double stored_date = date->NumberValue(context.local()).FromJust();
   17710     if (!std::isnan(expected_stored_date)) {
   17711       CHECK_EQ(expected_stored_date, stored_date);
   17712     } else {
   17713       uint64_t stored_bits = DoubleToBits(stored_date);
   17714       // Check if quiet nan (bits 51..62 all set).
   17715 #if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
   17716     !defined(_MIPS_ARCH_MIPS64R6) && !defined(_MIPS_ARCH_MIPS32R6) &&   \
   17717     !defined(USE_SIMULATOR)
   17718       // Most significant fraction bit for quiet nan is set to 0
   17719       // on MIPS architecture. Allowed by IEEE-754.
   17720       CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
   17721 #else
   17722       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
   17723 #endif
   17724     }
   17725   }
   17726 }
   17727 
   17728 
   17729 static void SpaghettiIncident(
   17730     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17731   v8::HandleScope scope(args.GetIsolate());
   17732   v8::TryCatch tc(args.GetIsolate());
   17733   v8::MaybeLocal<v8::String> str(
   17734       args[0]->ToString(args.GetIsolate()->GetCurrentContext()));
   17735   USE(str);
   17736   if (tc.HasCaught())
   17737     tc.ReThrow();
   17738 }
   17739 
   17740 
   17741 // Test that an exception can be propagated down through a spaghetti
   17742 // stack using ReThrow.
   17743 THREADED_TEST(SpaghettiStackReThrow) {
   17744   v8::Isolate* isolate = CcTest::isolate();
   17745   v8::HandleScope scope(isolate);
   17746   LocalContext context;
   17747   context->Global()
   17748       ->Set(context.local(), v8_str("s"),
   17749             v8::FunctionTemplate::New(isolate, SpaghettiIncident)
   17750                 ->GetFunction(context.local())
   17751                 .ToLocalChecked())
   17752       .FromJust();
   17753   v8::TryCatch try_catch(isolate);
   17754   CompileRun(
   17755       "var i = 0;"
   17756       "var o = {"
   17757       "  toString: function () {"
   17758       "    if (i == 10) {"
   17759       "      throw 'Hey!';"
   17760       "    } else {"
   17761       "      i++;"
   17762       "      return s(o);"
   17763       "    }"
   17764       "  }"
   17765       "};"
   17766       "s(o);");
   17767   CHECK(try_catch.HasCaught());
   17768   v8::String::Utf8Value value(try_catch.Exception());
   17769   CHECK_EQ(0, strcmp(*value, "Hey!"));
   17770 }
   17771 
   17772 
   17773 TEST(Regress528) {
   17774   v8::V8::Initialize();
   17775   v8::Isolate* isolate = CcTest::isolate();
   17776   i::FLAG_retain_maps_for_n_gc = 0;
   17777   v8::HandleScope scope(isolate);
   17778   v8::Local<Context> other_context;
   17779   int gc_count;
   17780 
   17781   // Create a context used to keep the code from aging in the compilation
   17782   // cache.
   17783   other_context = Context::New(isolate);
   17784 
   17785   // Context-dependent context data creates reference from the compilation
   17786   // cache to the global object.
   17787   const char* source_simple = "1";
   17788   {
   17789     v8::HandleScope scope(isolate);
   17790     v8::Local<Context> context = Context::New(isolate);
   17791 
   17792     context->Enter();
   17793     Local<v8::String> obj = v8_str("");
   17794     context->SetEmbedderData(0, obj);
   17795     CompileRun(source_simple);
   17796     context->Exit();
   17797   }
   17798   isolate->ContextDisposedNotification();
   17799   for (gc_count = 1; gc_count < 10; gc_count++) {
   17800     other_context->Enter();
   17801     CompileRun(source_simple);
   17802     other_context->Exit();
   17803     CcTest::heap()->CollectAllGarbage();
   17804     if (GetGlobalObjectsCount() == 1) break;
   17805   }
   17806   CHECK_GE(2, gc_count);
   17807   CHECK_EQ(1, GetGlobalObjectsCount());
   17808 
   17809   // Eval in a function creates reference from the compilation cache to the
   17810   // global object.
   17811   const char* source_eval = "function f(){eval('1')}; f()";
   17812   {
   17813     v8::HandleScope scope(isolate);
   17814     v8::Local<Context> context = Context::New(isolate);
   17815 
   17816     context->Enter();
   17817     CompileRun(source_eval);
   17818     context->Exit();
   17819   }
   17820   isolate->ContextDisposedNotification();
   17821   for (gc_count = 1; gc_count < 10; gc_count++) {
   17822     other_context->Enter();
   17823     CompileRun(source_eval);
   17824     other_context->Exit();
   17825     CcTest::heap()->CollectAllGarbage();
   17826     if (GetGlobalObjectsCount() == 1) break;
   17827   }
   17828   CHECK_GE(2, gc_count);
   17829   CHECK_EQ(1, GetGlobalObjectsCount());
   17830 
   17831   // Looking up the line number for an exception creates reference from the
   17832   // compilation cache to the global object.
   17833   const char* source_exception = "function f(){throw 1;} f()";
   17834   {
   17835     v8::HandleScope scope(isolate);
   17836     v8::Local<Context> context = Context::New(isolate);
   17837 
   17838     context->Enter();
   17839     v8::TryCatch try_catch(isolate);
   17840     CompileRun(source_exception);
   17841     CHECK(try_catch.HasCaught());
   17842     v8::Local<v8::Message> message = try_catch.Message();
   17843     CHECK(!message.IsEmpty());
   17844     CHECK_EQ(1, message->GetLineNumber(context).FromJust());
   17845     context->Exit();
   17846   }
   17847   isolate->ContextDisposedNotification();
   17848   for (gc_count = 1; gc_count < 10; gc_count++) {
   17849     other_context->Enter();
   17850     CompileRun(source_exception);
   17851     other_context->Exit();
   17852     CcTest::heap()->CollectAllGarbage();
   17853     if (GetGlobalObjectsCount() == 1) break;
   17854   }
   17855   CHECK_GE(2, gc_count);
   17856   CHECK_EQ(1, GetGlobalObjectsCount());
   17857 
   17858   isolate->ContextDisposedNotification();
   17859 }
   17860 
   17861 
   17862 THREADED_TEST(ScriptOrigin) {
   17863   LocalContext env;
   17864   v8::HandleScope scope(env->GetIsolate());
   17865   v8::ScriptOrigin origin = v8::ScriptOrigin(
   17866       v8_str("test"), v8::Integer::New(env->GetIsolate(), 1),
   17867       v8::Integer::New(env->GetIsolate(), 1), v8::True(env->GetIsolate()),
   17868       v8::Local<v8::Integer>(), v8::True(env->GetIsolate()),
   17869       v8_str("http://sourceMapUrl"), v8::True(env->GetIsolate()));
   17870   v8::Local<v8::String> script = v8_str("function f() {}\n\nfunction g() {}");
   17871   v8::Script::Compile(env.local(), script, &origin)
   17872       .ToLocalChecked()
   17873       ->Run(env.local())
   17874       .ToLocalChecked();
   17875   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   17876       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   17877   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   17878       env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
   17879 
   17880   v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
   17881   CHECK_EQ(0, strcmp("test",
   17882                      *v8::String::Utf8Value(script_origin_f.ResourceName())));
   17883   CHECK_EQ(
   17884       1,
   17885       script_origin_f.ResourceLineOffset()->Int32Value(env.local()).FromJust());
   17886   CHECK(script_origin_f.Options().IsSharedCrossOrigin());
   17887   CHECK(script_origin_f.Options().IsEmbedderDebugScript());
   17888   CHECK(script_origin_f.Options().IsOpaque());
   17889   printf("is name = %d\n", script_origin_f.SourceMapUrl()->IsUndefined());
   17890 
   17891   CHECK_EQ(0, strcmp("http://sourceMapUrl",
   17892                      *v8::String::Utf8Value(script_origin_f.SourceMapUrl())));
   17893 
   17894   v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
   17895   CHECK_EQ(0, strcmp("test",
   17896                      *v8::String::Utf8Value(script_origin_g.ResourceName())));
   17897   CHECK_EQ(
   17898       1,
   17899       script_origin_g.ResourceLineOffset()->Int32Value(env.local()).FromJust());
   17900   CHECK(script_origin_g.Options().IsSharedCrossOrigin());
   17901   CHECK(script_origin_g.Options().IsEmbedderDebugScript());
   17902   CHECK(script_origin_g.Options().IsOpaque());
   17903   CHECK_EQ(0, strcmp("http://sourceMapUrl",
   17904                      *v8::String::Utf8Value(script_origin_g.SourceMapUrl())));
   17905 }
   17906 
   17907 
   17908 THREADED_TEST(FunctionGetInferredName) {
   17909   LocalContext env;
   17910   v8::HandleScope scope(env->GetIsolate());
   17911   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   17912   v8::Local<v8::String> script =
   17913       v8_str("var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
   17914   v8::Script::Compile(env.local(), script, &origin)
   17915       .ToLocalChecked()
   17916       ->Run(env.local())
   17917       .ToLocalChecked();
   17918   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   17919       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   17920   CHECK_EQ(0,
   17921            strcmp("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName())));
   17922 }
   17923 
   17924 
   17925 THREADED_TEST(FunctionGetDebugName) {
   17926   LocalContext env;
   17927   v8::HandleScope scope(env->GetIsolate());
   17928   const char* code =
   17929       "var error = false;"
   17930       "function a() { this.x = 1; };"
   17931       "a.displayName = 'display_a';"
   17932       "var b = (function() {"
   17933       "  var f = function() { this.x = 2; };"
   17934       "  f.displayName = 'display_b';"
   17935       "  return f;"
   17936       "})();"
   17937       "var c = function() {};"
   17938       "c.__defineGetter__('displayName', function() {"
   17939       "  error = true;"
   17940       "  throw new Error();"
   17941       "});"
   17942       "function d() {};"
   17943       "d.__defineGetter__('displayName', function() {"
   17944       "  error = true;"
   17945       "  return 'wrong_display_name';"
   17946       "});"
   17947       "function e() {};"
   17948       "e.displayName = 'wrong_display_name';"
   17949       "e.__defineSetter__('displayName', function() {"
   17950       "  error = true;"
   17951       "  throw new Error();"
   17952       "});"
   17953       "function f() {};"
   17954       "f.displayName = { 'foo': 6, toString: function() {"
   17955       "  error = true;"
   17956       "  return 'wrong_display_name';"
   17957       "}};"
   17958       "var g = function() {"
   17959       "  arguments.callee.displayName = 'set_in_runtime';"
   17960       "}; g();"
   17961       "var h = function() {};"
   17962       "h.displayName = 'displayName';"
   17963       "Object.defineProperty(h, 'name', { value: 'function.name' });"
   17964       "var i = function() {};"
   17965       "i.displayName = 239;"
   17966       "Object.defineProperty(i, 'name', { value: 'function.name' });"
   17967       "var j = function() {};"
   17968       "Object.defineProperty(j, 'name', { value: 'function.name' });"
   17969       "var foo = { bar : { baz : function() {}}}; var k = foo.bar.baz;";
   17970   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   17971   v8::Script::Compile(env.local(), v8_str(code), &origin)
   17972       .ToLocalChecked()
   17973       ->Run(env.local())
   17974       .ToLocalChecked();
   17975   v8::Local<v8::Value> error =
   17976       env->Global()->Get(env.local(), v8_str("error")).ToLocalChecked();
   17977   CHECK_EQ(false, error->BooleanValue(env.local()).FromJust());
   17978   const char* functions[] = {"a", "display_a",
   17979                              "b", "display_b",
   17980                              "c", "c",
   17981                              "d", "d",
   17982                              "e", "e",
   17983                              "f", "f",
   17984                              "g", "set_in_runtime",
   17985                              "h", "displayName",
   17986                              "i", "function.name",
   17987                              "j", "function.name",
   17988                              "k", "foo.bar.baz"};
   17989   for (size_t i = 0; i < sizeof(functions) / sizeof(functions[0]) / 2; ++i) {
   17990     v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   17991         env->Global()
   17992             ->Get(env.local(),
   17993                   v8::String::NewFromUtf8(env->GetIsolate(), functions[i * 2],
   17994                                           v8::NewStringType::kNormal)
   17995                       .ToLocalChecked())
   17996             .ToLocalChecked());
   17997     CHECK_EQ(0, strcmp(functions[i * 2 + 1],
   17998                        *v8::String::Utf8Value(f->GetDebugName())));
   17999   }
   18000 }
   18001 
   18002 
   18003 THREADED_TEST(FunctionGetDisplayName) {
   18004   LocalContext env;
   18005   v8::HandleScope scope(env->GetIsolate());
   18006   const char* code = "var error = false;"
   18007                      "function a() { this.x = 1; };"
   18008                      "a.displayName = 'display_a';"
   18009                      "var b = (function() {"
   18010                      "  var f = function() { this.x = 2; };"
   18011                      "  f.displayName = 'display_b';"
   18012                      "  return f;"
   18013                      "})();"
   18014                      "var c = function() {};"
   18015                      "c.__defineGetter__('displayName', function() {"
   18016                      "  error = true;"
   18017                      "  throw new Error();"
   18018                      "});"
   18019                      "function d() {};"
   18020                      "d.__defineGetter__('displayName', function() {"
   18021                      "  error = true;"
   18022                      "  return 'wrong_display_name';"
   18023                      "});"
   18024                      "function e() {};"
   18025                      "e.displayName = 'wrong_display_name';"
   18026                      "e.__defineSetter__('displayName', function() {"
   18027                      "  error = true;"
   18028                      "  throw new Error();"
   18029                      "});"
   18030                      "function f() {};"
   18031                      "f.displayName = { 'foo': 6, toString: function() {"
   18032                      "  error = true;"
   18033                      "  return 'wrong_display_name';"
   18034                      "}};"
   18035                      "var g = function() {"
   18036                      "  arguments.callee.displayName = 'set_in_runtime';"
   18037                      "}; g();";
   18038   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   18039   v8::Script::Compile(env.local(), v8_str(code), &origin)
   18040       .ToLocalChecked()
   18041       ->Run(env.local())
   18042       .ToLocalChecked();
   18043   v8::Local<v8::Value> error =
   18044       env->Global()->Get(env.local(), v8_str("error")).ToLocalChecked();
   18045   v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
   18046       env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
   18047   v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
   18048       env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
   18049   v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
   18050       env->Global()->Get(env.local(), v8_str("c")).ToLocalChecked());
   18051   v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
   18052       env->Global()->Get(env.local(), v8_str("d")).ToLocalChecked());
   18053   v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
   18054       env->Global()->Get(env.local(), v8_str("e")).ToLocalChecked());
   18055   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   18056       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   18057   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   18058       env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
   18059   CHECK_EQ(false, error->BooleanValue(env.local()).FromJust());
   18060   CHECK_EQ(0, strcmp("display_a", *v8::String::Utf8Value(a->GetDisplayName())));
   18061   CHECK_EQ(0, strcmp("display_b", *v8::String::Utf8Value(b->GetDisplayName())));
   18062   CHECK(c->GetDisplayName()->IsUndefined());
   18063   CHECK(d->GetDisplayName()->IsUndefined());
   18064   CHECK(e->GetDisplayName()->IsUndefined());
   18065   CHECK(f->GetDisplayName()->IsUndefined());
   18066   CHECK_EQ(
   18067       0, strcmp("set_in_runtime", *v8::String::Utf8Value(g->GetDisplayName())));
   18068 }
   18069 
   18070 
   18071 THREADED_TEST(ScriptLineNumber) {
   18072   LocalContext env;
   18073   v8::HandleScope scope(env->GetIsolate());
   18074   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   18075   v8::Local<v8::String> script = v8_str("function f() {}\n\nfunction g() {}");
   18076   v8::Script::Compile(env.local(), script, &origin)
   18077       .ToLocalChecked()
   18078       ->Run(env.local())
   18079       .ToLocalChecked();
   18080   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   18081       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   18082   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   18083       env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
   18084   CHECK_EQ(0, f->GetScriptLineNumber());
   18085   CHECK_EQ(2, g->GetScriptLineNumber());
   18086 }
   18087 
   18088 
   18089 THREADED_TEST(ScriptColumnNumber) {
   18090   LocalContext env;
   18091   v8::Isolate* isolate = env->GetIsolate();
   18092   v8::HandleScope scope(isolate);
   18093   v8::ScriptOrigin origin =
   18094       v8::ScriptOrigin(v8_str("test"), v8::Integer::New(isolate, 3),
   18095                        v8::Integer::New(isolate, 2));
   18096   v8::Local<v8::String> script =
   18097       v8_str("function foo() {}\n\n     function bar() {}");
   18098   v8::Script::Compile(env.local(), script, &origin)
   18099       .ToLocalChecked()
   18100       ->Run(env.local())
   18101       .ToLocalChecked();
   18102   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   18103       env->Global()->Get(env.local(), v8_str("foo")).ToLocalChecked());
   18104   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
   18105       env->Global()->Get(env.local(), v8_str("bar")).ToLocalChecked());
   18106   CHECK_EQ(14, foo->GetScriptColumnNumber());
   18107   CHECK_EQ(17, bar->GetScriptColumnNumber());
   18108 }
   18109 
   18110 
   18111 THREADED_TEST(FunctionIsBuiltin) {
   18112   LocalContext env;
   18113   v8::Isolate* isolate = env->GetIsolate();
   18114   v8::HandleScope scope(isolate);
   18115   v8::Local<v8::Function> f;
   18116   f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor"));
   18117   CHECK(f->IsBuiltin());
   18118   f = v8::Local<v8::Function>::Cast(CompileRun("Object"));
   18119   CHECK(f->IsBuiltin());
   18120   f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__"));
   18121   CHECK(f->IsBuiltin());
   18122   f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString"));
   18123   CHECK(f->IsBuiltin());
   18124   f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;"));
   18125   CHECK(!f->IsBuiltin());
   18126 }
   18127 
   18128 
   18129 THREADED_TEST(FunctionGetScriptId) {
   18130   LocalContext env;
   18131   v8::Isolate* isolate = env->GetIsolate();
   18132   v8::HandleScope scope(isolate);
   18133   v8::ScriptOrigin origin =
   18134       v8::ScriptOrigin(v8_str("test"), v8::Integer::New(isolate, 3),
   18135                        v8::Integer::New(isolate, 2));
   18136   v8::Local<v8::String> scriptSource =
   18137       v8_str("function foo() {}\n\n     function bar() {}");
   18138   v8::Local<v8::Script> script(
   18139       v8::Script::Compile(env.local(), scriptSource, &origin).ToLocalChecked());
   18140   script->Run(env.local()).ToLocalChecked();
   18141   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   18142       env->Global()->Get(env.local(), v8_str("foo")).ToLocalChecked());
   18143   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
   18144       env->Global()->Get(env.local(), v8_str("bar")).ToLocalChecked());
   18145   CHECK_EQ(script->GetUnboundScript()->GetId(), foo->ScriptId());
   18146   CHECK_EQ(script->GetUnboundScript()->GetId(), bar->ScriptId());
   18147 }
   18148 
   18149 
   18150 THREADED_TEST(FunctionGetBoundFunction) {
   18151   LocalContext env;
   18152   v8::HandleScope scope(env->GetIsolate());
   18153   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   18154   v8::Local<v8::String> script = v8_str(
   18155       "var a = new Object();\n"
   18156       "a.x = 1;\n"
   18157       "function f () { return this.x };\n"
   18158       "var g = f.bind(a);\n"
   18159       "var b = g();");
   18160   v8::Script::Compile(env.local(), script, &origin)
   18161       .ToLocalChecked()
   18162       ->Run(env.local())
   18163       .ToLocalChecked();
   18164   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   18165       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   18166   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   18167       env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
   18168   CHECK(g->GetBoundFunction()->IsFunction());
   18169   Local<v8::Function> original_function = Local<v8::Function>::Cast(
   18170       g->GetBoundFunction());
   18171   CHECK(f->GetName()
   18172             ->Equals(env.local(), original_function->GetName())
   18173             .FromJust());
   18174   CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
   18175   CHECK_EQ(f->GetScriptColumnNumber(),
   18176            original_function->GetScriptColumnNumber());
   18177 }
   18178 
   18179 
   18180 static void GetterWhichReturns42(
   18181     Local<String> name,
   18182     const v8::PropertyCallbackInfo<v8::Value>& info) {
   18183   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   18184   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   18185   info.GetReturnValue().Set(v8_num(42));
   18186 }
   18187 
   18188 
   18189 static void SetterWhichSetsYOnThisTo23(
   18190     Local<String> name,
   18191     Local<Value> value,
   18192     const v8::PropertyCallbackInfo<void>& info) {
   18193   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   18194   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   18195   Local<Object>::Cast(info.This())
   18196       ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
   18197       .FromJust();
   18198 }
   18199 
   18200 
   18201 void FooGetInterceptor(Local<Name> name,
   18202                        const v8::PropertyCallbackInfo<v8::Value>& info) {
   18203   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   18204   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   18205   if (!name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   18206            .FromJust()) {
   18207     return;
   18208   }
   18209   info.GetReturnValue().Set(v8_num(42));
   18210 }
   18211 
   18212 
   18213 void FooSetInterceptor(Local<Name> name, Local<Value> value,
   18214                        const v8::PropertyCallbackInfo<v8::Value>& info) {
   18215   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   18216   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   18217   if (!name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   18218            .FromJust()) {
   18219     return;
   18220   }
   18221   Local<Object>::Cast(info.This())
   18222       ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
   18223       .FromJust();
   18224   info.GetReturnValue().Set(v8_num(23));
   18225 }
   18226 
   18227 
   18228 TEST(SetterOnConstructorPrototype) {
   18229   v8::Isolate* isolate = CcTest::isolate();
   18230   v8::HandleScope scope(isolate);
   18231   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   18232   templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
   18233                      SetterWhichSetsYOnThisTo23);
   18234   LocalContext context;
   18235   CHECK(context->Global()
   18236             ->Set(context.local(), v8_str("P"),
   18237                   templ->NewInstance(context.local()).ToLocalChecked())
   18238             .FromJust());
   18239   CompileRun("function C1() {"
   18240              "  this.x = 23;"
   18241              "};"
   18242              "C1.prototype = P;"
   18243              "function C2() {"
   18244              "  this.x = 23"
   18245              "};"
   18246              "C2.prototype = { };"
   18247              "C2.prototype.__proto__ = P;");
   18248 
   18249   v8::Local<v8::Script> script;
   18250   script = v8_compile("new C1();");
   18251   for (int i = 0; i < 10; i++) {
   18252     v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
   18253         script->Run(context.local()).ToLocalChecked());
   18254     CHECK_EQ(42, c1->Get(context.local(), v8_str("x"))
   18255                      .ToLocalChecked()
   18256                      ->Int32Value(context.local())
   18257                      .FromJust());
   18258     CHECK_EQ(23, c1->Get(context.local(), v8_str("y"))
   18259                      .ToLocalChecked()
   18260                      ->Int32Value(context.local())
   18261                      .FromJust());
   18262   }
   18263 
   18264   script = v8_compile("new C2();");
   18265   for (int i = 0; i < 10; i++) {
   18266     v8::Local<v8::Object> c2 = v8::Local<v8::Object>::Cast(
   18267         script->Run(context.local()).ToLocalChecked());
   18268     CHECK_EQ(42, c2->Get(context.local(), v8_str("x"))
   18269                      .ToLocalChecked()
   18270                      ->Int32Value(context.local())
   18271                      .FromJust());
   18272     CHECK_EQ(23, c2->Get(context.local(), v8_str("y"))
   18273                      .ToLocalChecked()
   18274                      ->Int32Value(context.local())
   18275                      .FromJust());
   18276   }
   18277 }
   18278 
   18279 
   18280 static void NamedPropertyGetterWhichReturns42(
   18281     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   18282   info.GetReturnValue().Set(v8_num(42));
   18283 }
   18284 
   18285 
   18286 static void NamedPropertySetterWhichSetsYOnThisTo23(
   18287     Local<Name> name, Local<Value> value,
   18288     const v8::PropertyCallbackInfo<v8::Value>& info) {
   18289   if (name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("x"))
   18290           .FromJust()) {
   18291     Local<Object>::Cast(info.This())
   18292         ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
   18293         .FromJust();
   18294   }
   18295 }
   18296 
   18297 
   18298 THREADED_TEST(InterceptorOnConstructorPrototype) {
   18299   v8::Isolate* isolate = CcTest::isolate();
   18300   v8::HandleScope scope(isolate);
   18301   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   18302   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   18303       NamedPropertyGetterWhichReturns42,
   18304       NamedPropertySetterWhichSetsYOnThisTo23));
   18305   LocalContext context;
   18306   CHECK(context->Global()
   18307             ->Set(context.local(), v8_str("P"),
   18308                   templ->NewInstance(context.local()).ToLocalChecked())
   18309             .FromJust());
   18310   CompileRun("function C1() {"
   18311              "  this.x = 23;"
   18312              "};"
   18313              "C1.prototype = P;"
   18314              "function C2() {"
   18315              "  this.x = 23"
   18316              "};"
   18317              "C2.prototype = { };"
   18318              "C2.prototype.__proto__ = P;");
   18319 
   18320   v8::Local<v8::Script> script;
   18321   script = v8_compile("new C1();");
   18322   for (int i = 0; i < 10; i++) {
   18323     v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
   18324         script->Run(context.local()).ToLocalChecked());
   18325     CHECK_EQ(23, c1->Get(context.local(), v8_str("x"))
   18326                      .ToLocalChecked()
   18327                      ->Int32Value(context.local())
   18328                      .FromJust());
   18329     CHECK_EQ(42, c1->Get(context.local(), v8_str("y"))
   18330                      .ToLocalChecked()
   18331                      ->Int32Value(context.local())
   18332                      .FromJust());
   18333   }
   18334 
   18335   script = v8_compile("new C2();");
   18336   for (int i = 0; i < 10; i++) {
   18337     v8::Local<v8::Object> c2 = v8::Local<v8::Object>::Cast(
   18338         script->Run(context.local()).ToLocalChecked());
   18339     CHECK_EQ(23, c2->Get(context.local(), v8_str("x"))
   18340                      .ToLocalChecked()
   18341                      ->Int32Value(context.local())
   18342                      .FromJust());
   18343     CHECK_EQ(42, c2->Get(context.local(), v8_str("y"))
   18344                      .ToLocalChecked()
   18345                      ->Int32Value(context.local())
   18346                      .FromJust());
   18347   }
   18348 }
   18349 
   18350 
   18351 TEST(Regress618) {
   18352   const char* source = "function C1() {"
   18353                        "  this.x = 23;"
   18354                        "};"
   18355                        "C1.prototype = P;";
   18356 
   18357   LocalContext context;
   18358   v8::Isolate* isolate = context->GetIsolate();
   18359   v8::HandleScope scope(isolate);
   18360   v8::Local<v8::Script> script;
   18361 
   18362   // Use a simple object as prototype.
   18363   v8::Local<v8::Object> prototype = v8::Object::New(isolate);
   18364   prototype->Set(context.local(), v8_str("y"), v8_num(42)).FromJust();
   18365   CHECK(context->Global()
   18366             ->Set(context.local(), v8_str("P"), prototype)
   18367             .FromJust());
   18368 
   18369   // This compile will add the code to the compilation cache.
   18370   CompileRun(source);
   18371 
   18372   script = v8_compile("new C1();");
   18373   // Allow enough iterations for the inobject slack tracking logic
   18374   // to finalize instance size and install the fast construct stub.
   18375   for (int i = 0; i < 256; i++) {
   18376     v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
   18377         script->Run(context.local()).ToLocalChecked());
   18378     CHECK_EQ(23, c1->Get(context.local(), v8_str("x"))
   18379                      .ToLocalChecked()
   18380                      ->Int32Value(context.local())
   18381                      .FromJust());
   18382     CHECK_EQ(42, c1->Get(context.local(), v8_str("y"))
   18383                      .ToLocalChecked()
   18384                      ->Int32Value(context.local())
   18385                      .FromJust());
   18386   }
   18387 
   18388   // Use an API object with accessors as prototype.
   18389   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   18390   templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
   18391                      SetterWhichSetsYOnThisTo23);
   18392   CHECK(context->Global()
   18393             ->Set(context.local(), v8_str("P"),
   18394                   templ->NewInstance(context.local()).ToLocalChecked())
   18395             .FromJust());
   18396 
   18397   // This compile will get the code from the compilation cache.
   18398   CompileRun(source);
   18399 
   18400   script = v8_compile("new C1();");
   18401   for (int i = 0; i < 10; i++) {
   18402     v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
   18403         script->Run(context.local()).ToLocalChecked());
   18404     CHECK_EQ(42, c1->Get(context.local(), v8_str("x"))
   18405                      .ToLocalChecked()
   18406                      ->Int32Value(context.local())
   18407                      .FromJust());
   18408     CHECK_EQ(23, c1->Get(context.local(), v8_str("y"))
   18409                      .ToLocalChecked()
   18410                      ->Int32Value(context.local())
   18411                      .FromJust());
   18412   }
   18413 }
   18414 
   18415 v8::Isolate* gc_callbacks_isolate = NULL;
   18416 int prologue_call_count = 0;
   18417 int epilogue_call_count = 0;
   18418 int prologue_call_count_second = 0;
   18419 int epilogue_call_count_second = 0;
   18420 int prologue_call_count_alloc = 0;
   18421 int epilogue_call_count_alloc = 0;
   18422 
   18423 void PrologueCallback(v8::Isolate* isolate,
   18424                       v8::GCType,
   18425                       v8::GCCallbackFlags flags) {
   18426   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   18427   CHECK_EQ(gc_callbacks_isolate, isolate);
   18428   ++prologue_call_count;
   18429 }
   18430 
   18431 void EpilogueCallback(v8::Isolate* isolate,
   18432                       v8::GCType,
   18433                       v8::GCCallbackFlags flags) {
   18434   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   18435   CHECK_EQ(gc_callbacks_isolate, isolate);
   18436   ++epilogue_call_count;
   18437 }
   18438 
   18439 
   18440 void PrologueCallbackSecond(v8::Isolate* isolate,
   18441                             v8::GCType,
   18442                             v8::GCCallbackFlags flags) {
   18443   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   18444   CHECK_EQ(gc_callbacks_isolate, isolate);
   18445   ++prologue_call_count_second;
   18446 }
   18447 
   18448 
   18449 void EpilogueCallbackSecond(v8::Isolate* isolate,
   18450                             v8::GCType,
   18451                             v8::GCCallbackFlags flags) {
   18452   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   18453   CHECK_EQ(gc_callbacks_isolate, isolate);
   18454   ++epilogue_call_count_second;
   18455 }
   18456 
   18457 
   18458 void PrologueCallbackAlloc(v8::Isolate* isolate,
   18459                            v8::GCType,
   18460                            v8::GCCallbackFlags flags) {
   18461   v8::HandleScope scope(isolate);
   18462 
   18463   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   18464   CHECK_EQ(gc_callbacks_isolate, isolate);
   18465   ++prologue_call_count_alloc;
   18466 
   18467   // Simulate full heap to see if we will reenter this callback
   18468   SimulateFullSpace(CcTest::heap()->new_space());
   18469 
   18470   Local<Object> obj = Object::New(isolate);
   18471   CHECK(!obj.IsEmpty());
   18472 
   18473   CcTest::heap()->CollectAllGarbage(
   18474       i::Heap::kAbortIncrementalMarkingMask);
   18475 }
   18476 
   18477 
   18478 void EpilogueCallbackAlloc(v8::Isolate* isolate,
   18479                            v8::GCType,
   18480                            v8::GCCallbackFlags flags) {
   18481   v8::HandleScope scope(isolate);
   18482 
   18483   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   18484   CHECK_EQ(gc_callbacks_isolate, isolate);
   18485   ++epilogue_call_count_alloc;
   18486 
   18487   // Simulate full heap to see if we will reenter this callback
   18488   SimulateFullSpace(CcTest::heap()->new_space());
   18489 
   18490   Local<Object> obj = Object::New(isolate);
   18491   CHECK(!obj.IsEmpty());
   18492 
   18493   CcTest::heap()->CollectAllGarbage(
   18494       i::Heap::kAbortIncrementalMarkingMask);
   18495 }
   18496 
   18497 
   18498 TEST(GCCallbacksOld) {
   18499   LocalContext context;
   18500 
   18501   gc_callbacks_isolate = context->GetIsolate();
   18502 
   18503   context->GetIsolate()->AddGCPrologueCallback(PrologueCallback);
   18504   context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallback);
   18505   CHECK_EQ(0, prologue_call_count);
   18506   CHECK_EQ(0, epilogue_call_count);
   18507   CcTest::heap()->CollectAllGarbage();
   18508   CHECK_EQ(1, prologue_call_count);
   18509   CHECK_EQ(1, epilogue_call_count);
   18510   context->GetIsolate()->AddGCPrologueCallback(PrologueCallbackSecond);
   18511   context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallbackSecond);
   18512   CcTest::heap()->CollectAllGarbage();
   18513   CHECK_EQ(2, prologue_call_count);
   18514   CHECK_EQ(2, epilogue_call_count);
   18515   CHECK_EQ(1, prologue_call_count_second);
   18516   CHECK_EQ(1, epilogue_call_count_second);
   18517   context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallback);
   18518   context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallback);
   18519   CcTest::heap()->CollectAllGarbage();
   18520   CHECK_EQ(2, prologue_call_count);
   18521   CHECK_EQ(2, epilogue_call_count);
   18522   CHECK_EQ(2, prologue_call_count_second);
   18523   CHECK_EQ(2, epilogue_call_count_second);
   18524   context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallbackSecond);
   18525   context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
   18526   CcTest::heap()->CollectAllGarbage();
   18527   CHECK_EQ(2, prologue_call_count);
   18528   CHECK_EQ(2, epilogue_call_count);
   18529   CHECK_EQ(2, prologue_call_count_second);
   18530   CHECK_EQ(2, epilogue_call_count_second);
   18531 }
   18532 
   18533 
   18534 TEST(GCCallbacks) {
   18535   LocalContext context;
   18536   v8::Isolate* isolate = context->GetIsolate();
   18537   gc_callbacks_isolate = isolate;
   18538   isolate->AddGCPrologueCallback(PrologueCallback);
   18539   isolate->AddGCEpilogueCallback(EpilogueCallback);
   18540   CHECK_EQ(0, prologue_call_count);
   18541   CHECK_EQ(0, epilogue_call_count);
   18542   CcTest::heap()->CollectAllGarbage();
   18543   CHECK_EQ(1, prologue_call_count);
   18544   CHECK_EQ(1, epilogue_call_count);
   18545   isolate->AddGCPrologueCallback(PrologueCallbackSecond);
   18546   isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
   18547   CcTest::heap()->CollectAllGarbage();
   18548   CHECK_EQ(2, prologue_call_count);
   18549   CHECK_EQ(2, epilogue_call_count);
   18550   CHECK_EQ(1, prologue_call_count_second);
   18551   CHECK_EQ(1, epilogue_call_count_second);
   18552   isolate->RemoveGCPrologueCallback(PrologueCallback);
   18553   isolate->RemoveGCEpilogueCallback(EpilogueCallback);
   18554   CcTest::heap()->CollectAllGarbage();
   18555   CHECK_EQ(2, prologue_call_count);
   18556   CHECK_EQ(2, epilogue_call_count);
   18557   CHECK_EQ(2, prologue_call_count_second);
   18558   CHECK_EQ(2, epilogue_call_count_second);
   18559   isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
   18560   isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
   18561   CcTest::heap()->CollectAllGarbage();
   18562   CHECK_EQ(2, prologue_call_count);
   18563   CHECK_EQ(2, epilogue_call_count);
   18564   CHECK_EQ(2, prologue_call_count_second);
   18565   CHECK_EQ(2, epilogue_call_count_second);
   18566 
   18567   CHECK_EQ(0, prologue_call_count_alloc);
   18568   CHECK_EQ(0, epilogue_call_count_alloc);
   18569   isolate->AddGCPrologueCallback(PrologueCallbackAlloc);
   18570   isolate->AddGCEpilogueCallback(EpilogueCallbackAlloc);
   18571   CcTest::heap()->CollectAllGarbage(
   18572       i::Heap::kAbortIncrementalMarkingMask);
   18573   CHECK_EQ(1, prologue_call_count_alloc);
   18574   CHECK_EQ(1, epilogue_call_count_alloc);
   18575   isolate->RemoveGCPrologueCallback(PrologueCallbackAlloc);
   18576   isolate->RemoveGCEpilogueCallback(EpilogueCallbackAlloc);
   18577 }
   18578 
   18579 
   18580 THREADED_TEST(TwoByteStringInOneByteCons) {
   18581   // See Chromium issue 47824.
   18582   LocalContext context;
   18583   v8::HandleScope scope(context->GetIsolate());
   18584 
   18585   const char* init_code =
   18586       "var str1 = 'abelspendabel';"
   18587       "var str2 = str1 + str1 + str1;"
   18588       "str2;";
   18589   Local<Value> result = CompileRun(init_code);
   18590 
   18591   Local<Value> indexof = CompileRun("str2.indexOf('els')");
   18592   Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
   18593 
   18594   CHECK(result->IsString());
   18595   i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
   18596   int length = string->length();
   18597   CHECK(string->IsOneByteRepresentation());
   18598 
   18599   i::Handle<i::String> flat_string = i::String::Flatten(string);
   18600 
   18601   CHECK(string->IsOneByteRepresentation());
   18602   CHECK(flat_string->IsOneByteRepresentation());
   18603 
   18604   // Create external resource.
   18605   uint16_t* uc16_buffer = new uint16_t[length + 1];
   18606 
   18607   i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
   18608   uc16_buffer[length] = 0;
   18609 
   18610   TestResource resource(uc16_buffer);
   18611 
   18612   flat_string->MakeExternal(&resource);
   18613 
   18614   CHECK(flat_string->IsTwoByteRepresentation());
   18615 
   18616   // If the cons string has been short-circuited, skip the following checks.
   18617   if (!string.is_identical_to(flat_string)) {
   18618     // At this point, we should have a Cons string which is flat and one-byte,
   18619     // with a first half that is a two-byte string (although it only contains
   18620     // one-byte characters). This is a valid sequence of steps, and it can
   18621     // happen in real pages.
   18622     CHECK(string->IsOneByteRepresentation());
   18623     i::ConsString* cons = i::ConsString::cast(*string);
   18624     CHECK_EQ(0, cons->second()->length());
   18625     CHECK(cons->first()->IsTwoByteRepresentation());
   18626   }
   18627 
   18628   // Check that some string operations work.
   18629 
   18630   // Atom RegExp.
   18631   Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
   18632   CHECK_EQ(6, reresult->Int32Value(context.local()).FromJust());
   18633 
   18634   // Nonatom RegExp.
   18635   reresult = CompileRun("str2.match(/abe./g).length;");
   18636   CHECK_EQ(6, reresult->Int32Value(context.local()).FromJust());
   18637 
   18638   reresult = CompileRun("str2.search(/bel/g);");
   18639   CHECK_EQ(1, reresult->Int32Value(context.local()).FromJust());
   18640 
   18641   reresult = CompileRun("str2.search(/be./g);");
   18642   CHECK_EQ(1, reresult->Int32Value(context.local()).FromJust());
   18643 
   18644   ExpectTrue("/bel/g.test(str2);");
   18645 
   18646   ExpectTrue("/be./g.test(str2);");
   18647 
   18648   reresult = CompileRun("/bel/g.exec(str2);");
   18649   CHECK(!reresult->IsNull());
   18650 
   18651   reresult = CompileRun("/be./g.exec(str2);");
   18652   CHECK(!reresult->IsNull());
   18653 
   18654   ExpectString("str2.substring(2, 10);", "elspenda");
   18655 
   18656   ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
   18657 
   18658   ExpectString("str2.charAt(2);", "e");
   18659 
   18660   ExpectObject("str2.indexOf('els');", indexof);
   18661 
   18662   ExpectObject("str2.lastIndexOf('dab');", lastindexof);
   18663 
   18664   reresult = CompileRun("str2.charCodeAt(2);");
   18665   CHECK_EQ(static_cast<int32_t>('e'),
   18666            reresult->Int32Value(context.local()).FromJust());
   18667 }
   18668 
   18669 
   18670 TEST(ContainsOnlyOneByte) {
   18671   v8::V8::Initialize();
   18672   v8::Isolate* isolate = CcTest::isolate();
   18673   v8::HandleScope scope(isolate);
   18674   // Make a buffer long enough that it won't automatically be converted.
   18675   const int length = 512;
   18676   // Ensure word aligned assignment.
   18677   const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
   18678   v8::base::SmartArrayPointer<uintptr_t> aligned_contents(
   18679       new uintptr_t[aligned_length]);
   18680   uint16_t* string_contents =
   18681       reinterpret_cast<uint16_t*>(aligned_contents.get());
   18682   // Set to contain only one byte.
   18683   for (int i = 0; i < length-1; i++) {
   18684     string_contents[i] = 0x41;
   18685   }
   18686   string_contents[length-1] = 0;
   18687   // Simple case.
   18688   Local<String> string =
   18689       String::NewExternalTwoByte(isolate,
   18690                                  new TestResource(string_contents, NULL, false))
   18691           .ToLocalChecked();
   18692   CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   18693   // Counter example.
   18694   string = String::NewFromTwoByte(isolate, string_contents,
   18695                                   v8::NewStringType::kNormal)
   18696                .ToLocalChecked();
   18697   CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
   18698   // Test left right and balanced cons strings.
   18699   Local<String> base = v8_str("a");
   18700   Local<String> left = base;
   18701   Local<String> right = base;
   18702   for (int i = 0; i < 1000; i++) {
   18703     left = String::Concat(base, left);
   18704     right = String::Concat(right, base);
   18705   }
   18706   Local<String> balanced = String::Concat(left, base);
   18707   balanced = String::Concat(balanced, right);
   18708   Local<String> cons_strings[] = {left, balanced, right};
   18709   Local<String> two_byte =
   18710       String::NewExternalTwoByte(isolate,
   18711                                  new TestResource(string_contents, NULL, false))
   18712           .ToLocalChecked();
   18713   USE(two_byte); USE(cons_strings);
   18714   for (size_t i = 0; i < arraysize(cons_strings); i++) {
   18715     // Base assumptions.
   18716     string = cons_strings[i];
   18717     CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
   18718     // Test left and right concatentation.
   18719     string = String::Concat(two_byte, cons_strings[i]);
   18720     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   18721     string = String::Concat(cons_strings[i], two_byte);
   18722     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   18723   }
   18724   // Set bits in different positions
   18725   // for strings of different lengths and alignments.
   18726   for (int alignment = 0; alignment < 7; alignment++) {
   18727     for (int size = 2; alignment + size < length; size *= 2) {
   18728       int zero_offset = size + alignment;
   18729       string_contents[zero_offset] = 0;
   18730       for (int i = 0; i < size; i++) {
   18731         int shift = 8 + (i % 7);
   18732         string_contents[alignment + i] = 1 << shift;
   18733         string = String::NewExternalTwoByte(
   18734                      isolate,
   18735                      new TestResource(string_contents + alignment, NULL, false))
   18736                      .ToLocalChecked();
   18737         CHECK_EQ(size, string->Length());
   18738         CHECK(!string->ContainsOnlyOneByte());
   18739         string_contents[alignment + i] = 0x41;
   18740       }
   18741       string_contents[zero_offset] = 0x41;
   18742     }
   18743   }
   18744 }
   18745 
   18746 
   18747 // Failed access check callback that performs a GC on each invocation.
   18748 void FailedAccessCheckCallbackGC(Local<v8::Object> target,
   18749                                  v8::AccessType type,
   18750                                  Local<v8::Value> data) {
   18751   CcTest::heap()->CollectAllGarbage();
   18752   CcTest::isolate()->ThrowException(
   18753       v8::Exception::Error(v8_str("cross context")));
   18754 }
   18755 
   18756 
   18757 TEST(GCInFailedAccessCheckCallback) {
   18758   // Install a failed access check callback that performs a GC on each
   18759   // invocation. Then force the callback to be called from va
   18760 
   18761   v8::V8::Initialize();
   18762   v8::Isolate* isolate = CcTest::isolate();
   18763 
   18764   isolate->SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
   18765 
   18766   v8::HandleScope scope(isolate);
   18767 
   18768   // Create an ObjectTemplate for global objects and install access
   18769   // check callbacks that will block access.
   18770   v8::Local<v8::ObjectTemplate> global_template =
   18771       v8::ObjectTemplate::New(isolate);
   18772   global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   18773 
   18774   // Create a context and set an x property on it's global object.
   18775   LocalContext context0(NULL, global_template);
   18776   CHECK(context0->Global()
   18777             ->Set(context0.local(), v8_str("x"), v8_num(42))
   18778             .FromJust());
   18779   v8::Local<v8::Object> global0 = context0->Global();
   18780 
   18781   // Create a context with a different security token so that the
   18782   // failed access check callback will be called on each access.
   18783   LocalContext context1(NULL, global_template);
   18784   CHECK(context1->Global()
   18785             ->Set(context1.local(), v8_str("other"), global0)
   18786             .FromJust());
   18787 
   18788   v8::TryCatch try_catch(isolate);
   18789 
   18790   // Get property with failed access check.
   18791   CHECK(CompileRun("other.x").IsEmpty());
   18792   CHECK(try_catch.HasCaught());
   18793   try_catch.Reset();
   18794 
   18795   // Get element with failed access check.
   18796   CHECK(CompileRun("other[0]").IsEmpty());
   18797   CHECK(try_catch.HasCaught());
   18798   try_catch.Reset();
   18799 
   18800   // Set property with failed access check.
   18801   CHECK(CompileRun("other.x = new Object()").IsEmpty());
   18802   CHECK(try_catch.HasCaught());
   18803   try_catch.Reset();
   18804 
   18805   // Set element with failed access check.
   18806   CHECK(CompileRun("other[0] = new Object()").IsEmpty());
   18807   CHECK(try_catch.HasCaught());
   18808   try_catch.Reset();
   18809 
   18810   // Get property attribute with failed access check.
   18811   CHECK(CompileRun("\'x\' in other").IsEmpty());
   18812   CHECK(try_catch.HasCaught());
   18813   try_catch.Reset();
   18814 
   18815   // Get property attribute for element with failed access check.
   18816   CHECK(CompileRun("0 in other").IsEmpty());
   18817   CHECK(try_catch.HasCaught());
   18818   try_catch.Reset();
   18819 
   18820   // Delete property.
   18821   CHECK(CompileRun("delete other.x").IsEmpty());
   18822   CHECK(try_catch.HasCaught());
   18823   try_catch.Reset();
   18824 
   18825   // Delete element.
   18826   CHECK(global0->Delete(context1.local(), 0).IsNothing());
   18827   CHECK(try_catch.HasCaught());
   18828   try_catch.Reset();
   18829 
   18830   // DefineAccessor.
   18831   CHECK(global0->SetAccessor(context1.local(), v8_str("x"), GetXValue, NULL,
   18832                              v8_str("x"))
   18833             .IsNothing());
   18834   CHECK(try_catch.HasCaught());
   18835   try_catch.Reset();
   18836 
   18837   // Define JavaScript accessor.
   18838   CHECK(CompileRun(
   18839             "Object.prototype.__defineGetter__.call("
   18840             "    other, \'x\', function() { return 42; })").IsEmpty());
   18841   CHECK(try_catch.HasCaught());
   18842   try_catch.Reset();
   18843 
   18844   // LookupAccessor.
   18845   CHECK(CompileRun(
   18846             "Object.prototype.__lookupGetter__.call("
   18847             "    other, \'x\')").IsEmpty());
   18848   CHECK(try_catch.HasCaught());
   18849   try_catch.Reset();
   18850 
   18851   // HasOwnElement.
   18852   CHECK(CompileRun(
   18853             "Object.prototype.hasOwnProperty.call("
   18854             "other, \'0\')").IsEmpty());
   18855   CHECK(try_catch.HasCaught());
   18856   try_catch.Reset();
   18857 
   18858   CHECK(global0->HasRealIndexedProperty(context1.local(), 0).IsNothing());
   18859   CHECK(try_catch.HasCaught());
   18860   try_catch.Reset();
   18861 
   18862   CHECK(
   18863       global0->HasRealNamedProperty(context1.local(), v8_str("x")).IsNothing());
   18864   CHECK(try_catch.HasCaught());
   18865   try_catch.Reset();
   18866 
   18867   CHECK(global0->HasRealNamedCallbackProperty(context1.local(), v8_str("x"))
   18868             .IsNothing());
   18869   CHECK(try_catch.HasCaught());
   18870   try_catch.Reset();
   18871 
   18872   // Reset the failed access check callback so it does not influence
   18873   // the other tests.
   18874   isolate->SetFailedAccessCheckCallbackFunction(NULL);
   18875 }
   18876 
   18877 
   18878 TEST(IsolateNewDispose) {
   18879   v8::Isolate* current_isolate = CcTest::isolate();
   18880   v8::Isolate::CreateParams create_params;
   18881   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   18882   v8::Isolate* isolate = v8::Isolate::New(create_params);
   18883   CHECK(isolate != NULL);
   18884   CHECK(current_isolate != isolate);
   18885   CHECK(current_isolate == CcTest::isolate());
   18886 
   18887   isolate->SetFatalErrorHandler(StoringErrorCallback);
   18888   last_location = last_message = NULL;
   18889   isolate->Dispose();
   18890   CHECK(!last_location);
   18891   CHECK(!last_message);
   18892 }
   18893 
   18894 
   18895 UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
   18896   v8::Isolate::CreateParams create_params;
   18897   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   18898   v8::Isolate* isolate = v8::Isolate::New(create_params);
   18899   {
   18900     v8::Isolate::Scope i_scope(isolate);
   18901     v8::HandleScope scope(isolate);
   18902     LocalContext context(isolate);
   18903     // Run something in this isolate.
   18904     ExpectTrue("true");
   18905     isolate->SetFatalErrorHandler(StoringErrorCallback);
   18906     last_location = last_message = NULL;
   18907     // Still entered, should fail.
   18908     isolate->Dispose();
   18909     CHECK(last_location);
   18910     CHECK(last_message);
   18911   }
   18912   isolate->Dispose();
   18913 }
   18914 
   18915 
   18916 static void BreakArrayGuarantees(const char* script) {
   18917   v8::Isolate::CreateParams create_params;
   18918   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   18919   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
   18920   isolate1->Enter();
   18921   v8::Persistent<v8::Context> context1;
   18922   {
   18923     v8::HandleScope scope(isolate1);
   18924     context1.Reset(isolate1, Context::New(isolate1));
   18925   }
   18926 
   18927   {
   18928     v8::HandleScope scope(isolate1);
   18929     v8::Local<v8::Context> context =
   18930         v8::Local<v8::Context>::New(isolate1, context1);
   18931     v8::Context::Scope context_scope(context);
   18932     v8::internal::Isolate* i_isolate =
   18933         reinterpret_cast<v8::internal::Isolate*>(isolate1);
   18934     CHECK_EQ(true, i_isolate->IsFastArrayConstructorPrototypeChainIntact());
   18935     // Run something in new isolate.
   18936     CompileRun(script);
   18937     CHECK_EQ(false, i_isolate->IsFastArrayConstructorPrototypeChainIntact());
   18938   }
   18939   isolate1->Exit();
   18940   isolate1->Dispose();
   18941 }
   18942 
   18943 
   18944 TEST(VerifyArrayPrototypeGuarantees) {
   18945   // Break fast array hole handling by element changes.
   18946   BreakArrayGuarantees("[].__proto__[1] = 3;");
   18947   BreakArrayGuarantees("Object.prototype[3] = 'three';");
   18948   BreakArrayGuarantees("Array.prototype.push(1);");
   18949   BreakArrayGuarantees("Array.prototype.unshift(1);");
   18950   // Break fast array hole handling by changing length.
   18951   BreakArrayGuarantees("Array.prototype.length = 30;");
   18952   // Break fast array hole handling by prototype structure changes.
   18953   BreakArrayGuarantees("[].__proto__.__proto__ = { funny: true };");
   18954   // By sending elements to dictionary mode.
   18955   BreakArrayGuarantees(
   18956       "Object.defineProperty(Array.prototype, 0, {"
   18957       "  get: function() { return 3; }});");
   18958   BreakArrayGuarantees(
   18959       "Object.defineProperty(Object.prototype, 0, {"
   18960       "  get: function() { return 3; }});");
   18961 }
   18962 
   18963 
   18964 TEST(RunTwoIsolatesOnSingleThread) {
   18965   // Run isolate 1.
   18966   v8::Isolate::CreateParams create_params;
   18967   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   18968   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
   18969   isolate1->Enter();
   18970   v8::Persistent<v8::Context> context1;
   18971   {
   18972     v8::HandleScope scope(isolate1);
   18973     context1.Reset(isolate1, Context::New(isolate1));
   18974   }
   18975 
   18976   {
   18977     v8::HandleScope scope(isolate1);
   18978     v8::Local<v8::Context> context =
   18979         v8::Local<v8::Context>::New(isolate1, context1);
   18980     v8::Context::Scope context_scope(context);
   18981     // Run something in new isolate.
   18982     CompileRun("var foo = 'isolate 1';");
   18983     ExpectString("function f() { return foo; }; f()", "isolate 1");
   18984   }
   18985 
   18986   // Run isolate 2.
   18987   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
   18988   v8::Persistent<v8::Context> context2;
   18989 
   18990   {
   18991     v8::Isolate::Scope iscope(isolate2);
   18992     v8::HandleScope scope(isolate2);
   18993     context2.Reset(isolate2, Context::New(isolate2));
   18994     v8::Local<v8::Context> context =
   18995         v8::Local<v8::Context>::New(isolate2, context2);
   18996     v8::Context::Scope context_scope(context);
   18997 
   18998     // Run something in new isolate.
   18999     CompileRun("var foo = 'isolate 2';");
   19000     ExpectString("function f() { return foo; }; f()", "isolate 2");
   19001   }
   19002 
   19003   {
   19004     v8::HandleScope scope(isolate1);
   19005     v8::Local<v8::Context> context =
   19006         v8::Local<v8::Context>::New(isolate1, context1);
   19007     v8::Context::Scope context_scope(context);
   19008     // Now again in isolate 1
   19009     ExpectString("function f() { return foo; }; f()", "isolate 1");
   19010   }
   19011 
   19012   isolate1->Exit();
   19013 
   19014   // Run some stuff in default isolate.
   19015   v8::Persistent<v8::Context> context_default;
   19016   {
   19017     v8::Isolate* isolate = CcTest::isolate();
   19018     v8::Isolate::Scope iscope(isolate);
   19019     v8::HandleScope scope(isolate);
   19020     context_default.Reset(isolate, Context::New(isolate));
   19021   }
   19022 
   19023   {
   19024     v8::HandleScope scope(CcTest::isolate());
   19025     v8::Local<v8::Context> context =
   19026         v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
   19027     v8::Context::Scope context_scope(context);
   19028     // Variables in other isolates should be not available, verify there
   19029     // is an exception.
   19030     ExpectTrue("function f() {"
   19031                "  try {"
   19032                "    foo;"
   19033                "    return false;"
   19034                "  } catch(e) {"
   19035                "    return true;"
   19036                "  }"
   19037                "};"
   19038                "var isDefaultIsolate = true;"
   19039                "f()");
   19040   }
   19041 
   19042   isolate1->Enter();
   19043 
   19044   {
   19045     v8::Isolate::Scope iscope(isolate2);
   19046     v8::HandleScope scope(isolate2);
   19047     v8::Local<v8::Context> context =
   19048         v8::Local<v8::Context>::New(isolate2, context2);
   19049     v8::Context::Scope context_scope(context);
   19050     ExpectString("function f() { return foo; }; f()", "isolate 2");
   19051   }
   19052 
   19053   {
   19054     v8::HandleScope scope(v8::Isolate::GetCurrent());
   19055     v8::Local<v8::Context> context =
   19056         v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
   19057     v8::Context::Scope context_scope(context);
   19058     ExpectString("function f() { return foo; }; f()", "isolate 1");
   19059   }
   19060 
   19061   {
   19062     v8::Isolate::Scope iscope(isolate2);
   19063     context2.Reset();
   19064   }
   19065 
   19066   context1.Reset();
   19067   isolate1->Exit();
   19068 
   19069   isolate2->SetFatalErrorHandler(StoringErrorCallback);
   19070   last_location = last_message = NULL;
   19071 
   19072   isolate1->Dispose();
   19073   CHECK(!last_location);
   19074   CHECK(!last_message);
   19075 
   19076   isolate2->Dispose();
   19077   CHECK(!last_location);
   19078   CHECK(!last_message);
   19079 
   19080   // Check that default isolate still runs.
   19081   {
   19082     v8::HandleScope scope(CcTest::isolate());
   19083     v8::Local<v8::Context> context =
   19084         v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
   19085     v8::Context::Scope context_scope(context);
   19086     ExpectTrue("function f() { return isDefaultIsolate; }; f()");
   19087   }
   19088 }
   19089 
   19090 
   19091 static int CalcFibonacci(v8::Isolate* isolate, int limit) {
   19092   v8::Isolate::Scope isolate_scope(isolate);
   19093   v8::HandleScope scope(isolate);
   19094   LocalContext context(isolate);
   19095   i::ScopedVector<char> code(1024);
   19096   i::SNPrintF(code, "function fib(n) {"
   19097                     "  if (n <= 2) return 1;"
   19098                     "  return fib(n-1) + fib(n-2);"
   19099                     "}"
   19100                     "fib(%d)", limit);
   19101   Local<Value> value = CompileRun(code.start());
   19102   CHECK(value->IsNumber());
   19103   return static_cast<int>(value->NumberValue(context.local()).FromJust());
   19104 }
   19105 
   19106 class IsolateThread : public v8::base::Thread {
   19107  public:
   19108   explicit IsolateThread(int fib_limit)
   19109       : Thread(Options("IsolateThread")), fib_limit_(fib_limit), result_(0) {}
   19110 
   19111   void Run() {
   19112     v8::Isolate::CreateParams create_params;
   19113     create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   19114     v8::Isolate* isolate = v8::Isolate::New(create_params);
   19115     result_ = CalcFibonacci(isolate, fib_limit_);
   19116     isolate->Dispose();
   19117   }
   19118 
   19119   int result() { return result_; }
   19120 
   19121  private:
   19122   int fib_limit_;
   19123   int result_;
   19124 };
   19125 
   19126 
   19127 TEST(MultipleIsolatesOnIndividualThreads) {
   19128   IsolateThread thread1(21);
   19129   IsolateThread thread2(12);
   19130 
   19131   // Compute some fibonacci numbers on 3 threads in 3 isolates.
   19132   thread1.Start();
   19133   thread2.Start();
   19134 
   19135   int result1 = CalcFibonacci(CcTest::isolate(), 21);
   19136   int result2 = CalcFibonacci(CcTest::isolate(), 12);
   19137 
   19138   thread1.Join();
   19139   thread2.Join();
   19140 
   19141   // Compare results. The actual fibonacci numbers for 12 and 21 are taken
   19142   // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
   19143   CHECK_EQ(result1, 10946);
   19144   CHECK_EQ(result2, 144);
   19145   CHECK_EQ(result1, thread1.result());
   19146   CHECK_EQ(result2, thread2.result());
   19147 }
   19148 
   19149 
   19150 TEST(IsolateDifferentContexts) {
   19151   v8::Isolate::CreateParams create_params;
   19152   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   19153   v8::Isolate* isolate = v8::Isolate::New(create_params);
   19154   Local<v8::Context> context;
   19155   {
   19156     v8::Isolate::Scope isolate_scope(isolate);
   19157     v8::HandleScope handle_scope(isolate);
   19158     context = v8::Context::New(isolate);
   19159     v8::Context::Scope context_scope(context);
   19160     Local<Value> v = CompileRun("2");
   19161     CHECK(v->IsNumber());
   19162     CHECK_EQ(2, static_cast<int>(v->NumberValue(context).FromJust()));
   19163   }
   19164   {
   19165     v8::Isolate::Scope isolate_scope(isolate);
   19166     v8::HandleScope handle_scope(isolate);
   19167     context = v8::Context::New(isolate);
   19168     v8::Context::Scope context_scope(context);
   19169     Local<Value> v = CompileRun("22");
   19170     CHECK(v->IsNumber());
   19171     CHECK_EQ(22, static_cast<int>(v->NumberValue(context).FromJust()));
   19172   }
   19173   isolate->Dispose();
   19174 }
   19175 
   19176 class InitDefaultIsolateThread : public v8::base::Thread {
   19177  public:
   19178   enum TestCase {
   19179     SetResourceConstraints,
   19180     SetFatalHandler,
   19181     SetCounterFunction,
   19182     SetCreateHistogramFunction,
   19183     SetAddHistogramSampleFunction
   19184   };
   19185 
   19186   explicit InitDefaultIsolateThread(TestCase testCase)
   19187       : Thread(Options("InitDefaultIsolateThread")),
   19188         testCase_(testCase),
   19189         result_(false) {}
   19190 
   19191   void Run() {
   19192     v8::Isolate::CreateParams create_params;
   19193     create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   19194     const intptr_t pageSizeMult =
   19195         v8::internal::Page::kPageSize / v8::internal::MB;
   19196     switch (testCase_) {
   19197       case SetResourceConstraints: {
   19198         create_params.constraints.set_max_semi_space_size(1 * pageSizeMult);
   19199         create_params.constraints.set_max_old_space_size(4 * pageSizeMult);
   19200         break;
   19201       }
   19202       default:
   19203         break;
   19204     }
   19205     v8::Isolate* isolate = v8::Isolate::New(create_params);
   19206     isolate->Enter();
   19207     switch (testCase_) {
   19208       case SetResourceConstraints:
   19209         // Already handled in pre-Isolate-creation block.
   19210         break;
   19211 
   19212       case SetFatalHandler:
   19213         isolate->SetFatalErrorHandler(NULL);
   19214         break;
   19215 
   19216       case SetCounterFunction:
   19217         CcTest::isolate()->SetCounterFunction(NULL);
   19218         break;
   19219 
   19220       case SetCreateHistogramFunction:
   19221         CcTest::isolate()->SetCreateHistogramFunction(NULL);
   19222         break;
   19223 
   19224       case SetAddHistogramSampleFunction:
   19225         CcTest::isolate()->SetAddHistogramSampleFunction(NULL);
   19226         break;
   19227     }
   19228     isolate->Exit();
   19229     isolate->Dispose();
   19230     result_ = true;
   19231   }
   19232 
   19233   bool result() { return result_; }
   19234 
   19235  private:
   19236   TestCase testCase_;
   19237   bool result_;
   19238 };
   19239 
   19240 
   19241 static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
   19242   InitDefaultIsolateThread thread(testCase);
   19243   thread.Start();
   19244   thread.Join();
   19245   CHECK_EQ(thread.result(), true);
   19246 }
   19247 
   19248 
   19249 TEST(InitializeDefaultIsolateOnSecondaryThread1) {
   19250   InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
   19251 }
   19252 
   19253 
   19254 TEST(InitializeDefaultIsolateOnSecondaryThread2) {
   19255   InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
   19256 }
   19257 
   19258 
   19259 TEST(InitializeDefaultIsolateOnSecondaryThread3) {
   19260   InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
   19261 }
   19262 
   19263 
   19264 TEST(InitializeDefaultIsolateOnSecondaryThread4) {
   19265   InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
   19266 }
   19267 
   19268 
   19269 TEST(InitializeDefaultIsolateOnSecondaryThread5) {
   19270   InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
   19271 }
   19272 
   19273 
   19274 TEST(StringCheckMultipleContexts) {
   19275   const char* code =
   19276       "(function() { return \"a\".charAt(0); })()";
   19277 
   19278   {
   19279     // Run the code twice in the first context to initialize the call IC.
   19280     LocalContext context1;
   19281     v8::HandleScope scope(context1->GetIsolate());
   19282     ExpectString(code, "a");
   19283     ExpectString(code, "a");
   19284   }
   19285 
   19286   {
   19287     // Change the String.prototype in the second context and check
   19288     // that the right function gets called.
   19289     LocalContext context2;
   19290     v8::HandleScope scope(context2->GetIsolate());
   19291     CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
   19292     ExpectString(code, "not a");
   19293   }
   19294 }
   19295 
   19296 
   19297 TEST(NumberCheckMultipleContexts) {
   19298   const char* code =
   19299       "(function() { return (42).toString(); })()";
   19300 
   19301   {
   19302     // Run the code twice in the first context to initialize the call IC.
   19303     LocalContext context1;
   19304     v8::HandleScope scope(context1->GetIsolate());
   19305     ExpectString(code, "42");
   19306     ExpectString(code, "42");
   19307   }
   19308 
   19309   {
   19310     // Change the Number.prototype in the second context and check
   19311     // that the right function gets called.
   19312     LocalContext context2;
   19313     v8::HandleScope scope(context2->GetIsolate());
   19314     CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
   19315     ExpectString(code, "not 42");
   19316   }
   19317 }
   19318 
   19319 
   19320 TEST(BooleanCheckMultipleContexts) {
   19321   const char* code =
   19322       "(function() { return true.toString(); })()";
   19323 
   19324   {
   19325     // Run the code twice in the first context to initialize the call IC.
   19326     LocalContext context1;
   19327     v8::HandleScope scope(context1->GetIsolate());
   19328     ExpectString(code, "true");
   19329     ExpectString(code, "true");
   19330   }
   19331 
   19332   {
   19333     // Change the Boolean.prototype in the second context and check
   19334     // that the right function gets called.
   19335     LocalContext context2;
   19336     v8::HandleScope scope(context2->GetIsolate());
   19337     CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
   19338     ExpectString(code, "");
   19339   }
   19340 }
   19341 
   19342 
   19343 TEST(DontDeleteCellLoadIC) {
   19344   const char* function_code =
   19345       "function readCell() { while (true) { return cell; } }";
   19346 
   19347   {
   19348     // Run the code twice in the first context to initialize the load
   19349     // IC for a don't delete cell.
   19350     LocalContext context1;
   19351     v8::HandleScope scope(context1->GetIsolate());
   19352     CompileRun("var cell = \"first\";");
   19353     ExpectBoolean("delete cell", false);
   19354     CompileRun(function_code);
   19355     ExpectString("readCell()", "first");
   19356     ExpectString("readCell()", "first");
   19357   }
   19358 
   19359   {
   19360     // Use a deletable cell in the second context.
   19361     LocalContext context2;
   19362     v8::HandleScope scope(context2->GetIsolate());
   19363     CompileRun("cell = \"second\";");
   19364     CompileRun(function_code);
   19365     ExpectString("readCell()", "second");
   19366     ExpectBoolean("delete cell", true);
   19367     ExpectString("(function() {"
   19368                  "  try {"
   19369                  "    return readCell();"
   19370                  "  } catch(e) {"
   19371                  "    return e.toString();"
   19372                  "  }"
   19373                  "})()",
   19374                  "ReferenceError: cell is not defined");
   19375     CompileRun("cell = \"new_second\";");
   19376     CcTest::heap()->CollectAllGarbage();
   19377     ExpectString("readCell()", "new_second");
   19378     ExpectString("readCell()", "new_second");
   19379   }
   19380 }
   19381 
   19382 
   19383 class Visitor42 : public v8::PersistentHandleVisitor {
   19384  public:
   19385   explicit Visitor42(v8::Persistent<v8::Object>* object)
   19386       : counter_(0), object_(object) { }
   19387 
   19388   virtual void VisitPersistentHandle(Persistent<Value>* value,
   19389                                      uint16_t class_id) {
   19390     if (class_id != 42) return;
   19391     CHECK_EQ(42, value->WrapperClassId());
   19392     v8::Isolate* isolate = CcTest::isolate();
   19393     v8::HandleScope handle_scope(isolate);
   19394     v8::Local<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
   19395     v8::Local<v8::Value> object = v8::Local<v8::Object>::New(isolate, *object_);
   19396     CHECK(handle->IsObject());
   19397     CHECK(Local<Object>::Cast(handle)
   19398               ->Equals(isolate->GetCurrentContext(), object)
   19399               .FromJust());
   19400     ++counter_;
   19401   }
   19402 
   19403   int counter_;
   19404   v8::Persistent<v8::Object>* object_;
   19405 };
   19406 
   19407 
   19408 TEST(PersistentHandleVisitor) {
   19409   LocalContext context;
   19410   v8::Isolate* isolate = context->GetIsolate();
   19411   v8::HandleScope scope(isolate);
   19412   v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
   19413   CHECK_EQ(0, object.WrapperClassId());
   19414   object.SetWrapperClassId(42);
   19415   CHECK_EQ(42, object.WrapperClassId());
   19416 
   19417   Visitor42 visitor(&object);
   19418   isolate->VisitHandlesWithClassIds(&visitor);
   19419   CHECK_EQ(1, visitor.counter_);
   19420 
   19421   object.Reset();
   19422 }
   19423 
   19424 
   19425 TEST(WrapperClassId) {
   19426   LocalContext context;
   19427   v8::Isolate* isolate = context->GetIsolate();
   19428   v8::HandleScope scope(isolate);
   19429   v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
   19430   CHECK_EQ(0, object.WrapperClassId());
   19431   object.SetWrapperClassId(65535);
   19432   CHECK_EQ(65535, object.WrapperClassId());
   19433   object.Reset();
   19434 }
   19435 
   19436 
   19437 TEST(PersistentHandleInNewSpaceVisitor) {
   19438   LocalContext context;
   19439   v8::Isolate* isolate = context->GetIsolate();
   19440   v8::HandleScope scope(isolate);
   19441   v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
   19442   CHECK_EQ(0, object1.WrapperClassId());
   19443   object1.SetWrapperClassId(42);
   19444   CHECK_EQ(42, object1.WrapperClassId());
   19445 
   19446   CcTest::heap()->CollectAllGarbage();
   19447   CcTest::heap()->CollectAllGarbage();
   19448 
   19449   v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
   19450   CHECK_EQ(0, object2.WrapperClassId());
   19451   object2.SetWrapperClassId(42);
   19452   CHECK_EQ(42, object2.WrapperClassId());
   19453 
   19454   Visitor42 visitor(&object2);
   19455   isolate->VisitHandlesForPartialDependence(&visitor);
   19456   CHECK_EQ(1, visitor.counter_);
   19457 
   19458   object1.Reset();
   19459   object2.Reset();
   19460 }
   19461 
   19462 
   19463 TEST(RegExp) {
   19464   i::FLAG_harmony_regexps = true;
   19465   i::FLAG_harmony_unicode_regexps = true;
   19466   LocalContext context;
   19467   v8::HandleScope scope(context->GetIsolate());
   19468 
   19469   v8::Local<v8::RegExp> re =
   19470       v8::RegExp::New(context.local(), v8_str("foo"), v8::RegExp::kNone)
   19471           .ToLocalChecked();
   19472   CHECK(re->IsRegExp());
   19473   CHECK(re->GetSource()->Equals(context.local(), v8_str("foo")).FromJust());
   19474   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   19475 
   19476   re = v8::RegExp::New(context.local(), v8_str("bar"),
   19477                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   19478                                                       v8::RegExp::kGlobal))
   19479            .ToLocalChecked();
   19480   CHECK(re->IsRegExp());
   19481   CHECK(re->GetSource()->Equals(context.local(), v8_str("bar")).FromJust());
   19482   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
   19483            static_cast<int>(re->GetFlags()));
   19484 
   19485   re = v8::RegExp::New(context.local(), v8_str("baz"),
   19486                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   19487                                                       v8::RegExp::kMultiline))
   19488            .ToLocalChecked();
   19489   CHECK(re->IsRegExp());
   19490   CHECK(re->GetSource()->Equals(context.local(), v8_str("baz")).FromJust());
   19491   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
   19492            static_cast<int>(re->GetFlags()));
   19493 
   19494   re = v8::RegExp::New(context.local(), v8_str("baz"),
   19495                        static_cast<v8::RegExp::Flags>(v8::RegExp::kUnicode |
   19496                                                       v8::RegExp::kSticky))
   19497            .ToLocalChecked();
   19498   CHECK(re->IsRegExp());
   19499   CHECK(re->GetSource()->Equals(context.local(), v8_str("baz")).FromJust());
   19500   CHECK_EQ(v8::RegExp::kUnicode | v8::RegExp::kSticky,
   19501            static_cast<int>(re->GetFlags()));
   19502 
   19503   re = CompileRun("/quux/").As<v8::RegExp>();
   19504   CHECK(re->IsRegExp());
   19505   CHECK(re->GetSource()->Equals(context.local(), v8_str("quux")).FromJust());
   19506   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   19507 
   19508   re = CompileRun("/quux/gm").As<v8::RegExp>();
   19509   CHECK(re->IsRegExp());
   19510   CHECK(re->GetSource()->Equals(context.local(), v8_str("quux")).FromJust());
   19511   CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
   19512            static_cast<int>(re->GetFlags()));
   19513 
   19514   // Override the RegExp constructor and check the API constructor
   19515   // still works.
   19516   CompileRun("RegExp = function() {}");
   19517 
   19518   re = v8::RegExp::New(context.local(), v8_str("foobar"), v8::RegExp::kNone)
   19519            .ToLocalChecked();
   19520   CHECK(re->IsRegExp());
   19521   CHECK(re->GetSource()->Equals(context.local(), v8_str("foobar")).FromJust());
   19522   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   19523 
   19524   re = v8::RegExp::New(context.local(), v8_str("foobarbaz"),
   19525                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   19526                                                       v8::RegExp::kMultiline))
   19527            .ToLocalChecked();
   19528   CHECK(re->IsRegExp());
   19529   CHECK(
   19530       re->GetSource()->Equals(context.local(), v8_str("foobarbaz")).FromJust());
   19531   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
   19532            static_cast<int>(re->GetFlags()));
   19533 
   19534   CHECK(context->Global()->Set(context.local(), v8_str("re"), re).FromJust());
   19535   ExpectTrue("re.test('FoobarbaZ')");
   19536 
   19537   // RegExps are objects on which you can set properties.
   19538   re->Set(context.local(), v8_str("property"),
   19539           v8::Integer::New(context->GetIsolate(), 32))
   19540       .FromJust();
   19541   v8::Local<v8::Value> value(CompileRun("re.property"));
   19542   CHECK_EQ(32, value->Int32Value(context.local()).FromJust());
   19543 
   19544   v8::TryCatch try_catch(context->GetIsolate());
   19545   CHECK(v8::RegExp::New(context.local(), v8_str("foo["), v8::RegExp::kNone)
   19546             .IsEmpty());
   19547   CHECK(try_catch.HasCaught());
   19548   CHECK(context->Global()
   19549             ->Set(context.local(), v8_str("ex"), try_catch.Exception())
   19550             .FromJust());
   19551   ExpectTrue("ex instanceof SyntaxError");
   19552 }
   19553 
   19554 
   19555 THREADED_TEST(Equals) {
   19556   LocalContext localContext;
   19557   v8::HandleScope handleScope(localContext->GetIsolate());
   19558 
   19559   v8::Local<v8::Object> globalProxy = localContext->Global();
   19560   v8::Local<Value> global = globalProxy->GetPrototype();
   19561 
   19562   CHECK(global->StrictEquals(global));
   19563   CHECK(!global->StrictEquals(globalProxy));
   19564   CHECK(!globalProxy->StrictEquals(global));
   19565   CHECK(globalProxy->StrictEquals(globalProxy));
   19566 
   19567   CHECK(global->Equals(localContext.local(), global).FromJust());
   19568   CHECK(!global->Equals(localContext.local(), globalProxy).FromJust());
   19569   CHECK(!globalProxy->Equals(localContext.local(), global).FromJust());
   19570   CHECK(globalProxy->Equals(localContext.local(), globalProxy).FromJust());
   19571 }
   19572 
   19573 
   19574 static void Getter(v8::Local<v8::Name> property,
   19575                    const v8::PropertyCallbackInfo<v8::Value>& info) {
   19576   info.GetReturnValue().Set(v8_str("42!"));
   19577 }
   19578 
   19579 
   19580 static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
   19581   v8::Local<v8::Array> result = v8::Array::New(info.GetIsolate());
   19582   result->Set(info.GetIsolate()->GetCurrentContext(), 0,
   19583               v8_str("universalAnswer"))
   19584       .FromJust();
   19585   info.GetReturnValue().Set(result);
   19586 }
   19587 
   19588 
   19589 TEST(NamedEnumeratorAndForIn) {
   19590   LocalContext context;
   19591   v8::Isolate* isolate = context->GetIsolate();
   19592   v8::HandleScope handle_scope(isolate);
   19593   v8::Context::Scope context_scope(context.local());
   19594 
   19595   v8::Local<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
   19596   tmpl->SetHandler(v8::NamedPropertyHandlerConfiguration(Getter, NULL, NULL,
   19597                                                          NULL, Enumerator));
   19598   CHECK(context->Global()
   19599             ->Set(context.local(), v8_str("o"),
   19600                   tmpl->NewInstance(context.local()).ToLocalChecked())
   19601             .FromJust());
   19602   v8::Local<v8::Array> result = v8::Local<v8::Array>::Cast(
   19603       CompileRun("var result = []; for (var k in o) result.push(k); result"));
   19604   CHECK_EQ(1u, result->Length());
   19605   CHECK(v8_str("universalAnswer")
   19606             ->Equals(context.local(),
   19607                      result->Get(context.local(), 0).ToLocalChecked())
   19608             .FromJust());
   19609 }
   19610 
   19611 
   19612 TEST(DefinePropertyPostDetach) {
   19613   LocalContext context;
   19614   v8::HandleScope scope(context->GetIsolate());
   19615   v8::Local<v8::Object> proxy = context->Global();
   19616   v8::Local<v8::Function> define_property =
   19617       CompileRun(
   19618           "(function() {"
   19619           "  Object.defineProperty("
   19620           "    this,"
   19621           "    1,"
   19622           "    { configurable: true, enumerable: true, value: 3 });"
   19623           "})")
   19624           .As<Function>();
   19625   context->DetachGlobal();
   19626   CHECK(define_property->Call(context.local(), proxy, 0, NULL).IsEmpty());
   19627 }
   19628 
   19629 
   19630 static void InstallContextId(v8::Local<Context> context, int id) {
   19631   Context::Scope scope(context);
   19632   CHECK(CompileRun("Object.prototype")
   19633             .As<Object>()
   19634             ->Set(context, v8_str("context_id"),
   19635                   v8::Integer::New(context->GetIsolate(), id))
   19636             .FromJust());
   19637 }
   19638 
   19639 
   19640 static void CheckContextId(v8::Local<Object> object, int expected) {
   19641   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   19642   CHECK_EQ(expected, object->Get(context, v8_str("context_id"))
   19643                          .ToLocalChecked()
   19644                          ->Int32Value(context)
   19645                          .FromJust());
   19646 }
   19647 
   19648 
   19649 THREADED_TEST(CreationContext) {
   19650   v8::Isolate* isolate = CcTest::isolate();
   19651   HandleScope handle_scope(isolate);
   19652   Local<Context> context1 = Context::New(isolate);
   19653   InstallContextId(context1, 1);
   19654   Local<Context> context2 = Context::New(isolate);
   19655   InstallContextId(context2, 2);
   19656   Local<Context> context3 = Context::New(isolate);
   19657   InstallContextId(context3, 3);
   19658 
   19659   Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
   19660 
   19661   Local<Object> object1;
   19662   Local<Function> func1;
   19663   {
   19664     Context::Scope scope(context1);
   19665     object1 = Object::New(isolate);
   19666     func1 = tmpl->GetFunction(context1).ToLocalChecked();
   19667   }
   19668 
   19669   Local<Object> object2;
   19670   Local<Function> func2;
   19671   {
   19672     Context::Scope scope(context2);
   19673     object2 = Object::New(isolate);
   19674     func2 = tmpl->GetFunction(context2).ToLocalChecked();
   19675   }
   19676 
   19677   Local<Object> instance1;
   19678   Local<Object> instance2;
   19679 
   19680   {
   19681     Context::Scope scope(context3);
   19682     instance1 = func1->NewInstance(context3).ToLocalChecked();
   19683     instance2 = func2->NewInstance(context3).ToLocalChecked();
   19684   }
   19685 
   19686   {
   19687     Local<Context> other_context = Context::New(isolate);
   19688     Context::Scope scope(other_context);
   19689     CHECK(object1->CreationContext() == context1);
   19690     CheckContextId(object1, 1);
   19691     CHECK(func1->CreationContext() == context1);
   19692     CheckContextId(func1, 1);
   19693     CHECK(instance1->CreationContext() == context1);
   19694     CheckContextId(instance1, 1);
   19695     CHECK(object2->CreationContext() == context2);
   19696     CheckContextId(object2, 2);
   19697     CHECK(func2->CreationContext() == context2);
   19698     CheckContextId(func2, 2);
   19699     CHECK(instance2->CreationContext() == context2);
   19700     CheckContextId(instance2, 2);
   19701   }
   19702 
   19703   {
   19704     Context::Scope scope(context1);
   19705     CHECK(object1->CreationContext() == context1);
   19706     CheckContextId(object1, 1);
   19707     CHECK(func1->CreationContext() == context1);
   19708     CheckContextId(func1, 1);
   19709     CHECK(instance1->CreationContext() == context1);
   19710     CheckContextId(instance1, 1);
   19711     CHECK(object2->CreationContext() == context2);
   19712     CheckContextId(object2, 2);
   19713     CHECK(func2->CreationContext() == context2);
   19714     CheckContextId(func2, 2);
   19715     CHECK(instance2->CreationContext() == context2);
   19716     CheckContextId(instance2, 2);
   19717   }
   19718 
   19719   {
   19720     Context::Scope scope(context2);
   19721     CHECK(object1->CreationContext() == context1);
   19722     CheckContextId(object1, 1);
   19723     CHECK(func1->CreationContext() == context1);
   19724     CheckContextId(func1, 1);
   19725     CHECK(instance1->CreationContext() == context1);
   19726     CheckContextId(instance1, 1);
   19727     CHECK(object2->CreationContext() == context2);
   19728     CheckContextId(object2, 2);
   19729     CHECK(func2->CreationContext() == context2);
   19730     CheckContextId(func2, 2);
   19731     CHECK(instance2->CreationContext() == context2);
   19732     CheckContextId(instance2, 2);
   19733   }
   19734 }
   19735 
   19736 
   19737 THREADED_TEST(CreationContextOfJsFunction) {
   19738   HandleScope handle_scope(CcTest::isolate());
   19739   Local<Context> context = Context::New(CcTest::isolate());
   19740   InstallContextId(context, 1);
   19741 
   19742   Local<Object> function;
   19743   {
   19744     Context::Scope scope(context);
   19745     function = CompileRun("function foo() {}; foo").As<Object>();
   19746   }
   19747 
   19748   Local<Context> other_context = Context::New(CcTest::isolate());
   19749   Context::Scope scope(other_context);
   19750   CHECK(function->CreationContext() == context);
   19751   CheckContextId(function, 1);
   19752 }
   19753 
   19754 
   19755 THREADED_TEST(CreationContextOfJsBoundFunction) {
   19756   HandleScope handle_scope(CcTest::isolate());
   19757   Local<Context> context1 = Context::New(CcTest::isolate());
   19758   InstallContextId(context1, 1);
   19759   Local<Context> context2 = Context::New(CcTest::isolate());
   19760   InstallContextId(context2, 2);
   19761 
   19762   Local<Function> target_function;
   19763   {
   19764     Context::Scope scope(context1);
   19765     target_function = CompileRun("function foo() {}; foo").As<Function>();
   19766   }
   19767 
   19768   Local<Function> bound_function1, bound_function2;
   19769   {
   19770     Context::Scope scope(context2);
   19771     CHECK(context2->Global()
   19772               ->Set(context2, v8_str("foo"), target_function)
   19773               .FromJust());
   19774     bound_function1 = CompileRun("foo.bind(1)").As<Function>();
   19775     bound_function2 =
   19776         CompileRun("Function.prototype.bind.call(foo, 2)").As<Function>();
   19777   }
   19778 
   19779   Local<Context> other_context = Context::New(CcTest::isolate());
   19780   Context::Scope scope(other_context);
   19781   CHECK(bound_function1->CreationContext() == context1);
   19782   CheckContextId(bound_function1, 1);
   19783   CHECK(bound_function2->CreationContext() == context2);
   19784   CheckContextId(bound_function2, 1);
   19785 }
   19786 
   19787 
   19788 void HasOwnPropertyIndexedPropertyGetter(
   19789     uint32_t index,
   19790     const v8::PropertyCallbackInfo<v8::Value>& info) {
   19791   if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
   19792 }
   19793 
   19794 
   19795 void HasOwnPropertyNamedPropertyGetter(
   19796     Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
   19797   if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   19798           .FromJust()) {
   19799     info.GetReturnValue().Set(v8_str("yes"));
   19800   }
   19801 }
   19802 
   19803 
   19804 void HasOwnPropertyIndexedPropertyQuery(
   19805     uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   19806   if (index == 42) info.GetReturnValue().Set(1);
   19807 }
   19808 
   19809 
   19810 void HasOwnPropertyNamedPropertyQuery(
   19811     Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   19812   if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   19813           .FromJust()) {
   19814     info.GetReturnValue().Set(1);
   19815   }
   19816 }
   19817 
   19818 
   19819 void HasOwnPropertyNamedPropertyQuery2(
   19820     Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   19821   if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("bar"))
   19822           .FromJust()) {
   19823     info.GetReturnValue().Set(1);
   19824   }
   19825 }
   19826 
   19827 
   19828 void HasOwnPropertyAccessorGetter(
   19829     Local<String> property,
   19830     const v8::PropertyCallbackInfo<v8::Value>& info) {
   19831   info.GetReturnValue().Set(v8_str("yes"));
   19832 }
   19833 
   19834 
   19835 TEST(HasOwnProperty) {
   19836   LocalContext env;
   19837   v8::Isolate* isolate = env->GetIsolate();
   19838   v8::HandleScope scope(isolate);
   19839   { // Check normal properties and defined getters.
   19840     Local<Value> value = CompileRun(
   19841         "function Foo() {"
   19842         "    this.foo = 11;"
   19843         "    this.__defineGetter__('baz', function() { return 1; });"
   19844         "};"
   19845         "function Bar() { "
   19846         "    this.bar = 13;"
   19847         "    this.__defineGetter__('bla', function() { return 2; });"
   19848         "};"
   19849         "Bar.prototype = new Foo();"
   19850         "new Bar();");
   19851     CHECK(value->IsObject());
   19852     Local<Object> object = value->ToObject(env.local()).ToLocalChecked();
   19853     CHECK(object->Has(env.local(), v8_str("foo")).FromJust());
   19854     CHECK(!object->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   19855     CHECK(object->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   19856     CHECK(object->Has(env.local(), v8_str("baz")).FromJust());
   19857     CHECK(!object->HasOwnProperty(env.local(), v8_str("baz")).FromJust());
   19858     CHECK(object->HasOwnProperty(env.local(), v8_str("bla")).FromJust());
   19859   }
   19860   { // Check named getter interceptors.
   19861     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   19862     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   19863         HasOwnPropertyNamedPropertyGetter));
   19864     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   19865     CHECK(!instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
   19866     CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   19867     CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   19868   }
   19869   { // Check indexed getter interceptors.
   19870     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   19871     templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
   19872         HasOwnPropertyIndexedPropertyGetter));
   19873     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   19874     CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
   19875     CHECK(!instance->HasOwnProperty(env.local(), v8_str("43")).FromJust());
   19876     CHECK(!instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   19877   }
   19878   { // Check named query interceptors.
   19879     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   19880     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   19881         0, 0, HasOwnPropertyNamedPropertyQuery));
   19882     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   19883     CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   19884     CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   19885   }
   19886   { // Check indexed query interceptors.
   19887     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   19888     templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
   19889         0, 0, HasOwnPropertyIndexedPropertyQuery));
   19890     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   19891     CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
   19892     CHECK(!instance->HasOwnProperty(env.local(), v8_str("41")).FromJust());
   19893   }
   19894   { // Check callbacks.
   19895     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   19896     templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
   19897     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   19898     CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   19899     CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   19900   }
   19901   { // Check that query wins on disagreement.
   19902     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   19903     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   19904         HasOwnPropertyNamedPropertyGetter, 0,
   19905         HasOwnPropertyNamedPropertyQuery2));
   19906     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   19907     CHECK(!instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   19908     CHECK(instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   19909   }
   19910 }
   19911 
   19912 
   19913 TEST(IndexedInterceptorWithStringProto) {
   19914   v8::Isolate* isolate = CcTest::isolate();
   19915   v8::HandleScope scope(isolate);
   19916   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   19917   templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
   19918       NULL, NULL, HasOwnPropertyIndexedPropertyQuery));
   19919   LocalContext context;
   19920   CHECK(context->Global()
   19921             ->Set(context.local(), v8_str("obj"),
   19922                   templ->NewInstance(context.local()).ToLocalChecked())
   19923             .FromJust());
   19924   CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
   19925   // These should be intercepted.
   19926   CHECK(CompileRun("42 in obj")->BooleanValue(context.local()).FromJust());
   19927   CHECK(CompileRun("'42' in obj")->BooleanValue(context.local()).FromJust());
   19928   // These should fall through to the String prototype.
   19929   CHECK(CompileRun("0 in obj")->BooleanValue(context.local()).FromJust());
   19930   CHECK(CompileRun("'0' in obj")->BooleanValue(context.local()).FromJust());
   19931   // And these should both fail.
   19932   CHECK(!CompileRun("32 in obj")->BooleanValue(context.local()).FromJust());
   19933   CHECK(!CompileRun("'32' in obj")->BooleanValue(context.local()).FromJust());
   19934 }
   19935 
   19936 
   19937 void CheckCodeGenerationAllowed() {
   19938   Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   19939   Local<Value> result = CompileRun("eval('42')");
   19940   CHECK_EQ(42, result->Int32Value(context).FromJust());
   19941   result = CompileRun("(function(e) { return e('42'); })(eval)");
   19942   CHECK_EQ(42, result->Int32Value(context).FromJust());
   19943   result = CompileRun("var f = new Function('return 42'); f()");
   19944   CHECK_EQ(42, result->Int32Value(context).FromJust());
   19945 }
   19946 
   19947 
   19948 void CheckCodeGenerationDisallowed() {
   19949   TryCatch try_catch(CcTest::isolate());
   19950 
   19951   Local<Value> result = CompileRun("eval('42')");
   19952   CHECK(result.IsEmpty());
   19953   CHECK(try_catch.HasCaught());
   19954   try_catch.Reset();
   19955 
   19956   result = CompileRun("(function(e) { return e('42'); })(eval)");
   19957   CHECK(result.IsEmpty());
   19958   CHECK(try_catch.HasCaught());
   19959   try_catch.Reset();
   19960 
   19961   result = CompileRun("var f = new Function('return 42'); f()");
   19962   CHECK(result.IsEmpty());
   19963   CHECK(try_catch.HasCaught());
   19964 }
   19965 
   19966 
   19967 bool CodeGenerationAllowed(Local<Context> context) {
   19968   ApiTestFuzzer::Fuzz();
   19969   return true;
   19970 }
   19971 
   19972 
   19973 bool CodeGenerationDisallowed(Local<Context> context) {
   19974   ApiTestFuzzer::Fuzz();
   19975   return false;
   19976 }
   19977 
   19978 
   19979 THREADED_TEST(AllowCodeGenFromStrings) {
   19980   LocalContext context;
   19981   v8::HandleScope scope(context->GetIsolate());
   19982 
   19983   // eval and the Function constructor allowed by default.
   19984   CHECK(context->IsCodeGenerationFromStringsAllowed());
   19985   CheckCodeGenerationAllowed();
   19986 
   19987   // Disallow eval and the Function constructor.
   19988   context->AllowCodeGenerationFromStrings(false);
   19989   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   19990   CheckCodeGenerationDisallowed();
   19991 
   19992   // Allow again.
   19993   context->AllowCodeGenerationFromStrings(true);
   19994   CheckCodeGenerationAllowed();
   19995 
   19996   // Disallow but setting a global callback that will allow the calls.
   19997   context->AllowCodeGenerationFromStrings(false);
   19998   context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
   19999       &CodeGenerationAllowed);
   20000   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   20001   CheckCodeGenerationAllowed();
   20002 
   20003   // Set a callback that disallows the code generation.
   20004   context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
   20005       &CodeGenerationDisallowed);
   20006   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   20007   CheckCodeGenerationDisallowed();
   20008 }
   20009 
   20010 
   20011 TEST(SetErrorMessageForCodeGenFromStrings) {
   20012   LocalContext context;
   20013   v8::HandleScope scope(context->GetIsolate());
   20014   TryCatch try_catch(context->GetIsolate());
   20015 
   20016   Local<String> message = v8_str("Message");
   20017   Local<String> expected_message = v8_str("Uncaught EvalError: Message");
   20018   context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
   20019       &CodeGenerationDisallowed);
   20020   context->AllowCodeGenerationFromStrings(false);
   20021   context->SetErrorMessageForCodeGenerationFromStrings(message);
   20022   Local<Value> result = CompileRun("eval('42')");
   20023   CHECK(result.IsEmpty());
   20024   CHECK(try_catch.HasCaught());
   20025   Local<String> actual_message = try_catch.Message()->Get();
   20026   CHECK(expected_message->Equals(context.local(), actual_message).FromJust());
   20027 }
   20028 
   20029 
   20030 static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
   20031 }
   20032 
   20033 
   20034 THREADED_TEST(CallAPIFunctionOnNonObject) {
   20035   LocalContext context;
   20036   v8::Isolate* isolate = context->GetIsolate();
   20037   v8::HandleScope scope(isolate);
   20038   Local<FunctionTemplate> templ =
   20039       v8::FunctionTemplate::New(isolate, NonObjectThis);
   20040   Local<Function> function =
   20041       templ->GetFunction(context.local()).ToLocalChecked();
   20042   CHECK(context->Global()
   20043             ->Set(context.local(), v8_str("f"), function)
   20044             .FromJust());
   20045   TryCatch try_catch(isolate);
   20046   CompileRun("f.call(2)");
   20047 }
   20048 
   20049 
   20050 // Regression test for issue 1470.
   20051 THREADED_TEST(ReadOnlyIndexedProperties) {
   20052   v8::Isolate* isolate = CcTest::isolate();
   20053   v8::HandleScope scope(isolate);
   20054   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20055 
   20056   LocalContext context;
   20057   Local<v8::Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
   20058   CHECK(context->Global()->Set(context.local(), v8_str("obj"), obj).FromJust());
   20059   obj->DefineOwnProperty(context.local(), v8_str("1"), v8_str("DONT_CHANGE"),
   20060                          v8::ReadOnly)
   20061       .FromJust();
   20062   obj->Set(context.local(), v8_str("1"), v8_str("foobar")).FromJust();
   20063   CHECK(v8_str("DONT_CHANGE")
   20064             ->Equals(context.local(),
   20065                      obj->Get(context.local(), v8_str("1")).ToLocalChecked())
   20066             .FromJust());
   20067   obj->DefineOwnProperty(context.local(), v8_str("2"), v8_str("DONT_CHANGE"),
   20068                          v8::ReadOnly)
   20069       .FromJust();
   20070   obj->Set(context.local(), v8_num(2), v8_str("foobar")).FromJust();
   20071   CHECK(v8_str("DONT_CHANGE")
   20072             ->Equals(context.local(),
   20073                      obj->Get(context.local(), v8_num(2)).ToLocalChecked())
   20074             .FromJust());
   20075 
   20076   // Test non-smi case.
   20077   obj->DefineOwnProperty(context.local(), v8_str("2000000000"),
   20078                          v8_str("DONT_CHANGE"), v8::ReadOnly)
   20079       .FromJust();
   20080   obj->Set(context.local(), v8_str("2000000000"), v8_str("foobar")).FromJust();
   20081   CHECK(v8_str("DONT_CHANGE")
   20082             ->Equals(context.local(),
   20083                      obj->Get(context.local(), v8_str("2000000000"))
   20084                          .ToLocalChecked())
   20085             .FromJust());
   20086 }
   20087 
   20088 
   20089 static int CountLiveMapsInMapCache(i::Context* context) {
   20090   i::FixedArray* map_cache = i::FixedArray::cast(context->map_cache());
   20091   int length = map_cache->length();
   20092   int count = 0;
   20093   for (int i = 0; i < length; i++) {
   20094     i::Object* value = map_cache->get(i);
   20095     if (value->IsWeakCell() && !i::WeakCell::cast(value)->cleared()) count++;
   20096   }
   20097   return count;
   20098 }
   20099 
   20100 
   20101 THREADED_TEST(Regress1516) {
   20102   LocalContext context;
   20103   v8::HandleScope scope(context->GetIsolate());
   20104 
   20105   // Object with 20 properties is not a common case, so it should be removed
   20106   // from the cache after GC.
   20107   { v8::HandleScope temp_scope(context->GetIsolate());
   20108     CompileRun(
   20109         "({"
   20110         "'a00': 0, 'a01': 0, 'a02': 0, 'a03': 0, 'a04': 0, "
   20111         "'a05': 0, 'a06': 0, 'a07': 0, 'a08': 0, 'a09': 0, "
   20112         "'a10': 0, 'a11': 0, 'a12': 0, 'a13': 0, 'a14': 0, "
   20113         "'a15': 0, 'a16': 0, 'a17': 0, 'a18': 0, 'a19': 0, "
   20114         "})");
   20115   }
   20116 
   20117   int elements = CountLiveMapsInMapCache(CcTest::i_isolate()->context());
   20118   CHECK_LE(1, elements);
   20119 
   20120   CcTest::heap()->CollectAllGarbage();
   20121 
   20122   CHECK_GT(elements, CountLiveMapsInMapCache(CcTest::i_isolate()->context()));
   20123 }
   20124 
   20125 
   20126 THREADED_TEST(Regress93759) {
   20127   v8::Isolate* isolate = CcTest::isolate();
   20128   HandleScope scope(isolate);
   20129 
   20130   // Template for object with security check.
   20131   Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
   20132   no_proto_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   20133 
   20134   // Templates for objects with hidden prototypes and possibly security check.
   20135   Local<FunctionTemplate> hidden_proto_template =
   20136       v8::FunctionTemplate::New(isolate);
   20137   hidden_proto_template->SetHiddenPrototype(true);
   20138 
   20139   Local<FunctionTemplate> protected_hidden_proto_template =
   20140       v8::FunctionTemplate::New(isolate);
   20141   protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallback(
   20142       AccessAlwaysBlocked);
   20143   protected_hidden_proto_template->SetHiddenPrototype(true);
   20144 
   20145   // Context for "foreign" objects used in test.
   20146   Local<Context> context = v8::Context::New(isolate);
   20147   context->Enter();
   20148 
   20149   // Plain object, no security check.
   20150   Local<Object> simple_object = Object::New(isolate);
   20151 
   20152   // Object with explicit security check.
   20153   Local<Object> protected_object =
   20154       no_proto_template->NewInstance(context).ToLocalChecked();
   20155 
   20156   // JSGlobalProxy object, always have security check.
   20157   Local<Object> proxy_object = context->Global();
   20158 
   20159   // Global object, the  prototype of proxy_object. No security checks.
   20160   Local<Object> global_object =
   20161       proxy_object->GetPrototype()->ToObject(context).ToLocalChecked();
   20162 
   20163   // Hidden prototype without security check.
   20164   Local<Object> hidden_prototype = hidden_proto_template->GetFunction(context)
   20165                                        .ToLocalChecked()
   20166                                        ->NewInstance(context)
   20167                                        .ToLocalChecked();
   20168   Local<Object> object_with_hidden =
   20169     Object::New(isolate);
   20170   object_with_hidden->SetPrototype(context, hidden_prototype).FromJust();
   20171 
   20172   context->Exit();
   20173 
   20174   // Template for object for second context. Values to test are put on it as
   20175   // properties.
   20176   Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
   20177   global_template->Set(v8_str("simple"), simple_object);
   20178   global_template->Set(v8_str("protected"), protected_object);
   20179   global_template->Set(v8_str("global"), global_object);
   20180   global_template->Set(v8_str("proxy"), proxy_object);
   20181   global_template->Set(v8_str("hidden"), object_with_hidden);
   20182 
   20183   LocalContext context2(NULL, global_template);
   20184 
   20185   Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
   20186   CHECK(result1->Equals(context2.local(), simple_object->GetPrototype())
   20187             .FromJust());
   20188 
   20189   Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
   20190   CHECK(result2->IsNull());
   20191 
   20192   Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
   20193   CHECK(result3->Equals(context2.local(), global_object->GetPrototype())
   20194             .FromJust());
   20195 
   20196   Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
   20197   CHECK(result4->IsNull());
   20198 
   20199   Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
   20200   CHECK(result5->Equals(context2.local(), object_with_hidden->GetPrototype()
   20201                                               ->ToObject(context2.local())
   20202                                               .ToLocalChecked()
   20203                                               ->GetPrototype())
   20204             .FromJust());
   20205 }
   20206 
   20207 
   20208 static void TestReceiver(Local<Value> expected_result,
   20209                          Local<Value> expected_receiver,
   20210                          const char* code) {
   20211   Local<Value> result = CompileRun(code);
   20212   Local<Context> context = CcTest::isolate()->GetCurrentContext();
   20213   CHECK(result->IsObject());
   20214   CHECK(expected_receiver
   20215             ->Equals(context,
   20216                      result.As<v8::Object>()->Get(context, 1).ToLocalChecked())
   20217             .FromJust());
   20218   CHECK(expected_result
   20219             ->Equals(context,
   20220                      result.As<v8::Object>()->Get(context, 0).ToLocalChecked())
   20221             .FromJust());
   20222 }
   20223 
   20224 
   20225 THREADED_TEST(ForeignFunctionReceiver) {
   20226   v8::Isolate* isolate = CcTest::isolate();
   20227   HandleScope scope(isolate);
   20228 
   20229   // Create two contexts with different "id" properties ('i' and 'o').
   20230   // Call a function both from its own context and from a the foreign
   20231   // context, and see what "this" is bound to (returning both "this"
   20232   // and "this.id" for comparison).
   20233 
   20234   Local<Context> foreign_context = v8::Context::New(isolate);
   20235   foreign_context->Enter();
   20236   Local<Value> foreign_function =
   20237     CompileRun("function func() { return { 0: this.id, "
   20238                "                           1: this, "
   20239                "                           toString: function() { "
   20240                "                               return this[0];"
   20241                "                           }"
   20242                "                         };"
   20243                "}"
   20244                "var id = 'i';"
   20245                "func;");
   20246   CHECK(foreign_function->IsFunction());
   20247   foreign_context->Exit();
   20248 
   20249   LocalContext context;
   20250 
   20251   Local<String> password = v8_str("Password");
   20252   // Don't get hit by security checks when accessing foreign_context's
   20253   // global receiver (aka. global proxy).
   20254   context->SetSecurityToken(password);
   20255   foreign_context->SetSecurityToken(password);
   20256 
   20257   Local<String> i = v8_str("i");
   20258   Local<String> o = v8_str("o");
   20259   Local<String> id = v8_str("id");
   20260 
   20261   CompileRun("function ownfunc() { return { 0: this.id, "
   20262              "                              1: this, "
   20263              "                              toString: function() { "
   20264              "                                  return this[0];"
   20265              "                              }"
   20266              "                             };"
   20267              "}"
   20268              "var id = 'o';"
   20269              "ownfunc");
   20270   CHECK(context->Global()
   20271             ->Set(context.local(), v8_str("func"), foreign_function)
   20272             .FromJust());
   20273 
   20274   // Sanity check the contexts.
   20275   CHECK(
   20276       i->Equals(
   20277            context.local(),
   20278            foreign_context->Global()->Get(context.local(), id).ToLocalChecked())
   20279           .FromJust());
   20280   CHECK(o->Equals(context.local(),
   20281                   context->Global()->Get(context.local(), id).ToLocalChecked())
   20282             .FromJust());
   20283 
   20284   // Checking local function's receiver.
   20285   // Calling function using its call/apply methods.
   20286   TestReceiver(o, context->Global(), "ownfunc.call()");
   20287   TestReceiver(o, context->Global(), "ownfunc.apply()");
   20288   // Making calls through built-in functions.
   20289   TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
   20290   CHECK(
   20291       o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/,ownfunc)[1]"))
   20292           .FromJust());
   20293   CHECK(
   20294       o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]"))
   20295           .FromJust());
   20296   CHECK(
   20297       o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]"))
   20298           .FromJust());
   20299   // Calling with environment record as base.
   20300   TestReceiver(o, context->Global(), "ownfunc()");
   20301   // Calling with no base.
   20302   TestReceiver(o, context->Global(), "(1,ownfunc)()");
   20303 
   20304   // Checking foreign function return value.
   20305   // Calling function using its call/apply methods.
   20306   TestReceiver(i, foreign_context->Global(), "func.call()");
   20307   TestReceiver(i, foreign_context->Global(), "func.apply()");
   20308   // Calling function using another context's call/apply methods.
   20309   TestReceiver(i, foreign_context->Global(),
   20310                "Function.prototype.call.call(func)");
   20311   TestReceiver(i, foreign_context->Global(),
   20312                "Function.prototype.call.apply(func)");
   20313   TestReceiver(i, foreign_context->Global(),
   20314                "Function.prototype.apply.call(func)");
   20315   TestReceiver(i, foreign_context->Global(),
   20316                "Function.prototype.apply.apply(func)");
   20317   // Making calls through built-in functions.
   20318   TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
   20319   // ToString(func()) is func()[0], i.e., the returned this.id.
   20320   CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/,func)[1]"))
   20321             .FromJust());
   20322   CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,func)[1]"))
   20323             .FromJust());
   20324   CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,func)[3]"))
   20325             .FromJust());
   20326 
   20327   // Calling with environment record as base.
   20328   TestReceiver(i, foreign_context->Global(), "func()");
   20329   // Calling with no base.
   20330   TestReceiver(i, foreign_context->Global(), "(1,func)()");
   20331 }
   20332 
   20333 
   20334 uint8_t callback_fired = 0;
   20335 
   20336 
   20337 void CallCompletedCallback1() {
   20338   v8::base::OS::Print("Firing callback 1.\n");
   20339   callback_fired ^= 1;  // Toggle first bit.
   20340 }
   20341 
   20342 
   20343 void CallCompletedCallback2() {
   20344   v8::base::OS::Print("Firing callback 2.\n");
   20345   callback_fired ^= 2;  // Toggle second bit.
   20346 }
   20347 
   20348 
   20349 void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
   20350   int32_t level =
   20351       args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
   20352   if (level < 3) {
   20353     level++;
   20354     v8::base::OS::Print("Entering recursion level %d.\n", level);
   20355     char script[64];
   20356     i::Vector<char> script_vector(script, sizeof(script));
   20357     i::SNPrintF(script_vector, "recursion(%d)", level);
   20358     CompileRun(script_vector.start());
   20359     v8::base::OS::Print("Leaving recursion level %d.\n", level);
   20360     CHECK_EQ(0, callback_fired);
   20361   } else {
   20362     v8::base::OS::Print("Recursion ends.\n");
   20363     CHECK_EQ(0, callback_fired);
   20364   }
   20365 }
   20366 
   20367 
   20368 TEST(CallCompletedCallback) {
   20369   LocalContext env;
   20370   v8::HandleScope scope(env->GetIsolate());
   20371   v8::Local<v8::FunctionTemplate> recursive_runtime =
   20372       v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
   20373   env->Global()
   20374       ->Set(env.local(), v8_str("recursion"),
   20375             recursive_runtime->GetFunction(env.local()).ToLocalChecked())
   20376       .FromJust();
   20377   // Adding the same callback a second time has no effect.
   20378   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
   20379   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
   20380   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback2);
   20381   v8::base::OS::Print("--- Script (1) ---\n");
   20382   Local<Script> script =
   20383       v8::Script::Compile(env.local(), v8_str("recursion(0)")).ToLocalChecked();
   20384   script->Run(env.local()).ToLocalChecked();
   20385   CHECK_EQ(3, callback_fired);
   20386 
   20387   v8::base::OS::Print("\n--- Script (2) ---\n");
   20388   callback_fired = 0;
   20389   env->GetIsolate()->RemoveCallCompletedCallback(CallCompletedCallback1);
   20390   script->Run(env.local()).ToLocalChecked();
   20391   CHECK_EQ(2, callback_fired);
   20392 
   20393   v8::base::OS::Print("\n--- Function ---\n");
   20394   callback_fired = 0;
   20395   Local<Function> recursive_function = Local<Function>::Cast(
   20396       env->Global()->Get(env.local(), v8_str("recursion")).ToLocalChecked());
   20397   v8::Local<Value> args[] = {v8_num(0)};
   20398   recursive_function->Call(env.local(), env->Global(), 1, args)
   20399       .ToLocalChecked();
   20400   CHECK_EQ(2, callback_fired);
   20401 }
   20402 
   20403 
   20404 void CallCompletedCallbackNoException() {
   20405   v8::HandleScope scope(CcTest::isolate());
   20406   CompileRun("1+1;");
   20407 }
   20408 
   20409 
   20410 void CallCompletedCallbackException() {
   20411   v8::HandleScope scope(CcTest::isolate());
   20412   CompileRun("throw 'second exception';");
   20413 }
   20414 
   20415 
   20416 TEST(CallCompletedCallbackOneException) {
   20417   LocalContext env;
   20418   v8::HandleScope scope(env->GetIsolate());
   20419   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackNoException);
   20420   CompileRun("throw 'exception';");
   20421 }
   20422 
   20423 
   20424 TEST(CallCompletedCallbackTwoExceptions) {
   20425   LocalContext env;
   20426   v8::HandleScope scope(env->GetIsolate());
   20427   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackException);
   20428   CompileRun("throw 'first exception';");
   20429 }
   20430 
   20431 
   20432 static void MicrotaskOne(const v8::FunctionCallbackInfo<Value>& info) {
   20433   v8::HandleScope scope(info.GetIsolate());
   20434   CompileRun("ext1Calls++;");
   20435 }
   20436 
   20437 
   20438 static void MicrotaskTwo(const v8::FunctionCallbackInfo<Value>& info) {
   20439   v8::HandleScope scope(info.GetIsolate());
   20440   CompileRun("ext2Calls++;");
   20441 }
   20442 
   20443 
   20444 void* g_passed_to_three = NULL;
   20445 
   20446 
   20447 static void MicrotaskThree(void* data) {
   20448   g_passed_to_three = data;
   20449 }
   20450 
   20451 
   20452 TEST(EnqueueMicrotask) {
   20453   LocalContext env;
   20454   v8::HandleScope scope(env->GetIsolate());
   20455   CompileRun(
   20456       "var ext1Calls = 0;"
   20457       "var ext2Calls = 0;");
   20458   CompileRun("1+1;");
   20459   CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   20460   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   20461 
   20462   env->GetIsolate()->EnqueueMicrotask(
   20463       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   20464   CompileRun("1+1;");
   20465   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   20466   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   20467 
   20468   env->GetIsolate()->EnqueueMicrotask(
   20469       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   20470   env->GetIsolate()->EnqueueMicrotask(
   20471       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   20472   CompileRun("1+1;");
   20473   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   20474   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   20475 
   20476   env->GetIsolate()->EnqueueMicrotask(
   20477       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   20478   CompileRun("1+1;");
   20479   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   20480   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   20481 
   20482   CompileRun("1+1;");
   20483   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   20484   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   20485 
   20486   g_passed_to_three = NULL;
   20487   env->GetIsolate()->EnqueueMicrotask(MicrotaskThree);
   20488   CompileRun("1+1;");
   20489   CHECK(!g_passed_to_three);
   20490   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   20491   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   20492 
   20493   int dummy;
   20494   env->GetIsolate()->EnqueueMicrotask(
   20495       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   20496   env->GetIsolate()->EnqueueMicrotask(MicrotaskThree, &dummy);
   20497   env->GetIsolate()->EnqueueMicrotask(
   20498       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   20499   CompileRun("1+1;");
   20500   CHECK_EQ(&dummy, g_passed_to_three);
   20501   CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   20502   CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   20503   g_passed_to_three = NULL;
   20504 }
   20505 
   20506 
   20507 static void MicrotaskExceptionOne(
   20508     const v8::FunctionCallbackInfo<Value>& info) {
   20509   v8::HandleScope scope(info.GetIsolate());
   20510   CompileRun("exception1Calls++;");
   20511   info.GetIsolate()->ThrowException(
   20512       v8::Exception::Error(v8_str("first")));
   20513 }
   20514 
   20515 
   20516 static void MicrotaskExceptionTwo(
   20517     const v8::FunctionCallbackInfo<Value>& info) {
   20518   v8::HandleScope scope(info.GetIsolate());
   20519   CompileRun("exception2Calls++;");
   20520   info.GetIsolate()->ThrowException(
   20521       v8::Exception::Error(v8_str("second")));
   20522 }
   20523 
   20524 
   20525 TEST(RunMicrotasksIgnoresThrownExceptions) {
   20526   LocalContext env;
   20527   v8::Isolate* isolate = env->GetIsolate();
   20528   v8::HandleScope scope(isolate);
   20529   CompileRun(
   20530       "var exception1Calls = 0;"
   20531       "var exception2Calls = 0;");
   20532   isolate->EnqueueMicrotask(
   20533       Function::New(env.local(), MicrotaskExceptionOne).ToLocalChecked());
   20534   isolate->EnqueueMicrotask(
   20535       Function::New(env.local(), MicrotaskExceptionTwo).ToLocalChecked());
   20536   TryCatch try_catch(isolate);
   20537   CompileRun("1+1;");
   20538   CHECK(!try_catch.HasCaught());
   20539   CHECK_EQ(1,
   20540            CompileRun("exception1Calls")->Int32Value(env.local()).FromJust());
   20541   CHECK_EQ(1,
   20542            CompileRun("exception2Calls")->Int32Value(env.local()).FromJust());
   20543 }
   20544 
   20545 
   20546 TEST(SetAutorunMicrotasks) {
   20547   LocalContext env;
   20548   v8::HandleScope scope(env->GetIsolate());
   20549   CompileRun(
   20550       "var ext1Calls = 0;"
   20551       "var ext2Calls = 0;");
   20552   CompileRun("1+1;");
   20553   CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   20554   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   20555 
   20556   env->GetIsolate()->EnqueueMicrotask(
   20557       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   20558   CompileRun("1+1;");
   20559   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   20560   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   20561 
   20562   env->GetIsolate()->SetAutorunMicrotasks(false);
   20563   env->GetIsolate()->EnqueueMicrotask(
   20564       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   20565   env->GetIsolate()->EnqueueMicrotask(
   20566       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   20567   CompileRun("1+1;");
   20568   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   20569   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   20570 
   20571   env->GetIsolate()->RunMicrotasks();
   20572   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   20573   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   20574 
   20575   env->GetIsolate()->EnqueueMicrotask(
   20576       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   20577   CompileRun("1+1;");
   20578   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   20579   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   20580 
   20581   env->GetIsolate()->RunMicrotasks();
   20582   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   20583   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   20584 
   20585   env->GetIsolate()->SetAutorunMicrotasks(true);
   20586   env->GetIsolate()->EnqueueMicrotask(
   20587       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   20588   CompileRun("1+1;");
   20589   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   20590   CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   20591 
   20592   env->GetIsolate()->EnqueueMicrotask(
   20593       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   20594   {
   20595     v8::Isolate::SuppressMicrotaskExecutionScope scope(env->GetIsolate());
   20596     CompileRun("1+1;");
   20597     CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   20598     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   20599   }
   20600 
   20601   CompileRun("1+1;");
   20602   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   20603   CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   20604 }
   20605 
   20606 
   20607 TEST(RunMicrotasksWithoutEnteringContext) {
   20608   v8::Isolate* isolate = CcTest::isolate();
   20609   HandleScope handle_scope(isolate);
   20610   isolate->SetAutorunMicrotasks(false);
   20611   Local<Context> context = Context::New(isolate);
   20612   {
   20613     Context::Scope context_scope(context);
   20614     CompileRun("var ext1Calls = 0;");
   20615     isolate->EnqueueMicrotask(
   20616         Function::New(context, MicrotaskOne).ToLocalChecked());
   20617   }
   20618   isolate->RunMicrotasks();
   20619   {
   20620     Context::Scope context_scope(context);
   20621     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(context).FromJust());
   20622   }
   20623   isolate->SetAutorunMicrotasks(true);
   20624 }
   20625 
   20626 
   20627 static void DebugEventInObserver(const v8::Debug::EventDetails& event_details) {
   20628   v8::DebugEvent event = event_details.GetEvent();
   20629   if (event != v8::Break) return;
   20630   Local<Object> exec_state = event_details.GetExecutionState();
   20631   Local<Context> context = CcTest::isolate()->GetCurrentContext();
   20632   Local<Value> break_id =
   20633       exec_state->Get(context, v8_str("break_id")).ToLocalChecked();
   20634   CompileRun("function f(id) { new FrameDetails(id, 0); }");
   20635   Local<Function> fun = Local<Function>::Cast(
   20636       CcTest::global()->Get(context, v8_str("f")).ToLocalChecked());
   20637   fun->Call(context, CcTest::global(), 1, &break_id).ToLocalChecked();
   20638 }
   20639 
   20640 
   20641 TEST(Regress385349) {
   20642   i::FLAG_harmony_object_observe = true;
   20643   i::FLAG_allow_natives_syntax = true;
   20644   v8::Isolate* isolate = CcTest::isolate();
   20645   HandleScope handle_scope(isolate);
   20646   isolate->SetAutorunMicrotasks(false);
   20647   Local<Context> context = Context::New(isolate);
   20648   v8::Debug::SetDebugEventListener(isolate, DebugEventInObserver);
   20649   {
   20650     Context::Scope context_scope(context);
   20651     CompileRun("var obj = {};"
   20652                "Object.observe(obj, function(changes) { debugger; });"
   20653                "obj.a = 0;");
   20654   }
   20655   isolate->RunMicrotasks();
   20656   isolate->SetAutorunMicrotasks(true);
   20657   v8::Debug::SetDebugEventListener(isolate, nullptr);
   20658 }
   20659 
   20660 
   20661 #ifdef ENABLE_DISASSEMBLER
   20662 static int probes_counter = 0;
   20663 static int misses_counter = 0;
   20664 static int updates_counter = 0;
   20665 
   20666 
   20667 static int* LookupCounter(const char* name) {
   20668   if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
   20669     return &probes_counter;
   20670   } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
   20671     return &misses_counter;
   20672   } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
   20673     return &updates_counter;
   20674   }
   20675   return NULL;
   20676 }
   20677 
   20678 
   20679 static const char* kMegamorphicTestProgram =
   20680     "function ClassA() { };"
   20681     "function ClassB() { };"
   20682     "ClassA.prototype.foo = function() { };"
   20683     "ClassB.prototype.foo = function() { };"
   20684     "function fooify(obj) { obj.foo(); };"
   20685     "var a = new ClassA();"
   20686     "var b = new ClassB();"
   20687     "for (var i = 0; i < 10000; i++) {"
   20688     "  fooify(a);"
   20689     "  fooify(b);"
   20690     "}";
   20691 #endif
   20692 
   20693 
   20694 static void StubCacheHelper(bool primary) {
   20695 #ifdef ENABLE_DISASSEMBLER
   20696   i::FLAG_native_code_counters = true;
   20697   if (primary) {
   20698     i::FLAG_test_primary_stub_cache = true;
   20699   } else {
   20700     i::FLAG_test_secondary_stub_cache = true;
   20701   }
   20702   i::FLAG_crankshaft = false;
   20703   LocalContext env;
   20704   env->GetIsolate()->SetCounterFunction(LookupCounter);
   20705   v8::HandleScope scope(env->GetIsolate());
   20706   int initial_probes = probes_counter;
   20707   int initial_misses = misses_counter;
   20708   int initial_updates = updates_counter;
   20709   CompileRun(kMegamorphicTestProgram);
   20710   int probes = probes_counter - initial_probes;
   20711   int misses = misses_counter - initial_misses;
   20712   int updates = updates_counter - initial_updates;
   20713   CHECK_LT(updates, 10);
   20714   CHECK_LT(misses, 10);
   20715   // TODO(verwaest): Update this test to overflow the degree of polymorphism
   20716   // before megamorphism. The number of probes will only work once we teach the
   20717   // serializer to embed references to counters in the stubs, given that the
   20718   // megamorphic_stub_cache_probes is updated in a snapshot-generated stub.
   20719   CHECK_GE(probes, 0);
   20720 #endif
   20721 }
   20722 
   20723 
   20724 TEST(SecondaryStubCache) {
   20725   StubCacheHelper(true);
   20726 }
   20727 
   20728 
   20729 TEST(PrimaryStubCache) {
   20730   StubCacheHelper(false);
   20731 }
   20732 
   20733 
   20734 #ifdef DEBUG
   20735 static int cow_arrays_created_runtime = 0;
   20736 
   20737 
   20738 static int* LookupCounterCOWArrays(const char* name) {
   20739   if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) {
   20740     return &cow_arrays_created_runtime;
   20741   }
   20742   return NULL;
   20743 }
   20744 #endif
   20745 
   20746 
   20747 TEST(CheckCOWArraysCreatedRuntimeCounter) {
   20748 #ifdef DEBUG
   20749   i::FLAG_native_code_counters = true;
   20750   LocalContext env;
   20751   env->GetIsolate()->SetCounterFunction(LookupCounterCOWArrays);
   20752   v8::HandleScope scope(env->GetIsolate());
   20753   int initial_cow_arrays = cow_arrays_created_runtime;
   20754   CompileRun("var o = [1, 2, 3];");
   20755   CHECK_EQ(1, cow_arrays_created_runtime - initial_cow_arrays);
   20756   CompileRun("var o = {foo: [4, 5, 6], bar: [3, 0]};");
   20757   CHECK_EQ(3, cow_arrays_created_runtime - initial_cow_arrays);
   20758   CompileRun("var o = {foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'};");
   20759   CHECK_EQ(4, cow_arrays_created_runtime - initial_cow_arrays);
   20760 #endif
   20761 }
   20762 
   20763 
   20764 TEST(StaticGetters) {
   20765   LocalContext context;
   20766   i::Factory* factory = CcTest::i_isolate()->factory();
   20767   v8::Isolate* isolate = CcTest::isolate();
   20768   v8::HandleScope scope(isolate);
   20769   i::Handle<i::Object> undefined_value = factory->undefined_value();
   20770   CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
   20771   i::Handle<i::Object> null_value = factory->null_value();
   20772   CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
   20773   i::Handle<i::Object> true_value = factory->true_value();
   20774   CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
   20775   i::Handle<i::Object> false_value = factory->false_value();
   20776   CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
   20777 }
   20778 
   20779 
   20780 UNINITIALIZED_TEST(IsolateEmbedderData) {
   20781   CcTest::DisableAutomaticDispose();
   20782   v8::Isolate::CreateParams create_params;
   20783   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20784   v8::Isolate* isolate = v8::Isolate::New(create_params);
   20785   isolate->Enter();
   20786   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   20787   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   20788     CHECK(!isolate->GetData(slot));
   20789     CHECK(!i_isolate->GetData(slot));
   20790   }
   20791   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   20792     void* data = reinterpret_cast<void*>(0xacce55ed + slot);
   20793     isolate->SetData(slot, data);
   20794   }
   20795   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   20796     void* data = reinterpret_cast<void*>(0xacce55ed + slot);
   20797     CHECK_EQ(data, isolate->GetData(slot));
   20798     CHECK_EQ(data, i_isolate->GetData(slot));
   20799   }
   20800   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   20801     void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
   20802     isolate->SetData(slot, data);
   20803   }
   20804   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   20805     void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
   20806     CHECK_EQ(data, isolate->GetData(slot));
   20807     CHECK_EQ(data, i_isolate->GetData(slot));
   20808   }
   20809   isolate->Exit();
   20810   isolate->Dispose();
   20811 }
   20812 
   20813 
   20814 TEST(StringEmpty) {
   20815   LocalContext context;
   20816   i::Factory* factory = CcTest::i_isolate()->factory();
   20817   v8::Isolate* isolate = CcTest::isolate();
   20818   v8::HandleScope scope(isolate);
   20819   i::Handle<i::Object> empty_string = factory->empty_string();
   20820   CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
   20821 }
   20822 
   20823 
   20824 static int instance_checked_getter_count = 0;
   20825 static void InstanceCheckedGetter(
   20826     Local<String> name,
   20827     const v8::PropertyCallbackInfo<v8::Value>& info) {
   20828   CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   20829             .FromJust());
   20830   instance_checked_getter_count++;
   20831   info.GetReturnValue().Set(v8_num(11));
   20832 }
   20833 
   20834 
   20835 static int instance_checked_setter_count = 0;
   20836 static void InstanceCheckedSetter(Local<String> name,
   20837                       Local<Value> value,
   20838                       const v8::PropertyCallbackInfo<void>& info) {
   20839   CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   20840             .FromJust());
   20841   CHECK(value->Equals(info.GetIsolate()->GetCurrentContext(), v8_num(23))
   20842             .FromJust());
   20843   instance_checked_setter_count++;
   20844 }
   20845 
   20846 
   20847 static void CheckInstanceCheckedResult(int getters, int setters,
   20848                                        bool expects_callbacks,
   20849                                        TryCatch* try_catch) {
   20850   if (expects_callbacks) {
   20851     CHECK(!try_catch->HasCaught());
   20852     CHECK_EQ(getters, instance_checked_getter_count);
   20853     CHECK_EQ(setters, instance_checked_setter_count);
   20854   } else {
   20855     CHECK(try_catch->HasCaught());
   20856     CHECK_EQ(0, instance_checked_getter_count);
   20857     CHECK_EQ(0, instance_checked_setter_count);
   20858   }
   20859   try_catch->Reset();
   20860 }
   20861 
   20862 
   20863 static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
   20864   instance_checked_getter_count = 0;
   20865   instance_checked_setter_count = 0;
   20866   TryCatch try_catch(CcTest::isolate());
   20867 
   20868   // Test path through generic runtime code.
   20869   CompileRun("obj.foo");
   20870   CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
   20871   CompileRun("obj.foo = 23");
   20872   CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
   20873 
   20874   // Test path through generated LoadIC and StoredIC.
   20875   CompileRun("function test_get(o) { o.foo; }"
   20876              "test_get(obj);");
   20877   CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
   20878   CompileRun("test_get(obj);");
   20879   CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
   20880   CompileRun("test_get(obj);");
   20881   CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
   20882   CompileRun("function test_set(o) { o.foo = 23; }"
   20883              "test_set(obj);");
   20884   CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
   20885   CompileRun("test_set(obj);");
   20886   CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
   20887   CompileRun("test_set(obj);");
   20888   CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
   20889 
   20890   // Test path through optimized code.
   20891   CompileRun("%OptimizeFunctionOnNextCall(test_get);"
   20892              "test_get(obj);");
   20893   CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
   20894   CompileRun("%OptimizeFunctionOnNextCall(test_set);"
   20895              "test_set(obj);");
   20896   CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
   20897 
   20898   // Cleanup so that closures start out fresh in next check.
   20899   CompileRun("%DeoptimizeFunction(test_get);"
   20900              "%ClearFunctionTypeFeedback(test_get);"
   20901              "%DeoptimizeFunction(test_set);"
   20902              "%ClearFunctionTypeFeedback(test_set);");
   20903 }
   20904 
   20905 
   20906 THREADED_TEST(InstanceCheckOnInstanceAccessor) {
   20907   v8::internal::FLAG_allow_natives_syntax = true;
   20908   LocalContext context;
   20909   v8::HandleScope scope(context->GetIsolate());
   20910 
   20911   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   20912   Local<ObjectTemplate> inst = templ->InstanceTemplate();
   20913   inst->SetAccessor(v8_str("foo"), InstanceCheckedGetter, InstanceCheckedSetter,
   20914                     Local<Value>(), v8::DEFAULT, v8::None,
   20915                     v8::AccessorSignature::New(context->GetIsolate(), templ));
   20916   CHECK(context->Global()
   20917             ->Set(context.local(), v8_str("f"),
   20918                   templ->GetFunction(context.local()).ToLocalChecked())
   20919             .FromJust());
   20920 
   20921   printf("Testing positive ...\n");
   20922   CompileRun("var obj = new f();");
   20923   CHECK(templ->HasInstance(
   20924       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   20925   CheckInstanceCheckedAccessors(true);
   20926 
   20927   printf("Testing negative ...\n");
   20928   CompileRun("var obj = {};"
   20929              "obj.__proto__ = new f();");
   20930   CHECK(!templ->HasInstance(
   20931       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   20932   CheckInstanceCheckedAccessors(false);
   20933 }
   20934 
   20935 
   20936 static void EmptyInterceptorGetter(
   20937     Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {}
   20938 
   20939 
   20940 static void EmptyInterceptorSetter(
   20941     Local<String> name, Local<Value> value,
   20942     const v8::PropertyCallbackInfo<v8::Value>& info) {}
   20943 
   20944 
   20945 THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
   20946   v8::internal::FLAG_allow_natives_syntax = true;
   20947   LocalContext context;
   20948   v8::HandleScope scope(context->GetIsolate());
   20949 
   20950   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   20951   Local<ObjectTemplate> inst = templ->InstanceTemplate();
   20952   templ->InstanceTemplate()->SetNamedPropertyHandler(EmptyInterceptorGetter,
   20953                                                      EmptyInterceptorSetter);
   20954   inst->SetAccessor(v8_str("foo"), InstanceCheckedGetter, InstanceCheckedSetter,
   20955                     Local<Value>(), v8::DEFAULT, v8::None,
   20956                     v8::AccessorSignature::New(context->GetIsolate(), templ));
   20957   CHECK(context->Global()
   20958             ->Set(context.local(), v8_str("f"),
   20959                   templ->GetFunction(context.local()).ToLocalChecked())
   20960             .FromJust());
   20961 
   20962   printf("Testing positive ...\n");
   20963   CompileRun("var obj = new f();");
   20964   CHECK(templ->HasInstance(
   20965       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   20966   CheckInstanceCheckedAccessors(true);
   20967 
   20968   printf("Testing negative ...\n");
   20969   CompileRun("var obj = {};"
   20970              "obj.__proto__ = new f();");
   20971   CHECK(!templ->HasInstance(
   20972       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   20973   CheckInstanceCheckedAccessors(false);
   20974 }
   20975 
   20976 
   20977 THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
   20978   v8::internal::FLAG_allow_natives_syntax = true;
   20979   LocalContext context;
   20980   v8::HandleScope scope(context->GetIsolate());
   20981 
   20982   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   20983   Local<ObjectTemplate> proto = templ->PrototypeTemplate();
   20984   proto->SetAccessor(v8_str("foo"), InstanceCheckedGetter,
   20985                      InstanceCheckedSetter, Local<Value>(), v8::DEFAULT,
   20986                      v8::None,
   20987                      v8::AccessorSignature::New(context->GetIsolate(), templ));
   20988   CHECK(context->Global()
   20989             ->Set(context.local(), v8_str("f"),
   20990                   templ->GetFunction(context.local()).ToLocalChecked())
   20991             .FromJust());
   20992 
   20993   printf("Testing positive ...\n");
   20994   CompileRun("var obj = new f();");
   20995   CHECK(templ->HasInstance(
   20996       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   20997   CheckInstanceCheckedAccessors(true);
   20998 
   20999   printf("Testing negative ...\n");
   21000   CompileRun("var obj = {};"
   21001              "obj.__proto__ = new f();");
   21002   CHECK(!templ->HasInstance(
   21003       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   21004   CheckInstanceCheckedAccessors(false);
   21005 
   21006   printf("Testing positive with modified prototype chain ...\n");
   21007   CompileRun("var obj = new f();"
   21008              "var pro = {};"
   21009              "pro.__proto__ = obj.__proto__;"
   21010              "obj.__proto__ = pro;");
   21011   CHECK(templ->HasInstance(
   21012       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   21013   CheckInstanceCheckedAccessors(true);
   21014 }
   21015 
   21016 
   21017 TEST(TryFinallyMessage) {
   21018   LocalContext context;
   21019   v8::HandleScope scope(context->GetIsolate());
   21020   {
   21021     // Test that the original error message is not lost if there is a
   21022     // recursive call into Javascript is done in the finally block, e.g. to
   21023     // initialize an IC. (crbug.com/129171)
   21024     TryCatch try_catch(context->GetIsolate());
   21025     const char* trigger_ic =
   21026         "try {                      \n"
   21027         "  throw new Error('test'); \n"
   21028         "} finally {                \n"
   21029         "  var x = 0;               \n"
   21030         "  x++;                     \n"  // Trigger an IC initialization here.
   21031         "}                          \n";
   21032     CompileRun(trigger_ic);
   21033     CHECK(try_catch.HasCaught());
   21034     Local<Message> message = try_catch.Message();
   21035     CHECK(!message.IsEmpty());
   21036     CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
   21037   }
   21038 
   21039   {
   21040     // Test that the original exception message is indeed overwritten if
   21041     // a new error is thrown in the finally block.
   21042     TryCatch try_catch(context->GetIsolate());
   21043     const char* throw_again =
   21044         "try {                       \n"
   21045         "  throw new Error('test');  \n"
   21046         "} finally {                 \n"
   21047         "  var x = 0;                \n"
   21048         "  x++;                      \n"
   21049         "  throw new Error('again'); \n"  // This is the new uncaught error.
   21050         "}                           \n";
   21051     CompileRun(throw_again);
   21052     CHECK(try_catch.HasCaught());
   21053     Local<Message> message = try_catch.Message();
   21054     CHECK(!message.IsEmpty());
   21055     CHECK_EQ(6, message->GetLineNumber(context.local()).FromJust());
   21056   }
   21057 }
   21058 
   21059 
   21060 static void Helper137002(bool do_store,
   21061                          bool polymorphic,
   21062                          bool remove_accessor,
   21063                          bool interceptor) {
   21064   LocalContext context;
   21065   Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
   21066   if (interceptor) {
   21067     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(FooGetInterceptor,
   21068                                                             FooSetInterceptor));
   21069   } else {
   21070     templ->SetAccessor(v8_str("foo"),
   21071                        GetterWhichReturns42,
   21072                        SetterWhichSetsYOnThisTo23);
   21073   }
   21074   CHECK(context->Global()
   21075             ->Set(context.local(), v8_str("obj"),
   21076                   templ->NewInstance(context.local()).ToLocalChecked())
   21077             .FromJust());
   21078 
   21079   // Turn monomorphic on slow object with native accessor, then turn
   21080   // polymorphic, finally optimize to create negative lookup and fail.
   21081   CompileRun(do_store ?
   21082              "function f(x) { x.foo = void 0; }" :
   21083              "function f(x) { return x.foo; }");
   21084   CompileRun("obj.y = void 0;");
   21085   if (!interceptor) {
   21086     CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
   21087   }
   21088   CompileRun("obj.__proto__ = null;"
   21089              "f(obj); f(obj); f(obj);");
   21090   if (polymorphic) {
   21091     CompileRun("f({});");
   21092   }
   21093   CompileRun("obj.y = void 0;"
   21094              "%OptimizeFunctionOnNextCall(f);");
   21095   if (remove_accessor) {
   21096     CompileRun("delete obj.foo;");
   21097   }
   21098   CompileRun("var result = f(obj);");
   21099   if (do_store) {
   21100     CompileRun("result = obj.y;");
   21101   }
   21102   if (remove_accessor && !interceptor) {
   21103     CHECK(context->Global()
   21104               ->Get(context.local(), v8_str("result"))
   21105               .ToLocalChecked()
   21106               ->IsUndefined());
   21107   } else {
   21108     CHECK_EQ(do_store ? 23 : 42, context->Global()
   21109                                      ->Get(context.local(), v8_str("result"))
   21110                                      .ToLocalChecked()
   21111                                      ->Int32Value(context.local())
   21112                                      .FromJust());
   21113   }
   21114 }
   21115 
   21116 
   21117 THREADED_TEST(Regress137002a) {
   21118   i::FLAG_allow_natives_syntax = true;
   21119   i::FLAG_compilation_cache = false;
   21120   v8::HandleScope scope(CcTest::isolate());
   21121   for (int i = 0; i < 16; i++) {
   21122     Helper137002(i & 8, i & 4, i & 2, i & 1);
   21123   }
   21124 }
   21125 
   21126 
   21127 THREADED_TEST(Regress137002b) {
   21128   i::FLAG_allow_natives_syntax = true;
   21129   LocalContext context;
   21130   v8::Isolate* isolate = context->GetIsolate();
   21131   v8::HandleScope scope(isolate);
   21132   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21133   templ->SetAccessor(v8_str("foo"),
   21134                      GetterWhichReturns42,
   21135                      SetterWhichSetsYOnThisTo23);
   21136   CHECK(context->Global()
   21137             ->Set(context.local(), v8_str("obj"),
   21138                   templ->NewInstance(context.local()).ToLocalChecked())
   21139             .FromJust());
   21140 
   21141   // Turn monomorphic on slow object with native accessor, then just
   21142   // delete the property and fail.
   21143   CompileRun("function load(x) { return x.foo; }"
   21144              "function store(x) { x.foo = void 0; }"
   21145              "function keyed_load(x, key) { return x[key]; }"
   21146              // Second version of function has a different source (add void 0)
   21147              // so that it does not share code with the first version.  This
   21148              // ensures that the ICs are monomorphic.
   21149              "function load2(x) { void 0; return x.foo; }"
   21150              "function store2(x) { void 0; x.foo = void 0; }"
   21151              "function keyed_load2(x, key) { void 0; return x[key]; }"
   21152 
   21153              "obj.y = void 0;"
   21154              "obj.__proto__ = null;"
   21155              "var subobj = {};"
   21156              "subobj.y = void 0;"
   21157              "subobj.__proto__ = obj;"
   21158              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
   21159 
   21160              // Make the ICs monomorphic.
   21161              "load(obj); load(obj);"
   21162              "load2(subobj); load2(subobj);"
   21163              "store(obj); store(obj);"
   21164              "store2(subobj); store2(subobj);"
   21165              "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
   21166              "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
   21167 
   21168              // Actually test the shiny new ICs and better not crash. This
   21169              // serves as a regression test for issue 142088 as well.
   21170              "load(obj);"
   21171              "load2(subobj);"
   21172              "store(obj);"
   21173              "store2(subobj);"
   21174              "keyed_load(obj, 'foo');"
   21175              "keyed_load2(subobj, 'foo');"
   21176 
   21177              // Delete the accessor.  It better not be called any more now.
   21178              "delete obj.foo;"
   21179              "obj.y = void 0;"
   21180              "subobj.y = void 0;"
   21181 
   21182              "var load_result = load(obj);"
   21183              "var load_result2 = load2(subobj);"
   21184              "var keyed_load_result = keyed_load(obj, 'foo');"
   21185              "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
   21186              "store(obj);"
   21187              "store2(subobj);"
   21188              "var y_from_obj = obj.y;"
   21189              "var y_from_subobj = subobj.y;");
   21190   CHECK(context->Global()
   21191             ->Get(context.local(), v8_str("load_result"))
   21192             .ToLocalChecked()
   21193             ->IsUndefined());
   21194   CHECK(context->Global()
   21195             ->Get(context.local(), v8_str("load_result2"))
   21196             .ToLocalChecked()
   21197             ->IsUndefined());
   21198   CHECK(context->Global()
   21199             ->Get(context.local(), v8_str("keyed_load_result"))
   21200             .ToLocalChecked()
   21201             ->IsUndefined());
   21202   CHECK(context->Global()
   21203             ->Get(context.local(), v8_str("keyed_load_result2"))
   21204             .ToLocalChecked()
   21205             ->IsUndefined());
   21206   CHECK(context->Global()
   21207             ->Get(context.local(), v8_str("y_from_obj"))
   21208             .ToLocalChecked()
   21209             ->IsUndefined());
   21210   CHECK(context->Global()
   21211             ->Get(context.local(), v8_str("y_from_subobj"))
   21212             .ToLocalChecked()
   21213             ->IsUndefined());
   21214 }
   21215 
   21216 
   21217 THREADED_TEST(Regress142088) {
   21218   i::FLAG_allow_natives_syntax = true;
   21219   LocalContext context;
   21220   v8::Isolate* isolate = context->GetIsolate();
   21221   v8::HandleScope scope(isolate);
   21222   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21223   templ->SetAccessor(v8_str("foo"),
   21224                      GetterWhichReturns42,
   21225                      SetterWhichSetsYOnThisTo23);
   21226   CHECK(context->Global()
   21227             ->Set(context.local(), v8_str("obj"),
   21228                   templ->NewInstance(context.local()).ToLocalChecked())
   21229             .FromJust());
   21230 
   21231   CompileRun("function load(x) { return x.foo; }"
   21232              "var o = Object.create(obj);"
   21233              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
   21234              "load(o); load(o); load(o); load(o);");
   21235 }
   21236 
   21237 
   21238 THREADED_TEST(Regress137496) {
   21239   i::FLAG_expose_gc = true;
   21240   LocalContext context;
   21241   v8::HandleScope scope(context->GetIsolate());
   21242 
   21243   // Compile a try-finally clause where the finally block causes a GC
   21244   // while there still is a message pending for external reporting.
   21245   TryCatch try_catch(context->GetIsolate());
   21246   try_catch.SetVerbose(true);
   21247   CompileRun("try { throw new Error(); } finally { gc(); }");
   21248   CHECK(try_catch.HasCaught());
   21249 }
   21250 
   21251 
   21252 THREADED_TEST(Regress157124) {
   21253   LocalContext context;
   21254   v8::Isolate* isolate = context->GetIsolate();
   21255   v8::HandleScope scope(isolate);
   21256   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21257   Local<Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
   21258   obj->GetIdentityHash();
   21259   obj->DeletePrivate(context.local(),
   21260                      v8::Private::ForApi(isolate, v8_str("Bug")))
   21261       .FromJust();
   21262 }
   21263 
   21264 
   21265 THREADED_TEST(Regress2535) {
   21266   LocalContext context;
   21267   v8::HandleScope scope(context->GetIsolate());
   21268   Local<Value> set_value = CompileRun("new Set();");
   21269   Local<Object> set_object(Local<Object>::Cast(set_value));
   21270   CHECK_EQ(0, set_object->InternalFieldCount());
   21271   Local<Value> map_value = CompileRun("new Map();");
   21272   Local<Object> map_object(Local<Object>::Cast(map_value));
   21273   CHECK_EQ(0, map_object->InternalFieldCount());
   21274 }
   21275 
   21276 
   21277 THREADED_TEST(Regress2746) {
   21278   LocalContext context;
   21279   v8::Isolate* isolate = context->GetIsolate();
   21280   v8::HandleScope scope(isolate);
   21281   Local<Object> obj = Object::New(isolate);
   21282   Local<v8::Private> key = v8::Private::New(isolate, v8_str("key"));
   21283   CHECK(
   21284       obj->SetPrivate(context.local(), key, v8::Undefined(isolate)).FromJust());
   21285   Local<Value> value = obj->GetPrivate(context.local(), key).ToLocalChecked();
   21286   CHECK(!value.IsEmpty());
   21287   CHECK(value->IsUndefined());
   21288 }
   21289 
   21290 
   21291 THREADED_TEST(Regress260106) {
   21292   LocalContext context;
   21293   v8::Isolate* isolate = context->GetIsolate();
   21294   v8::HandleScope scope(isolate);
   21295   Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
   21296                                                         DummyCallHandler);
   21297   CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
   21298   Local<Function> function =
   21299       templ->GetFunction(context.local()).ToLocalChecked();
   21300   CHECK(!function.IsEmpty());
   21301   CHECK(function->IsFunction());
   21302 }
   21303 
   21304 
   21305 THREADED_TEST(JSONParseObject) {
   21306   LocalContext context;
   21307   HandleScope scope(context->GetIsolate());
   21308   Local<Value> obj =
   21309       v8::JSON::Parse(context->GetIsolate(), v8_str("{\"x\":42}"))
   21310           .ToLocalChecked();
   21311   Local<Object> global = context->Global();
   21312   global->Set(context.local(), v8_str("obj"), obj).FromJust();
   21313   ExpectString("JSON.stringify(obj)", "{\"x\":42}");
   21314 }
   21315 
   21316 
   21317 THREADED_TEST(JSONParseNumber) {
   21318   LocalContext context;
   21319   HandleScope scope(context->GetIsolate());
   21320   Local<Value> obj =
   21321       v8::JSON::Parse(context->GetIsolate(), v8_str("42")).ToLocalChecked();
   21322   Local<Object> global = context->Global();
   21323   global->Set(context.local(), v8_str("obj"), obj).FromJust();
   21324   ExpectString("JSON.stringify(obj)", "42");
   21325 }
   21326 
   21327 
   21328 #if V8_OS_POSIX && !V8_OS_NACL
   21329 class ThreadInterruptTest {
   21330  public:
   21331   ThreadInterruptTest() : sem_(0), sem_value_(0) { }
   21332   ~ThreadInterruptTest() {}
   21333 
   21334   void RunTest() {
   21335     InterruptThread i_thread(this);
   21336     i_thread.Start();
   21337 
   21338     sem_.Wait();
   21339     CHECK_EQ(kExpectedValue, sem_value_);
   21340   }
   21341 
   21342  private:
   21343   static const int kExpectedValue = 1;
   21344 
   21345   class InterruptThread : public v8::base::Thread {
   21346    public:
   21347     explicit InterruptThread(ThreadInterruptTest* test)
   21348         : Thread(Options("InterruptThread")), test_(test) {}
   21349 
   21350     virtual void Run() {
   21351       struct sigaction action;
   21352 
   21353       // Ensure that we'll enter waiting condition
   21354       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
   21355 
   21356       // Setup signal handler
   21357       memset(&action, 0, sizeof(action));
   21358       action.sa_handler = SignalHandler;
   21359       sigaction(SIGCHLD, &action, NULL);
   21360 
   21361       // Send signal
   21362       kill(getpid(), SIGCHLD);
   21363 
   21364       // Ensure that if wait has returned because of error
   21365       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
   21366 
   21367       // Set value and signal semaphore
   21368       test_->sem_value_ = 1;
   21369       test_->sem_.Signal();
   21370     }
   21371 
   21372     static void SignalHandler(int signal) {
   21373     }
   21374 
   21375    private:
   21376      ThreadInterruptTest* test_;
   21377   };
   21378 
   21379   v8::base::Semaphore sem_;
   21380   volatile int sem_value_;
   21381 };
   21382 
   21383 
   21384 THREADED_TEST(SemaphoreInterruption) {
   21385   ThreadInterruptTest().RunTest();
   21386 }
   21387 
   21388 
   21389 #endif  // V8_OS_POSIX
   21390 
   21391 
   21392 void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   21393   CHECK(false);
   21394 }
   21395 
   21396 
   21397 TEST(JSONStringifyAccessCheck) {
   21398   v8::V8::Initialize();
   21399   v8::Isolate* isolate = CcTest::isolate();
   21400   v8::HandleScope scope(isolate);
   21401 
   21402   // Create an ObjectTemplate for global objects and install access
   21403   // check callbacks that will block access.
   21404   v8::Local<v8::ObjectTemplate> global_template =
   21405       v8::ObjectTemplate::New(isolate);
   21406   global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   21407 
   21408   // Create a context and set an x property on it's global object.
   21409   LocalContext context0(NULL, global_template);
   21410   v8::Local<v8::Object> global0 = context0->Global();
   21411   global0->Set(context0.local(), v8_str("x"), v8_num(42)).FromJust();
   21412   ExpectString("JSON.stringify(this)", "{\"x\":42}");
   21413 
   21414   for (int i = 0; i < 2; i++) {
   21415     if (i == 1) {
   21416       // Install a toJSON function on the second run.
   21417       v8::Local<v8::FunctionTemplate> toJSON =
   21418           v8::FunctionTemplate::New(isolate, UnreachableCallback);
   21419 
   21420       global0->Set(context0.local(), v8_str("toJSON"),
   21421                    toJSON->GetFunction(context0.local()).ToLocalChecked())
   21422           .FromJust();
   21423     }
   21424     // Create a context with a different security token so that the
   21425     // failed access check callback will be called on each access.
   21426     LocalContext context1(NULL, global_template);
   21427     CHECK(context1->Global()
   21428               ->Set(context1.local(), v8_str("other"), global0)
   21429               .FromJust());
   21430 
   21431     CHECK(CompileRun("JSON.stringify(other)").IsEmpty());
   21432     CHECK(CompileRun("JSON.stringify({ 'a' : other, 'b' : ['c'] })").IsEmpty());
   21433     CHECK(CompileRun("JSON.stringify([other, 'b', 'c'])").IsEmpty());
   21434   }
   21435 }
   21436 
   21437 
   21438 bool access_check_fail_thrown = false;
   21439 bool catch_callback_called = false;
   21440 
   21441 
   21442 // Failed access check callback that performs a GC on each invocation.
   21443 void FailedAccessCheckThrows(Local<v8::Object> target,
   21444                              v8::AccessType type,
   21445                              Local<v8::Value> data) {
   21446   access_check_fail_thrown = true;
   21447   i::PrintF("Access check failed. Error thrown.\n");
   21448   CcTest::isolate()->ThrowException(
   21449       v8::Exception::Error(v8_str("cross context")));
   21450 }
   21451 
   21452 
   21453 void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   21454   for (int i = 0; i < args.Length(); i++) {
   21455     i::PrintF("%s\n", *String::Utf8Value(args[i]));
   21456   }
   21457   catch_callback_called = true;
   21458 }
   21459 
   21460 
   21461 void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   21462   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   21463   CHECK(
   21464       args[0]
   21465           ->ToObject(context)
   21466           .ToLocalChecked()
   21467           ->HasOwnProperty(context, args[1]->ToString(context).ToLocalChecked())
   21468           .IsNothing());
   21469 }
   21470 
   21471 
   21472 void CheckCorrectThrow(const char* script) {
   21473   // Test that the script, when wrapped into a try-catch, triggers the catch
   21474   // clause due to failed access check throwing an exception.
   21475   // The subsequent try-catch should run without any exception.
   21476   access_check_fail_thrown = false;
   21477   catch_callback_called = false;
   21478   i::ScopedVector<char> source(1024);
   21479   i::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
   21480   CompileRun(source.start());
   21481   CHECK(access_check_fail_thrown);
   21482   CHECK(catch_callback_called);
   21483 
   21484   access_check_fail_thrown = false;
   21485   catch_callback_called = false;
   21486   CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
   21487   CHECK(!access_check_fail_thrown);
   21488   CHECK(!catch_callback_called);
   21489 }
   21490 
   21491 
   21492 TEST(AccessCheckThrows) {
   21493   i::FLAG_allow_natives_syntax = true;
   21494   v8::V8::Initialize();
   21495   v8::Isolate* isolate = CcTest::isolate();
   21496   isolate->SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
   21497   v8::HandleScope scope(isolate);
   21498 
   21499   // Create an ObjectTemplate for global objects and install access
   21500   // check callbacks that will block access.
   21501   v8::Local<v8::ObjectTemplate> global_template =
   21502       v8::ObjectTemplate::New(isolate);
   21503   global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   21504 
   21505   // Create a context and set an x property on it's global object.
   21506   LocalContext context0(NULL, global_template);
   21507   v8::Local<v8::Object> global0 = context0->Global();
   21508 
   21509   // Create a context with a different security token so that the
   21510   // failed access check callback will be called on each access.
   21511   LocalContext context1(NULL, global_template);
   21512   CHECK(context1->Global()
   21513             ->Set(context1.local(), v8_str("other"), global0)
   21514             .FromJust());
   21515 
   21516   v8::Local<v8::FunctionTemplate> catcher_fun =
   21517       v8::FunctionTemplate::New(isolate, CatcherCallback);
   21518   CHECK(context1->Global()
   21519             ->Set(context1.local(), v8_str("catcher"),
   21520                   catcher_fun->GetFunction(context1.local()).ToLocalChecked())
   21521             .FromJust());
   21522 
   21523   v8::Local<v8::FunctionTemplate> has_own_property_fun =
   21524       v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
   21525   CHECK(context1->Global()
   21526             ->Set(context1.local(), v8_str("has_own_property"),
   21527                   has_own_property_fun->GetFunction(context1.local())
   21528                       .ToLocalChecked())
   21529             .FromJust());
   21530 
   21531   {
   21532     v8::TryCatch try_catch(isolate);
   21533     access_check_fail_thrown = false;
   21534     CompileRun("other.x;");
   21535     CHECK(access_check_fail_thrown);
   21536     CHECK(try_catch.HasCaught());
   21537   }
   21538 
   21539   CheckCorrectThrow("other.x");
   21540   CheckCorrectThrow("other[1]");
   21541   CheckCorrectThrow("JSON.stringify(other)");
   21542   CheckCorrectThrow("has_own_property(other, 'x')");
   21543   CheckCorrectThrow("%GetProperty(other, 'x')");
   21544   CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 0)");
   21545   CheckCorrectThrow("%AddNamedProperty(other, 'x', 'foo', 1)");
   21546   CheckCorrectThrow("%DeleteProperty_Sloppy(other, 'x')");
   21547   CheckCorrectThrow("%DeleteProperty_Strict(other, 'x')");
   21548   CheckCorrectThrow("%DeleteProperty_Sloppy(other, '1')");
   21549   CheckCorrectThrow("%DeleteProperty_Strict(other, '1')");
   21550   CheckCorrectThrow("%HasOwnProperty(other, 'x')");
   21551   CheckCorrectThrow("%HasProperty('x', other)");
   21552   CheckCorrectThrow("%PropertyIsEnumerable(other, 'x')");
   21553   // PROPERTY_ATTRIBUTES_NONE = 0
   21554   CheckCorrectThrow("%DefineAccessorPropertyUnchecked("
   21555                         "other, 'x', null, null, 1)");
   21556 
   21557   // Reset the failed access check callback so it does not influence
   21558   // the other tests.
   21559   isolate->SetFailedAccessCheckCallbackFunction(NULL);
   21560 }
   21561 
   21562 
   21563 class RequestInterruptTestBase {
   21564  public:
   21565   RequestInterruptTestBase()
   21566       : env_(),
   21567         isolate_(env_->GetIsolate()),
   21568         sem_(0),
   21569         warmup_(20000),
   21570         should_continue_(true) {
   21571   }
   21572 
   21573   virtual ~RequestInterruptTestBase() { }
   21574 
   21575   virtual void StartInterruptThread() = 0;
   21576 
   21577   virtual void TestBody() = 0;
   21578 
   21579   void RunTest() {
   21580     StartInterruptThread();
   21581 
   21582     v8::HandleScope handle_scope(isolate_);
   21583 
   21584     TestBody();
   21585 
   21586     // Verify we arrived here because interruptor was called
   21587     // not due to a bug causing us to exit the loop too early.
   21588     CHECK(!should_continue());
   21589   }
   21590 
   21591   void WakeUpInterruptor() {
   21592     sem_.Signal();
   21593   }
   21594 
   21595   bool should_continue() const { return should_continue_; }
   21596 
   21597   bool ShouldContinue() {
   21598     if (warmup_ > 0) {
   21599       if (--warmup_ == 0) {
   21600         WakeUpInterruptor();
   21601       }
   21602     }
   21603 
   21604     return should_continue_;
   21605   }
   21606 
   21607   static void ShouldContinueCallback(
   21608       const v8::FunctionCallbackInfo<Value>& info) {
   21609     RequestInterruptTestBase* test =
   21610         reinterpret_cast<RequestInterruptTestBase*>(
   21611             info.Data().As<v8::External>()->Value());
   21612     info.GetReturnValue().Set(test->ShouldContinue());
   21613   }
   21614 
   21615   LocalContext env_;
   21616   v8::Isolate* isolate_;
   21617   v8::base::Semaphore sem_;
   21618   int warmup_;
   21619   bool should_continue_;
   21620 };
   21621 
   21622 
   21623 class RequestInterruptTestBaseWithSimpleInterrupt
   21624     : public RequestInterruptTestBase {
   21625  public:
   21626   RequestInterruptTestBaseWithSimpleInterrupt() : i_thread(this) { }
   21627 
   21628   virtual void StartInterruptThread() {
   21629     i_thread.Start();
   21630   }
   21631 
   21632  private:
   21633   class InterruptThread : public v8::base::Thread {
   21634    public:
   21635     explicit InterruptThread(RequestInterruptTestBase* test)
   21636         : Thread(Options("RequestInterruptTest")), test_(test) {}
   21637 
   21638     virtual void Run() {
   21639       test_->sem_.Wait();
   21640       test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
   21641     }
   21642 
   21643     static void OnInterrupt(v8::Isolate* isolate, void* data) {
   21644       reinterpret_cast<RequestInterruptTestBase*>(data)->
   21645           should_continue_ = false;
   21646     }
   21647 
   21648    private:
   21649      RequestInterruptTestBase* test_;
   21650   };
   21651 
   21652   InterruptThread i_thread;
   21653 };
   21654 
   21655 
   21656 class RequestInterruptTestWithFunctionCall
   21657     : public RequestInterruptTestBaseWithSimpleInterrupt {
   21658  public:
   21659   virtual void TestBody() {
   21660     Local<Function> func = Function::New(env_.local(), ShouldContinueCallback,
   21661                                          v8::External::New(isolate_, this))
   21662                                .ToLocalChecked();
   21663     CHECK(env_->Global()
   21664               ->Set(env_.local(), v8_str("ShouldContinue"), func)
   21665               .FromJust());
   21666 
   21667     CompileRun("while (ShouldContinue()) { }");
   21668   }
   21669 };
   21670 
   21671 
   21672 class RequestInterruptTestWithMethodCall
   21673     : public RequestInterruptTestBaseWithSimpleInterrupt {
   21674  public:
   21675   virtual void TestBody() {
   21676     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   21677     v8::Local<v8::Template> proto = t->PrototypeTemplate();
   21678     proto->Set(v8_str("shouldContinue"),
   21679                Function::New(env_.local(), ShouldContinueCallback,
   21680                              v8::External::New(isolate_, this))
   21681                    .ToLocalChecked());
   21682     CHECK(env_->Global()
   21683               ->Set(env_.local(), v8_str("Klass"),
   21684                     t->GetFunction(env_.local()).ToLocalChecked())
   21685               .FromJust());
   21686 
   21687     CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
   21688   }
   21689 };
   21690 
   21691 
   21692 class RequestInterruptTestWithAccessor
   21693     : public RequestInterruptTestBaseWithSimpleInterrupt {
   21694  public:
   21695   virtual void TestBody() {
   21696     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   21697     v8::Local<v8::Template> proto = t->PrototypeTemplate();
   21698     proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
   21699         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
   21700     CHECK(env_->Global()
   21701               ->Set(env_.local(), v8_str("Klass"),
   21702                     t->GetFunction(env_.local()).ToLocalChecked())
   21703               .FromJust());
   21704 
   21705     CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
   21706   }
   21707 };
   21708 
   21709 
   21710 class RequestInterruptTestWithNativeAccessor
   21711     : public RequestInterruptTestBaseWithSimpleInterrupt {
   21712  public:
   21713   virtual void TestBody() {
   21714     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   21715     t->InstanceTemplate()->SetNativeDataProperty(
   21716         v8_str("shouldContinue"),
   21717         &ShouldContinueNativeGetter,
   21718         NULL,
   21719         v8::External::New(isolate_, this));
   21720     CHECK(env_->Global()
   21721               ->Set(env_.local(), v8_str("Klass"),
   21722                     t->GetFunction(env_.local()).ToLocalChecked())
   21723               .FromJust());
   21724 
   21725     CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
   21726   }
   21727 
   21728  private:
   21729   static void ShouldContinueNativeGetter(
   21730       Local<String> property,
   21731       const v8::PropertyCallbackInfo<v8::Value>& info) {
   21732     RequestInterruptTestBase* test =
   21733         reinterpret_cast<RequestInterruptTestBase*>(
   21734             info.Data().As<v8::External>()->Value());
   21735     info.GetReturnValue().Set(test->ShouldContinue());
   21736   }
   21737 };
   21738 
   21739 
   21740 class RequestInterruptTestWithMethodCallAndInterceptor
   21741     : public RequestInterruptTestBaseWithSimpleInterrupt {
   21742  public:
   21743   virtual void TestBody() {
   21744     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   21745     v8::Local<v8::Template> proto = t->PrototypeTemplate();
   21746     proto->Set(v8_str("shouldContinue"),
   21747                Function::New(env_.local(), ShouldContinueCallback,
   21748                              v8::External::New(isolate_, this))
   21749                    .ToLocalChecked());
   21750     v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
   21751     instance_template->SetHandler(
   21752         v8::NamedPropertyHandlerConfiguration(EmptyInterceptor));
   21753 
   21754     CHECK(env_->Global()
   21755               ->Set(env_.local(), v8_str("Klass"),
   21756                     t->GetFunction(env_.local()).ToLocalChecked())
   21757               .FromJust());
   21758 
   21759     CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
   21760   }
   21761 
   21762  private:
   21763   static void EmptyInterceptor(
   21764       Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {}
   21765 };
   21766 
   21767 
   21768 class RequestInterruptTestWithMathAbs
   21769     : public RequestInterruptTestBaseWithSimpleInterrupt {
   21770  public:
   21771   virtual void TestBody() {
   21772     env_->Global()
   21773         ->Set(env_.local(), v8_str("WakeUpInterruptor"),
   21774               Function::New(env_.local(), WakeUpInterruptorCallback,
   21775                             v8::External::New(isolate_, this))
   21776                   .ToLocalChecked())
   21777         .FromJust();
   21778 
   21779     env_->Global()
   21780         ->Set(env_.local(), v8_str("ShouldContinue"),
   21781               Function::New(env_.local(), ShouldContinueCallback,
   21782                             v8::External::New(isolate_, this))
   21783                   .ToLocalChecked())
   21784         .FromJust();
   21785 
   21786     i::FLAG_allow_natives_syntax = true;
   21787     CompileRun("function loopish(o) {"
   21788                "  var pre = 10;"
   21789                "  while (o.abs(1) > 0) {"
   21790                "    if (o.abs(1) >= 0 && !ShouldContinue()) break;"
   21791                "    if (pre > 0) {"
   21792                "      if (--pre === 0) WakeUpInterruptor(o === Math);"
   21793                "    }"
   21794                "  }"
   21795                "}"
   21796                "var i = 50;"
   21797                "var obj = {abs: function () { return i-- }, x: null};"
   21798                "delete obj.x;"
   21799                "loopish(obj);"
   21800                "%OptimizeFunctionOnNextCall(loopish);"
   21801                "loopish(Math);");
   21802 
   21803     i::FLAG_allow_natives_syntax = false;
   21804   }
   21805 
   21806  private:
   21807   static void WakeUpInterruptorCallback(
   21808       const v8::FunctionCallbackInfo<Value>& info) {
   21809     if (!info[0]
   21810              ->BooleanValue(info.GetIsolate()->GetCurrentContext())
   21811              .FromJust()) {
   21812       return;
   21813     }
   21814 
   21815     RequestInterruptTestBase* test =
   21816         reinterpret_cast<RequestInterruptTestBase*>(
   21817             info.Data().As<v8::External>()->Value());
   21818     test->WakeUpInterruptor();
   21819   }
   21820 
   21821   static void ShouldContinueCallback(
   21822       const v8::FunctionCallbackInfo<Value>& info) {
   21823     RequestInterruptTestBase* test =
   21824         reinterpret_cast<RequestInterruptTestBase*>(
   21825             info.Data().As<v8::External>()->Value());
   21826     info.GetReturnValue().Set(test->should_continue());
   21827   }
   21828 };
   21829 
   21830 
   21831 TEST(RequestInterruptTestWithFunctionCall) {
   21832   RequestInterruptTestWithFunctionCall().RunTest();
   21833 }
   21834 
   21835 
   21836 TEST(RequestInterruptTestWithMethodCall) {
   21837   RequestInterruptTestWithMethodCall().RunTest();
   21838 }
   21839 
   21840 
   21841 TEST(RequestInterruptTestWithAccessor) {
   21842   RequestInterruptTestWithAccessor().RunTest();
   21843 }
   21844 
   21845 
   21846 TEST(RequestInterruptTestWithNativeAccessor) {
   21847   RequestInterruptTestWithNativeAccessor().RunTest();
   21848 }
   21849 
   21850 
   21851 TEST(RequestInterruptTestWithMethodCallAndInterceptor) {
   21852   RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
   21853 }
   21854 
   21855 
   21856 TEST(RequestInterruptTestWithMathAbs) {
   21857   RequestInterruptTestWithMathAbs().RunTest();
   21858 }
   21859 
   21860 
   21861 class RequestMultipleInterrupts : public RequestInterruptTestBase {
   21862  public:
   21863   RequestMultipleInterrupts() : i_thread(this), counter_(0) {}
   21864 
   21865   virtual void StartInterruptThread() {
   21866     i_thread.Start();
   21867   }
   21868 
   21869   virtual void TestBody() {
   21870     Local<Function> func = Function::New(env_.local(), ShouldContinueCallback,
   21871                                          v8::External::New(isolate_, this))
   21872                                .ToLocalChecked();
   21873     CHECK(env_->Global()
   21874               ->Set(env_.local(), v8_str("ShouldContinue"), func)
   21875               .FromJust());
   21876 
   21877     CompileRun("while (ShouldContinue()) { }");
   21878   }
   21879 
   21880  private:
   21881   class InterruptThread : public v8::base::Thread {
   21882    public:
   21883     enum { NUM_INTERRUPTS = 10 };
   21884     explicit InterruptThread(RequestMultipleInterrupts* test)
   21885         : Thread(Options("RequestInterruptTest")), test_(test) {}
   21886 
   21887     virtual void Run() {
   21888       test_->sem_.Wait();
   21889       for (int i = 0; i < NUM_INTERRUPTS; i++) {
   21890         test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
   21891       }
   21892     }
   21893 
   21894     static void OnInterrupt(v8::Isolate* isolate, void* data) {
   21895       RequestMultipleInterrupts* test =
   21896           reinterpret_cast<RequestMultipleInterrupts*>(data);
   21897       test->should_continue_ = ++test->counter_ < NUM_INTERRUPTS;
   21898     }
   21899 
   21900    private:
   21901     RequestMultipleInterrupts* test_;
   21902   };
   21903 
   21904   InterruptThread i_thread;
   21905   int counter_;
   21906 };
   21907 
   21908 
   21909 TEST(RequestMultipleInterrupts) { RequestMultipleInterrupts().RunTest(); }
   21910 
   21911 
   21912 static bool interrupt_was_called = false;
   21913 
   21914 
   21915 void SmallScriptsInterruptCallback(v8::Isolate* isolate, void* data) {
   21916   interrupt_was_called = true;
   21917 }
   21918 
   21919 
   21920 TEST(RequestInterruptSmallScripts) {
   21921   LocalContext env;
   21922   v8::Isolate* isolate = CcTest::isolate();
   21923   v8::HandleScope scope(isolate);
   21924 
   21925   interrupt_was_called = false;
   21926   isolate->RequestInterrupt(&SmallScriptsInterruptCallback, NULL);
   21927   CompileRun("(function(x){return x;})(1);");
   21928   CHECK(interrupt_was_called);
   21929 }
   21930 
   21931 
   21932 static Local<Value> function_new_expected_env;
   21933 static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
   21934   CHECK(
   21935       function_new_expected_env->Equals(info.GetIsolate()->GetCurrentContext(),
   21936                                         info.Data())
   21937           .FromJust());
   21938   info.GetReturnValue().Set(17);
   21939 }
   21940 
   21941 
   21942 THREADED_TEST(FunctionNew) {
   21943   LocalContext env;
   21944   v8::Isolate* isolate = env->GetIsolate();
   21945   v8::HandleScope scope(isolate);
   21946   Local<Object> data = v8::Object::New(isolate);
   21947   function_new_expected_env = data;
   21948   Local<Function> func =
   21949       Function::New(env.local(), FunctionNewCallback, data).ToLocalChecked();
   21950   CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   21951   Local<Value> result = CompileRun("func();");
   21952   CHECK(v8::Integer::New(isolate, 17)->Equals(env.local(), result).FromJust());
   21953   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   21954   // Verify function not cached
   21955   auto serial_number = handle(
   21956       i::Smi::cast(i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*func))
   21957                        ->shared()
   21958                        ->get_api_func_data()
   21959                        ->serial_number()),
   21960       i_isolate);
   21961   auto cache = i_isolate->function_cache();
   21962   CHECK(cache->Lookup(serial_number)->IsTheHole());
   21963   // Verify that each Function::New creates a new function instance
   21964   Local<Object> data2 = v8::Object::New(isolate);
   21965   function_new_expected_env = data2;
   21966   Local<Function> func2 =
   21967       Function::New(env.local(), FunctionNewCallback, data2).ToLocalChecked();
   21968   CHECK(!func2->IsNull());
   21969   CHECK(!func->Equals(env.local(), func2).FromJust());
   21970   CHECK(env->Global()->Set(env.local(), v8_str("func2"), func2).FromJust());
   21971   Local<Value> result2 = CompileRun("func2();");
   21972   CHECK(v8::Integer::New(isolate, 17)->Equals(env.local(), result2).FromJust());
   21973 }
   21974 
   21975 
   21976 TEST(EscapeableHandleScope) {
   21977   HandleScope outer_scope(CcTest::isolate());
   21978   LocalContext context;
   21979   const int runs = 10;
   21980   Local<String> values[runs];
   21981   for (int i = 0; i < runs; i++) {
   21982     v8::EscapableHandleScope inner_scope(CcTest::isolate());
   21983     Local<String> value;
   21984     if (i != 0) value = v8_str("escape value");
   21985     values[i] = inner_scope.Escape(value);
   21986   }
   21987   for (int i = 0; i < runs; i++) {
   21988     Local<String> expected;
   21989     if (i != 0) {
   21990       CHECK(v8_str("escape value")
   21991                 ->Equals(context.local(), values[i])
   21992                 .FromJust());
   21993     } else {
   21994       CHECK(values[i].IsEmpty());
   21995     }
   21996   }
   21997 }
   21998 
   21999 
   22000 static void SetterWhichExpectsThisAndHolderToDiffer(
   22001     Local<String>, Local<Value>, const v8::PropertyCallbackInfo<void>& info) {
   22002   CHECK(info.Holder() != info.This());
   22003 }
   22004 
   22005 
   22006 TEST(Regress239669) {
   22007   LocalContext context;
   22008   v8::Isolate* isolate = context->GetIsolate();
   22009   v8::HandleScope scope(isolate);
   22010   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   22011   templ->SetAccessor(v8_str("x"), 0, SetterWhichExpectsThisAndHolderToDiffer);
   22012   CHECK(context->Global()
   22013             ->Set(context.local(), v8_str("P"),
   22014                   templ->NewInstance(context.local()).ToLocalChecked())
   22015             .FromJust());
   22016   CompileRun(
   22017       "function C1() {"
   22018       "  this.x = 23;"
   22019       "};"
   22020       "C1.prototype = P;"
   22021       "for (var i = 0; i < 4; i++ ) {"
   22022       "  new C1();"
   22023       "}");
   22024 }
   22025 
   22026 
   22027 class ApiCallOptimizationChecker {
   22028  private:
   22029   static Local<Object> data;
   22030   static Local<Object> receiver;
   22031   static Local<Object> holder;
   22032   static Local<Object> callee;
   22033   static int count;
   22034 
   22035   static void OptimizationCallback(
   22036       const v8::FunctionCallbackInfo<v8::Value>& info) {
   22037     CHECK(callee == info.Callee());
   22038     CHECK(data == info.Data());
   22039     CHECK(receiver == info.This());
   22040     if (info.Length() == 1) {
   22041       CHECK(v8_num(1)
   22042                 ->Equals(info.GetIsolate()->GetCurrentContext(), info[0])
   22043                 .FromJust());
   22044     }
   22045     CHECK(holder == info.Holder());
   22046     count++;
   22047     info.GetReturnValue().Set(v8_str("returned"));
   22048   }
   22049 
   22050  public:
   22051   enum SignatureType {
   22052     kNoSignature,
   22053     kSignatureOnReceiver,
   22054     kSignatureOnPrototype
   22055   };
   22056 
   22057   void RunAll() {
   22058     SignatureType signature_types[] =
   22059       {kNoSignature, kSignatureOnReceiver, kSignatureOnPrototype};
   22060     for (unsigned i = 0; i < arraysize(signature_types); i++) {
   22061       SignatureType signature_type = signature_types[i];
   22062       for (int j = 0; j < 2; j++) {
   22063         bool global = j == 0;
   22064         int key = signature_type +
   22065             arraysize(signature_types) * (global ? 1 : 0);
   22066         Run(signature_type, global, key);
   22067       }
   22068     }
   22069   }
   22070 
   22071   void Run(SignatureType signature_type, bool global, int key) {
   22072     v8::Isolate* isolate = CcTest::isolate();
   22073     v8::HandleScope scope(isolate);
   22074     // Build a template for signature checks.
   22075     Local<v8::ObjectTemplate> signature_template;
   22076     Local<v8::Signature> signature;
   22077     {
   22078       Local<v8::FunctionTemplate> parent_template =
   22079         FunctionTemplate::New(isolate);
   22080       parent_template->SetHiddenPrototype(true);
   22081       Local<v8::FunctionTemplate> function_template
   22082           = FunctionTemplate::New(isolate);
   22083       function_template->Inherit(parent_template);
   22084       switch (signature_type) {
   22085         case kNoSignature:
   22086           break;
   22087         case kSignatureOnReceiver:
   22088           signature = v8::Signature::New(isolate, function_template);
   22089           break;
   22090         case kSignatureOnPrototype:
   22091           signature = v8::Signature::New(isolate, parent_template);
   22092           break;
   22093       }
   22094       signature_template = function_template->InstanceTemplate();
   22095     }
   22096     // Global object must pass checks.
   22097     Local<v8::Context> context =
   22098         v8::Context::New(isolate, NULL, signature_template);
   22099     v8::Context::Scope context_scope(context);
   22100     // Install regular object that can pass signature checks.
   22101     Local<Object> function_receiver =
   22102         signature_template->NewInstance(context).ToLocalChecked();
   22103     CHECK(context->Global()
   22104               ->Set(context, v8_str("function_receiver"), function_receiver)
   22105               .FromJust());
   22106     // Get the holder objects.
   22107     Local<Object> inner_global =
   22108         Local<Object>::Cast(context->Global()->GetPrototype());
   22109     // Install functions on hidden prototype object if there is one.
   22110     data = Object::New(isolate);
   22111     Local<FunctionTemplate> function_template = FunctionTemplate::New(
   22112         isolate, OptimizationCallback, data, signature);
   22113     Local<Function> function =
   22114         function_template->GetFunction(context).ToLocalChecked();
   22115     Local<Object> global_holder = inner_global;
   22116     Local<Object> function_holder = function_receiver;
   22117     if (signature_type == kSignatureOnPrototype) {
   22118       function_holder = Local<Object>::Cast(function_holder->GetPrototype());
   22119       global_holder = Local<Object>::Cast(global_holder->GetPrototype());
   22120     }
   22121     global_holder->Set(context, v8_str("g_f"), function).FromJust();
   22122     global_holder->SetAccessorProperty(v8_str("g_acc"), function, function);
   22123     function_holder->Set(context, v8_str("f"), function).FromJust();
   22124     function_holder->SetAccessorProperty(v8_str("acc"), function, function);
   22125     // Initialize expected values.
   22126     callee = function;
   22127     count = 0;
   22128     if (global) {
   22129       receiver = context->Global();
   22130       holder = inner_global;
   22131     } else {
   22132       holder = function_receiver;
   22133       // If not using a signature, add something else to the prototype chain
   22134       // to test the case that holder != receiver
   22135       if (signature_type == kNoSignature) {
   22136         receiver = Local<Object>::Cast(CompileRun(
   22137             "var receiver_subclass = {};\n"
   22138             "receiver_subclass.__proto__ = function_receiver;\n"
   22139             "receiver_subclass"));
   22140       } else {
   22141         receiver = Local<Object>::Cast(CompileRun(
   22142           "var receiver_subclass = function_receiver;\n"
   22143           "receiver_subclass"));
   22144       }
   22145     }
   22146     // With no signature, the holder is not set.
   22147     if (signature_type == kNoSignature) holder = receiver;
   22148     // build wrap_function
   22149     i::ScopedVector<char> wrap_function(200);
   22150     if (global) {
   22151       i::SNPrintF(
   22152           wrap_function,
   22153           "function wrap_f_%d() { var f = g_f; return f(); }\n"
   22154           "function wrap_get_%d() { return this.g_acc; }\n"
   22155           "function wrap_set_%d() { return this.g_acc = 1; }\n",
   22156           key, key, key);
   22157     } else {
   22158       i::SNPrintF(
   22159           wrap_function,
   22160           "function wrap_f_%d() { return receiver_subclass.f(); }\n"
   22161           "function wrap_get_%d() { return receiver_subclass.acc; }\n"
   22162           "function wrap_set_%d() { return receiver_subclass.acc = 1; }\n",
   22163           key, key, key);
   22164     }
   22165     // build source string
   22166     i::ScopedVector<char> source(1000);
   22167     i::SNPrintF(
   22168         source,
   22169         "%s\n"  // wrap functions
   22170         "function wrap_f() { return wrap_f_%d(); }\n"
   22171         "function wrap_get() { return wrap_get_%d(); }\n"
   22172         "function wrap_set() { return wrap_set_%d(); }\n"
   22173         "check = function(returned) {\n"
   22174         "  if (returned !== 'returned') { throw returned; }\n"
   22175         "}\n"
   22176         "\n"
   22177         "check(wrap_f());\n"
   22178         "check(wrap_f());\n"
   22179         "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
   22180         "check(wrap_f());\n"
   22181         "\n"
   22182         "check(wrap_get());\n"
   22183         "check(wrap_get());\n"
   22184         "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
   22185         "check(wrap_get());\n"
   22186         "\n"
   22187         "check = function(returned) {\n"
   22188         "  if (returned !== 1) { throw returned; }\n"
   22189         "}\n"
   22190         "check(wrap_set());\n"
   22191         "check(wrap_set());\n"
   22192         "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
   22193         "check(wrap_set());\n",
   22194         wrap_function.start(), key, key, key, key, key, key);
   22195     v8::TryCatch try_catch(isolate);
   22196     CompileRun(source.start());
   22197     CHECK(!try_catch.HasCaught());
   22198     CHECK_EQ(9, count);
   22199   }
   22200 };
   22201 
   22202 
   22203 Local<Object> ApiCallOptimizationChecker::data;
   22204 Local<Object> ApiCallOptimizationChecker::receiver;
   22205 Local<Object> ApiCallOptimizationChecker::holder;
   22206 Local<Object> ApiCallOptimizationChecker::callee;
   22207 int ApiCallOptimizationChecker::count = 0;
   22208 
   22209 
   22210 TEST(FunctionCallOptimization) {
   22211   i::FLAG_allow_natives_syntax = true;
   22212   ApiCallOptimizationChecker checker;
   22213   checker.RunAll();
   22214 }
   22215 
   22216 
   22217 TEST(FunctionCallOptimizationMultipleArgs) {
   22218   i::FLAG_allow_natives_syntax = true;
   22219   LocalContext context;
   22220   v8::Isolate* isolate = context->GetIsolate();
   22221   v8::HandleScope scope(isolate);
   22222   Local<Object> global = context->Global();
   22223   Local<v8::Function> function =
   22224       Function::New(context.local(), Returns42).ToLocalChecked();
   22225   global->Set(context.local(), v8_str("x"), function).FromJust();
   22226   CompileRun(
   22227       "function x_wrap() {\n"
   22228       "  for (var i = 0; i < 5; i++) {\n"
   22229       "    x(1,2,3);\n"
   22230       "  }\n"
   22231       "}\n"
   22232       "x_wrap();\n"
   22233       "%OptimizeFunctionOnNextCall(x_wrap);"
   22234       "x_wrap();\n");
   22235 }
   22236 
   22237 
   22238 static void ReturnsSymbolCallback(
   22239     const v8::FunctionCallbackInfo<v8::Value>& info) {
   22240   info.GetReturnValue().Set(v8::Symbol::New(info.GetIsolate()));
   22241 }
   22242 
   22243 
   22244 TEST(ApiCallbackCanReturnSymbols) {
   22245   i::FLAG_allow_natives_syntax = true;
   22246   LocalContext context;
   22247   v8::Isolate* isolate = context->GetIsolate();
   22248   v8::HandleScope scope(isolate);
   22249   Local<Object> global = context->Global();
   22250   Local<v8::Function> function =
   22251       Function::New(context.local(), ReturnsSymbolCallback).ToLocalChecked();
   22252   global->Set(context.local(), v8_str("x"), function).FromJust();
   22253   CompileRun(
   22254       "function x_wrap() {\n"
   22255       "  for (var i = 0; i < 5; i++) {\n"
   22256       "    x();\n"
   22257       "  }\n"
   22258       "}\n"
   22259       "x_wrap();\n"
   22260       "%OptimizeFunctionOnNextCall(x_wrap);"
   22261       "x_wrap();\n");
   22262 }
   22263 
   22264 
   22265 TEST(EmptyApiCallback) {
   22266   LocalContext context;
   22267   auto isolate = context->GetIsolate();
   22268   v8::HandleScope scope(isolate);
   22269   auto global = context->Global();
   22270   auto function = FunctionTemplate::New(isolate)
   22271                       ->GetFunction(context.local())
   22272                       .ToLocalChecked();
   22273   global->Set(context.local(), v8_str("x"), function).FromJust();
   22274 
   22275   auto result = CompileRun("x()");
   22276   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
   22277 
   22278   result = CompileRun("x(1,2,3)");
   22279   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
   22280 
   22281   result = CompileRun("x.call(undefined)");
   22282   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
   22283 
   22284   result = CompileRun("x.call(null)");
   22285   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
   22286 
   22287   result = CompileRun("7 + x.call(3) + 11");
   22288   CHECK(result->IsInt32());
   22289   CHECK_EQ(21, result->Int32Value(context.local()).FromJust());
   22290 
   22291   result = CompileRun("7 + x.call(3, 101, 102, 103, 104) + 11");
   22292   CHECK(result->IsInt32());
   22293   CHECK_EQ(21, result->Int32Value(context.local()).FromJust());
   22294 
   22295   result = CompileRun("var y = []; x.call(y)");
   22296   CHECK(result->IsArray());
   22297 
   22298   result = CompileRun("x.call(y, 1, 2, 3, 4)");
   22299   CHECK(result->IsArray());
   22300 }
   22301 
   22302 
   22303 TEST(SimpleSignatureCheck) {
   22304   LocalContext context;
   22305   auto isolate = context->GetIsolate();
   22306   v8::HandleScope scope(isolate);
   22307   auto global = context->Global();
   22308   auto sig_obj = FunctionTemplate::New(isolate);
   22309   auto sig = v8::Signature::New(isolate, sig_obj);
   22310   auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
   22311   global->Set(context.local(), v8_str("sig_obj"),
   22312               sig_obj->GetFunction(context.local()).ToLocalChecked())
   22313       .FromJust();
   22314   global->Set(context.local(), v8_str("x"),
   22315               x->GetFunction(context.local()).ToLocalChecked())
   22316       .FromJust();
   22317   CompileRun("var s = new sig_obj();");
   22318   {
   22319     TryCatch try_catch(isolate);
   22320     CompileRun("x()");
   22321     CHECK(try_catch.HasCaught());
   22322   }
   22323   {
   22324     TryCatch try_catch(isolate);
   22325     CompileRun("x.call(1)");
   22326     CHECK(try_catch.HasCaught());
   22327   }
   22328   {
   22329     TryCatch try_catch(isolate);
   22330     auto result = CompileRun("s.x = x; s.x()");
   22331     CHECK(!try_catch.HasCaught());
   22332     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   22333   }
   22334   {
   22335     TryCatch try_catch(isolate);
   22336     auto result = CompileRun("x.call(s)");
   22337     CHECK(!try_catch.HasCaught());
   22338     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   22339   }
   22340 }
   22341 
   22342 
   22343 TEST(ChainSignatureCheck) {
   22344   LocalContext context;
   22345   auto isolate = context->GetIsolate();
   22346   v8::HandleScope scope(isolate);
   22347   auto global = context->Global();
   22348   auto sig_obj = FunctionTemplate::New(isolate);
   22349   auto sig = v8::Signature::New(isolate, sig_obj);
   22350   for (int i = 0; i < 4; ++i) {
   22351     auto temp = FunctionTemplate::New(isolate);
   22352     temp->Inherit(sig_obj);
   22353     sig_obj = temp;
   22354   }
   22355   auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
   22356   global->Set(context.local(), v8_str("sig_obj"),
   22357               sig_obj->GetFunction(context.local()).ToLocalChecked())
   22358       .FromJust();
   22359   global->Set(context.local(), v8_str("x"),
   22360               x->GetFunction(context.local()).ToLocalChecked())
   22361       .FromJust();
   22362   CompileRun("var s = new sig_obj();");
   22363   {
   22364     TryCatch try_catch(isolate);
   22365     CompileRun("x()");
   22366     CHECK(try_catch.HasCaught());
   22367   }
   22368   {
   22369     TryCatch try_catch(isolate);
   22370     CompileRun("x.call(1)");
   22371     CHECK(try_catch.HasCaught());
   22372   }
   22373   {
   22374     TryCatch try_catch(isolate);
   22375     auto result = CompileRun("s.x = x; s.x()");
   22376     CHECK(!try_catch.HasCaught());
   22377     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   22378   }
   22379   {
   22380     TryCatch try_catch(isolate);
   22381     auto result = CompileRun("x.call(s)");
   22382     CHECK(!try_catch.HasCaught());
   22383     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   22384   }
   22385 }
   22386 
   22387 
   22388 TEST(PrototypeSignatureCheck) {
   22389   LocalContext context;
   22390   auto isolate = context->GetIsolate();
   22391   v8::HandleScope scope(isolate);
   22392   auto global = context->Global();
   22393   auto sig_obj = FunctionTemplate::New(isolate);
   22394   sig_obj->SetHiddenPrototype(true);
   22395   auto sig = v8::Signature::New(isolate, sig_obj);
   22396   auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
   22397   global->Set(context.local(), v8_str("sig_obj"),
   22398               sig_obj->GetFunction(context.local()).ToLocalChecked())
   22399       .FromJust();
   22400   global->Set(context.local(), v8_str("x"),
   22401               x->GetFunction(context.local()).ToLocalChecked())
   22402       .FromJust();
   22403   CompileRun("s = {}; s.__proto__ = new sig_obj();");
   22404   {
   22405     TryCatch try_catch(isolate);
   22406     CompileRun("x()");
   22407     CHECK(try_catch.HasCaught());
   22408   }
   22409   {
   22410     TryCatch try_catch(isolate);
   22411     CompileRun("x.call(1)");
   22412     CHECK(try_catch.HasCaught());
   22413   }
   22414   {
   22415     TryCatch try_catch(isolate);
   22416     auto result = CompileRun("s.x = x; s.x()");
   22417     CHECK(!try_catch.HasCaught());
   22418     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   22419   }
   22420   {
   22421     TryCatch try_catch(isolate);
   22422     auto result = CompileRun("x.call(s)");
   22423     CHECK(!try_catch.HasCaught());
   22424     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   22425   }
   22426 }
   22427 
   22428 
   22429 static const char* last_event_message;
   22430 static int last_event_status;
   22431 void StoringEventLoggerCallback(const char* message, int status) {
   22432     last_event_message = message;
   22433     last_event_status = status;
   22434 }
   22435 
   22436 
   22437 TEST(EventLogging) {
   22438   v8::Isolate* isolate = CcTest::isolate();
   22439   isolate->SetEventLogger(StoringEventLoggerCallback);
   22440   v8::internal::HistogramTimer histogramTimer(
   22441       "V8.Test", 0, 10000, v8::internal::HistogramTimer::MILLISECOND, 50,
   22442       reinterpret_cast<v8::internal::Isolate*>(isolate));
   22443   histogramTimer.Start();
   22444   CHECK_EQ(0, strcmp("V8.Test", last_event_message));
   22445   CHECK_EQ(0, last_event_status);
   22446   histogramTimer.Stop();
   22447   CHECK_EQ(0, strcmp("V8.Test", last_event_message));
   22448   CHECK_EQ(1, last_event_status);
   22449 }
   22450 
   22451 
   22452 TEST(Promises) {
   22453   LocalContext context;
   22454   v8::Isolate* isolate = context->GetIsolate();
   22455   v8::HandleScope scope(isolate);
   22456 
   22457   // Creation.
   22458   Local<v8::Promise::Resolver> pr =
   22459       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   22460   Local<v8::Promise::Resolver> rr =
   22461       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   22462   Local<v8::Promise> p = pr->GetPromise();
   22463   Local<v8::Promise> r = rr->GetPromise();
   22464 
   22465   // IsPromise predicate.
   22466   CHECK(p->IsPromise());
   22467   CHECK(r->IsPromise());
   22468   Local<Value> o = v8::Object::New(isolate);
   22469   CHECK(!o->IsPromise());
   22470 
   22471   // Resolution and rejection.
   22472   pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
   22473   CHECK(p->IsPromise());
   22474   rr->Reject(context.local(), v8::Integer::New(isolate, 2)).FromJust();
   22475   CHECK(r->IsPromise());
   22476 }
   22477 
   22478 
   22479 TEST(PromiseThen) {
   22480   LocalContext context;
   22481   v8::Isolate* isolate = context->GetIsolate();
   22482   v8::HandleScope scope(isolate);
   22483   Local<Object> global = context->Global();
   22484 
   22485   // Creation.
   22486   Local<v8::Promise::Resolver> pr =
   22487       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   22488   Local<v8::Promise::Resolver> qr =
   22489       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   22490   Local<v8::Promise> p = pr->GetPromise();
   22491   Local<v8::Promise> q = qr->GetPromise();
   22492 
   22493   CHECK(p->IsPromise());
   22494   CHECK(q->IsPromise());
   22495 
   22496   pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
   22497   qr->Resolve(context.local(), p).FromJust();
   22498 
   22499   // Chaining non-pending promises.
   22500   CompileRun(
   22501       "var x1 = 0;\n"
   22502       "var x2 = 0;\n"
   22503       "function f1(x) { x1 = x; return x+1 };\n"
   22504       "function f2(x) { x2 = x; return x+1 };\n");
   22505   Local<Function> f1 = Local<Function>::Cast(
   22506       global->Get(context.local(), v8_str("f1")).ToLocalChecked());
   22507   Local<Function> f2 = Local<Function>::Cast(
   22508       global->Get(context.local(), v8_str("f2")).ToLocalChecked());
   22509 
   22510   // Then
   22511   CompileRun("x1 = x2 = 0;");
   22512   q->Then(context.local(), f1).ToLocalChecked();
   22513   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   22514                   .ToLocalChecked()
   22515                   ->Int32Value(context.local())
   22516                   .FromJust());
   22517   isolate->RunMicrotasks();
   22518   CHECK_EQ(1, global->Get(context.local(), v8_str("x1"))
   22519                   .ToLocalChecked()
   22520                   ->Int32Value(context.local())
   22521                   .FromJust());
   22522 
   22523   // Then
   22524   CompileRun("x1 = x2 = 0;");
   22525   pr = v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   22526   qr = v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   22527 
   22528   qr->Resolve(context.local(), pr).FromJust();
   22529   qr->GetPromise()
   22530       ->Then(context.local(), f1)
   22531       .ToLocalChecked()
   22532       ->Then(context.local(), f2)
   22533       .ToLocalChecked();
   22534 
   22535   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   22536                   .ToLocalChecked()
   22537                   ->Int32Value(context.local())
   22538                   .FromJust());
   22539   CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
   22540                   .ToLocalChecked()
   22541                   ->Int32Value(context.local())
   22542                   .FromJust());
   22543   isolate->RunMicrotasks();
   22544   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   22545                   .ToLocalChecked()
   22546                   ->Int32Value(context.local())
   22547                   .FromJust());
   22548   CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
   22549                   .ToLocalChecked()
   22550                   ->Int32Value(context.local())
   22551                   .FromJust());
   22552 
   22553   pr->Resolve(context.local(), v8::Integer::New(isolate, 3)).FromJust();
   22554 
   22555   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   22556                   .ToLocalChecked()
   22557                   ->Int32Value(context.local())
   22558                   .FromJust());
   22559   CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
   22560                   .ToLocalChecked()
   22561                   ->Int32Value(context.local())
   22562                   .FromJust());
   22563   isolate->RunMicrotasks();
   22564   CHECK_EQ(3, global->Get(context.local(), v8_str("x1"))
   22565                   .ToLocalChecked()
   22566                   ->Int32Value(context.local())
   22567                   .FromJust());
   22568   CHECK_EQ(4, global->Get(context.local(), v8_str("x2"))
   22569                   .ToLocalChecked()
   22570                   ->Int32Value(context.local())
   22571                   .FromJust());
   22572 }
   22573 
   22574 
   22575 TEST(DisallowJavascriptExecutionScope) {
   22576   LocalContext context;
   22577   v8::Isolate* isolate = context->GetIsolate();
   22578   v8::HandleScope scope(isolate);
   22579   v8::Isolate::DisallowJavascriptExecutionScope no_js(
   22580       isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
   22581   CompileRun("2+2");
   22582 }
   22583 
   22584 
   22585 TEST(AllowJavascriptExecutionScope) {
   22586   LocalContext context;
   22587   v8::Isolate* isolate = context->GetIsolate();
   22588   v8::HandleScope scope(isolate);
   22589   v8::Isolate::DisallowJavascriptExecutionScope no_js(
   22590       isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
   22591   v8::Isolate::DisallowJavascriptExecutionScope throw_js(
   22592       isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
   22593   { v8::Isolate::AllowJavascriptExecutionScope yes_js(isolate);
   22594     CompileRun("1+1");
   22595   }
   22596 }
   22597 
   22598 
   22599 TEST(ThrowOnJavascriptExecution) {
   22600   LocalContext context;
   22601   v8::Isolate* isolate = context->GetIsolate();
   22602   v8::HandleScope scope(isolate);
   22603   v8::TryCatch try_catch(isolate);
   22604   v8::Isolate::DisallowJavascriptExecutionScope throw_js(
   22605       isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
   22606   CompileRun("1+1");
   22607   CHECK(try_catch.HasCaught());
   22608 }
   22609 
   22610 
   22611 TEST(Regress354123) {
   22612   LocalContext current;
   22613   v8::Isolate* isolate = current->GetIsolate();
   22614   v8::HandleScope scope(isolate);
   22615 
   22616   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   22617   templ->SetAccessCheckCallback(AccessCounter);
   22618   CHECK(current->Global()
   22619             ->Set(current.local(), v8_str("friend"),
   22620                   templ->NewInstance(current.local()).ToLocalChecked())
   22621             .FromJust());
   22622 
   22623   // Test access using __proto__ from the prototype chain.
   22624   access_count = 0;
   22625   CompileRun("friend.__proto__ = {};");
   22626   CHECK_EQ(2, access_count);
   22627   CompileRun("friend.__proto__;");
   22628   CHECK_EQ(4, access_count);
   22629 
   22630   // Test access using __proto__ as a hijacked function (A).
   22631   access_count = 0;
   22632   CompileRun("var p = Object.prototype;"
   22633              "var f = Object.getOwnPropertyDescriptor(p, '__proto__').set;"
   22634              "f.call(friend, {});");
   22635   CHECK_EQ(1, access_count);
   22636   CompileRun("var p = Object.prototype;"
   22637              "var f = Object.getOwnPropertyDescriptor(p, '__proto__').get;"
   22638              "f.call(friend);");
   22639   CHECK_EQ(2, access_count);
   22640 
   22641   // Test access using __proto__ as a hijacked function (B).
   22642   access_count = 0;
   22643   CompileRun("var f = Object.prototype.__lookupSetter__('__proto__');"
   22644              "f.call(friend, {});");
   22645   CHECK_EQ(1, access_count);
   22646   CompileRun("var f = Object.prototype.__lookupGetter__('__proto__');"
   22647              "f.call(friend);");
   22648   CHECK_EQ(2, access_count);
   22649 
   22650   // Test access using Object.setPrototypeOf reflective method.
   22651   access_count = 0;
   22652   CompileRun("Object.setPrototypeOf(friend, {});");
   22653   CHECK_EQ(1, access_count);
   22654   CompileRun("Object.getPrototypeOf(friend);");
   22655   CHECK_EQ(2, access_count);
   22656 }
   22657 
   22658 
   22659 TEST(CaptureStackTraceForStackOverflow) {
   22660   v8::internal::FLAG_stack_size = 150;
   22661   LocalContext current;
   22662   v8::Isolate* isolate = current->GetIsolate();
   22663   v8::HandleScope scope(isolate);
   22664   isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10,
   22665                                                      v8::StackTrace::kDetailed);
   22666   v8::TryCatch try_catch(isolate);
   22667   CompileRun("(function f(x) { f(x+1); })(0)");
   22668   CHECK(try_catch.HasCaught());
   22669 }
   22670 
   22671 
   22672 TEST(ScriptNameAndLineNumber) {
   22673   LocalContext env;
   22674   v8::Isolate* isolate = env->GetIsolate();
   22675   v8::HandleScope scope(isolate);
   22676   const char* url = "http://www.foo.com/foo.js";
   22677   v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
   22678   v8::ScriptCompiler::Source script_source(v8_str("var foo;"), origin);
   22679   Local<Script> script =
   22680       v8::ScriptCompiler::Compile(env.local(), &script_source).ToLocalChecked();
   22681   Local<Value> script_name = script->GetUnboundScript()->GetScriptName();
   22682   CHECK(!script_name.IsEmpty());
   22683   CHECK(script_name->IsString());
   22684   String::Utf8Value utf8_name(script_name);
   22685   CHECK_EQ(0, strcmp(url, *utf8_name));
   22686   int line_number = script->GetUnboundScript()->GetLineNumber(0);
   22687   CHECK_EQ(13, line_number);
   22688 }
   22689 
   22690 void CheckMagicComments(Local<Script> script, const char* expected_source_url,
   22691                         const char* expected_source_mapping_url) {
   22692   if (expected_source_url != NULL) {
   22693     v8::String::Utf8Value url(script->GetUnboundScript()->GetSourceURL());
   22694     CHECK_EQ(0, strcmp(expected_source_url, *url));
   22695   } else {
   22696     CHECK(script->GetUnboundScript()->GetSourceURL()->IsUndefined());
   22697   }
   22698   if (expected_source_mapping_url != NULL) {
   22699     v8::String::Utf8Value url(
   22700         script->GetUnboundScript()->GetSourceMappingURL());
   22701     CHECK_EQ(0, strcmp(expected_source_mapping_url, *url));
   22702   } else {
   22703     CHECK(script->GetUnboundScript()->GetSourceMappingURL()->IsUndefined());
   22704   }
   22705 }
   22706 
   22707 void SourceURLHelper(const char* source, const char* expected_source_url,
   22708                      const char* expected_source_mapping_url) {
   22709   Local<Script> script = v8_compile(source);
   22710   CheckMagicComments(script, expected_source_url, expected_source_mapping_url);
   22711 }
   22712 
   22713 
   22714 TEST(ScriptSourceURLAndSourceMappingURL) {
   22715   LocalContext env;
   22716   v8::Isolate* isolate = env->GetIsolate();
   22717   v8::HandleScope scope(isolate);
   22718   SourceURLHelper("function foo() {}\n"
   22719                   "//# sourceURL=bar1.js\n", "bar1.js", NULL);
   22720   SourceURLHelper("function foo() {}\n"
   22721                   "//# sourceMappingURL=bar2.js\n", NULL, "bar2.js");
   22722 
   22723   // Both sourceURL and sourceMappingURL.
   22724   SourceURLHelper("function foo() {}\n"
   22725                   "//# sourceURL=bar3.js\n"
   22726                   "//# sourceMappingURL=bar4.js\n", "bar3.js", "bar4.js");
   22727 
   22728   // Two source URLs; the first one is ignored.
   22729   SourceURLHelper("function foo() {}\n"
   22730                   "//# sourceURL=ignoreme.js\n"
   22731                   "//# sourceURL=bar5.js\n", "bar5.js", NULL);
   22732   SourceURLHelper("function foo() {}\n"
   22733                   "//# sourceMappingURL=ignoreme.js\n"
   22734                   "//# sourceMappingURL=bar6.js\n", NULL, "bar6.js");
   22735 
   22736   // SourceURL or sourceMappingURL in the middle of the script.
   22737   SourceURLHelper("function foo() {}\n"
   22738                   "//# sourceURL=bar7.js\n"
   22739                   "function baz() {}\n", "bar7.js", NULL);
   22740   SourceURLHelper("function foo() {}\n"
   22741                   "//# sourceMappingURL=bar8.js\n"
   22742                   "function baz() {}\n", NULL, "bar8.js");
   22743 
   22744   // Too much whitespace.
   22745   SourceURLHelper("function foo() {}\n"
   22746                   "//#  sourceURL=bar9.js\n"
   22747                   "//#  sourceMappingURL=bar10.js\n", NULL, NULL);
   22748   SourceURLHelper("function foo() {}\n"
   22749                   "//# sourceURL =bar11.js\n"
   22750                   "//# sourceMappingURL =bar12.js\n", NULL, NULL);
   22751 
   22752   // Disallowed characters in value.
   22753   SourceURLHelper("function foo() {}\n"
   22754                   "//# sourceURL=bar13 .js   \n"
   22755                   "//# sourceMappingURL=bar14 .js \n",
   22756                   NULL, NULL);
   22757   SourceURLHelper("function foo() {}\n"
   22758                   "//# sourceURL=bar15\t.js   \n"
   22759                   "//# sourceMappingURL=bar16\t.js \n",
   22760                   NULL, NULL);
   22761   SourceURLHelper("function foo() {}\n"
   22762                   "//# sourceURL=bar17'.js   \n"
   22763                   "//# sourceMappingURL=bar18'.js \n",
   22764                   NULL, NULL);
   22765   SourceURLHelper("function foo() {}\n"
   22766                   "//# sourceURL=bar19\".js   \n"
   22767                   "//# sourceMappingURL=bar20\".js \n",
   22768                   NULL, NULL);
   22769 
   22770   // Not too much whitespace.
   22771   SourceURLHelper("function foo() {}\n"
   22772                   "//# sourceURL=  bar21.js   \n"
   22773                   "//# sourceMappingURL=  bar22.js \n", "bar21.js", "bar22.js");
   22774 }
   22775 
   22776 
   22777 TEST(GetOwnPropertyDescriptor) {
   22778   LocalContext env;
   22779   v8::Isolate* isolate = env->GetIsolate();
   22780   v8::HandleScope scope(isolate);
   22781   CompileRun(
   22782     "var x = { value : 13};"
   22783     "Object.defineProperty(x, 'p0', {value : 12});"
   22784     "Object.defineProperty(x, 'p1', {"
   22785     "  set : function(value) { this.value = value; },"
   22786     "  get : function() { return this.value; },"
   22787     "});");
   22788   Local<Object> x = Local<Object>::Cast(
   22789       env->Global()->Get(env.local(), v8_str("x")).ToLocalChecked());
   22790   Local<Value> desc =
   22791       x->GetOwnPropertyDescriptor(env.local(), v8_str("no_prop"))
   22792           .ToLocalChecked();
   22793   CHECK(desc->IsUndefined());
   22794   desc =
   22795       x->GetOwnPropertyDescriptor(env.local(), v8_str("p0")).ToLocalChecked();
   22796   CHECK(v8_num(12)
   22797             ->Equals(env.local(), Local<Object>::Cast(desc)
   22798                                       ->Get(env.local(), v8_str("value"))
   22799                                       .ToLocalChecked())
   22800             .FromJust());
   22801   desc =
   22802       x->GetOwnPropertyDescriptor(env.local(), v8_str("p1")).ToLocalChecked();
   22803   Local<Function> set =
   22804       Local<Function>::Cast(Local<Object>::Cast(desc)
   22805                                 ->Get(env.local(), v8_str("set"))
   22806                                 .ToLocalChecked());
   22807   Local<Function> get =
   22808       Local<Function>::Cast(Local<Object>::Cast(desc)
   22809                                 ->Get(env.local(), v8_str("get"))
   22810                                 .ToLocalChecked());
   22811   CHECK(v8_num(13)
   22812             ->Equals(env.local(),
   22813                      get->Call(env.local(), x, 0, NULL).ToLocalChecked())
   22814             .FromJust());
   22815   Local<Value> args[] = {v8_num(14)};
   22816   set->Call(env.local(), x, 1, args).ToLocalChecked();
   22817   CHECK(v8_num(14)
   22818             ->Equals(env.local(),
   22819                      get->Call(env.local(), x, 0, NULL).ToLocalChecked())
   22820             .FromJust());
   22821 }
   22822 
   22823 
   22824 TEST(Regress411877) {
   22825   v8::Isolate* isolate = CcTest::isolate();
   22826   v8::HandleScope handle_scope(isolate);
   22827   v8::Local<v8::ObjectTemplate> object_template =
   22828       v8::ObjectTemplate::New(isolate);
   22829   object_template->SetAccessCheckCallback(AccessCounter);
   22830 
   22831   v8::Local<Context> context = Context::New(isolate);
   22832   v8::Context::Scope context_scope(context);
   22833 
   22834   CHECK(context->Global()
   22835             ->Set(context, v8_str("o"),
   22836                   object_template->NewInstance(context).ToLocalChecked())
   22837             .FromJust());
   22838   CompileRun("Object.getOwnPropertyNames(o)");
   22839 }
   22840 
   22841 
   22842 TEST(GetHiddenPropertyTableAfterAccessCheck) {
   22843   v8::Isolate* isolate = CcTest::isolate();
   22844   v8::HandleScope handle_scope(isolate);
   22845   v8::Local<v8::ObjectTemplate> object_template =
   22846       v8::ObjectTemplate::New(isolate);
   22847   object_template->SetAccessCheckCallback(AccessCounter);
   22848 
   22849   v8::Local<Context> context = Context::New(isolate);
   22850   v8::Context::Scope context_scope(context);
   22851 
   22852   v8::Local<v8::Object> obj =
   22853       object_template->NewInstance(context).ToLocalChecked();
   22854   obj->Set(context, v8_str("key"), v8_str("value")).FromJust();
   22855   obj->Delete(context, v8_str("key")).FromJust();
   22856 
   22857   obj->SetPrivate(context, v8::Private::New(isolate, v8_str("hidden key 2")),
   22858                   v8_str("hidden value 2"))
   22859       .FromJust();
   22860 }
   22861 
   22862 
   22863 TEST(Regress411793) {
   22864   v8::Isolate* isolate = CcTest::isolate();
   22865   v8::HandleScope handle_scope(isolate);
   22866   v8::Local<v8::ObjectTemplate> object_template =
   22867       v8::ObjectTemplate::New(isolate);
   22868   object_template->SetAccessCheckCallback(AccessCounter);
   22869 
   22870   v8::Local<Context> context = Context::New(isolate);
   22871   v8::Context::Scope context_scope(context);
   22872 
   22873   CHECK(context->Global()
   22874             ->Set(context, v8_str("o"),
   22875                   object_template->NewInstance(context).ToLocalChecked())
   22876             .FromJust());
   22877   CompileRun(
   22878       "Object.defineProperty(o, 'key', "
   22879       "    { get: function() {}, set: function() {} });");
   22880 }
   22881 
   22882 class TestSourceStream : public v8::ScriptCompiler::ExternalSourceStream {
   22883  public:
   22884   explicit TestSourceStream(const char** chunks) : chunks_(chunks), index_(0) {}
   22885 
   22886   virtual size_t GetMoreData(const uint8_t** src) {
   22887     // Unlike in real use cases, this function will never block.
   22888     if (chunks_[index_] == NULL) {
   22889       return 0;
   22890     }
   22891     // Copy the data, since the caller takes ownership of it.
   22892     size_t len = strlen(chunks_[index_]);
   22893     // We don't need to zero-terminate since we return the length.
   22894     uint8_t* copy = new uint8_t[len];
   22895     memcpy(copy, chunks_[index_], len);
   22896     *src = copy;
   22897     ++index_;
   22898     return len;
   22899   }
   22900 
   22901   // Helper for constructing a string from chunks (the compilation needs it
   22902   // too).
   22903   static char* FullSourceString(const char** chunks) {
   22904     size_t total_len = 0;
   22905     for (size_t i = 0; chunks[i] != NULL; ++i) {
   22906       total_len += strlen(chunks[i]);
   22907     }
   22908     char* full_string = new char[total_len + 1];
   22909     size_t offset = 0;
   22910     for (size_t i = 0; chunks[i] != NULL; ++i) {
   22911       size_t len = strlen(chunks[i]);
   22912       memcpy(full_string + offset, chunks[i], len);
   22913       offset += len;
   22914     }
   22915     full_string[total_len] = 0;
   22916     return full_string;
   22917   }
   22918 
   22919  private:
   22920   const char** chunks_;
   22921   unsigned index_;
   22922 };
   22923 
   22924 
   22925 // Helper function for running streaming tests.
   22926 void RunStreamingTest(const char** chunks,
   22927                       v8::ScriptCompiler::StreamedSource::Encoding encoding =
   22928                           v8::ScriptCompiler::StreamedSource::ONE_BYTE,
   22929                       bool expected_success = true,
   22930                       const char* expected_source_url = NULL,
   22931                       const char* expected_source_mapping_url = NULL) {
   22932   LocalContext env;
   22933   v8::Isolate* isolate = env->GetIsolate();
   22934   v8::HandleScope scope(isolate);
   22935   v8::TryCatch try_catch(isolate);
   22936 
   22937   v8::ScriptCompiler::StreamedSource source(new TestSourceStream(chunks),
   22938                                             encoding);
   22939   v8::ScriptCompiler::ScriptStreamingTask* task =
   22940       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
   22941 
   22942   // TestSourceStream::GetMoreData won't block, so it's OK to just run the
   22943   // task here in the main thread.
   22944   task->Run();
   22945   delete task;
   22946 
   22947   // Possible errors are only produced while compiling.
   22948   CHECK_EQ(false, try_catch.HasCaught());
   22949 
   22950   v8::ScriptOrigin origin(v8_str("http://foo.com"));
   22951   char* full_source = TestSourceStream::FullSourceString(chunks);
   22952   v8::MaybeLocal<Script> script = v8::ScriptCompiler::Compile(
   22953       env.local(), &source, v8_str(full_source), origin);
   22954   if (expected_success) {
   22955     CHECK(!script.IsEmpty());
   22956     v8::Local<Value> result(
   22957         script.ToLocalChecked()->Run(env.local()).ToLocalChecked());
   22958     // All scripts are supposed to return the fixed value 13 when ran.
   22959     CHECK_EQ(13, result->Int32Value(env.local()).FromJust());
   22960     CheckMagicComments(script.ToLocalChecked(), expected_source_url,
   22961                        expected_source_mapping_url);
   22962   } else {
   22963     CHECK(script.IsEmpty());
   22964     CHECK(try_catch.HasCaught());
   22965   }
   22966   delete[] full_source;
   22967 }
   22968 
   22969 
   22970 TEST(StreamingSimpleScript) {
   22971   // This script is unrealistically small, since no one chunk is enough to fill
   22972   // the backing buffer of Scanner, let alone overflow it.
   22973   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
   22974                           NULL};
   22975   RunStreamingTest(chunks);
   22976 }
   22977 
   22978 
   22979 TEST(StreamingBiggerScript) {
   22980   const char* chunk1 =
   22981       "function foo() {\n"
   22982       "  // Make this chunk sufficiently long so that it will overflow the\n"
   22983       "  // backing buffer of the Scanner.\n"
   22984       "  var i = 0;\n"
   22985       "  var result = 0;\n"
   22986       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   22987       "  result = 0;\n"
   22988       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   22989       "  result = 0;\n"
   22990       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   22991       "  result = 0;\n"
   22992       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   22993       "  return result;\n"
   22994       "}\n";
   22995   const char* chunks[] = {chunk1, "foo(); ", NULL};
   22996   RunStreamingTest(chunks);
   22997 }
   22998 
   22999 
   23000 TEST(StreamingScriptWithParseError) {
   23001   // Test that parse errors from streamed scripts are propagated correctly.
   23002   {
   23003     char chunk1[] =
   23004         "  // This will result in a parse error.\n"
   23005         "  var if else then foo";
   23006     char chunk2[] = "  13\n";
   23007     const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
   23008 
   23009     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::ONE_BYTE,
   23010                      false);
   23011   }
   23012   // Test that the next script succeeds normally.
   23013   {
   23014     char chunk1[] =
   23015         "  // This will be parsed successfully.\n"
   23016         "  function foo() { return ";
   23017     char chunk2[] = "  13; }\n";
   23018     const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
   23019 
   23020     RunStreamingTest(chunks);
   23021   }
   23022 }
   23023 
   23024 
   23025 TEST(StreamingUtf8Script) {
   23026   // We'd want to write \uc481 instead of \xec\x92\x81, but Windows compilers
   23027   // don't like it.
   23028   const char* chunk1 =
   23029       "function foo() {\n"
   23030       "  // This function will contain an UTF-8 character which is not in\n"
   23031       "  // ASCII.\n"
   23032       "  var foob\xec\x92\x81r = 13;\n"
   23033       "  return foob\xec\x92\x81r;\n"
   23034       "}\n";
   23035   const char* chunks[] = {chunk1, "foo(); ", NULL};
   23036   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   23037 }
   23038 
   23039 
   23040 TEST(StreamingUtf8ScriptWithSplitCharactersSanityCheck) {
   23041   // A sanity check to prove that the approach of splitting UTF-8
   23042   // characters is correct. Here is an UTF-8 character which will take three
   23043   // bytes.
   23044   const char* reference = "\xec\x92\x81";
   23045   CHECK(3u == strlen(reference));  // NOLINT - no CHECK_EQ for unsigned.
   23046 
   23047   char chunk1[] =
   23048       "function foo() {\n"
   23049       "  // This function will contain an UTF-8 character which is not in\n"
   23050       "  // ASCII.\n"
   23051       "  var foob";
   23052   char chunk2[] =
   23053       "XXXr = 13;\n"
   23054       "  return foob\xec\x92\x81r;\n"
   23055       "}\n";
   23056   for (int i = 0; i < 3; ++i) {
   23057     chunk2[i] = reference[i];
   23058   }
   23059   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
   23060   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   23061 }
   23062 
   23063 
   23064 TEST(StreamingUtf8ScriptWithSplitCharacters) {
   23065   // Stream data where a multi-byte UTF-8 character is split between two data
   23066   // chunks.
   23067   const char* reference = "\xec\x92\x81";
   23068   char chunk1[] =
   23069       "function foo() {\n"
   23070       "  // This function will contain an UTF-8 character which is not in\n"
   23071       "  // ASCII.\n"
   23072       "  var foobX";
   23073   char chunk2[] =
   23074       "XXr = 13;\n"
   23075       "  return foob\xec\x92\x81r;\n"
   23076       "}\n";
   23077   chunk1[strlen(chunk1) - 1] = reference[0];
   23078   chunk2[0] = reference[1];
   23079   chunk2[1] = reference[2];
   23080   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
   23081   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   23082 }
   23083 
   23084 
   23085 TEST(StreamingUtf8ScriptWithSplitCharactersValidEdgeCases) {
   23086   // Tests edge cases which should still be decoded correctly.
   23087 
   23088   // Case 1: a chunk contains only bytes for a split character (and no other
   23089   // data). This kind of a chunk would be exceptionally small, but we should
   23090   // still decode it correctly.
   23091   const char* reference = "\xec\x92\x81";
   23092   // The small chunk is at the beginning of the split character
   23093   {
   23094     char chunk1[] =
   23095         "function foo() {\n"
   23096         "  // This function will contain an UTF-8 character which is not in\n"
   23097         "  // ASCII.\n"
   23098         "  var foob";
   23099     char chunk2[] = "XX";
   23100     char chunk3[] =
   23101         "Xr = 13;\n"
   23102         "  return foob\xec\x92\x81r;\n"
   23103         "}\n";
   23104     chunk2[0] = reference[0];
   23105     chunk2[1] = reference[1];
   23106     chunk3[0] = reference[2];
   23107     const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
   23108     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   23109   }
   23110   // The small chunk is at the end of a character
   23111   {
   23112     char chunk1[] =
   23113         "function foo() {\n"
   23114         "  // This function will contain an UTF-8 character which is not in\n"
   23115         "  // ASCII.\n"
   23116         "  var foobX";
   23117     char chunk2[] = "XX";
   23118     char chunk3[] =
   23119         "r = 13;\n"
   23120         "  return foob\xec\x92\x81r;\n"
   23121         "}\n";
   23122     chunk1[strlen(chunk1) - 1] = reference[0];
   23123     chunk2[0] = reference[1];
   23124     chunk2[1] = reference[2];
   23125     const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
   23126     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   23127   }
   23128   // Case 2: the script ends with a multi-byte character. Make sure that it's
   23129   // decoded correctly and not just ignored.
   23130   {
   23131     char chunk1[] =
   23132         "var foob\xec\x92\x81 = 13;\n"
   23133         "foob\xec\x92\x81";
   23134     const char* chunks[] = {chunk1, NULL};
   23135     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   23136   }
   23137 }
   23138 
   23139 
   23140 TEST(StreamingUtf8ScriptWithSplitCharactersInvalidEdgeCases) {
   23141   // Test cases where a UTF-8 character is split over several chunks. Those
   23142   // cases are not supported (the embedder should give the data in big enough
   23143   // chunks), but we shouldn't crash, just produce a parse error.
   23144   const char* reference = "\xec\x92\x81";
   23145   char chunk1[] =
   23146       "function foo() {\n"
   23147       "  // This function will contain an UTF-8 character which is not in\n"
   23148       "  // ASCII.\n"
   23149       "  var foobX";
   23150   char chunk2[] = "X";
   23151   char chunk3[] =
   23152       "Xr = 13;\n"
   23153       "  return foob\xec\x92\x81r;\n"
   23154       "}\n";
   23155   chunk1[strlen(chunk1) - 1] = reference[0];
   23156   chunk2[0] = reference[1];
   23157   chunk3[0] = reference[2];
   23158   const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
   23159 
   23160   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
   23161 }
   23162 
   23163 
   23164 TEST(StreamingProducesParserCache) {
   23165   i::FLAG_min_preparse_length = 0;
   23166   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
   23167                           NULL};
   23168 
   23169   LocalContext env;
   23170   v8::Isolate* isolate = env->GetIsolate();
   23171   v8::HandleScope scope(isolate);
   23172 
   23173   v8::ScriptCompiler::StreamedSource source(
   23174       new TestSourceStream(chunks),
   23175       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
   23176   v8::ScriptCompiler::ScriptStreamingTask* task =
   23177       v8::ScriptCompiler::StartStreamingScript(
   23178           isolate, &source, v8::ScriptCompiler::kProduceParserCache);
   23179 
   23180   // TestSourceStream::GetMoreData won't block, so it's OK to just run the
   23181   // task here in the main thread.
   23182   task->Run();
   23183   delete task;
   23184 
   23185   const v8::ScriptCompiler::CachedData* cached_data = source.GetCachedData();
   23186   CHECK(cached_data != NULL);
   23187   CHECK(cached_data->data != NULL);
   23188   CHECK(!cached_data->rejected);
   23189   CHECK_GT(cached_data->length, 0);
   23190 }
   23191 
   23192 
   23193 TEST(StreamingWithDebuggingEnabledLate) {
   23194   // The streaming parser can only parse lazily, i.e. inner functions are not
   23195   // fully parsed. However, we may compile inner functions eagerly when
   23196   // debugging. Make sure that we can deal with this when turning on debugging
   23197   // after streaming parser has already finished parsing.
   23198   i::FLAG_min_preparse_length = 0;
   23199   const char* chunks[] = {"with({x:1}) {",
   23200                           "  var foo = function foo(y) {",
   23201                           "    return x + y;",
   23202                           "  };",
   23203                           "  foo(2);",
   23204                           "}",
   23205                           NULL};
   23206 
   23207   LocalContext env;
   23208   v8::Isolate* isolate = env->GetIsolate();
   23209   v8::HandleScope scope(isolate);
   23210   v8::TryCatch try_catch(isolate);
   23211 
   23212   v8::ScriptCompiler::StreamedSource source(
   23213       new TestSourceStream(chunks),
   23214       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
   23215   v8::ScriptCompiler::ScriptStreamingTask* task =
   23216       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
   23217 
   23218   task->Run();
   23219   delete task;
   23220 
   23221   CHECK(!try_catch.HasCaught());
   23222 
   23223   v8::ScriptOrigin origin(v8_str("http://foo.com"));
   23224   char* full_source = TestSourceStream::FullSourceString(chunks);
   23225 
   23226   EnableDebugger(isolate);
   23227 
   23228   v8::Local<Script> script =
   23229       v8::ScriptCompiler::Compile(env.local(), &source, v8_str(full_source),
   23230                                   origin)
   23231           .ToLocalChecked();
   23232 
   23233   Maybe<uint32_t> result =
   23234       script->Run(env.local()).ToLocalChecked()->Uint32Value(env.local());
   23235   CHECK_EQ(3U, result.FromMaybe(0));
   23236 
   23237   delete[] full_source;
   23238 
   23239   DisableDebugger(isolate);
   23240 }
   23241 
   23242 
   23243 TEST(StreamingScriptWithInvalidUtf8) {
   23244   // Regression test for a crash: test that invalid UTF-8 bytes in the end of a
   23245   // chunk don't produce a crash.
   23246   const char* reference = "\xec\x92\x81\x80\x80";
   23247   char chunk1[] =
   23248       "function foo() {\n"
   23249       "  // This function will contain an UTF-8 character which is not in\n"
   23250       "  // ASCII.\n"
   23251       "  var foobXXXXX";  // Too many bytes which look like incomplete chars!
   23252   char chunk2[] =
   23253       "r = 13;\n"
   23254       "  return foob\xec\x92\x81\x80\x80r;\n"
   23255       "}\n";
   23256   for (int i = 0; i < 5; ++i) chunk1[strlen(chunk1) - 5 + i] = reference[i];
   23257 
   23258   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
   23259   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
   23260 }
   23261 
   23262 
   23263 TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit) {
   23264   // Regression test: Stream data where there are several multi-byte UTF-8
   23265   // characters in a sequence and one of them is split between two data chunks.
   23266   const char* reference = "\xec\x92\x81";
   23267   char chunk1[] =
   23268       "function foo() {\n"
   23269       "  // This function will contain an UTF-8 character which is not in\n"
   23270       "  // ASCII.\n"
   23271       "  var foob\xec\x92\x81X";
   23272   char chunk2[] =
   23273       "XXr = 13;\n"
   23274       "  return foob\xec\x92\x81\xec\x92\x81r;\n"
   23275       "}\n";
   23276   chunk1[strlen(chunk1) - 1] = reference[0];
   23277   chunk2[0] = reference[1];
   23278   chunk2[1] = reference[2];
   23279   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
   23280   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   23281 }
   23282 
   23283 
   23284 TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit2) {
   23285   // Another regression test, similar to the previous one. The difference is
   23286   // that the split character is not the last one in the sequence.
   23287   const char* reference = "\xec\x92\x81";
   23288   char chunk1[] =
   23289       "function foo() {\n"
   23290       "  // This function will contain an UTF-8 character which is not in\n"
   23291       "  // ASCII.\n"
   23292       "  var foobX";
   23293   char chunk2[] =
   23294       "XX\xec\x92\x81r = 13;\n"
   23295       "  return foob\xec\x92\x81\xec\x92\x81r;\n"
   23296       "}\n";
   23297   chunk1[strlen(chunk1) - 1] = reference[0];
   23298   chunk2[0] = reference[1];
   23299   chunk2[1] = reference[2];
   23300   const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
   23301   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   23302 }
   23303 
   23304 
   23305 TEST(StreamingWithHarmonyScopes) {
   23306   // Don't use RunStreamingTest here so that both scripts get to use the same
   23307   // LocalContext and HandleScope.
   23308   LocalContext env;
   23309   v8::Isolate* isolate = env->GetIsolate();
   23310   v8::HandleScope scope(isolate);
   23311 
   23312   // First, run a script with a let variable.
   23313   CompileRun("\"use strict\"; let x = 1;");
   23314 
   23315   // Then stream a script which (erroneously) tries to introduce the same
   23316   // variable again.
   23317   const char* chunks[] = {"\"use strict\"; let x = 2;", NULL};
   23318 
   23319   v8::TryCatch try_catch(isolate);
   23320   v8::ScriptCompiler::StreamedSource source(
   23321       new TestSourceStream(chunks),
   23322       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
   23323   v8::ScriptCompiler::ScriptStreamingTask* task =
   23324       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
   23325   task->Run();
   23326   delete task;
   23327 
   23328   // Parsing should succeed (the script will be parsed and compiled in a context
   23329   // independent way, so the error is not detected).
   23330   CHECK_EQ(false, try_catch.HasCaught());
   23331 
   23332   v8::ScriptOrigin origin(v8_str("http://foo.com"));
   23333   char* full_source = TestSourceStream::FullSourceString(chunks);
   23334   v8::Local<Script> script =
   23335       v8::ScriptCompiler::Compile(env.local(), &source, v8_str(full_source),
   23336                                   origin)
   23337           .ToLocalChecked();
   23338   CHECK(!script.IsEmpty());
   23339   CHECK_EQ(false, try_catch.HasCaught());
   23340 
   23341   // Running the script exposes the error.
   23342   CHECK(script->Run(env.local()).IsEmpty());
   23343   CHECK(try_catch.HasCaught());
   23344   delete[] full_source;
   23345 }
   23346 
   23347 
   23348 TEST(CodeCache) {
   23349   v8::Isolate::CreateParams create_params;
   23350   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   23351 
   23352   const char* source = "Math.sqrt(4)";
   23353   const char* origin = "code cache test";
   23354   v8::ScriptCompiler::CachedData* cache;
   23355 
   23356   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
   23357   {
   23358     v8::Isolate::Scope iscope(isolate1);
   23359     v8::HandleScope scope(isolate1);
   23360     v8::Local<v8::Context> context = v8::Context::New(isolate1);
   23361     v8::Context::Scope cscope(context);
   23362     v8::Local<v8::String> source_string = v8_str(source);
   23363     v8::ScriptOrigin script_origin(v8_str(origin));
   23364     v8::ScriptCompiler::Source source(source_string, script_origin);
   23365     v8::ScriptCompiler::CompileOptions option =
   23366         v8::ScriptCompiler::kProduceCodeCache;
   23367     v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
   23368     int length = source.GetCachedData()->length;
   23369     uint8_t* cache_data = new uint8_t[length];
   23370     memcpy(cache_data, source.GetCachedData()->data, length);
   23371     cache = new v8::ScriptCompiler::CachedData(
   23372         cache_data, length, v8::ScriptCompiler::CachedData::BufferOwned);
   23373   }
   23374   isolate1->Dispose();
   23375 
   23376   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
   23377   {
   23378     v8::Isolate::Scope iscope(isolate2);
   23379     v8::HandleScope scope(isolate2);
   23380     v8::Local<v8::Context> context = v8::Context::New(isolate2);
   23381     v8::Context::Scope cscope(context);
   23382     v8::Local<v8::String> source_string = v8_str(source);
   23383     v8::ScriptOrigin script_origin(v8_str(origin));
   23384     v8::ScriptCompiler::Source source(source_string, script_origin, cache);
   23385     v8::ScriptCompiler::CompileOptions option =
   23386         v8::ScriptCompiler::kConsumeCodeCache;
   23387     v8::Local<v8::Script> script;
   23388     {
   23389       i::DisallowCompilation no_compile(
   23390           reinterpret_cast<i::Isolate*>(isolate2));
   23391       script = v8::ScriptCompiler::Compile(context, &source, option)
   23392                    .ToLocalChecked();
   23393     }
   23394     CHECK_EQ(2, script->Run(context)
   23395                     .ToLocalChecked()
   23396                     ->ToInt32(context)
   23397                     .ToLocalChecked()
   23398                     ->Int32Value(context)
   23399                     .FromJust());
   23400   }
   23401   isolate2->Dispose();
   23402 }
   23403 
   23404 
   23405 void TestInvalidCacheData(v8::ScriptCompiler::CompileOptions option) {
   23406   const char* garbage = "garbage garbage garbage garbage garbage garbage";
   23407   const uint8_t* data = reinterpret_cast<const uint8_t*>(garbage);
   23408   int length = 16;
   23409   v8::ScriptCompiler::CachedData* cached_data =
   23410       new v8::ScriptCompiler::CachedData(data, length);
   23411   CHECK(!cached_data->rejected);
   23412   v8::ScriptOrigin origin(v8_str("origin"));
   23413   v8::ScriptCompiler::Source source(v8_str("42"), origin, cached_data);
   23414   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   23415   v8::Local<v8::Script> script =
   23416       v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
   23417   CHECK(cached_data->rejected);
   23418   CHECK_EQ(
   23419       42,
   23420       script->Run(context).ToLocalChecked()->Int32Value(context).FromJust());
   23421 }
   23422 
   23423 
   23424 TEST(InvalidCacheData) {
   23425   v8::V8::Initialize();
   23426   v8::HandleScope scope(CcTest::isolate());
   23427   LocalContext context;
   23428   TestInvalidCacheData(v8::ScriptCompiler::kConsumeParserCache);
   23429   TestInvalidCacheData(v8::ScriptCompiler::kConsumeCodeCache);
   23430 }
   23431 
   23432 
   23433 TEST(ParserCacheRejectedGracefully) {
   23434   i::FLAG_min_preparse_length = 0;
   23435   v8::V8::Initialize();
   23436   v8::HandleScope scope(CcTest::isolate());
   23437   LocalContext context;
   23438   // Produce valid cached data.
   23439   v8::ScriptOrigin origin(v8_str("origin"));
   23440   v8::Local<v8::String> source_str = v8_str("function foo() {}");
   23441   v8::ScriptCompiler::Source source(source_str, origin);
   23442   v8::Local<v8::Script> script =
   23443       v8::ScriptCompiler::Compile(context.local(), &source,
   23444                                   v8::ScriptCompiler::kProduceParserCache)
   23445           .ToLocalChecked();
   23446   USE(script);
   23447   const v8::ScriptCompiler::CachedData* original_cached_data =
   23448       source.GetCachedData();
   23449   CHECK(original_cached_data != NULL);
   23450   CHECK(original_cached_data->data != NULL);
   23451   CHECK(!original_cached_data->rejected);
   23452   CHECK_GT(original_cached_data->length, 0);
   23453   // Recompiling the same script with it won't reject the data.
   23454   {
   23455     v8::ScriptCompiler::Source source_with_cached_data(
   23456         source_str, origin,
   23457         new v8::ScriptCompiler::CachedData(original_cached_data->data,
   23458                                            original_cached_data->length));
   23459     v8::Local<v8::Script> script =
   23460         v8::ScriptCompiler::Compile(context.local(), &source_with_cached_data,
   23461                                     v8::ScriptCompiler::kConsumeParserCache)
   23462             .ToLocalChecked();
   23463     USE(script);
   23464     const v8::ScriptCompiler::CachedData* new_cached_data =
   23465         source_with_cached_data.GetCachedData();
   23466     CHECK(new_cached_data != NULL);
   23467     CHECK(!new_cached_data->rejected);
   23468   }
   23469   // Compile an incompatible script with the cached data. The new script doesn't
   23470   // have the same starting position for the function as the old one, so the old
   23471   // cached data will be incompatible with it and will be rejected.
   23472   {
   23473     v8::Local<v8::String> incompatible_source_str =
   23474         v8_str("   function foo() {}");
   23475     v8::ScriptCompiler::Source source_with_cached_data(
   23476         incompatible_source_str, origin,
   23477         new v8::ScriptCompiler::CachedData(original_cached_data->data,
   23478                                            original_cached_data->length));
   23479     v8::Local<v8::Script> script =
   23480         v8::ScriptCompiler::Compile(context.local(), &source_with_cached_data,
   23481                                     v8::ScriptCompiler::kConsumeParserCache)
   23482             .ToLocalChecked();
   23483     USE(script);
   23484     const v8::ScriptCompiler::CachedData* new_cached_data =
   23485         source_with_cached_data.GetCachedData();
   23486     CHECK(new_cached_data != NULL);
   23487     CHECK(new_cached_data->rejected);
   23488   }
   23489 }
   23490 
   23491 
   23492 TEST(StringConcatOverflow) {
   23493   v8::V8::Initialize();
   23494   v8::HandleScope scope(CcTest::isolate());
   23495   RandomLengthOneByteResource* r =
   23496       new RandomLengthOneByteResource(i::String::kMaxLength);
   23497   v8::Local<v8::String> str =
   23498       v8::String::NewExternalOneByte(CcTest::isolate(), r).ToLocalChecked();
   23499   CHECK(!str.IsEmpty());
   23500   v8::TryCatch try_catch(CcTest::isolate());
   23501   v8::Local<v8::String> result = v8::String::Concat(str, str);
   23502   CHECK(result.IsEmpty());
   23503   CHECK(!try_catch.HasCaught());
   23504 }
   23505 
   23506 
   23507 TEST(TurboAsmDisablesNeuter) {
   23508   v8::V8::Initialize();
   23509   v8::HandleScope scope(CcTest::isolate());
   23510   LocalContext context;
   23511   bool should_be_neuterable = !i::FLAG_turbo_asm;
   23512   const char* load =
   23513       "function Module(stdlib, foreign, heap) {"
   23514       "  'use asm';"
   23515       "  var MEM32 = new stdlib.Int32Array(heap);"
   23516       "  function load() { return MEM32[0]; }"
   23517       "  return { load: load };"
   23518       "}"
   23519       "var buffer = new ArrayBuffer(4);"
   23520       "Module(this, {}, buffer).load();"
   23521       "buffer";
   23522 
   23523   i::FLAG_turbo_osr = false;  // TODO(titzer): test requires eager TF.
   23524   v8::Local<v8::ArrayBuffer> result = CompileRun(load).As<v8::ArrayBuffer>();
   23525   CHECK_EQ(should_be_neuterable, result->IsNeuterable());
   23526 
   23527   const char* store =
   23528       "function Module(stdlib, foreign, heap) {"
   23529       "  'use asm';"
   23530       "  var MEM32 = new stdlib.Int32Array(heap);"
   23531       "  function store() { MEM32[0] = 0; }"
   23532       "  return { store: store };"
   23533       "}"
   23534       "var buffer = new ArrayBuffer(4);"
   23535       "Module(this, {}, buffer).store();"
   23536       "buffer";
   23537 
   23538   i::FLAG_turbo_osr = false;  // TODO(titzer): test requires eager TF.
   23539   result = CompileRun(store).As<v8::ArrayBuffer>();
   23540   CHECK_EQ(should_be_neuterable, result->IsNeuterable());
   23541 }
   23542 
   23543 
   23544 TEST(GetPrototypeAccessControl) {
   23545   i::FLAG_allow_natives_syntax = true;
   23546   v8::Isolate* isolate = CcTest::isolate();
   23547   v8::HandleScope handle_scope(isolate);
   23548   LocalContext env;
   23549 
   23550   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   23551   obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   23552 
   23553   CHECK(env->Global()
   23554             ->Set(env.local(), v8_str("prohibited"),
   23555                   obj_template->NewInstance(env.local()).ToLocalChecked())
   23556             .FromJust());
   23557 
   23558   CHECK(CompileRun(
   23559             "function f() { return %_GetPrototype(prohibited); }"
   23560             "%OptimizeFunctionOnNextCall(f);"
   23561             "f();")->IsNull());
   23562 }
   23563 
   23564 
   23565 TEST(GetPrototypeHidden) {
   23566   i::FLAG_allow_natives_syntax = true;
   23567   v8::Isolate* isolate = CcTest::isolate();
   23568   v8::HandleScope handle_scope(isolate);
   23569   LocalContext env;
   23570 
   23571   Local<FunctionTemplate> t = FunctionTemplate::New(isolate);
   23572   t->SetHiddenPrototype(true);
   23573   Local<Object> proto = t->GetFunction(env.local())
   23574                             .ToLocalChecked()
   23575                             ->NewInstance(env.local())
   23576                             .ToLocalChecked();
   23577   Local<Object> object = Object::New(isolate);
   23578   Local<Object> proto2 = Object::New(isolate);
   23579   object->SetPrototype(env.local(), proto).FromJust();
   23580   proto->SetPrototype(env.local(), proto2).FromJust();
   23581 
   23582   CHECK(env->Global()->Set(env.local(), v8_str("object"), object).FromJust());
   23583   CHECK(env->Global()->Set(env.local(), v8_str("proto"), proto).FromJust());
   23584   CHECK(env->Global()->Set(env.local(), v8_str("proto2"), proto2).FromJust());
   23585 
   23586   v8::Local<v8::Value> result = CompileRun("%_GetPrototype(object)");
   23587   CHECK(result->Equals(env.local(), proto2).FromJust());
   23588 
   23589   result = CompileRun(
   23590       "function f() { return %_GetPrototype(object); }"
   23591       "%OptimizeFunctionOnNextCall(f);"
   23592       "f()");
   23593   CHECK(result->Equals(env.local(), proto2).FromJust());
   23594 }
   23595 
   23596 
   23597 TEST(ClassPrototypeCreationContext) {
   23598   v8::Isolate* isolate = CcTest::isolate();
   23599   v8::HandleScope handle_scope(isolate);
   23600   LocalContext env;
   23601 
   23602   Local<Object> result = Local<Object>::Cast(
   23603       CompileRun("'use strict'; class Example { }; Example.prototype"));
   23604   CHECK(env.local() == result->CreationContext());
   23605 }
   23606 
   23607 
   23608 TEST(SimpleStreamingScriptWithSourceURL) {
   23609   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo();\n",
   23610                           "//# sourceURL=bar2.js\n", NULL};
   23611   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
   23612                    "bar2.js");
   23613 }
   23614 
   23615 
   23616 TEST(StreamingScriptWithSplitSourceURL) {
   23617   const char* chunks[] = {"function foo() { ret", "urn 13; } f",
   23618                           "oo();\n//# sourceURL=b", "ar2.js\n", NULL};
   23619   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
   23620                    "bar2.js");
   23621 }
   23622 
   23623 
   23624 TEST(StreamingScriptWithSourceMappingURLInTheMiddle) {
   23625   const char* chunks[] = {"function foo() { ret", "urn 13; }\n//#",
   23626                           " sourceMappingURL=bar2.js\n", "foo();", NULL};
   23627   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true, NULL,
   23628                    "bar2.js");
   23629 }
   23630 
   23631 
   23632 TEST(NewStringRangeError) {
   23633   v8::Isolate* isolate = CcTest::isolate();
   23634   v8::HandleScope handle_scope(isolate);
   23635   const int length = i::String::kMaxLength + 1;
   23636   const int buffer_size = length * sizeof(uint16_t);
   23637   void* buffer = malloc(buffer_size);
   23638   if (buffer == NULL) return;
   23639   memset(buffer, 'A', buffer_size);
   23640   {
   23641     v8::TryCatch try_catch(isolate);
   23642     char* data = reinterpret_cast<char*>(buffer);
   23643     CHECK(v8::String::NewFromUtf8(isolate, data, v8::NewStringType::kNormal,
   23644                                   length)
   23645               .IsEmpty());
   23646     CHECK(!try_catch.HasCaught());
   23647   }
   23648   {
   23649     v8::TryCatch try_catch(isolate);
   23650     uint8_t* data = reinterpret_cast<uint8_t*>(buffer);
   23651     CHECK(v8::String::NewFromOneByte(isolate, data, v8::NewStringType::kNormal,
   23652                                      length)
   23653               .IsEmpty());
   23654     CHECK(!try_catch.HasCaught());
   23655   }
   23656   {
   23657     v8::TryCatch try_catch(isolate);
   23658     uint16_t* data = reinterpret_cast<uint16_t*>(buffer);
   23659     CHECK(v8::String::NewFromTwoByte(isolate, data, v8::NewStringType::kNormal,
   23660                                      length)
   23661               .IsEmpty());
   23662     CHECK(!try_catch.HasCaught());
   23663   }
   23664   free(buffer);
   23665 }
   23666 
   23667 
   23668 TEST(SealHandleScope) {
   23669   v8::Isolate* isolate = CcTest::isolate();
   23670   v8::HandleScope handle_scope(isolate);
   23671   LocalContext env;
   23672 
   23673   v8::SealHandleScope seal(isolate);
   23674 
   23675   // Should fail
   23676   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   23677 
   23678   USE(obj);
   23679 }
   23680 
   23681 
   23682 TEST(SealHandleScopeNested) {
   23683   v8::Isolate* isolate = CcTest::isolate();
   23684   v8::HandleScope handle_scope(isolate);
   23685   LocalContext env;
   23686 
   23687   v8::SealHandleScope seal(isolate);
   23688 
   23689   {
   23690     v8::HandleScope handle_scope(isolate);
   23691 
   23692     // Should work
   23693     v8::Local<v8::Object> obj = v8::Object::New(isolate);
   23694 
   23695     USE(obj);
   23696   }
   23697 }
   23698 
   23699 
   23700 static bool access_was_called = false;
   23701 
   23702 
   23703 static bool AccessAlwaysAllowedWithFlag(Local<v8::Context> accessing_context,
   23704                                         Local<v8::Object> accessed_object) {
   23705   access_was_called = true;
   23706   return true;
   23707 }
   23708 
   23709 
   23710 static bool AccessAlwaysBlockedWithFlag(Local<v8::Context> accessing_context,
   23711                                         Local<v8::Object> accessed_object) {
   23712   access_was_called = true;
   23713   return false;
   23714 }
   23715 
   23716 
   23717 TEST(StrongModeAccessCheckAllowed) {
   23718   i::FLAG_strong_mode = true;
   23719   v8::Isolate* isolate = CcTest::isolate();
   23720   v8::HandleScope handle_scope(isolate);
   23721   v8::Local<Value> value;
   23722   access_was_called = false;
   23723 
   23724   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   23725 
   23726   obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
   23727   obj_template->SetAccessCheckCallback(AccessAlwaysAllowedWithFlag);
   23728 
   23729   // Create an environment
   23730   v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
   23731   context0->Enter();
   23732   v8::Local<v8::Object> global0 = context0->Global();
   23733   global0->Set(context0, v8_str("object"),
   23734                obj_template->NewInstance(context0).ToLocalChecked())
   23735       .FromJust();
   23736   {
   23737     v8::TryCatch try_catch(isolate);
   23738     value = CompileRun("'use strong'; object.x");
   23739     CHECK(!try_catch.HasCaught());
   23740     CHECK(!access_was_called);
   23741     CHECK_EQ(42, value->Int32Value(context0).FromJust());
   23742   }
   23743   {
   23744     v8::TryCatch try_catch(isolate);
   23745     value = CompileRun("'use strong'; object.foo");
   23746     CHECK(try_catch.HasCaught());
   23747     CHECK(!access_was_called);
   23748   }
   23749   {
   23750     v8::TryCatch try_catch(isolate);
   23751     value = CompileRun("'use strong'; object[10]");
   23752     CHECK(try_catch.HasCaught());
   23753     CHECK(!access_was_called);
   23754   }
   23755 
   23756   // Create an environment
   23757   v8::Local<Context> context1 = Context::New(isolate);
   23758   context1->Enter();
   23759   v8::Local<v8::Object> global1 = context1->Global();
   23760   global1->Set(context1, v8_str("object"),
   23761                obj_template->NewInstance(context1).ToLocalChecked())
   23762       .FromJust();
   23763   {
   23764     v8::TryCatch try_catch(isolate);
   23765     value = CompileRun("'use strong'; object.x");
   23766     CHECK(!try_catch.HasCaught());
   23767     CHECK(access_was_called);
   23768     CHECK_EQ(42, value->Int32Value(context1).FromJust());
   23769   }
   23770   access_was_called = false;
   23771   {
   23772     v8::TryCatch try_catch(isolate);
   23773     value = CompileRun("'use strong'; object.foo");
   23774     CHECK(try_catch.HasCaught());
   23775     CHECK(access_was_called);
   23776   }
   23777   access_was_called = false;
   23778   {
   23779     v8::TryCatch try_catch(isolate);
   23780     value = CompileRun("'use strong'; object[10]");
   23781     CHECK(try_catch.HasCaught());
   23782     CHECK(access_was_called);
   23783   }
   23784 
   23785   context1->Exit();
   23786   context0->Exit();
   23787 }
   23788 
   23789 
   23790 TEST(StrongModeAccessCheckBlocked) {
   23791   i::FLAG_strong_mode = true;
   23792   v8::Isolate* isolate = CcTest::isolate();
   23793   v8::HandleScope handle_scope(isolate);
   23794   v8::Local<Value> value;
   23795   access_was_called = false;
   23796 
   23797   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   23798 
   23799   obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
   23800   obj_template->SetAccessCheckCallback(AccessAlwaysBlockedWithFlag);
   23801 
   23802   // Create an environment
   23803   v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
   23804   context0->Enter();
   23805   v8::Local<v8::Object> global0 = context0->Global();
   23806   global0->Set(context0, v8_str("object"),
   23807                obj_template->NewInstance(context0).ToLocalChecked())
   23808       .FromJust();
   23809   {
   23810     v8::TryCatch try_catch(isolate);
   23811     value = CompileRun("'use strong'; object.x");
   23812     CHECK(!try_catch.HasCaught());
   23813     CHECK(!access_was_called);
   23814     CHECK_EQ(42, value->Int32Value(context0).FromJust());
   23815   }
   23816   {
   23817     v8::TryCatch try_catch(isolate);
   23818     value = CompileRun("'use strong'; object.foo");
   23819     CHECK(try_catch.HasCaught());
   23820     CHECK(!access_was_called);
   23821   }
   23822   {
   23823     v8::TryCatch try_catch(isolate);
   23824     value = CompileRun("'use strong'; object[10]");
   23825     CHECK(try_catch.HasCaught());
   23826     CHECK(!access_was_called);
   23827   }
   23828 
   23829   // Create an environment
   23830   v8::Local<Context> context1 = Context::New(isolate);
   23831   context1->Enter();
   23832   v8::Local<v8::Object> global1 = context1->Global();
   23833   global1->Set(context1, v8_str("object"),
   23834                obj_template->NewInstance(context1).ToLocalChecked())
   23835       .FromJust();
   23836   {
   23837     v8::TryCatch try_catch(isolate);
   23838     value = CompileRun("'use strong'; object.x");
   23839     CHECK(try_catch.HasCaught());
   23840     CHECK(access_was_called);
   23841   }
   23842   access_was_called = false;
   23843   {
   23844     v8::TryCatch try_catch(isolate);
   23845     value = CompileRun("'use strong'; object.foo");
   23846     CHECK(try_catch.HasCaught());
   23847     CHECK(access_was_called);
   23848   }
   23849   access_was_called = false;
   23850   {
   23851     v8::TryCatch try_catch(isolate);
   23852     value = CompileRun("'use strong'; object[10]");
   23853     CHECK(try_catch.HasCaught());
   23854     CHECK(access_was_called);
   23855   }
   23856 
   23857   context1->Exit();
   23858   context0->Exit();
   23859 }
   23860 
   23861 
   23862 TEST(StrongModeArityCallFromApi) {
   23863   i::FLAG_strong_mode = true;
   23864   LocalContext env;
   23865   v8::Isolate* isolate = env->GetIsolate();
   23866   v8::HandleScope scope(isolate);
   23867   Local<Function> fun;
   23868   {
   23869     v8::TryCatch try_catch(isolate);
   23870     fun = Local<Function>::Cast(CompileRun(
   23871         "function f(x) { 'use strong'; }"
   23872         "f"));
   23873 
   23874     CHECK(!try_catch.HasCaught());
   23875   }
   23876 
   23877   {
   23878     v8::TryCatch try_catch(isolate);
   23879     CHECK(fun->Call(env.local(), v8::Undefined(isolate), 0, nullptr).IsEmpty());
   23880     CHECK(try_catch.HasCaught());
   23881   }
   23882 
   23883   {
   23884     v8::TryCatch try_catch(isolate);
   23885     v8::Local<Value> args[] = {v8_num(42)};
   23886     fun->Call(env.local(), v8::Undefined(isolate), arraysize(args), args)
   23887         .ToLocalChecked();
   23888     CHECK(!try_catch.HasCaught());
   23889   }
   23890 
   23891   {
   23892     v8::TryCatch try_catch(isolate);
   23893     v8::Local<Value> args[] = {v8_num(42), v8_num(555)};
   23894     fun->Call(env.local(), v8::Undefined(isolate), arraysize(args), args)
   23895         .ToLocalChecked();
   23896     CHECK(!try_catch.HasCaught());
   23897   }
   23898 }
   23899 
   23900 
   23901 TEST(StrongModeArityCallFromApi2) {
   23902   i::FLAG_strong_mode = true;
   23903   LocalContext env;
   23904   v8::Isolate* isolate = env->GetIsolate();
   23905   v8::HandleScope scope(isolate);
   23906   Local<Function> fun;
   23907   {
   23908     v8::TryCatch try_catch(isolate);
   23909     fun = Local<Function>::Cast(CompileRun(
   23910         "'use strong';"
   23911         "function f(x) {}"
   23912         "f"));
   23913 
   23914     CHECK(!try_catch.HasCaught());
   23915   }
   23916 
   23917   {
   23918     v8::TryCatch try_catch(isolate);
   23919     CHECK(fun->Call(env.local(), v8::Undefined(isolate), 0, nullptr).IsEmpty());
   23920     CHECK(try_catch.HasCaught());
   23921   }
   23922 
   23923   {
   23924     v8::TryCatch try_catch(isolate);
   23925     v8::Local<Value> args[] = {v8_num(42)};
   23926     fun->Call(env.local(), v8::Undefined(isolate), arraysize(args), args)
   23927         .ToLocalChecked();
   23928     CHECK(!try_catch.HasCaught());
   23929   }
   23930 
   23931   {
   23932     v8::TryCatch try_catch(isolate);
   23933     v8::Local<Value> args[] = {v8_num(42), v8_num(555)};
   23934     fun->Call(env.local(), v8::Undefined(isolate), arraysize(args), args)
   23935         .ToLocalChecked();
   23936     CHECK(!try_catch.HasCaught());
   23937   }
   23938 }
   23939 
   23940 
   23941 TEST(StrongObjectDelete) {
   23942   i::FLAG_strong_mode = true;
   23943   LocalContext env;
   23944   v8::Isolate* isolate = env->GetIsolate();
   23945   v8::HandleScope scope(isolate);
   23946   Local<Object> obj;
   23947   {
   23948     v8::TryCatch try_catch(isolate);
   23949     obj = Local<Object>::Cast(CompileRun(
   23950         "'use strong';"
   23951         "({});"));
   23952     CHECK(!try_catch.HasCaught());
   23953   }
   23954   obj->DefineOwnProperty(env.local(), v8_str("foo"), v8_num(1), v8::None)
   23955       .FromJust();
   23956   obj->DefineOwnProperty(env.local(), v8_str("2"), v8_num(1), v8::None)
   23957       .FromJust();
   23958   CHECK(obj->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   23959   CHECK(obj->HasOwnProperty(env.local(), v8_str("2")).FromJust());
   23960   CHECK(!obj->Delete(env.local(), v8_str("foo")).FromJust());
   23961   CHECK(!obj->Delete(env.local(), 2).FromJust());
   23962 }
   23963 
   23964 
   23965 static void ExtrasBindingTestRuntimeFunction(
   23966     const v8::FunctionCallbackInfo<v8::Value>& args) {
   23967   CHECK_EQ(
   23968       3,
   23969       args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust());
   23970   args.GetReturnValue().Set(v8_num(7));
   23971 }
   23972 
   23973 
   23974 TEST(ExtrasBindingObject) {
   23975   v8::Isolate* isolate = CcTest::isolate();
   23976   v8::HandleScope handle_scope(isolate);
   23977   LocalContext env;
   23978 
   23979   // standalone.gypi ensures we include the test-extra.js file, which should
   23980   // export the tested functions.
   23981   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   23982 
   23983   auto func = binding->Get(env.local(), v8_str("testExtraShouldReturnFive"))
   23984                   .ToLocalChecked()
   23985                   .As<v8::Function>();
   23986   auto undefined = v8::Undefined(isolate);
   23987   auto result = func->Call(env.local(), undefined, 0, {})
   23988                     .ToLocalChecked()
   23989                     .As<v8::Number>();
   23990   CHECK_EQ(5, result->Int32Value(env.local()).FromJust());
   23991 
   23992   v8::Local<v8::FunctionTemplate> runtimeFunction =
   23993       v8::FunctionTemplate::New(isolate, ExtrasBindingTestRuntimeFunction);
   23994   binding->Set(env.local(), v8_str("runtime"),
   23995                runtimeFunction->GetFunction(env.local()).ToLocalChecked())
   23996       .FromJust();
   23997   func = binding->Get(env.local(), v8_str("testExtraShouldCallToRuntime"))
   23998              .ToLocalChecked()
   23999              .As<v8::Function>();
   24000   result = func->Call(env.local(), undefined, 0, {})
   24001                .ToLocalChecked()
   24002                .As<v8::Number>();
   24003   CHECK_EQ(7, result->Int32Value(env.local()).FromJust());
   24004 }
   24005 
   24006 
   24007 TEST(ExperimentalExtras) {
   24008   i::FLAG_experimental_extras = true;
   24009 
   24010   v8::Isolate* isolate = CcTest::isolate();
   24011   v8::HandleScope handle_scope(isolate);
   24012   LocalContext env;
   24013 
   24014   // standalone.gypi ensures we include the test-experimental-extra.js file,
   24015   // which should export the tested functions.
   24016   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   24017 
   24018   auto func =
   24019       binding->Get(env.local(), v8_str("testExperimentalExtraShouldReturnTen"))
   24020           .ToLocalChecked()
   24021           .As<v8::Function>();
   24022   auto undefined = v8::Undefined(isolate);
   24023   auto result = func->Call(env.local(), undefined, 0, {})
   24024                     .ToLocalChecked()
   24025                     .As<v8::Number>();
   24026   CHECK_EQ(10, result->Int32Value(env.local()).FromJust());
   24027 
   24028   v8::Local<v8::FunctionTemplate> runtimeFunction =
   24029       v8::FunctionTemplate::New(isolate, ExtrasBindingTestRuntimeFunction);
   24030   binding->Set(env.local(), v8_str("runtime"),
   24031                runtimeFunction->GetFunction(env.local()).ToLocalChecked())
   24032       .FromJust();
   24033   func = binding->Get(env.local(),
   24034                       v8_str("testExperimentalExtraShouldCallToRuntime"))
   24035              .ToLocalChecked()
   24036              .As<v8::Function>();
   24037   result = func->Call(env.local(), undefined, 0, {})
   24038                .ToLocalChecked()
   24039                .As<v8::Number>();
   24040   CHECK_EQ(7, result->Int32Value(env.local()).FromJust());
   24041 }
   24042 
   24043 
   24044 TEST(ExtrasUtilsObject) {
   24045   LocalContext context;
   24046   v8::Isolate* isolate = context->GetIsolate();
   24047   v8::HandleScope handle_scope(isolate);
   24048 
   24049   LocalContext env;
   24050   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   24051 
   24052   auto func = binding->Get(env.local(), v8_str("testExtraCanUseUtils"))
   24053                   .ToLocalChecked()
   24054                   .As<v8::Function>();
   24055   auto undefined = v8::Undefined(isolate);
   24056   auto result = func->Call(env.local(), undefined, 0, {})
   24057                     .ToLocalChecked()
   24058                     .As<v8::Object>();
   24059 
   24060   auto private_symbol = result->Get(env.local(), v8_str("privateSymbol"))
   24061                             .ToLocalChecked()
   24062                             .As<v8::Symbol>();
   24063   i::Handle<i::Symbol> ips = v8::Utils::OpenHandle(*private_symbol);
   24064   CHECK_EQ(true, ips->IsPrivate());
   24065 
   24066   CompileRun("var result = 0; function store(x) { result = x; }");
   24067   auto store = CompileRun("store").As<v8::Function>();
   24068 
   24069   auto fulfilled_promise = result->Get(env.local(), v8_str("fulfilledPromise"))
   24070                                .ToLocalChecked()
   24071                                .As<v8::Promise>();
   24072   fulfilled_promise->Then(env.local(), store).ToLocalChecked();
   24073   isolate->RunMicrotasks();
   24074   CHECK_EQ(1, CompileRun("result")->Int32Value(env.local()).FromJust());
   24075 
   24076   auto fulfilled_promise_2 =
   24077       result->Get(env.local(), v8_str("fulfilledPromise2"))
   24078           .ToLocalChecked()
   24079           .As<v8::Promise>();
   24080   fulfilled_promise_2->Then(env.local(), store).ToLocalChecked();
   24081   isolate->RunMicrotasks();
   24082   CHECK_EQ(2, CompileRun("result")->Int32Value(env.local()).FromJust());
   24083 
   24084   auto rejected_promise = result->Get(env.local(), v8_str("rejectedPromise"))
   24085                               .ToLocalChecked()
   24086                               .As<v8::Promise>();
   24087   rejected_promise->Catch(env.local(), store).ToLocalChecked();
   24088   isolate->RunMicrotasks();
   24089   CHECK_EQ(3, CompileRun("result")->Int32Value(env.local()).FromJust());
   24090 }
   24091 
   24092 
   24093 TEST(Map) {
   24094   v8::Isolate* isolate = CcTest::isolate();
   24095   v8::HandleScope handle_scope(isolate);
   24096   LocalContext env;
   24097 
   24098   v8::Local<v8::Map> map = v8::Map::New(isolate);
   24099   CHECK(map->IsObject());
   24100   CHECK(map->IsMap());
   24101   CHECK(map->GetPrototype()->StrictEquals(CompileRun("Map.prototype")));
   24102   CHECK_EQ(0U, map->Size());
   24103 
   24104   v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4]])");
   24105   CHECK(val->IsMap());
   24106   map = v8::Local<v8::Map>::Cast(val);
   24107   CHECK_EQ(2U, map->Size());
   24108 
   24109   v8::Local<v8::Array> contents = map->AsArray();
   24110   CHECK_EQ(4U, contents->Length());
   24111   CHECK_EQ(
   24112       1,
   24113       contents->Get(env.local(), 0).ToLocalChecked().As<v8::Int32>()->Value());
   24114   CHECK_EQ(
   24115       2,
   24116       contents->Get(env.local(), 1).ToLocalChecked().As<v8::Int32>()->Value());
   24117   CHECK_EQ(
   24118       3,
   24119       contents->Get(env.local(), 2).ToLocalChecked().As<v8::Int32>()->Value());
   24120   CHECK_EQ(
   24121       4,
   24122       contents->Get(env.local(), 3).ToLocalChecked().As<v8::Int32>()->Value());
   24123 
   24124   CHECK_EQ(2U, map->Size());
   24125 
   24126   CHECK(map->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
   24127   CHECK(map->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
   24128 
   24129   CHECK(!map->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
   24130   CHECK(!map->Has(env.local(), map).FromJust());
   24131 
   24132   CHECK_EQ(2, map->Get(env.local(), v8::Integer::New(isolate, 1))
   24133                   .ToLocalChecked()
   24134                   ->Int32Value(env.local())
   24135                   .FromJust());
   24136   CHECK_EQ(4, map->Get(env.local(), v8::Integer::New(isolate, 3))
   24137                   .ToLocalChecked()
   24138                   ->Int32Value(env.local())
   24139                   .FromJust());
   24140 
   24141   CHECK(map->Get(env.local(), v8::Integer::New(isolate, 42))
   24142             .ToLocalChecked()
   24143             ->IsUndefined());
   24144 
   24145   CHECK(!map->Set(env.local(), map, map).IsEmpty());
   24146   CHECK_EQ(3U, map->Size());
   24147   CHECK(map->Has(env.local(), map).FromJust());
   24148 
   24149   CHECK(map->Delete(env.local(), map).FromJust());
   24150   CHECK_EQ(2U, map->Size());
   24151   CHECK(!map->Has(env.local(), map).FromJust());
   24152   CHECK(!map->Delete(env.local(), map).FromJust());
   24153 
   24154   map->Clear();
   24155   CHECK_EQ(0U, map->Size());
   24156 }
   24157 
   24158 
   24159 TEST(Set) {
   24160   v8::Isolate* isolate = CcTest::isolate();
   24161   v8::HandleScope handle_scope(isolate);
   24162   LocalContext env;
   24163 
   24164   v8::Local<v8::Set> set = v8::Set::New(isolate);
   24165   CHECK(set->IsObject());
   24166   CHECK(set->IsSet());
   24167   CHECK(set->GetPrototype()->StrictEquals(CompileRun("Set.prototype")));
   24168   CHECK_EQ(0U, set->Size());
   24169 
   24170   v8::Local<v8::Value> val = CompileRun("new Set([1, 2])");
   24171   CHECK(val->IsSet());
   24172   set = v8::Local<v8::Set>::Cast(val);
   24173   CHECK_EQ(2U, set->Size());
   24174 
   24175   v8::Local<v8::Array> keys = set->AsArray();
   24176   CHECK_EQ(2U, keys->Length());
   24177   CHECK_EQ(1,
   24178            keys->Get(env.local(), 0).ToLocalChecked().As<v8::Int32>()->Value());
   24179   CHECK_EQ(2,
   24180            keys->Get(env.local(), 1).ToLocalChecked().As<v8::Int32>()->Value());
   24181 
   24182   CHECK_EQ(2U, set->Size());
   24183 
   24184   CHECK(set->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
   24185   CHECK(set->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
   24186 
   24187   CHECK(!set->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
   24188   CHECK(!set->Has(env.local(), set).FromJust());
   24189 
   24190   CHECK(!set->Add(env.local(), set).IsEmpty());
   24191   CHECK_EQ(3U, set->Size());
   24192   CHECK(set->Has(env.local(), set).FromJust());
   24193 
   24194   CHECK(set->Delete(env.local(), set).FromJust());
   24195   CHECK_EQ(2U, set->Size());
   24196   CHECK(!set->Has(env.local(), set).FromJust());
   24197   CHECK(!set->Delete(env.local(), set).FromJust());
   24198 
   24199   set->Clear();
   24200   CHECK_EQ(0U, set->Size());
   24201 }
   24202 
   24203 
   24204 TEST(CompatibleReceiverCheckOnCachedICHandler) {
   24205   v8::Isolate* isolate = CcTest::isolate();
   24206   v8::HandleScope scope(isolate);
   24207   v8::Local<v8::FunctionTemplate> parent = FunctionTemplate::New(isolate);
   24208   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, parent);
   24209   auto returns_42 =
   24210       v8::FunctionTemplate::New(isolate, Returns42, Local<Value>(), signature);
   24211   parent->PrototypeTemplate()->SetAccessorProperty(v8_str("age"), returns_42);
   24212   v8::Local<v8::FunctionTemplate> child = v8::FunctionTemplate::New(isolate);
   24213   child->Inherit(parent);
   24214   LocalContext env;
   24215   CHECK(env->Global()
   24216             ->Set(env.local(), v8_str("Child"),
   24217                   child->GetFunction(env.local()).ToLocalChecked())
   24218             .FromJust());
   24219 
   24220   // Make sure there's a compiled stub for "Child.prototype.age" in the cache.
   24221   CompileRun(
   24222       "var real = new Child();\n"
   24223       "for (var i = 0; i < 3; ++i) {\n"
   24224       "  real.age;\n"
   24225       "}\n");
   24226 
   24227   // Check that the cached stub is never used.
   24228   ExpectInt32(
   24229       "var fake = Object.create(Child.prototype);\n"
   24230       "var result = 0;\n"
   24231       "function test(d) {\n"
   24232       "  if (d == 3) return;\n"
   24233       "  try {\n"
   24234       "    fake.age;\n"
   24235       "    result = 1;\n"
   24236       "  } catch (e) {\n"
   24237       "  }\n"
   24238       "  test(d+1);\n"
   24239       "}\n"
   24240       "test(0);\n"
   24241       "result;\n",
   24242       0);
   24243 }
   24244 
   24245 class FutexInterruptionThread : public v8::base::Thread {
   24246  public:
   24247   explicit FutexInterruptionThread(v8::Isolate* isolate)
   24248       : Thread(Options("FutexInterruptionThread")), isolate_(isolate) {}
   24249 
   24250   virtual void Run() {
   24251     // Wait a bit before terminating.
   24252     v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
   24253     isolate_->TerminateExecution();
   24254   }
   24255 
   24256  private:
   24257   v8::Isolate* isolate_;
   24258 };
   24259 
   24260 
   24261 TEST(FutexInterruption) {
   24262   i::FLAG_harmony_sharedarraybuffer = true;
   24263   v8::Isolate* isolate = CcTest::isolate();
   24264   v8::HandleScope scope(isolate);
   24265   LocalContext env;
   24266 
   24267   FutexInterruptionThread timeout_thread(isolate);
   24268 
   24269   v8::TryCatch try_catch(CcTest::isolate());
   24270   timeout_thread.Start();
   24271 
   24272   CompileRun(
   24273       "var ab = new SharedArrayBuffer(4);"
   24274       "var i32a = new Int32Array(ab);"
   24275       "Atomics.futexWait(i32a, 0, 0);");
   24276   CHECK(try_catch.HasTerminated());
   24277   timeout_thread.Join();
   24278 }
   24279 
   24280 
   24281 TEST(EstimatedContextSize) {
   24282   v8::Isolate* isolate = CcTest::isolate();
   24283   v8::HandleScope scope(isolate);
   24284   LocalContext env;
   24285   CHECK(50000 < env->EstimatedSize());
   24286 }
   24287 
   24288 
   24289 static int nb_uncaught_exception_callback_calls = 0;
   24290 
   24291 
   24292 bool NoAbortOnUncaughtException(v8::Isolate* isolate) {
   24293   ++nb_uncaught_exception_callback_calls;
   24294   return false;
   24295 }
   24296 
   24297 
   24298 TEST(AbortOnUncaughtExceptionNoAbort) {
   24299   v8::Isolate* isolate = CcTest::isolate();
   24300   v8::HandleScope handle_scope(isolate);
   24301   v8::Local<v8::ObjectTemplate> global_template =
   24302       v8::ObjectTemplate::New(isolate);
   24303   LocalContext env(NULL, global_template);
   24304 
   24305   i::FLAG_abort_on_uncaught_exception = true;
   24306   isolate->SetAbortOnUncaughtExceptionCallback(NoAbortOnUncaughtException);
   24307 
   24308   CompileRun("function boom() { throw new Error(\"boom\") }");
   24309 
   24310   v8::Local<v8::Object> global_object = env->Global();
   24311   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   24312       global_object->Get(env.local(), v8_str("boom")).ToLocalChecked());
   24313 
   24314   CHECK(foo->Call(env.local(), global_object, 0, NULL).IsEmpty());
   24315 
   24316   CHECK_EQ(1, nb_uncaught_exception_callback_calls);
   24317 }
   24318 
   24319 
   24320 TEST(AccessCheckedIsConcatSpreadable) {
   24321   i::FLAG_harmony_concat_spreadable = true;
   24322   v8::Isolate* isolate = CcTest::isolate();
   24323   HandleScope scope(isolate);
   24324   LocalContext env;
   24325 
   24326   // Object with access check
   24327   Local<ObjectTemplate> spreadable_template = v8::ObjectTemplate::New(isolate);
   24328   spreadable_template->SetAccessCheckCallback(AccessBlocker);
   24329   spreadable_template->Set(v8::Symbol::GetIsConcatSpreadable(isolate),
   24330                            v8::Boolean::New(isolate, true));
   24331   Local<Object> object =
   24332       spreadable_template->NewInstance(env.local()).ToLocalChecked();
   24333 
   24334   allowed_access = true;
   24335   CHECK(env->Global()->Set(env.local(), v8_str("object"), object).FromJust());
   24336   object->Set(env.local(), v8_str("length"), v8_num(2)).FromJust();
   24337   object->Set(env.local(), 0U, v8_str("a")).FromJust();
   24338   object->Set(env.local(), 1U, v8_str("b")).FromJust();
   24339 
   24340   // Access check is allowed, and the object is spread
   24341   CompileRun("var result = [].concat(object)");
   24342   ExpectTrue("Array.isArray(result)");
   24343   ExpectString("result[0]", "a");
   24344   ExpectString("result[1]", "b");
   24345   ExpectTrue("result.length === 2");
   24346   ExpectTrue("object[Symbol.isConcatSpreadable]");
   24347 
   24348   // If access check fails, the value of @@isConcatSpreadable is ignored
   24349   allowed_access = false;
   24350   CompileRun("var result = [].concat(object)");
   24351   ExpectTrue("Array.isArray(result)");
   24352   ExpectTrue("result[0] === object");
   24353   ExpectTrue("result.length === 1");
   24354   ExpectTrue("object[Symbol.isConcatSpreadable] === undefined");
   24355 }
   24356 
   24357 
   24358 TEST(AccessCheckedToStringTag) {
   24359   i::FLAG_harmony_tostring = true;
   24360   v8::Isolate* isolate = CcTest::isolate();
   24361   HandleScope scope(isolate);
   24362   LocalContext env;
   24363 
   24364   // Object with access check
   24365   Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
   24366   object_template->SetAccessCheckCallback(AccessBlocker);
   24367   Local<Object> object =
   24368       object_template->NewInstance(env.local()).ToLocalChecked();
   24369 
   24370   allowed_access = true;
   24371   env->Global()->Set(env.local(), v8_str("object"), object).FromJust();
   24372   object->Set(env.local(), v8::Symbol::GetToStringTag(isolate), v8_str("hello"))
   24373       .FromJust();
   24374 
   24375   // Access check is allowed, and the toStringTag is read
   24376   CompileRun("var result = Object.prototype.toString.call(object)");
   24377   ExpectString("result", "[object hello]");
   24378   ExpectString("object[Symbol.toStringTag]", "hello");
   24379 
   24380   // ToString through the API should succeed too.
   24381   String::Utf8Value result_allowed(
   24382       object->ObjectProtoToString(env.local()).ToLocalChecked());
   24383   CHECK_EQ(0, strcmp(*result_allowed, "[object hello]"));
   24384 
   24385   // If access check fails, the value of @@toStringTag is ignored
   24386   allowed_access = false;
   24387   CompileRun("var result = Object.prototype.toString.call(object)");
   24388   ExpectString("result", "[object Object]");
   24389   ExpectTrue("object[Symbol.toStringTag] === undefined");
   24390 
   24391   // ToString through the API should also fail.
   24392   String::Utf8Value result_denied(
   24393       object->ObjectProtoToString(env.local()).ToLocalChecked());
   24394   CHECK_EQ(0, strcmp(*result_denied, "[object Object]"));
   24395 }
   24396 
   24397 
   24398 TEST(ObjectTemplateIntrinsics) {
   24399   v8::Isolate* isolate = CcTest::isolate();
   24400   v8::HandleScope scope(isolate);
   24401   LocalContext env;
   24402 
   24403   Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
   24404   object_template->SetIntrinsicDataProperty(v8_str("values"),
   24405                                             v8::kArrayProto_values);
   24406   Local<Object> object =
   24407       object_template->NewInstance(env.local()).ToLocalChecked();
   24408 
   24409   CHECK(env->Global()->Set(env.local(), v8_str("obj1"), object).FromJust());
   24410   ExpectString("typeof obj1.values", "function");
   24411 
   24412   auto values = Local<Function>::Cast(
   24413       object->Get(env.local(), v8_str("values")).ToLocalChecked());
   24414   auto fn = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*values));
   24415   auto ctx = v8::Utils::OpenHandle(*env.local());
   24416   CHECK_EQ(fn->GetCreationContext(), *ctx);
   24417 
   24418   {
   24419     LocalContext env2;
   24420     Local<Object> object2 =
   24421         object_template->NewInstance(env2.local()).ToLocalChecked();
   24422     CHECK(
   24423         env2->Global()->Set(env2.local(), v8_str("obj2"), object2).FromJust());
   24424     ExpectString("typeof obj2.values", "function");
   24425     CHECK_NE(*object->Get(env2.local(), v8_str("values")).ToLocalChecked(),
   24426              *object2->Get(env2.local(), v8_str("values")).ToLocalChecked());
   24427 
   24428     auto values2 = Local<Function>::Cast(
   24429         object2->Get(env2.local(), v8_str("values")).ToLocalChecked());
   24430     auto fn2 = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*values2));
   24431     auto ctx2 = v8::Utils::OpenHandle(*env2.local());
   24432     CHECK_EQ(fn2->GetCreationContext(), *ctx2);
   24433   }
   24434 }
   24435 
   24436 
   24437 TEST(Proxy) {
   24438   i::FLAG_harmony_proxies = true;
   24439   LocalContext context;
   24440   v8::Isolate* isolate = CcTest::isolate();
   24441   v8::HandleScope scope(isolate);
   24442   v8::Local<v8::Object> target = CompileRun("({})").As<v8::Object>();
   24443   v8::Local<v8::Object> handler = CompileRun("({})").As<v8::Object>();
   24444 
   24445   v8::Local<v8::Proxy> proxy =
   24446       v8::Proxy::New(context.local(), target, handler).ToLocalChecked();
   24447   CHECK(proxy->IsProxy());
   24448   CHECK(!target->IsProxy());
   24449   CHECK(!proxy->IsRevoked());
   24450   CHECK(proxy->GetTarget()->SameValue(target));
   24451   CHECK(proxy->GetHandler()->SameValue(handler));
   24452 
   24453   proxy->Revoke();
   24454   CHECK(proxy->IsProxy());
   24455   CHECK(!target->IsProxy());
   24456   CHECK(proxy->IsRevoked());
   24457   CHECK(proxy->GetTarget()->SameValue(target));
   24458   CHECK(proxy->GetHandler()->IsNull());
   24459 }
   24460